.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * RTL8XXXU mac80211 USB driver |
---|
3 | 4 | * |
---|
.. | .. |
---|
10 | 11 | * rtl8723au driver. As the Realtek 8xxx chips are very similar in |
---|
11 | 12 | * their programming interface, I have started adding support for |
---|
12 | 13 | * additional 8xxx chips like the 8192cu, 8188cus, etc. |
---|
13 | | - * |
---|
14 | | - * This program is free software; you can redistribute it and/or modify it |
---|
15 | | - * under the terms of version 2 of the GNU General Public License as |
---|
16 | | - * published by the Free Software Foundation. |
---|
17 | | - * |
---|
18 | | - * This program is distributed in the hope that it will be useful, but WITHOUT |
---|
19 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
20 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
21 | | - * more details. |
---|
22 | 14 | */ |
---|
23 | 15 | |
---|
24 | 16 | #include <linux/init.h> |
---|
.. | .. |
---|
1153 | 1145 | switch (hw->conf.chandef.width) { |
---|
1154 | 1146 | case NL80211_CHAN_WIDTH_20_NOHT: |
---|
1155 | 1147 | ht = false; |
---|
| 1148 | + /* fall through */ |
---|
1156 | 1149 | case NL80211_CHAN_WIDTH_20: |
---|
1157 | 1150 | opmode |= BW_OPMODE_20MHZ; |
---|
1158 | 1151 | rtl8xxxu_write8(priv, REG_BW_OPMODE, opmode); |
---|
.. | .. |
---|
1262 | 1255 | void rtl8xxxu_gen2_config_channel(struct ieee80211_hw *hw) |
---|
1263 | 1256 | { |
---|
1264 | 1257 | struct rtl8xxxu_priv *priv = hw->priv; |
---|
1265 | | - u32 val32, rsr; |
---|
| 1258 | + u32 val32; |
---|
1266 | 1259 | u8 val8, subchannel; |
---|
1267 | 1260 | u16 rf_mode_bw; |
---|
1268 | 1261 | bool ht = true; |
---|
.. | .. |
---|
1271 | 1264 | |
---|
1272 | 1265 | rf_mode_bw = rtl8xxxu_read16(priv, REG_WMAC_TRXPTCL_CTL); |
---|
1273 | 1266 | rf_mode_bw &= ~WMAC_TRXPTCL_CTL_BW_MASK; |
---|
1274 | | - rsr = rtl8xxxu_read32(priv, REG_RESPONSE_RATE_SET); |
---|
1275 | 1267 | channel = hw->conf.chandef.chan->hw_value; |
---|
1276 | 1268 | |
---|
1277 | 1269 | /* Hack */ |
---|
.. | .. |
---|
1280 | 1272 | switch (hw->conf.chandef.width) { |
---|
1281 | 1273 | case NL80211_CHAN_WIDTH_20_NOHT: |
---|
1282 | 1274 | ht = false; |
---|
| 1275 | + /* fall through */ |
---|
1283 | 1276 | case NL80211_CHAN_WIDTH_20: |
---|
1284 | 1277 | rf_mode_bw |= WMAC_TRXPTCL_CTL_BW_20; |
---|
1285 | 1278 | subchannel = 0; |
---|
.. | .. |
---|
1614 | 1607 | static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) |
---|
1615 | 1608 | { |
---|
1616 | 1609 | struct device *dev = &priv->udev->dev; |
---|
1617 | | - u32 val32, bonding; |
---|
| 1610 | + u32 val32, bonding, sys_cfg; |
---|
1618 | 1611 | u16 val16; |
---|
1619 | 1612 | |
---|
1620 | | - val32 = rtl8xxxu_read32(priv, REG_SYS_CFG); |
---|
1621 | | - priv->chip_cut = (val32 & SYS_CFG_CHIP_VERSION_MASK) >> |
---|
| 1613 | + sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG); |
---|
| 1614 | + priv->chip_cut = (sys_cfg & SYS_CFG_CHIP_VERSION_MASK) >> |
---|
1622 | 1615 | SYS_CFG_CHIP_VERSION_SHIFT; |
---|
1623 | | - if (val32 & SYS_CFG_TRP_VAUX_EN) { |
---|
| 1616 | + if (sys_cfg & SYS_CFG_TRP_VAUX_EN) { |
---|
1624 | 1617 | dev_info(dev, "Unsupported test chip\n"); |
---|
1625 | 1618 | return -ENOTSUPP; |
---|
1626 | 1619 | } |
---|
1627 | 1620 | |
---|
1628 | | - if (val32 & SYS_CFG_BT_FUNC) { |
---|
| 1621 | + if (sys_cfg & SYS_CFG_BT_FUNC) { |
---|
1629 | 1622 | if (priv->chip_cut >= 3) { |
---|
1630 | 1623 | sprintf(priv->chip_name, "8723BU"); |
---|
1631 | 1624 | priv->rtl_chip = RTL8723B; |
---|
.. | .. |
---|
1647 | 1640 | if (val32 & MULTI_GPS_FUNC_EN) |
---|
1648 | 1641 | priv->has_gps = 1; |
---|
1649 | 1642 | priv->is_multi_func = 1; |
---|
1650 | | - } else if (val32 & SYS_CFG_TYPE_ID) { |
---|
| 1643 | + } else if (sys_cfg & SYS_CFG_TYPE_ID) { |
---|
1651 | 1644 | bonding = rtl8xxxu_read32(priv, REG_HPON_FSM); |
---|
1652 | 1645 | bonding &= HPON_FSM_BONDING_MASK; |
---|
1653 | 1646 | if (priv->fops->tx_desc_size == |
---|
.. | .. |
---|
1695 | 1688 | case RTL8188E: |
---|
1696 | 1689 | case RTL8192E: |
---|
1697 | 1690 | case RTL8723B: |
---|
1698 | | - switch (val32 & SYS_CFG_VENDOR_EXT_MASK) { |
---|
| 1691 | + switch (sys_cfg & SYS_CFG_VENDOR_EXT_MASK) { |
---|
1699 | 1692 | case SYS_CFG_VENDOR_ID_TSMC: |
---|
1700 | 1693 | sprintf(priv->chip_vendor, "TSMC"); |
---|
1701 | 1694 | break; |
---|
.. | .. |
---|
1712 | 1705 | } |
---|
1713 | 1706 | break; |
---|
1714 | 1707 | default: |
---|
1715 | | - if (val32 & SYS_CFG_VENDOR_ID) { |
---|
| 1708 | + if (sys_cfg & SYS_CFG_VENDOR_ID) { |
---|
1716 | 1709 | sprintf(priv->chip_vendor, "UMC"); |
---|
1717 | 1710 | priv->vendor_umc = 1; |
---|
1718 | 1711 | } else { |
---|
.. | .. |
---|
1748 | 1741 | case 3: |
---|
1749 | 1742 | priv->ep_tx_low_queue = 1; |
---|
1750 | 1743 | priv->ep_tx_count++; |
---|
| 1744 | + /* fall through */ |
---|
1751 | 1745 | case 2: |
---|
1752 | 1746 | priv->ep_tx_normal_queue = 1; |
---|
1753 | 1747 | priv->ep_tx_count++; |
---|
| 1748 | + /* fall through */ |
---|
1754 | 1749 | case 1: |
---|
1755 | 1750 | priv->ep_tx_high_queue = 1; |
---|
1756 | 1751 | priv->ep_tx_count++; |
---|
.. | .. |
---|
1879 | 1874 | |
---|
1880 | 1875 | /* We have 8 bits to indicate validity */ |
---|
1881 | 1876 | map_addr = offset * 8; |
---|
1882 | | - if (map_addr >= EFUSE_MAP_LEN) { |
---|
1883 | | - dev_warn(dev, "%s: Illegal map_addr (%04x), " |
---|
1884 | | - "efuse corrupt!\n", |
---|
1885 | | - __func__, map_addr); |
---|
1886 | | - ret = -EINVAL; |
---|
1887 | | - goto exit; |
---|
1888 | | - } |
---|
1889 | 1877 | for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { |
---|
1890 | 1878 | /* Check word enable condition in the section */ |
---|
1891 | 1879 | if (word_mask & BIT(i)) { |
---|
.. | .. |
---|
1896 | 1884 | ret = rtl8xxxu_read_efuse8(priv, efuse_addr++, &val8); |
---|
1897 | 1885 | if (ret) |
---|
1898 | 1886 | goto exit; |
---|
| 1887 | + if (map_addr >= EFUSE_MAP_LEN - 1) { |
---|
| 1888 | + dev_warn(dev, "%s: Illegal map_addr (%04x), " |
---|
| 1889 | + "efuse corrupt!\n", |
---|
| 1890 | + __func__, map_addr); |
---|
| 1891 | + ret = -EINVAL; |
---|
| 1892 | + goto exit; |
---|
| 1893 | + } |
---|
1899 | 1894 | priv->efuse_wifi.raw[map_addr++] = val8; |
---|
1900 | 1895 | |
---|
1901 | 1896 | ret = rtl8xxxu_read_efuse8(priv, efuse_addr++, &val8); |
---|
.. | .. |
---|
2930 | 2925 | } |
---|
2931 | 2926 | |
---|
2932 | 2927 | if (!(simubitmap & 0x30) && priv->tx_paths > 1) { |
---|
2933 | | - /* path B RX OK */ |
---|
| 2928 | + /* path B TX OK */ |
---|
2934 | 2929 | for (i = 4; i < 6; i++) |
---|
2935 | 2930 | result[3][i] = result[c1][i]; |
---|
2936 | 2931 | } |
---|
2937 | 2932 | |
---|
2938 | | - if (!(simubitmap & 0x30) && priv->tx_paths > 1) { |
---|
| 2933 | + if (!(simubitmap & 0xc0) && priv->tx_paths > 1) { |
---|
2939 | 2934 | /* path B RX OK */ |
---|
2940 | 2935 | for (i = 6; i < 8; i++) |
---|
2941 | 2936 | result[3][i] = result[c1][i]; |
---|
.. | .. |
---|
3119 | 3114 | u32 i, val32; |
---|
3120 | 3115 | int path_a_ok, path_b_ok; |
---|
3121 | 3116 | int retry = 2; |
---|
3122 | | - const u32 adda_regs[RTL8XXXU_ADDA_REGS] = { |
---|
| 3117 | + static const u32 adda_regs[RTL8XXXU_ADDA_REGS] = { |
---|
3123 | 3118 | REG_FPGA0_XCD_SWITCH_CTRL, REG_BLUETOOTH, |
---|
3124 | 3119 | REG_RX_WAIT_CCA, REG_TX_CCK_RFON, |
---|
3125 | 3120 | REG_TX_CCK_BBON, REG_TX_OFDM_RFON, |
---|
.. | .. |
---|
3129 | 3124 | REG_RX_TO_RX, REG_STANDBY, |
---|
3130 | 3125 | REG_SLEEP, REG_PMPD_ANAEN |
---|
3131 | 3126 | }; |
---|
3132 | | - const u32 iqk_mac_regs[RTL8XXXU_MAC_REGS] = { |
---|
| 3127 | + static const u32 iqk_mac_regs[RTL8XXXU_MAC_REGS] = { |
---|
3133 | 3128 | REG_TXPAUSE, REG_BEACON_CTRL, |
---|
3134 | 3129 | REG_BEACON_CTRL_1, REG_GPIO_MUXCFG |
---|
3135 | 3130 | }; |
---|
3136 | | - const u32 iqk_bb_regs[RTL8XXXU_BB_REGS] = { |
---|
| 3131 | + static const u32 iqk_bb_regs[RTL8XXXU_BB_REGS] = { |
---|
3137 | 3132 | REG_OFDM0_TRX_PATH_ENABLE, REG_OFDM0_TR_MUX_PAR, |
---|
3138 | 3133 | REG_FPGA0_XCD_RF_SW_CTRL, REG_CONFIG_ANT_A, REG_CONFIG_ANT_B, |
---|
3139 | 3134 | REG_FPGA0_XAB_RF_SW_CTRL, REG_FPGA0_XA_RF_INT_OE, |
---|
.. | .. |
---|
3824 | 3819 | rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0e); |
---|
3825 | 3820 | } |
---|
3826 | 3821 | |
---|
3827 | | -#ifdef NEED_PS_TDMA |
---|
3828 | | -static void rtl8723bu_set_ps_tdma(struct rtl8xxxu_priv *priv, |
---|
3829 | | - u8 arg1, u8 arg2, u8 arg3, u8 arg4, u8 arg5) |
---|
| 3822 | +void rtl8723bu_set_ps_tdma(struct rtl8xxxu_priv *priv, |
---|
| 3823 | + u8 arg1, u8 arg2, u8 arg3, u8 arg4, u8 arg5) |
---|
3830 | 3824 | { |
---|
3831 | 3825 | struct h2c_cmd h2c; |
---|
3832 | 3826 | |
---|
.. | .. |
---|
3839 | 3833 | h2c.b_type_dma.data5 = arg5; |
---|
3840 | 3834 | rtl8xxxu_gen2_h2c_cmd(priv, &h2c, sizeof(h2c.b_type_dma)); |
---|
3841 | 3835 | } |
---|
3842 | | -#endif |
---|
3843 | 3836 | |
---|
3844 | 3837 | void rtl8xxxu_gen2_disable_rf(struct rtl8xxxu_priv *priv) |
---|
3845 | 3838 | { |
---|
.. | .. |
---|
3895 | 3888 | |
---|
3896 | 3889 | /* Check if MAC is already powered on */ |
---|
3897 | 3890 | val8 = rtl8xxxu_read8(priv, REG_CR); |
---|
| 3891 | + val16 = rtl8xxxu_read16(priv, REG_SYS_CLKR); |
---|
3898 | 3892 | |
---|
3899 | 3893 | /* |
---|
3900 | 3894 | * Fix 92DU-VC S3 hang with the reason is that secondary mac is not |
---|
3901 | 3895 | * initialized. First MAC returns 0xea, second MAC returns 0x00 |
---|
3902 | 3896 | */ |
---|
3903 | | - if (val8 == 0xea) |
---|
| 3897 | + if (val8 == 0xea || !(val16 & SYS_CLK_MAC_CLK_ENABLE)) |
---|
3904 | 3898 | macpower = false; |
---|
3905 | 3899 | else |
---|
3906 | 3900 | macpower = true; |
---|
.. | .. |
---|
4051 | 4045 | RCR_ACCEPT_MGMT_FRAME | RCR_HTC_LOC_CTRL | |
---|
4052 | 4046 | RCR_APPEND_PHYSTAT | RCR_APPEND_ICV | RCR_APPEND_MIC; |
---|
4053 | 4047 | rtl8xxxu_write32(priv, REG_RCR, val32); |
---|
| 4048 | + priv->regrcr = val32; |
---|
4054 | 4049 | |
---|
4055 | 4050 | /* |
---|
4056 | 4051 | * Accept all multicast |
---|
.. | .. |
---|
4310 | 4305 | rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8); |
---|
4311 | 4306 | } |
---|
4312 | 4307 | |
---|
4313 | | -void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv, u32 ramask, int sgi) |
---|
| 4308 | +void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv, |
---|
| 4309 | + u32 ramask, u8 rateid, int sgi) |
---|
4314 | 4310 | { |
---|
4315 | 4311 | struct h2c_cmd h2c; |
---|
4316 | 4312 | |
---|
.. | .. |
---|
4330 | 4326 | } |
---|
4331 | 4327 | |
---|
4332 | 4328 | void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv, |
---|
4333 | | - u32 ramask, int sgi) |
---|
| 4329 | + u32 ramask, u8 rateid, int sgi) |
---|
4334 | 4330 | { |
---|
4335 | 4331 | struct h2c_cmd h2c; |
---|
4336 | | - u8 bw = 0; |
---|
| 4332 | + u8 bw = RTL8XXXU_CHANNEL_WIDTH_20; |
---|
4337 | 4333 | |
---|
4338 | 4334 | memset(&h2c, 0, sizeof(struct h2c_cmd)); |
---|
4339 | 4335 | |
---|
.. | .. |
---|
4343 | 4339 | h2c.b_macid_cfg.ramask2 = (ramask >> 16) & 0xff; |
---|
4344 | 4340 | h2c.b_macid_cfg.ramask3 = (ramask >> 24) & 0xff; |
---|
4345 | 4341 | |
---|
4346 | | - h2c.ramask.arg = 0x80; |
---|
4347 | | - h2c.b_macid_cfg.data1 = 0; |
---|
| 4342 | + h2c.b_macid_cfg.data1 = rateid; |
---|
4348 | 4343 | if (sgi) |
---|
4349 | 4344 | h2c.b_macid_cfg.data1 |= BIT(7); |
---|
4350 | 4345 | |
---|
4351 | 4346 | h2c.b_macid_cfg.data2 = bw; |
---|
4352 | 4347 | |
---|
4353 | | - dev_dbg(&priv->udev->dev, "%s: rate mask %08x, arg %02x, size %zi\n", |
---|
4354 | | - __func__, ramask, h2c.ramask.arg, sizeof(h2c.b_macid_cfg)); |
---|
| 4348 | + dev_dbg(&priv->udev->dev, "%s: rate mask %08x, rateid %02x, sgi %d, size %zi\n", |
---|
| 4349 | + __func__, ramask, rateid, sgi, sizeof(h2c.b_macid_cfg)); |
---|
4355 | 4350 | rtl8xxxu_gen2_h2c_cmd(priv, &h2c, sizeof(h2c.b_macid_cfg)); |
---|
4356 | 4351 | } |
---|
4357 | 4352 | |
---|
.. | .. |
---|
4375 | 4370 | void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv, |
---|
4376 | 4371 | u8 macid, bool connect) |
---|
4377 | 4372 | { |
---|
4378 | | -#ifdef RTL8XXXU_GEN2_REPORT_CONNECT |
---|
4379 | 4373 | /* |
---|
4380 | | - * Barry Day reports this causes issues with 8192eu and 8723bu |
---|
4381 | | - * devices reconnecting. The reason for this is unclear, but |
---|
4382 | | - * until it is better understood, leave the code in place but |
---|
4383 | | - * disabled, so it is not lost. |
---|
| 4374 | + * The firmware turns on the rate control when it knows it's |
---|
| 4375 | + * connected to a network. |
---|
4384 | 4376 | */ |
---|
4385 | 4377 | struct h2c_cmd h2c; |
---|
4386 | 4378 | |
---|
.. | .. |
---|
4393 | 4385 | h2c.media_status_rpt.parm &= ~BIT(0); |
---|
4394 | 4386 | |
---|
4395 | 4387 | rtl8xxxu_gen2_h2c_cmd(priv, &h2c, sizeof(h2c.media_status_rpt)); |
---|
4396 | | -#endif |
---|
4397 | 4388 | } |
---|
4398 | 4389 | |
---|
4399 | 4390 | void rtl8xxxu_gen1_init_aggregation(struct rtl8xxxu_priv *priv) |
---|
.. | .. |
---|
4484 | 4475 | rtl8xxxu_write8(priv, REG_INIRTS_RATE_SEL, rate_idx); |
---|
4485 | 4476 | } |
---|
4486 | 4477 | |
---|
| 4478 | +static u16 |
---|
| 4479 | +rtl8xxxu_wireless_mode(struct ieee80211_hw *hw, struct ieee80211_sta *sta) |
---|
| 4480 | +{ |
---|
| 4481 | + u16 network_type = WIRELESS_MODE_UNKNOWN; |
---|
| 4482 | + |
---|
| 4483 | + if (hw->conf.chandef.chan->band == NL80211_BAND_5GHZ) { |
---|
| 4484 | + if (sta->vht_cap.vht_supported) |
---|
| 4485 | + network_type = WIRELESS_MODE_AC; |
---|
| 4486 | + else if (sta->ht_cap.ht_supported) |
---|
| 4487 | + network_type = WIRELESS_MODE_N_5G; |
---|
| 4488 | + |
---|
| 4489 | + network_type |= WIRELESS_MODE_A; |
---|
| 4490 | + } else { |
---|
| 4491 | + if (sta->vht_cap.vht_supported) |
---|
| 4492 | + network_type = WIRELESS_MODE_AC; |
---|
| 4493 | + else if (sta->ht_cap.ht_supported) |
---|
| 4494 | + network_type = WIRELESS_MODE_N_24G; |
---|
| 4495 | + |
---|
| 4496 | + if (sta->supp_rates[0] <= 0xf) |
---|
| 4497 | + network_type |= WIRELESS_MODE_B; |
---|
| 4498 | + else if (sta->supp_rates[0] & 0xf) |
---|
| 4499 | + network_type |= (WIRELESS_MODE_B | WIRELESS_MODE_G); |
---|
| 4500 | + else |
---|
| 4501 | + network_type |= WIRELESS_MODE_G; |
---|
| 4502 | + } |
---|
| 4503 | + |
---|
| 4504 | + return network_type; |
---|
| 4505 | +} |
---|
| 4506 | + |
---|
| 4507 | +static void rtl8xxxu_set_aifs(struct rtl8xxxu_priv *priv, u8 slot_time) |
---|
| 4508 | +{ |
---|
| 4509 | + u32 reg_edca_param[IEEE80211_NUM_ACS] = { |
---|
| 4510 | + [IEEE80211_AC_VO] = REG_EDCA_VO_PARAM, |
---|
| 4511 | + [IEEE80211_AC_VI] = REG_EDCA_VI_PARAM, |
---|
| 4512 | + [IEEE80211_AC_BE] = REG_EDCA_BE_PARAM, |
---|
| 4513 | + [IEEE80211_AC_BK] = REG_EDCA_BK_PARAM, |
---|
| 4514 | + }; |
---|
| 4515 | + u32 val32; |
---|
| 4516 | + u16 wireless_mode = 0; |
---|
| 4517 | + u8 aifs, aifsn, sifs; |
---|
| 4518 | + int i; |
---|
| 4519 | + |
---|
| 4520 | + if (priv->vif) { |
---|
| 4521 | + struct ieee80211_sta *sta; |
---|
| 4522 | + |
---|
| 4523 | + rcu_read_lock(); |
---|
| 4524 | + sta = ieee80211_find_sta(priv->vif, priv->vif->bss_conf.bssid); |
---|
| 4525 | + if (sta) |
---|
| 4526 | + wireless_mode = rtl8xxxu_wireless_mode(priv->hw, sta); |
---|
| 4527 | + rcu_read_unlock(); |
---|
| 4528 | + } |
---|
| 4529 | + |
---|
| 4530 | + if (priv->hw->conf.chandef.chan->band == NL80211_BAND_5GHZ || |
---|
| 4531 | + (wireless_mode & WIRELESS_MODE_N_24G)) |
---|
| 4532 | + sifs = 16; |
---|
| 4533 | + else |
---|
| 4534 | + sifs = 10; |
---|
| 4535 | + |
---|
| 4536 | + for (i = 0; i < IEEE80211_NUM_ACS; i++) { |
---|
| 4537 | + val32 = rtl8xxxu_read32(priv, reg_edca_param[i]); |
---|
| 4538 | + |
---|
| 4539 | + /* It was set in conf_tx. */ |
---|
| 4540 | + aifsn = val32 & 0xff; |
---|
| 4541 | + |
---|
| 4542 | + /* aifsn not set yet or already fixed */ |
---|
| 4543 | + if (aifsn < 2 || aifsn > 15) |
---|
| 4544 | + continue; |
---|
| 4545 | + |
---|
| 4546 | + aifs = aifsn * slot_time + sifs; |
---|
| 4547 | + |
---|
| 4548 | + val32 &= ~0xff; |
---|
| 4549 | + val32 |= aifs; |
---|
| 4550 | + rtl8xxxu_write32(priv, reg_edca_param[i], val32); |
---|
| 4551 | + } |
---|
| 4552 | +} |
---|
| 4553 | + |
---|
4487 | 4554 | static void |
---|
4488 | 4555 | rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
---|
4489 | 4556 | struct ieee80211_bss_conf *bss_conf, u32 changed) |
---|
.. | .. |
---|
4526 | 4593 | sgi = 1; |
---|
4527 | 4594 | rcu_read_unlock(); |
---|
4528 | 4595 | |
---|
4529 | | - priv->fops->update_rate_mask(priv, ramask, sgi); |
---|
| 4596 | + priv->vif = vif; |
---|
| 4597 | + priv->rssi_level = RTL8XXXU_RATR_STA_INIT; |
---|
| 4598 | + |
---|
| 4599 | + priv->fops->update_rate_mask(priv, ramask, 0, sgi); |
---|
4530 | 4600 | |
---|
4531 | 4601 | rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff); |
---|
4532 | 4602 | |
---|
.. | .. |
---|
4566 | 4636 | else |
---|
4567 | 4637 | val8 = 20; |
---|
4568 | 4638 | rtl8xxxu_write8(priv, REG_SLOT, val8); |
---|
| 4639 | + |
---|
| 4640 | + rtl8xxxu_set_aifs(priv, val8); |
---|
4569 | 4641 | } |
---|
4570 | 4642 | |
---|
4571 | 4643 | if (changed & BSS_CHANGED_BSSID) { |
---|
.. | .. |
---|
4778 | 4850 | struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info); |
---|
4779 | 4851 | struct rtl8xxxu_priv *priv = hw->priv; |
---|
4780 | 4852 | struct device *dev = &priv->udev->dev; |
---|
| 4853 | + u8 *qc = ieee80211_get_qos_ctl(hdr); |
---|
| 4854 | + u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; |
---|
4781 | 4855 | u32 rate; |
---|
4782 | 4856 | u16 rate_flags = tx_info->control.rates[0].flags; |
---|
4783 | 4857 | u16 seq_number; |
---|
.. | .. |
---|
4789 | 4863 | rate = tx_rate->hw_value; |
---|
4790 | 4864 | |
---|
4791 | 4865 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX) |
---|
4792 | | - dev_info(dev, "%s: TX rate: %d, pkt size %d\n", |
---|
4793 | | - __func__, rate, cpu_to_le16(tx_desc->pkt_size)); |
---|
| 4866 | + dev_info(dev, "%s: TX rate: %d, pkt size %u\n", |
---|
| 4867 | + __func__, rate, le16_to_cpu(tx_desc->pkt_size)); |
---|
4794 | 4868 | |
---|
4795 | 4869 | seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); |
---|
4796 | 4870 | |
---|
.. | .. |
---|
4801 | 4875 | |
---|
4802 | 4876 | tx_desc->txdw3 = cpu_to_le32((u32)seq_number << TXDESC32_SEQ_SHIFT); |
---|
4803 | 4877 | |
---|
4804 | | - if (ampdu_enable) |
---|
| 4878 | + if (ampdu_enable && test_bit(tid, priv->tid_tx_operational)) |
---|
4805 | 4879 | tx_desc->txdw1 |= cpu_to_le32(TXDESC32_AGG_ENABLE); |
---|
4806 | 4880 | else |
---|
4807 | 4881 | tx_desc->txdw1 |= cpu_to_le32(TXDESC32_AGG_BREAK); |
---|
.. | .. |
---|
4849 | 4923 | struct rtl8xxxu_priv *priv = hw->priv; |
---|
4850 | 4924 | struct device *dev = &priv->udev->dev; |
---|
4851 | 4925 | struct rtl8xxxu_txdesc40 *tx_desc40; |
---|
| 4926 | + u8 *qc = ieee80211_get_qos_ctl(hdr); |
---|
| 4927 | + u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; |
---|
4852 | 4928 | u32 rate; |
---|
4853 | 4929 | u16 rate_flags = tx_info->control.rates[0].flags; |
---|
4854 | 4930 | u16 seq_number; |
---|
.. | .. |
---|
4862 | 4938 | rate = tx_rate->hw_value; |
---|
4863 | 4939 | |
---|
4864 | 4940 | if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX) |
---|
4865 | | - dev_info(dev, "%s: TX rate: %d, pkt size %d\n", |
---|
4866 | | - __func__, rate, cpu_to_le16(tx_desc40->pkt_size)); |
---|
| 4941 | + dev_info(dev, "%s: TX rate: %d, pkt size %u\n", |
---|
| 4942 | + __func__, rate, le16_to_cpu(tx_desc40->pkt_size)); |
---|
4867 | 4943 | |
---|
4868 | 4944 | seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); |
---|
4869 | 4945 | |
---|
.. | .. |
---|
4875 | 4951 | |
---|
4876 | 4952 | tx_desc40->txdw9 = cpu_to_le32((u32)seq_number << TXDESC40_SEQ_SHIFT); |
---|
4877 | 4953 | |
---|
4878 | | - if (ampdu_enable) |
---|
| 4954 | + if (ampdu_enable && test_bit(tid, priv->tid_tx_operational)) |
---|
4879 | 4955 | tx_desc40->txdw2 |= cpu_to_le32(TXDESC40_AGG_ENABLE); |
---|
4880 | 4956 | else |
---|
4881 | 4957 | tx_desc40->txdw2 |= cpu_to_le32(TXDESC40_AGG_BREAK); |
---|
.. | .. |
---|
4921 | 4997 | struct device *dev = &priv->udev->dev; |
---|
4922 | 4998 | u32 queue, rts_rate; |
---|
4923 | 4999 | u16 pktlen = skb->len; |
---|
4924 | | - u16 seq_number; |
---|
4925 | 5000 | u16 rate_flag = tx_info->control.rates[0].flags; |
---|
4926 | 5001 | int tx_desc_size = priv->fops->tx_desc_size; |
---|
4927 | 5002 | int ret; |
---|
4928 | | - bool usedesc40, ampdu_enable, sgi = false, short_preamble = false; |
---|
| 5003 | + bool ampdu_enable, sgi = false, short_preamble = false; |
---|
4929 | 5004 | |
---|
4930 | 5005 | if (skb_headroom(skb) < tx_desc_size) { |
---|
4931 | 5006 | dev_warn(dev, |
---|
.. | .. |
---|
4949 | 5024 | if (ieee80211_is_action(hdr->frame_control)) |
---|
4950 | 5025 | rtl8xxxu_dump_action(dev, hdr); |
---|
4951 | 5026 | |
---|
4952 | | - usedesc40 = (tx_desc_size == 40); |
---|
4953 | 5027 | tx_info->rate_driver_data[0] = hw; |
---|
4954 | 5028 | |
---|
4955 | 5029 | if (control && control->sta) |
---|
4956 | 5030 | sta = control->sta; |
---|
| 5031 | + |
---|
| 5032 | + queue = rtl8xxxu_queue_select(hw, skb); |
---|
4957 | 5033 | |
---|
4958 | 5034 | tx_desc = skb_push(skb, tx_desc_size); |
---|
4959 | 5035 | |
---|
.. | .. |
---|
4967 | 5043 | is_broadcast_ether_addr(ieee80211_get_DA(hdr))) |
---|
4968 | 5044 | tx_desc->txdw0 |= TXDESC_BROADMULTICAST; |
---|
4969 | 5045 | |
---|
4970 | | - queue = rtl8xxxu_queue_select(hw, skb); |
---|
4971 | 5046 | tx_desc->txdw1 = cpu_to_le32(queue << TXDESC_QUEUE_SHIFT); |
---|
4972 | 5047 | |
---|
4973 | 5048 | if (tx_info->control.hw_key) { |
---|
.. | .. |
---|
4990 | 5065 | if (ieee80211_is_data_qos(hdr->frame_control) && sta) { |
---|
4991 | 5066 | if (sta->ht_cap.ht_supported) { |
---|
4992 | 5067 | u32 ampdu, val32; |
---|
| 5068 | + u8 *qc = ieee80211_get_qos_ctl(hdr); |
---|
| 5069 | + u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; |
---|
4993 | 5070 | |
---|
4994 | 5071 | ampdu = (u32)sta->ht_cap.ampdu_density; |
---|
4995 | 5072 | val32 = ampdu << TXDESC_AMPDU_DENSITY_SHIFT; |
---|
4996 | 5073 | tx_desc->txdw2 |= cpu_to_le32(val32); |
---|
4997 | 5074 | |
---|
4998 | 5075 | ampdu_enable = true; |
---|
| 5076 | + |
---|
| 5077 | + if (!test_bit(tid, priv->tx_aggr_started) && |
---|
| 5078 | + !(skb->protocol == cpu_to_be16(ETH_P_PAE))) |
---|
| 5079 | + if (!ieee80211_start_tx_ba_session(sta, tid, 0)) |
---|
| 5080 | + set_bit(tid, priv->tx_aggr_started); |
---|
4999 | 5081 | } |
---|
5000 | 5082 | } |
---|
5001 | 5083 | |
---|
.. | .. |
---|
5016 | 5098 | else |
---|
5017 | 5099 | rts_rate = 0; |
---|
5018 | 5100 | |
---|
5019 | | - seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); |
---|
5020 | 5101 | |
---|
5021 | 5102 | priv->fops->fill_txdesc(hw, hdr, tx_info, tx_desc, sgi, short_preamble, |
---|
5022 | 5103 | ampdu_enable, rts_rate); |
---|
.. | .. |
---|
5104 | 5185 | pending = priv->rx_urb_pending_count; |
---|
5105 | 5186 | } else { |
---|
5106 | 5187 | skb = (struct sk_buff *)rx_urb->urb.context; |
---|
5107 | | - dev_kfree_skb(skb); |
---|
| 5188 | + dev_kfree_skb_irq(skb); |
---|
5108 | 5189 | usb_free_urb(&rx_urb->urb); |
---|
5109 | 5190 | } |
---|
5110 | 5191 | |
---|
.. | .. |
---|
5157 | 5238 | } |
---|
5158 | 5239 | } |
---|
5159 | 5240 | |
---|
| 5241 | +/* |
---|
| 5242 | + * The RTL8723BU/RTL8192EU vendor driver use coexistence table type |
---|
| 5243 | + * 0-7 to represent writing different combinations of register values |
---|
| 5244 | + * to REG_BT_COEX_TABLEs. It's for different kinds of coexistence use |
---|
| 5245 | + * cases which Realtek doesn't provide detail for these settings. Keep |
---|
| 5246 | + * this aligned with vendor driver for easier maintenance. |
---|
| 5247 | + */ |
---|
| 5248 | +static |
---|
| 5249 | +void rtl8723bu_set_coex_with_type(struct rtl8xxxu_priv *priv, u8 type) |
---|
| 5250 | +{ |
---|
| 5251 | + switch (type) { |
---|
| 5252 | + case 0: |
---|
| 5253 | + rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, 0x55555555); |
---|
| 5254 | + rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, 0x55555555); |
---|
| 5255 | + rtl8xxxu_write32(priv, REG_BT_COEX_TABLE3, 0x00ffffff); |
---|
| 5256 | + rtl8xxxu_write8(priv, REG_BT_COEX_TABLE4, 0x03); |
---|
| 5257 | + break; |
---|
| 5258 | + case 1: |
---|
| 5259 | + case 3: |
---|
| 5260 | + rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, 0x55555555); |
---|
| 5261 | + rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, 0x5a5a5a5a); |
---|
| 5262 | + rtl8xxxu_write32(priv, REG_BT_COEX_TABLE3, 0x00ffffff); |
---|
| 5263 | + rtl8xxxu_write8(priv, REG_BT_COEX_TABLE4, 0x03); |
---|
| 5264 | + break; |
---|
| 5265 | + case 2: |
---|
| 5266 | + rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, 0x5a5a5a5a); |
---|
| 5267 | + rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, 0x5a5a5a5a); |
---|
| 5268 | + rtl8xxxu_write32(priv, REG_BT_COEX_TABLE3, 0x00ffffff); |
---|
| 5269 | + rtl8xxxu_write8(priv, REG_BT_COEX_TABLE4, 0x03); |
---|
| 5270 | + break; |
---|
| 5271 | + case 4: |
---|
| 5272 | + rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, 0x5a5a5a5a); |
---|
| 5273 | + rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, 0xaaaa5a5a); |
---|
| 5274 | + rtl8xxxu_write32(priv, REG_BT_COEX_TABLE3, 0x00ffffff); |
---|
| 5275 | + rtl8xxxu_write8(priv, REG_BT_COEX_TABLE4, 0x03); |
---|
| 5276 | + break; |
---|
| 5277 | + case 5: |
---|
| 5278 | + rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, 0x5a5a5a5a); |
---|
| 5279 | + rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, 0xaa5a5a5a); |
---|
| 5280 | + rtl8xxxu_write32(priv, REG_BT_COEX_TABLE3, 0x00ffffff); |
---|
| 5281 | + rtl8xxxu_write8(priv, REG_BT_COEX_TABLE4, 0x03); |
---|
| 5282 | + break; |
---|
| 5283 | + case 6: |
---|
| 5284 | + rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, 0x55555555); |
---|
| 5285 | + rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, 0xaaaaaaaa); |
---|
| 5286 | + rtl8xxxu_write32(priv, REG_BT_COEX_TABLE3, 0x00ffffff); |
---|
| 5287 | + rtl8xxxu_write8(priv, REG_BT_COEX_TABLE4, 0x03); |
---|
| 5288 | + break; |
---|
| 5289 | + case 7: |
---|
| 5290 | + rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, 0xaaaaaaaa); |
---|
| 5291 | + rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, 0xaaaaaaaa); |
---|
| 5292 | + rtl8xxxu_write32(priv, REG_BT_COEX_TABLE3, 0x00ffffff); |
---|
| 5293 | + rtl8xxxu_write8(priv, REG_BT_COEX_TABLE4, 0x03); |
---|
| 5294 | + break; |
---|
| 5295 | + default: |
---|
| 5296 | + break; |
---|
| 5297 | + } |
---|
| 5298 | +} |
---|
| 5299 | + |
---|
| 5300 | +static |
---|
| 5301 | +void rtl8723bu_update_bt_link_info(struct rtl8xxxu_priv *priv, u8 bt_info) |
---|
| 5302 | +{ |
---|
| 5303 | + struct rtl8xxxu_btcoex *btcoex = &priv->bt_coex; |
---|
| 5304 | + |
---|
| 5305 | + if (bt_info & BT_INFO_8723B_1ANT_B_INQ_PAGE) |
---|
| 5306 | + btcoex->c2h_bt_inquiry = true; |
---|
| 5307 | + else |
---|
| 5308 | + btcoex->c2h_bt_inquiry = false; |
---|
| 5309 | + |
---|
| 5310 | + if (!(bt_info & BT_INFO_8723B_1ANT_B_CONNECTION)) { |
---|
| 5311 | + btcoex->bt_status = BT_8723B_1ANT_STATUS_NON_CONNECTED_IDLE; |
---|
| 5312 | + btcoex->has_sco = false; |
---|
| 5313 | + btcoex->has_hid = false; |
---|
| 5314 | + btcoex->has_pan = false; |
---|
| 5315 | + btcoex->has_a2dp = false; |
---|
| 5316 | + } else { |
---|
| 5317 | + if ((bt_info & 0x1f) == BT_INFO_8723B_1ANT_B_CONNECTION) |
---|
| 5318 | + btcoex->bt_status = BT_8723B_1ANT_STATUS_CONNECTED_IDLE; |
---|
| 5319 | + else if ((bt_info & BT_INFO_8723B_1ANT_B_SCO_ESCO) || |
---|
| 5320 | + (bt_info & BT_INFO_8723B_1ANT_B_SCO_BUSY)) |
---|
| 5321 | + btcoex->bt_status = BT_8723B_1ANT_STATUS_SCO_BUSY; |
---|
| 5322 | + else if (bt_info & BT_INFO_8723B_1ANT_B_ACL_BUSY) |
---|
| 5323 | + btcoex->bt_status = BT_8723B_1ANT_STATUS_ACL_BUSY; |
---|
| 5324 | + else |
---|
| 5325 | + btcoex->bt_status = BT_8723B_1ANT_STATUS_MAX; |
---|
| 5326 | + |
---|
| 5327 | + if (bt_info & BT_INFO_8723B_1ANT_B_FTP) |
---|
| 5328 | + btcoex->has_pan = true; |
---|
| 5329 | + else |
---|
| 5330 | + btcoex->has_pan = false; |
---|
| 5331 | + |
---|
| 5332 | + if (bt_info & BT_INFO_8723B_1ANT_B_A2DP) |
---|
| 5333 | + btcoex->has_a2dp = true; |
---|
| 5334 | + else |
---|
| 5335 | + btcoex->has_a2dp = false; |
---|
| 5336 | + |
---|
| 5337 | + if (bt_info & BT_INFO_8723B_1ANT_B_HID) |
---|
| 5338 | + btcoex->has_hid = true; |
---|
| 5339 | + else |
---|
| 5340 | + btcoex->has_hid = false; |
---|
| 5341 | + |
---|
| 5342 | + if (bt_info & BT_INFO_8723B_1ANT_B_SCO_ESCO) |
---|
| 5343 | + btcoex->has_sco = true; |
---|
| 5344 | + else |
---|
| 5345 | + btcoex->has_sco = false; |
---|
| 5346 | + } |
---|
| 5347 | + |
---|
| 5348 | + if (!btcoex->has_a2dp && !btcoex->has_sco && |
---|
| 5349 | + !btcoex->has_pan && btcoex->has_hid) |
---|
| 5350 | + btcoex->hid_only = true; |
---|
| 5351 | + else |
---|
| 5352 | + btcoex->hid_only = false; |
---|
| 5353 | + |
---|
| 5354 | + if (!btcoex->has_sco && !btcoex->has_pan && |
---|
| 5355 | + !btcoex->has_hid && btcoex->has_a2dp) |
---|
| 5356 | + btcoex->has_a2dp = true; |
---|
| 5357 | + else |
---|
| 5358 | + btcoex->has_a2dp = false; |
---|
| 5359 | + |
---|
| 5360 | + if (btcoex->bt_status == BT_8723B_1ANT_STATUS_SCO_BUSY || |
---|
| 5361 | + btcoex->bt_status == BT_8723B_1ANT_STATUS_ACL_BUSY) |
---|
| 5362 | + btcoex->bt_busy = true; |
---|
| 5363 | + else |
---|
| 5364 | + btcoex->bt_busy = false; |
---|
| 5365 | +} |
---|
| 5366 | + |
---|
| 5367 | +static |
---|
| 5368 | +void rtl8723bu_handle_bt_inquiry(struct rtl8xxxu_priv *priv) |
---|
| 5369 | +{ |
---|
| 5370 | + struct ieee80211_vif *vif; |
---|
| 5371 | + struct rtl8xxxu_btcoex *btcoex; |
---|
| 5372 | + bool wifi_connected; |
---|
| 5373 | + |
---|
| 5374 | + vif = priv->vif; |
---|
| 5375 | + btcoex = &priv->bt_coex; |
---|
| 5376 | + wifi_connected = (vif && vif->bss_conf.assoc); |
---|
| 5377 | + |
---|
| 5378 | + if (!wifi_connected) { |
---|
| 5379 | + rtl8723bu_set_ps_tdma(priv, 0x8, 0x0, 0x0, 0x0, 0x0); |
---|
| 5380 | + rtl8723bu_set_coex_with_type(priv, 0); |
---|
| 5381 | + } else if (btcoex->has_sco || btcoex->has_hid || btcoex->has_a2dp) { |
---|
| 5382 | + rtl8723bu_set_ps_tdma(priv, 0x61, 0x35, 0x3, 0x11, 0x11); |
---|
| 5383 | + rtl8723bu_set_coex_with_type(priv, 4); |
---|
| 5384 | + } else if (btcoex->has_pan) { |
---|
| 5385 | + rtl8723bu_set_ps_tdma(priv, 0x61, 0x3f, 0x3, 0x11, 0x11); |
---|
| 5386 | + rtl8723bu_set_coex_with_type(priv, 4); |
---|
| 5387 | + } else { |
---|
| 5388 | + rtl8723bu_set_ps_tdma(priv, 0x8, 0x0, 0x0, 0x0, 0x0); |
---|
| 5389 | + rtl8723bu_set_coex_with_type(priv, 7); |
---|
| 5390 | + } |
---|
| 5391 | +} |
---|
| 5392 | + |
---|
| 5393 | +static |
---|
| 5394 | +void rtl8723bu_handle_bt_info(struct rtl8xxxu_priv *priv) |
---|
| 5395 | +{ |
---|
| 5396 | + struct ieee80211_vif *vif; |
---|
| 5397 | + struct rtl8xxxu_btcoex *btcoex; |
---|
| 5398 | + bool wifi_connected; |
---|
| 5399 | + |
---|
| 5400 | + vif = priv->vif; |
---|
| 5401 | + btcoex = &priv->bt_coex; |
---|
| 5402 | + wifi_connected = (vif && vif->bss_conf.assoc); |
---|
| 5403 | + |
---|
| 5404 | + if (wifi_connected) { |
---|
| 5405 | + u32 val32 = 0; |
---|
| 5406 | + u32 high_prio_tx = 0, high_prio_rx = 0; |
---|
| 5407 | + |
---|
| 5408 | + val32 = rtl8xxxu_read32(priv, 0x770); |
---|
| 5409 | + high_prio_tx = val32 & 0x0000ffff; |
---|
| 5410 | + high_prio_rx = (val32 & 0xffff0000) >> 16; |
---|
| 5411 | + |
---|
| 5412 | + if (btcoex->bt_busy) { |
---|
| 5413 | + if (btcoex->hid_only) { |
---|
| 5414 | + rtl8723bu_set_ps_tdma(priv, 0x61, 0x20, |
---|
| 5415 | + 0x3, 0x11, 0x11); |
---|
| 5416 | + rtl8723bu_set_coex_with_type(priv, 5); |
---|
| 5417 | + } else if (btcoex->a2dp_only) { |
---|
| 5418 | + rtl8723bu_set_ps_tdma(priv, 0x61, 0x35, |
---|
| 5419 | + 0x3, 0x11, 0x11); |
---|
| 5420 | + rtl8723bu_set_coex_with_type(priv, 4); |
---|
| 5421 | + } else if ((btcoex->has_a2dp && btcoex->has_pan) || |
---|
| 5422 | + (btcoex->has_hid && btcoex->has_a2dp && |
---|
| 5423 | + btcoex->has_pan)) { |
---|
| 5424 | + rtl8723bu_set_ps_tdma(priv, 0x51, 0x21, |
---|
| 5425 | + 0x3, 0x10, 0x10); |
---|
| 5426 | + rtl8723bu_set_coex_with_type(priv, 4); |
---|
| 5427 | + } else if (btcoex->has_hid && btcoex->has_a2dp) { |
---|
| 5428 | + rtl8723bu_set_ps_tdma(priv, 0x51, 0x21, |
---|
| 5429 | + 0x3, 0x10, 0x10); |
---|
| 5430 | + rtl8723bu_set_coex_with_type(priv, 3); |
---|
| 5431 | + } else { |
---|
| 5432 | + rtl8723bu_set_ps_tdma(priv, 0x61, 0x35, |
---|
| 5433 | + 0x3, 0x11, 0x11); |
---|
| 5434 | + rtl8723bu_set_coex_with_type(priv, 4); |
---|
| 5435 | + } |
---|
| 5436 | + } else { |
---|
| 5437 | + rtl8723bu_set_ps_tdma(priv, 0x8, 0x0, 0x0, 0x0, 0x0); |
---|
| 5438 | + if (high_prio_tx + high_prio_rx <= 60) |
---|
| 5439 | + rtl8723bu_set_coex_with_type(priv, 2); |
---|
| 5440 | + else |
---|
| 5441 | + rtl8723bu_set_coex_with_type(priv, 7); |
---|
| 5442 | + } |
---|
| 5443 | + } else { |
---|
| 5444 | + rtl8723bu_set_ps_tdma(priv, 0x8, 0x0, 0x0, 0x0, 0x0); |
---|
| 5445 | + rtl8723bu_set_coex_with_type(priv, 0); |
---|
| 5446 | + } |
---|
| 5447 | +} |
---|
| 5448 | + |
---|
| 5449 | +static struct ieee80211_rate rtl8xxxu_legacy_ratetable[] = { |
---|
| 5450 | + {.bitrate = 10, .hw_value = 0x00,}, |
---|
| 5451 | + {.bitrate = 20, .hw_value = 0x01,}, |
---|
| 5452 | + {.bitrate = 55, .hw_value = 0x02,}, |
---|
| 5453 | + {.bitrate = 110, .hw_value = 0x03,}, |
---|
| 5454 | + {.bitrate = 60, .hw_value = 0x04,}, |
---|
| 5455 | + {.bitrate = 90, .hw_value = 0x05,}, |
---|
| 5456 | + {.bitrate = 120, .hw_value = 0x06,}, |
---|
| 5457 | + {.bitrate = 180, .hw_value = 0x07,}, |
---|
| 5458 | + {.bitrate = 240, .hw_value = 0x08,}, |
---|
| 5459 | + {.bitrate = 360, .hw_value = 0x09,}, |
---|
| 5460 | + {.bitrate = 480, .hw_value = 0x0a,}, |
---|
| 5461 | + {.bitrate = 540, .hw_value = 0x0b,}, |
---|
| 5462 | +}; |
---|
| 5463 | + |
---|
| 5464 | +static void rtl8xxxu_desc_to_mcsrate(u16 rate, u8 *mcs, u8 *nss) |
---|
| 5465 | +{ |
---|
| 5466 | + if (rate <= DESC_RATE_54M) |
---|
| 5467 | + return; |
---|
| 5468 | + |
---|
| 5469 | + if (rate >= DESC_RATE_MCS0 && rate <= DESC_RATE_MCS15) { |
---|
| 5470 | + if (rate < DESC_RATE_MCS8) |
---|
| 5471 | + *nss = 1; |
---|
| 5472 | + else |
---|
| 5473 | + *nss = 2; |
---|
| 5474 | + *mcs = rate - DESC_RATE_MCS0; |
---|
| 5475 | + } |
---|
| 5476 | +} |
---|
| 5477 | + |
---|
| 5478 | +static void rtl8xxxu_c2hcmd_callback(struct work_struct *work) |
---|
| 5479 | +{ |
---|
| 5480 | + struct rtl8xxxu_priv *priv; |
---|
| 5481 | + struct rtl8723bu_c2h *c2h; |
---|
| 5482 | + struct sk_buff *skb = NULL; |
---|
| 5483 | + unsigned long flags; |
---|
| 5484 | + u8 bt_info = 0; |
---|
| 5485 | + struct rtl8xxxu_btcoex *btcoex; |
---|
| 5486 | + struct rtl8xxxu_ra_report *rarpt; |
---|
| 5487 | + u8 rate, sgi, bw; |
---|
| 5488 | + u32 bit_rate; |
---|
| 5489 | + u8 mcs = 0, nss = 0; |
---|
| 5490 | + |
---|
| 5491 | + priv = container_of(work, struct rtl8xxxu_priv, c2hcmd_work); |
---|
| 5492 | + btcoex = &priv->bt_coex; |
---|
| 5493 | + rarpt = &priv->ra_report; |
---|
| 5494 | + |
---|
| 5495 | + while (!skb_queue_empty(&priv->c2hcmd_queue)) { |
---|
| 5496 | + spin_lock_irqsave(&priv->c2hcmd_lock, flags); |
---|
| 5497 | + skb = __skb_dequeue(&priv->c2hcmd_queue); |
---|
| 5498 | + spin_unlock_irqrestore(&priv->c2hcmd_lock, flags); |
---|
| 5499 | + |
---|
| 5500 | + c2h = (struct rtl8723bu_c2h *)skb->data; |
---|
| 5501 | + |
---|
| 5502 | + switch (c2h->id) { |
---|
| 5503 | + case C2H_8723B_BT_INFO: |
---|
| 5504 | + bt_info = c2h->bt_info.bt_info; |
---|
| 5505 | + |
---|
| 5506 | + rtl8723bu_update_bt_link_info(priv, bt_info); |
---|
| 5507 | + if (btcoex->c2h_bt_inquiry) { |
---|
| 5508 | + rtl8723bu_handle_bt_inquiry(priv); |
---|
| 5509 | + break; |
---|
| 5510 | + } |
---|
| 5511 | + rtl8723bu_handle_bt_info(priv); |
---|
| 5512 | + break; |
---|
| 5513 | + case C2H_8723B_RA_REPORT: |
---|
| 5514 | + rarpt->txrate.flags = 0; |
---|
| 5515 | + rate = c2h->ra_report.rate; |
---|
| 5516 | + sgi = c2h->ra_report.sgi; |
---|
| 5517 | + |
---|
| 5518 | + if (rate < DESC_RATE_MCS0) { |
---|
| 5519 | + rarpt->txrate.legacy = |
---|
| 5520 | + rtl8xxxu_legacy_ratetable[rate].bitrate; |
---|
| 5521 | + } else { |
---|
| 5522 | + rtl8xxxu_desc_to_mcsrate(rate, &mcs, &nss); |
---|
| 5523 | + rarpt->txrate.flags |= RATE_INFO_FLAGS_MCS; |
---|
| 5524 | + |
---|
| 5525 | + rarpt->txrate.mcs = mcs; |
---|
| 5526 | + rarpt->txrate.nss = nss; |
---|
| 5527 | + |
---|
| 5528 | + if (sgi) { |
---|
| 5529 | + rarpt->txrate.flags |= |
---|
| 5530 | + RATE_INFO_FLAGS_SHORT_GI; |
---|
| 5531 | + } |
---|
| 5532 | + |
---|
| 5533 | + if (skb->len >= offsetofend(typeof(*c2h), ra_report.bw)) { |
---|
| 5534 | + if (c2h->ra_report.bw == RTL8XXXU_CHANNEL_WIDTH_40) |
---|
| 5535 | + bw = RATE_INFO_BW_40; |
---|
| 5536 | + else |
---|
| 5537 | + bw = RATE_INFO_BW_20; |
---|
| 5538 | + rarpt->txrate.bw = bw; |
---|
| 5539 | + } |
---|
| 5540 | + } |
---|
| 5541 | + bit_rate = cfg80211_calculate_bitrate(&rarpt->txrate); |
---|
| 5542 | + rarpt->bit_rate = bit_rate; |
---|
| 5543 | + rarpt->desc_rate = rate; |
---|
| 5544 | + break; |
---|
| 5545 | + default: |
---|
| 5546 | + break; |
---|
| 5547 | + } |
---|
| 5548 | + |
---|
| 5549 | + dev_kfree_skb(skb); |
---|
| 5550 | + } |
---|
| 5551 | +} |
---|
| 5552 | + |
---|
5160 | 5553 | static void rtl8723bu_handle_c2h(struct rtl8xxxu_priv *priv, |
---|
5161 | 5554 | struct sk_buff *skb) |
---|
5162 | 5555 | { |
---|
5163 | 5556 | struct rtl8723bu_c2h *c2h = (struct rtl8723bu_c2h *)skb->data; |
---|
5164 | 5557 | struct device *dev = &priv->udev->dev; |
---|
5165 | 5558 | int len; |
---|
| 5559 | + unsigned long flags; |
---|
5166 | 5560 | |
---|
5167 | 5561 | len = skb->len - 2; |
---|
5168 | 5562 | |
---|
.. | .. |
---|
5190 | 5584 | case C2H_8723B_RA_REPORT: |
---|
5191 | 5585 | dev_dbg(dev, |
---|
5192 | 5586 | "C2H RA RPT: rate %02x, unk %i, macid %02x, noise %i\n", |
---|
5193 | | - c2h->ra_report.rate, c2h->ra_report.dummy0_0, |
---|
| 5587 | + c2h->ra_report.rate, c2h->ra_report.sgi, |
---|
5194 | 5588 | c2h->ra_report.macid, c2h->ra_report.noisy_state); |
---|
5195 | 5589 | break; |
---|
5196 | 5590 | default: |
---|
.. | .. |
---|
5200 | 5594 | 16, 1, c2h->raw.payload, len, false); |
---|
5201 | 5595 | break; |
---|
5202 | 5596 | } |
---|
| 5597 | + |
---|
| 5598 | + spin_lock_irqsave(&priv->c2hcmd_lock, flags); |
---|
| 5599 | + __skb_queue_tail(&priv->c2hcmd_queue, skb); |
---|
| 5600 | + spin_unlock_irqrestore(&priv->c2hcmd_lock, flags); |
---|
| 5601 | + |
---|
| 5602 | + schedule_work(&priv->c2hcmd_work); |
---|
5203 | 5603 | } |
---|
5204 | 5604 | |
---|
5205 | 5605 | int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb) |
---|
.. | .. |
---|
5324 | 5724 | struct device *dev = &priv->udev->dev; |
---|
5325 | 5725 | dev_dbg(dev, "%s: C2H packet\n", __func__); |
---|
5326 | 5726 | rtl8723bu_handle_c2h(priv, skb); |
---|
5327 | | - dev_kfree_skb(skb); |
---|
5328 | 5727 | return RX_TYPE_C2H; |
---|
5329 | 5728 | } |
---|
5330 | 5729 | |
---|
.. | .. |
---|
5474 | 5873 | |
---|
5475 | 5874 | switch (vif->type) { |
---|
5476 | 5875 | case NL80211_IFTYPE_STATION: |
---|
| 5876 | + if (!priv->vif) |
---|
| 5877 | + priv->vif = vif; |
---|
| 5878 | + else |
---|
| 5879 | + return -EOPNOTSUPP; |
---|
5477 | 5880 | rtl8xxxu_stop_tx_beacon(priv); |
---|
5478 | 5881 | |
---|
5479 | 5882 | val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL); |
---|
.. | .. |
---|
5497 | 5900 | struct rtl8xxxu_priv *priv = hw->priv; |
---|
5498 | 5901 | |
---|
5499 | 5902 | dev_dbg(&priv->udev->dev, "%s\n", __func__); |
---|
| 5903 | + |
---|
| 5904 | + if (priv->vif) |
---|
| 5905 | + priv->vif = NULL; |
---|
5500 | 5906 | } |
---|
5501 | 5907 | |
---|
5502 | 5908 | static int rtl8xxxu_config(struct ieee80211_hw *hw, u32 changed) |
---|
5503 | 5909 | { |
---|
5504 | 5910 | struct rtl8xxxu_priv *priv = hw->priv; |
---|
5505 | 5911 | struct device *dev = &priv->udev->dev; |
---|
5506 | | - u16 val16; |
---|
5507 | 5912 | int ret = 0, channel; |
---|
5508 | 5913 | bool ht40; |
---|
5509 | 5914 | |
---|
.. | .. |
---|
5512 | 5917 | "%s: channel: %i (changed %08x chandef.width %02x)\n", |
---|
5513 | 5918 | __func__, hw->conf.chandef.chan->hw_value, |
---|
5514 | 5919 | changed, hw->conf.chandef.width); |
---|
5515 | | - |
---|
5516 | | - if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { |
---|
5517 | | - val16 = ((hw->conf.long_frame_max_tx_count << |
---|
5518 | | - RETRY_LIMIT_LONG_SHIFT) & RETRY_LIMIT_LONG_MASK) | |
---|
5519 | | - ((hw->conf.short_frame_max_tx_count << |
---|
5520 | | - RETRY_LIMIT_SHORT_SHIFT) & RETRY_LIMIT_SHORT_MASK); |
---|
5521 | | - rtl8xxxu_write16(priv, REG_RETRY_LIMIT, val16); |
---|
5522 | | - } |
---|
5523 | 5920 | |
---|
5524 | 5921 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { |
---|
5525 | 5922 | switch (hw->conf.chandef.width) { |
---|
.. | .. |
---|
5603 | 6000 | unsigned int *total_flags, u64 multicast) |
---|
5604 | 6001 | { |
---|
5605 | 6002 | struct rtl8xxxu_priv *priv = hw->priv; |
---|
5606 | | - u32 rcr = rtl8xxxu_read32(priv, REG_RCR); |
---|
| 6003 | + u32 rcr = priv->regrcr; |
---|
5607 | 6004 | |
---|
5608 | 6005 | dev_dbg(&priv->udev->dev, "%s: changed_flags %08x, total_flags %08x\n", |
---|
5609 | 6006 | __func__, changed_flags, *total_flags); |
---|
.. | .. |
---|
5649 | 6046 | */ |
---|
5650 | 6047 | |
---|
5651 | 6048 | rtl8xxxu_write32(priv, REG_RCR, rcr); |
---|
| 6049 | + priv->regrcr = rcr; |
---|
5652 | 6050 | |
---|
5653 | 6051 | *total_flags &= (FIF_ALLMULTI | FIF_FCSFAIL | FIF_BCN_PRBRESP_PROMISC | |
---|
5654 | 6052 | FIF_CONTROL | FIF_OTHER_BSS | FIF_PSPOLL | |
---|
.. | .. |
---|
5746 | 6144 | struct device *dev = &priv->udev->dev; |
---|
5747 | 6145 | u8 ampdu_factor, ampdu_density; |
---|
5748 | 6146 | struct ieee80211_sta *sta = params->sta; |
---|
| 6147 | + u16 tid = params->tid; |
---|
5749 | 6148 | enum ieee80211_ampdu_mlme_action action = params->action; |
---|
5750 | 6149 | |
---|
5751 | 6150 | switch (action) { |
---|
.. | .. |
---|
5758 | 6157 | dev_dbg(dev, |
---|
5759 | 6158 | "Changed HT: ampdu_factor %02x, ampdu_density %02x\n", |
---|
5760 | 6159 | ampdu_factor, ampdu_density); |
---|
5761 | | - break; |
---|
| 6160 | + return IEEE80211_AMPDU_TX_START_IMMEDIATE; |
---|
| 6161 | + case IEEE80211_AMPDU_TX_STOP_CONT: |
---|
5762 | 6162 | case IEEE80211_AMPDU_TX_STOP_FLUSH: |
---|
5763 | | - dev_dbg(dev, "%s: IEEE80211_AMPDU_TX_STOP_FLUSH\n", __func__); |
---|
5764 | | - rtl8xxxu_set_ampdu_factor(priv, 0); |
---|
5765 | | - rtl8xxxu_set_ampdu_min_space(priv, 0); |
---|
5766 | | - break; |
---|
5767 | 6163 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: |
---|
5768 | | - dev_dbg(dev, "%s: IEEE80211_AMPDU_TX_STOP_FLUSH_CONT\n", |
---|
5769 | | - __func__); |
---|
| 6164 | + dev_dbg(dev, "%s: IEEE80211_AMPDU_TX_STOP\n", __func__); |
---|
5770 | 6165 | rtl8xxxu_set_ampdu_factor(priv, 0); |
---|
5771 | 6166 | rtl8xxxu_set_ampdu_min_space(priv, 0); |
---|
| 6167 | + clear_bit(tid, priv->tx_aggr_started); |
---|
| 6168 | + clear_bit(tid, priv->tid_tx_operational); |
---|
| 6169 | + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
---|
| 6170 | + break; |
---|
| 6171 | + case IEEE80211_AMPDU_TX_OPERATIONAL: |
---|
| 6172 | + dev_dbg(dev, "%s: IEEE80211_AMPDU_TX_OPERATIONAL\n", __func__); |
---|
| 6173 | + set_bit(tid, priv->tid_tx_operational); |
---|
5772 | 6174 | break; |
---|
5773 | 6175 | case IEEE80211_AMPDU_RX_START: |
---|
5774 | 6176 | dev_dbg(dev, "%s: IEEE80211_AMPDU_RX_START\n", __func__); |
---|
.. | .. |
---|
5780 | 6182 | break; |
---|
5781 | 6183 | } |
---|
5782 | 6184 | return 0; |
---|
| 6185 | +} |
---|
| 6186 | + |
---|
| 6187 | +static void |
---|
| 6188 | +rtl8xxxu_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
---|
| 6189 | + struct ieee80211_sta *sta, struct station_info *sinfo) |
---|
| 6190 | +{ |
---|
| 6191 | + struct rtl8xxxu_priv *priv = hw->priv; |
---|
| 6192 | + |
---|
| 6193 | + sinfo->txrate = priv->ra_report.txrate; |
---|
| 6194 | + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); |
---|
| 6195 | +} |
---|
| 6196 | + |
---|
| 6197 | +static u8 rtl8xxxu_signal_to_snr(int signal) |
---|
| 6198 | +{ |
---|
| 6199 | + if (signal < RTL8XXXU_NOISE_FLOOR_MIN) |
---|
| 6200 | + signal = RTL8XXXU_NOISE_FLOOR_MIN; |
---|
| 6201 | + else if (signal > 0) |
---|
| 6202 | + signal = 0; |
---|
| 6203 | + return (u8)(signal - RTL8XXXU_NOISE_FLOOR_MIN); |
---|
| 6204 | +} |
---|
| 6205 | + |
---|
| 6206 | +static void rtl8xxxu_refresh_rate_mask(struct rtl8xxxu_priv *priv, |
---|
| 6207 | + int signal, struct ieee80211_sta *sta) |
---|
| 6208 | +{ |
---|
| 6209 | + struct ieee80211_hw *hw = priv->hw; |
---|
| 6210 | + u16 wireless_mode; |
---|
| 6211 | + u8 rssi_level, ratr_idx; |
---|
| 6212 | + u8 txbw_40mhz; |
---|
| 6213 | + u8 snr, snr_thresh_high, snr_thresh_low; |
---|
| 6214 | + u8 go_up_gap = 5; |
---|
| 6215 | + |
---|
| 6216 | + rssi_level = priv->rssi_level; |
---|
| 6217 | + snr = rtl8xxxu_signal_to_snr(signal); |
---|
| 6218 | + snr_thresh_high = RTL8XXXU_SNR_THRESH_HIGH; |
---|
| 6219 | + snr_thresh_low = RTL8XXXU_SNR_THRESH_LOW; |
---|
| 6220 | + txbw_40mhz = (hw->conf.chandef.width == NL80211_CHAN_WIDTH_40) ? 1 : 0; |
---|
| 6221 | + |
---|
| 6222 | + switch (rssi_level) { |
---|
| 6223 | + case RTL8XXXU_RATR_STA_MID: |
---|
| 6224 | + snr_thresh_high += go_up_gap; |
---|
| 6225 | + break; |
---|
| 6226 | + case RTL8XXXU_RATR_STA_LOW: |
---|
| 6227 | + snr_thresh_high += go_up_gap; |
---|
| 6228 | + snr_thresh_low += go_up_gap; |
---|
| 6229 | + break; |
---|
| 6230 | + default: |
---|
| 6231 | + break; |
---|
| 6232 | + } |
---|
| 6233 | + |
---|
| 6234 | + if (snr > snr_thresh_high) |
---|
| 6235 | + rssi_level = RTL8XXXU_RATR_STA_HIGH; |
---|
| 6236 | + else if (snr > snr_thresh_low) |
---|
| 6237 | + rssi_level = RTL8XXXU_RATR_STA_MID; |
---|
| 6238 | + else |
---|
| 6239 | + rssi_level = RTL8XXXU_RATR_STA_LOW; |
---|
| 6240 | + |
---|
| 6241 | + if (rssi_level != priv->rssi_level) { |
---|
| 6242 | + int sgi = 0; |
---|
| 6243 | + u32 rate_bitmap = 0; |
---|
| 6244 | + |
---|
| 6245 | + rcu_read_lock(); |
---|
| 6246 | + rate_bitmap = (sta->supp_rates[0] & 0xfff) | |
---|
| 6247 | + (sta->ht_cap.mcs.rx_mask[0] << 12) | |
---|
| 6248 | + (sta->ht_cap.mcs.rx_mask[1] << 20); |
---|
| 6249 | + if (sta->ht_cap.cap & |
---|
| 6250 | + (IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20)) |
---|
| 6251 | + sgi = 1; |
---|
| 6252 | + rcu_read_unlock(); |
---|
| 6253 | + |
---|
| 6254 | + wireless_mode = rtl8xxxu_wireless_mode(hw, sta); |
---|
| 6255 | + switch (wireless_mode) { |
---|
| 6256 | + case WIRELESS_MODE_B: |
---|
| 6257 | + ratr_idx = RATEID_IDX_B; |
---|
| 6258 | + if (rate_bitmap & 0x0000000c) |
---|
| 6259 | + rate_bitmap &= 0x0000000d; |
---|
| 6260 | + else |
---|
| 6261 | + rate_bitmap &= 0x0000000f; |
---|
| 6262 | + break; |
---|
| 6263 | + case WIRELESS_MODE_A: |
---|
| 6264 | + case WIRELESS_MODE_G: |
---|
| 6265 | + ratr_idx = RATEID_IDX_G; |
---|
| 6266 | + if (rssi_level == RTL8XXXU_RATR_STA_HIGH) |
---|
| 6267 | + rate_bitmap &= 0x00000f00; |
---|
| 6268 | + else |
---|
| 6269 | + rate_bitmap &= 0x00000ff0; |
---|
| 6270 | + break; |
---|
| 6271 | + case (WIRELESS_MODE_B | WIRELESS_MODE_G): |
---|
| 6272 | + ratr_idx = RATEID_IDX_BG; |
---|
| 6273 | + if (rssi_level == RTL8XXXU_RATR_STA_HIGH) |
---|
| 6274 | + rate_bitmap &= 0x00000f00; |
---|
| 6275 | + else if (rssi_level == RTL8XXXU_RATR_STA_MID) |
---|
| 6276 | + rate_bitmap &= 0x00000ff0; |
---|
| 6277 | + else |
---|
| 6278 | + rate_bitmap &= 0x00000ff5; |
---|
| 6279 | + break; |
---|
| 6280 | + case WIRELESS_MODE_N_24G: |
---|
| 6281 | + case WIRELESS_MODE_N_5G: |
---|
| 6282 | + case (WIRELESS_MODE_G | WIRELESS_MODE_N_24G): |
---|
| 6283 | + case (WIRELESS_MODE_A | WIRELESS_MODE_N_5G): |
---|
| 6284 | + if (priv->tx_paths == 2 && priv->rx_paths == 2) |
---|
| 6285 | + ratr_idx = RATEID_IDX_GN_N2SS; |
---|
| 6286 | + else |
---|
| 6287 | + ratr_idx = RATEID_IDX_GN_N1SS; |
---|
| 6288 | + break; |
---|
| 6289 | + case (WIRELESS_MODE_B | WIRELESS_MODE_G | WIRELESS_MODE_N_24G): |
---|
| 6290 | + case (WIRELESS_MODE_B | WIRELESS_MODE_N_24G): |
---|
| 6291 | + if (txbw_40mhz) { |
---|
| 6292 | + if (priv->tx_paths == 2 && priv->rx_paths == 2) |
---|
| 6293 | + ratr_idx = RATEID_IDX_BGN_40M_2SS; |
---|
| 6294 | + else |
---|
| 6295 | + ratr_idx = RATEID_IDX_BGN_40M_1SS; |
---|
| 6296 | + } else { |
---|
| 6297 | + if (priv->tx_paths == 2 && priv->rx_paths == 2) |
---|
| 6298 | + ratr_idx = RATEID_IDX_BGN_20M_2SS_BN; |
---|
| 6299 | + else |
---|
| 6300 | + ratr_idx = RATEID_IDX_BGN_20M_1SS_BN; |
---|
| 6301 | + } |
---|
| 6302 | + |
---|
| 6303 | + if (priv->tx_paths == 2 && priv->rx_paths == 2) { |
---|
| 6304 | + if (rssi_level == RTL8XXXU_RATR_STA_HIGH) { |
---|
| 6305 | + rate_bitmap &= 0x0f8f0000; |
---|
| 6306 | + } else if (rssi_level == RTL8XXXU_RATR_STA_MID) { |
---|
| 6307 | + rate_bitmap &= 0x0f8ff000; |
---|
| 6308 | + } else { |
---|
| 6309 | + if (txbw_40mhz) |
---|
| 6310 | + rate_bitmap &= 0x0f8ff015; |
---|
| 6311 | + else |
---|
| 6312 | + rate_bitmap &= 0x0f8ff005; |
---|
| 6313 | + } |
---|
| 6314 | + } else { |
---|
| 6315 | + if (rssi_level == RTL8XXXU_RATR_STA_HIGH) { |
---|
| 6316 | + rate_bitmap &= 0x000f0000; |
---|
| 6317 | + } else if (rssi_level == RTL8XXXU_RATR_STA_MID) { |
---|
| 6318 | + rate_bitmap &= 0x000ff000; |
---|
| 6319 | + } else { |
---|
| 6320 | + if (txbw_40mhz) |
---|
| 6321 | + rate_bitmap &= 0x000ff015; |
---|
| 6322 | + else |
---|
| 6323 | + rate_bitmap &= 0x000ff005; |
---|
| 6324 | + } |
---|
| 6325 | + } |
---|
| 6326 | + break; |
---|
| 6327 | + default: |
---|
| 6328 | + ratr_idx = RATEID_IDX_BGN_40M_2SS; |
---|
| 6329 | + rate_bitmap &= 0x0fffffff; |
---|
| 6330 | + break; |
---|
| 6331 | + } |
---|
| 6332 | + |
---|
| 6333 | + priv->rssi_level = rssi_level; |
---|
| 6334 | + priv->fops->update_rate_mask(priv, rate_bitmap, ratr_idx, sgi); |
---|
| 6335 | + } |
---|
| 6336 | +} |
---|
| 6337 | + |
---|
| 6338 | +static void rtl8xxxu_watchdog_callback(struct work_struct *work) |
---|
| 6339 | +{ |
---|
| 6340 | + struct ieee80211_vif *vif; |
---|
| 6341 | + struct rtl8xxxu_priv *priv; |
---|
| 6342 | + |
---|
| 6343 | + priv = container_of(work, struct rtl8xxxu_priv, ra_watchdog.work); |
---|
| 6344 | + vif = priv->vif; |
---|
| 6345 | + |
---|
| 6346 | + if (vif && vif->type == NL80211_IFTYPE_STATION) { |
---|
| 6347 | + int signal; |
---|
| 6348 | + struct ieee80211_sta *sta; |
---|
| 6349 | + |
---|
| 6350 | + rcu_read_lock(); |
---|
| 6351 | + sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); |
---|
| 6352 | + if (!sta) { |
---|
| 6353 | + struct device *dev = &priv->udev->dev; |
---|
| 6354 | + |
---|
| 6355 | + dev_dbg(dev, "%s: no sta found\n", __func__); |
---|
| 6356 | + rcu_read_unlock(); |
---|
| 6357 | + goto out; |
---|
| 6358 | + } |
---|
| 6359 | + rcu_read_unlock(); |
---|
| 6360 | + |
---|
| 6361 | + signal = ieee80211_ave_rssi(vif); |
---|
| 6362 | + rtl8xxxu_refresh_rate_mask(priv, signal, sta); |
---|
| 6363 | + } |
---|
| 6364 | + |
---|
| 6365 | +out: |
---|
| 6366 | + schedule_delayed_work(&priv->ra_watchdog, 2 * HZ); |
---|
5783 | 6367 | } |
---|
5784 | 6368 | |
---|
5785 | 6369 | static int rtl8xxxu_start(struct ieee80211_hw *hw) |
---|
.. | .. |
---|
5846 | 6430 | rtl8xxxu_queue_rx_urb(priv, rx_urb); |
---|
5847 | 6431 | } |
---|
5848 | 6432 | } |
---|
| 6433 | + |
---|
| 6434 | + schedule_delayed_work(&priv->ra_watchdog, 2 * HZ); |
---|
5849 | 6435 | exit: |
---|
5850 | 6436 | /* |
---|
5851 | 6437 | * Accept all data and mgmt frames |
---|
.. | .. |
---|
5897 | 6483 | if (priv->usb_interrupts) |
---|
5898 | 6484 | rtl8xxxu_write32(priv, REG_USB_HIMR, 0); |
---|
5899 | 6485 | |
---|
| 6486 | + cancel_delayed_work_sync(&priv->ra_watchdog); |
---|
| 6487 | + |
---|
5900 | 6488 | rtl8xxxu_free_rx_resources(priv); |
---|
5901 | 6489 | rtl8xxxu_free_tx_resources(priv); |
---|
5902 | 6490 | } |
---|
.. | .. |
---|
5916 | 6504 | .sw_scan_complete = rtl8xxxu_sw_scan_complete, |
---|
5917 | 6505 | .set_key = rtl8xxxu_set_key, |
---|
5918 | 6506 | .ampdu_action = rtl8xxxu_ampdu_action, |
---|
| 6507 | + .sta_statistics = rtl8xxxu_sta_statistics, |
---|
5919 | 6508 | }; |
---|
5920 | 6509 | |
---|
5921 | 6510 | static int rtl8xxxu_parse_usb(struct rtl8xxxu_priv *priv, |
---|
.. | .. |
---|
6019 | 6608 | } |
---|
6020 | 6609 | break; |
---|
6021 | 6610 | case 0x7392: |
---|
6022 | | - if (id->idProduct == 0x7811) |
---|
| 6611 | + if (id->idProduct == 0x7811 || id->idProduct == 0xa611) |
---|
6023 | 6612 | untested = 0; |
---|
6024 | 6613 | break; |
---|
6025 | 6614 | case 0x050d: |
---|
.. | .. |
---|
6069 | 6658 | INIT_LIST_HEAD(&priv->rx_urb_pending_list); |
---|
6070 | 6659 | spin_lock_init(&priv->rx_urb_lock); |
---|
6071 | 6660 | INIT_WORK(&priv->rx_urb_wq, rtl8xxxu_rx_urb_work); |
---|
| 6661 | + INIT_DELAYED_WORK(&priv->ra_watchdog, rtl8xxxu_watchdog_callback); |
---|
| 6662 | + spin_lock_init(&priv->c2hcmd_lock); |
---|
| 6663 | + INIT_WORK(&priv->c2hcmd_work, rtl8xxxu_c2hcmd_callback); |
---|
| 6664 | + skb_queue_head_init(&priv->c2hcmd_queue); |
---|
6072 | 6665 | |
---|
6073 | 6666 | usb_set_intfdata(interface, hw); |
---|
6074 | 6667 | |
---|
.. | .. |
---|
6223 | 6816 | .driver_info = (unsigned long)&rtl8192eu_fops}, |
---|
6224 | 6817 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0xb720, 0xff, 0xff, 0xff), |
---|
6225 | 6818 | .driver_info = (unsigned long)&rtl8723bu_fops}, |
---|
| 6819 | +{USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xa611, 0xff, 0xff, 0xff), |
---|
| 6820 | + .driver_info = (unsigned long)&rtl8723bu_fops}, |
---|
6226 | 6821 | #ifdef CONFIG_RTL8XXXU_UNTESTED |
---|
6227 | 6822 | /* Still supported by rtlwifi */ |
---|
6228 | 6823 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8176, 0xff, 0xff, 0xff), |
---|
.. | .. |
---|
6244 | 6839 | {USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3308, 0xff, 0xff, 0xff), |
---|
6245 | 6840 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
---|
6246 | 6841 | /* Currently untested 8188 series devices */ |
---|
| 6842 | +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x018a, 0xff, 0xff, 0xff), |
---|
| 6843 | + .driver_info = (unsigned long)&rtl8192cu_fops}, |
---|
6247 | 6844 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8191, 0xff, 0xff, 0xff), |
---|
6248 | 6845 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
---|
6249 | 6846 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8170, 0xff, 0xff, 0xff), |
---|