You've already forked linux-rockchip
mirror of
https://github.com/armbian/linux-rockchip.git
synced 2026-01-06 11:08:10 -08:00
rtw88: new Realtek 802.11ac driver
This is a new mac80211 driver for Realtek 802.11ac wireless network chips. rtw88 now supports RTL8822BE/RTL8822CE now, with basic station mode functionalities. The firmware for both can be found at linux-firmware. https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git For RTL8822BE: rtw88/rtw8822b_fw.bin For RTL8822CE: rtw88/rtw8822c_fw.bin And for now, only PCI buses (RTL8xxxE) are supported. We will add support for USB and SDIO in the future. The bus interface abstraction can be seen in this driver such as hci.h. Most of the hardware setting are the same except for some TRX path or probing setup should be separated. Supported: * Basic STA/AP/ADHOC mode, and TDLS (STA is well tested) Missing feature: * WOW/PNO * USB & SDIO bus (such as RTL8xxxU/RTL8xxxS) * BT coexistence (8822B/8822C are combo ICs) * Multiple interfaces (for now single STA is better supported) * Dynamic hardware calibrations (to improve/stabilize performance) Potential problems: * static calibration spends too much time, and it is painful for driver to leave IDLE state. And slows down associate process. But reload function are under development, will be added soon! * TRX statictics misleading, as we are not reporting status correctly, or say, not reporting for "every" packet. The next patch set should have BT coexistence code since RTL8822B/C are combo ICs, and the driver for BT can be found after Linux Kernel v4.20. So it is better to add it first to make WiFi + BT work concurrently. Although now rtw88 is simple but we are developing more features for it. Even we want to add support for more chips such as RTL8821C/RTL8814B. Finally, rtw88 has many authors, listed alphabetically: Ping-Ke Shih <pkshih@realtek.com> Tzu-En Huang <tehuang@realtek.com> Yan-Hsuan Chuang <yhchuang@realtek.com> Reviewed-by: Stanislaw Gruszka <sgruszka@redhat.com> Reviewed-by: Brian Norris <briannorris@chromium.org> Tested-by: Brian Norris <briannorris@chromium.org> Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
committed by
Kalle Valo
parent
c745f72266
commit
e3037485c6
@@ -13396,6 +13396,12 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.g
|
||||
S: Maintained
|
||||
F: drivers/net/wireless/realtek/rtlwifi/
|
||||
|
||||
REALTEK WIRELESS DRIVER (rtw88)
|
||||
M: Yan-Hsuan Chuang <yhchuang@realtek.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/wireless/realtek/rtw88/
|
||||
|
||||
RTL8XXXU WIRELESS DRIVER (rtl8xxxu)
|
||||
M: Jes Sorensen <Jes.Sorensen@gmail.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
|
||||
@@ -14,5 +14,6 @@ if WLAN_VENDOR_REALTEK
|
||||
source "drivers/net/wireless/realtek/rtl818x/Kconfig"
|
||||
source "drivers/net/wireless/realtek/rtlwifi/Kconfig"
|
||||
source "drivers/net/wireless/realtek/rtl8xxxu/Kconfig"
|
||||
source "drivers/net/wireless/realtek/rtw88/Kconfig"
|
||||
|
||||
endif # WLAN_VENDOR_REALTEK
|
||||
|
||||
@@ -6,4 +6,5 @@ obj-$(CONFIG_RTL8180) += rtl818x/
|
||||
obj-$(CONFIG_RTL8187) += rtl818x/
|
||||
obj-$(CONFIG_RTLWIFI) += rtlwifi/
|
||||
obj-$(CONFIG_RTL8XXXU) += rtl8xxxu/
|
||||
obj-$(CONFIG_RTW88) += rtw88/
|
||||
|
||||
|
||||
54
drivers/net/wireless/realtek/rtw88/Kconfig
Normal file
54
drivers/net/wireless/realtek/rtw88/Kconfig
Normal file
@@ -0,0 +1,54 @@
|
||||
menuconfig RTW88
|
||||
tristate "Realtek 802.11ac wireless chips support"
|
||||
depends on MAC80211
|
||||
help
|
||||
This module adds support for mac80211-based wireless drivers that
|
||||
enables Realtek IEEE 802.11ac wireless chipsets.
|
||||
|
||||
If you choose to build a module, it'll be called rtw88.
|
||||
|
||||
if RTW88
|
||||
|
||||
config RTW88_CORE
|
||||
tristate
|
||||
|
||||
config RTW88_PCI
|
||||
tristate
|
||||
|
||||
config RTW88_8822BE
|
||||
bool "Realtek 8822BE PCI wireless network adapter"
|
||||
depends on PCI
|
||||
select RTW88_CORE
|
||||
select RTW88_PCI
|
||||
help
|
||||
Select this option will enable support for 8822BE chipset
|
||||
|
||||
802.11ac PCIe wireless network adapter
|
||||
|
||||
config RTW88_8822CE
|
||||
bool "Realtek 8822CE PCI wireless network adapter"
|
||||
depends on PCI
|
||||
select RTW88_CORE
|
||||
select RTW88_PCI
|
||||
help
|
||||
Select this option will enable support for 8822CE chipset
|
||||
|
||||
802.11ac PCIe wireless network adapter
|
||||
|
||||
config RTW88_DEBUG
|
||||
bool "Realtek rtw88 debug support"
|
||||
depends on RTW88_CORE
|
||||
help
|
||||
Enable debug support
|
||||
|
||||
If unsure, say Y to simplify debug problems
|
||||
|
||||
config RTW88_DEBUGFS
|
||||
bool "Realtek rtw88 debugfs support"
|
||||
depends on RTW88_CORE
|
||||
help
|
||||
Enable debug support
|
||||
|
||||
If unsure, say Y to simplify debug problems
|
||||
|
||||
endif
|
||||
20
drivers/net/wireless/realtek/rtw88/Makefile
Normal file
20
drivers/net/wireless/realtek/rtw88/Makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
obj-$(CONFIG_RTW88_CORE) += rtw88.o
|
||||
rtw88-y += main.o \
|
||||
mac80211.o \
|
||||
util.o \
|
||||
debug.o \
|
||||
tx.o \
|
||||
rx.o \
|
||||
mac.o \
|
||||
phy.o \
|
||||
efuse.o \
|
||||
fw.o \
|
||||
ps.o \
|
||||
sec.o \
|
||||
regd.o
|
||||
|
||||
rtw88-$(CONFIG_RTW88_8822BE) += rtw8822b.o rtw8822b_table.o
|
||||
rtw88-$(CONFIG_RTW88_8822CE) += rtw8822c.o rtw8822c_table.o
|
||||
|
||||
obj-$(CONFIG_RTW88_PCI) += rtwpci.o
|
||||
rtwpci-objs := pci.o
|
||||
637
drivers/net/wireless/realtek/rtw88/debug.c
Normal file
637
drivers/net/wireless/realtek/rtw88/debug.c
Normal file
File diff suppressed because it is too large
Load Diff
52
drivers/net/wireless/realtek/rtw88/debug.h
Normal file
52
drivers/net/wireless/realtek/rtw88/debug.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#ifndef __RTW_DEBUG_H
|
||||
#define __RTW_DEBUG_H
|
||||
|
||||
enum rtw_debug_mask {
|
||||
RTW_DBG_PCI = 0x00000001,
|
||||
RTW_DBG_TX = 0x00000002,
|
||||
RTW_DBG_RX = 0x00000004,
|
||||
RTW_DBG_PHY = 0x00000008,
|
||||
RTW_DBG_FW = 0x00000010,
|
||||
RTW_DBG_EFUSE = 0x00000020,
|
||||
RTW_DBG_COEX = 0x00000040,
|
||||
RTW_DBG_RFK = 0x00000080,
|
||||
RTW_DBG_REGD = 0x00000100,
|
||||
RTW_DBG_DEBUGFS = 0x00000200,
|
||||
|
||||
RTW_DBG_ALL = 0xffffffff
|
||||
};
|
||||
|
||||
#ifdef CONFIG_RTW88_DEBUGFS
|
||||
|
||||
void rtw_debugfs_init(struct rtw_dev *rtwdev);
|
||||
|
||||
#else
|
||||
|
||||
static inline void rtw_debugfs_init(struct rtw_dev *rtwdev) {}
|
||||
|
||||
#endif /* CONFIG_RTW88_DEBUGFS */
|
||||
|
||||
#ifdef CONFIG_RTW88_DEBUG
|
||||
|
||||
__printf(3, 4)
|
||||
void __rtw_dbg(struct rtw_dev *rtwdev, enum rtw_debug_mask mask,
|
||||
const char *fmt, ...);
|
||||
|
||||
#define rtw_dbg(rtwdev, a...) __rtw_dbg(rtwdev, ##a)
|
||||
|
||||
#else
|
||||
|
||||
static inline void rtw_dbg(struct rtw_dev *rtwdev, enum rtw_debug_mask mask,
|
||||
const char *fmt, ...) {}
|
||||
|
||||
#endif /* CONFIG_RTW88_DEBUG */
|
||||
|
||||
#define rtw_info(rtwdev, a...) dev_info(rtwdev->dev, ##a)
|
||||
#define rtw_warn(rtwdev, a...) dev_warn(rtwdev->dev, ##a)
|
||||
#define rtw_err(rtwdev, a...) dev_err(rtwdev->dev, ##a)
|
||||
|
||||
#endif
|
||||
160
drivers/net/wireless/realtek/rtw88/efuse.c
Normal file
160
drivers/net/wireless/realtek/rtw88/efuse.c
Normal file
@@ -0,0 +1,160 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#include "main.h"
|
||||
#include "efuse.h"
|
||||
#include "reg.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define RTW_EFUSE_BANK_WIFI 0x0
|
||||
|
||||
static void switch_efuse_bank(struct rtw_dev *rtwdev)
|
||||
{
|
||||
rtw_write32_mask(rtwdev, REG_LDO_EFUSE_CTRL, BIT_MASK_EFUSE_BANK_SEL,
|
||||
RTW_EFUSE_BANK_WIFI);
|
||||
}
|
||||
|
||||
#define invalid_efuse_header(hdr1, hdr2) \
|
||||
((hdr1) == 0xff || (((hdr1) & 0x1f) == 0xf && (hdr2) == 0xff))
|
||||
#define invalid_efuse_content(word_en, i) \
|
||||
(((word_en) & BIT(i)) != 0x0)
|
||||
#define get_efuse_blk_idx_2_byte(hdr1, hdr2) \
|
||||
((((hdr2) & 0xf0) >> 1) | (((hdr1) >> 5) & 0x07))
|
||||
#define get_efuse_blk_idx_1_byte(hdr1) \
|
||||
(((hdr1) & 0xf0) >> 4)
|
||||
#define block_idx_to_logical_idx(blk_idx, i) \
|
||||
(((blk_idx) << 3) + ((i) << 1))
|
||||
|
||||
/* efuse header format
|
||||
*
|
||||
* | 7 5 4 0 | 7 4 3 0 | 15 8 7 0 |
|
||||
* block[2:0] 0 1111 block[6:3] word_en[3:0] byte0 byte1
|
||||
* | header 1 (optional) | header 2 | word N |
|
||||
*
|
||||
* word_en: 4 bits each word. 0 -> write; 1 -> not write
|
||||
* N: 1~4, depends on word_en
|
||||
*/
|
||||
static int rtw_dump_logical_efuse_map(struct rtw_dev *rtwdev, u8 *phy_map,
|
||||
u8 *log_map)
|
||||
{
|
||||
u32 physical_size = rtwdev->efuse.physical_size;
|
||||
u32 protect_size = rtwdev->efuse.protect_size;
|
||||
u32 logical_size = rtwdev->efuse.logical_size;
|
||||
u32 phy_idx, log_idx;
|
||||
u8 hdr1, hdr2;
|
||||
u8 blk_idx;
|
||||
u8 word_en;
|
||||
int i;
|
||||
|
||||
for (phy_idx = 0; phy_idx < physical_size - protect_size;) {
|
||||
hdr1 = phy_map[phy_idx];
|
||||
hdr2 = phy_map[phy_idx + 1];
|
||||
if (invalid_efuse_header(hdr1, hdr2))
|
||||
break;
|
||||
|
||||
if ((hdr1 & 0x1f) == 0xf) {
|
||||
/* 2-byte header format */
|
||||
blk_idx = get_efuse_blk_idx_2_byte(hdr1, hdr2);
|
||||
word_en = hdr2 & 0xf;
|
||||
phy_idx += 2;
|
||||
} else {
|
||||
/* 1-byte header format */
|
||||
blk_idx = get_efuse_blk_idx_1_byte(hdr1);
|
||||
word_en = hdr1 & 0xf;
|
||||
phy_idx += 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (invalid_efuse_content(word_en, i))
|
||||
continue;
|
||||
|
||||
log_idx = block_idx_to_logical_idx(blk_idx, i);
|
||||
if (phy_idx + 1 > physical_size - protect_size ||
|
||||
log_idx + 1 > logical_size)
|
||||
return -EINVAL;
|
||||
|
||||
log_map[log_idx] = phy_map[phy_idx];
|
||||
log_map[log_idx + 1] = phy_map[phy_idx + 1];
|
||||
phy_idx += 2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtw_dump_physical_efuse_map(struct rtw_dev *rtwdev, u8 *map)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u32 size = rtwdev->efuse.physical_size;
|
||||
u32 efuse_ctl;
|
||||
u32 addr;
|
||||
u32 cnt;
|
||||
|
||||
switch_efuse_bank(rtwdev);
|
||||
|
||||
/* disable 2.5V LDO */
|
||||
chip->ops->cfg_ldo25(rtwdev, false);
|
||||
|
||||
efuse_ctl = rtw_read32(rtwdev, REG_EFUSE_CTRL);
|
||||
|
||||
for (addr = 0; addr < size; addr++) {
|
||||
efuse_ctl &= ~(BIT_MASK_EF_DATA | BITS_EF_ADDR);
|
||||
efuse_ctl |= (addr & BIT_MASK_EF_ADDR) << BIT_SHIFT_EF_ADDR;
|
||||
rtw_write32(rtwdev, REG_EFUSE_CTRL, efuse_ctl & (~BIT_EF_FLAG));
|
||||
|
||||
cnt = 1000000;
|
||||
do {
|
||||
udelay(1);
|
||||
efuse_ctl = rtw_read32(rtwdev, REG_EFUSE_CTRL);
|
||||
if (--cnt == 0)
|
||||
return -EBUSY;
|
||||
} while (!(efuse_ctl & BIT_EF_FLAG));
|
||||
|
||||
*(map + addr) = (u8)(efuse_ctl & BIT_MASK_EF_DATA);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtw_parse_efuse_map(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
u32 phy_size = efuse->physical_size;
|
||||
u32 log_size = efuse->logical_size;
|
||||
u8 *phy_map = NULL;
|
||||
u8 *log_map = NULL;
|
||||
int ret = 0;
|
||||
|
||||
phy_map = kmalloc(phy_size, GFP_KERNEL);
|
||||
log_map = kmalloc(log_size, GFP_KERNEL);
|
||||
if (!phy_map || !log_map) {
|
||||
ret = -ENOMEM;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
ret = rtw_dump_physical_efuse_map(rtwdev, phy_map);
|
||||
if (ret) {
|
||||
rtw_err(rtwdev, "failed to dump efuse physical map\n");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
memset(log_map, 0xff, log_size);
|
||||
ret = rtw_dump_logical_efuse_map(rtwdev, phy_map, log_map);
|
||||
if (ret) {
|
||||
rtw_err(rtwdev, "failed to dump efuse logical map\n");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
ret = chip->ops->read_efuse(rtwdev, log_map);
|
||||
if (ret) {
|
||||
rtw_err(rtwdev, "failed to read efuse map\n");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
out_free:
|
||||
kfree(log_map);
|
||||
kfree(phy_map);
|
||||
|
||||
return ret;
|
||||
}
|
||||
26
drivers/net/wireless/realtek/rtw88/efuse.h
Normal file
26
drivers/net/wireless/realtek/rtw88/efuse.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#ifndef __RTW_EFUSE_H__
|
||||
#define __RTW_EFUSE_H__
|
||||
|
||||
#define EFUSE_HW_CAP_IGNORE 0
|
||||
#define EFUSE_HW_CAP_PTCL_VHT 3
|
||||
#define EFUSE_HW_CAP_SUPP_BW80 7
|
||||
#define EFUSE_HW_CAP_SUPP_BW40 6
|
||||
|
||||
#define GET_EFUSE_HW_CAP_HCI(hw_cap) \
|
||||
le32_get_bits(*((__le32 *)(hw_cap) + 0x01), GENMASK(3, 0))
|
||||
#define GET_EFUSE_HW_CAP_BW(hw_cap) \
|
||||
le32_get_bits(*((__le32 *)(hw_cap) + 0x01), GENMASK(18, 16))
|
||||
#define GET_EFUSE_HW_CAP_NSS(hw_cap) \
|
||||
le32_get_bits(*((__le32 *)(hw_cap) + 0x01), GENMASK(20, 19))
|
||||
#define GET_EFUSE_HW_CAP_ANT_NUM(hw_cap) \
|
||||
le32_get_bits(*((__le32 *)(hw_cap) + 0x01), GENMASK(23, 21))
|
||||
#define GET_EFUSE_HW_CAP_PTCL(hw_cap) \
|
||||
le32_get_bits(*((__le32 *)(hw_cap) + 0x01), GENMASK(27, 26))
|
||||
|
||||
int rtw_parse_efuse_map(struct rtw_dev *rtwdev);
|
||||
|
||||
#endif
|
||||
633
drivers/net/wireless/realtek/rtw88/fw.c
Normal file
633
drivers/net/wireless/realtek/rtw88/fw.c
Normal file
File diff suppressed because it is too large
Load Diff
222
drivers/net/wireless/realtek/rtw88/fw.h
Normal file
222
drivers/net/wireless/realtek/rtw88/fw.h
Normal file
@@ -0,0 +1,222 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#ifndef __RTW_FW_H_
|
||||
#define __RTW_FW_H_
|
||||
|
||||
#define H2C_PKT_SIZE 32
|
||||
#define H2C_PKT_HDR_SIZE 8
|
||||
|
||||
/* FW bin information */
|
||||
#define FW_HDR_SIZE 64
|
||||
#define FW_HDR_CHKSUM_SIZE 8
|
||||
#define FW_HDR_VERSION 4
|
||||
#define FW_HDR_SUBVERSION 6
|
||||
#define FW_HDR_SUBINDEX 7
|
||||
#define FW_HDR_MONTH 16
|
||||
#define FW_HDR_DATE 17
|
||||
#define FW_HDR_HOUR 18
|
||||
#define FW_HDR_MIN 19
|
||||
#define FW_HDR_YEAR 20
|
||||
#define FW_HDR_MEM_USAGE 24
|
||||
#define FW_HDR_H2C_FMT_VER 28
|
||||
#define FW_HDR_DMEM_ADDR 32
|
||||
#define FW_HDR_DMEM_SIZE 36
|
||||
#define FW_HDR_IMEM_SIZE 48
|
||||
#define FW_HDR_EMEM_SIZE 52
|
||||
#define FW_HDR_EMEM_ADDR 56
|
||||
#define FW_HDR_IMEM_ADDR 60
|
||||
|
||||
#define FIFO_PAGE_SIZE_SHIFT 12
|
||||
#define FIFO_PAGE_SIZE 4096
|
||||
#define RSVD_PAGE_START_ADDR 0x780
|
||||
#define FIFO_DUMP_ADDR 0x8000
|
||||
|
||||
enum rtw_c2h_cmd_id {
|
||||
C2H_BT_INFO = 0x09,
|
||||
C2H_HW_FEATURE_REPORT = 0x19,
|
||||
C2H_HW_FEATURE_DUMP = 0xfd,
|
||||
C2H_HALMAC = 0xff,
|
||||
};
|
||||
|
||||
enum rtw_c2h_cmd_id_ext {
|
||||
C2H_CCX_RPT = 0x0f,
|
||||
};
|
||||
|
||||
struct rtw_c2h_cmd {
|
||||
u8 id;
|
||||
u8 seq;
|
||||
u8 payload[0];
|
||||
} __packed;
|
||||
|
||||
enum rtw_rsvd_packet_type {
|
||||
RSVD_BEACON,
|
||||
RSVD_PS_POLL,
|
||||
RSVD_PROBE_RESP,
|
||||
RSVD_NULL,
|
||||
RSVD_QOS_NULL,
|
||||
};
|
||||
|
||||
enum rtw_fw_rf_type {
|
||||
FW_RF_1T2R = 0,
|
||||
FW_RF_2T4R = 1,
|
||||
FW_RF_2T2R = 2,
|
||||
FW_RF_2T3R = 3,
|
||||
FW_RF_1T1R = 4,
|
||||
FW_RF_2T2R_GREEN = 5,
|
||||
FW_RF_3T3R = 6,
|
||||
FW_RF_3T4R = 7,
|
||||
FW_RF_4T4R = 8,
|
||||
FW_RF_MAX_TYPE = 0xF,
|
||||
};
|
||||
|
||||
struct rtw_iqk_para {
|
||||
u8 clear;
|
||||
u8 segment_iqk;
|
||||
};
|
||||
|
||||
struct rtw_rsvd_page {
|
||||
struct list_head list;
|
||||
struct sk_buff *skb;
|
||||
enum rtw_rsvd_packet_type type;
|
||||
u8 page;
|
||||
bool add_txdesc;
|
||||
};
|
||||
|
||||
/* C2H */
|
||||
#define GET_CCX_REPORT_SEQNUM(c2h_payload) (c2h_payload[8] & 0xfc)
|
||||
#define GET_CCX_REPORT_STATUS(c2h_payload) (c2h_payload[9] & 0xc0)
|
||||
|
||||
/* PKT H2C */
|
||||
#define H2C_PKT_CMD_ID 0xFF
|
||||
#define H2C_PKT_CATEGORY 0x01
|
||||
|
||||
#define H2C_PKT_GENERAL_INFO 0x0D
|
||||
#define H2C_PKT_PHYDM_INFO 0x11
|
||||
#define H2C_PKT_IQK 0x0E
|
||||
|
||||
#define SET_PKT_H2C_CATEGORY(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(6, 0))
|
||||
#define SET_PKT_H2C_CMD_ID(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8))
|
||||
#define SET_PKT_H2C_SUB_CMD_ID(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 16))
|
||||
#define SET_PKT_H2C_TOTAL_LEN(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 0))
|
||||
|
||||
static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id)
|
||||
{
|
||||
SET_PKT_H2C_CATEGORY(h2c_pkt, H2C_PKT_CATEGORY);
|
||||
SET_PKT_H2C_CMD_ID(h2c_pkt, H2C_PKT_CMD_ID);
|
||||
SET_PKT_H2C_SUB_CMD_ID(h2c_pkt, sub_id);
|
||||
}
|
||||
|
||||
#define FW_OFFLOAD_H2C_SET_SEQ_NUM(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(31, 16))
|
||||
#define GENERAL_INFO_SET_FW_TX_BOUNDARY(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(23, 16))
|
||||
|
||||
#define PHYDM_INFO_SET_REF_TYPE(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(7, 0))
|
||||
#define PHYDM_INFO_SET_RF_TYPE(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(15, 8))
|
||||
#define PHYDM_INFO_SET_CUT_VER(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(23, 16))
|
||||
#define PHYDM_INFO_SET_RX_ANT_STATUS(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(27, 24))
|
||||
#define PHYDM_INFO_SET_TX_ANT_STATUS(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(31, 28))
|
||||
#define IQK_SET_CLEAR(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(0))
|
||||
#define IQK_SET_SEGMENT_IQK(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(1))
|
||||
|
||||
/* Command H2C */
|
||||
#define H2C_CMD_RSVD_PAGE 0x0
|
||||
#define H2C_CMD_MEDIA_STATUS_RPT 0x01
|
||||
#define H2C_CMD_SET_PWR_MODE 0x20
|
||||
#define H2C_CMD_RA_INFO 0x40
|
||||
#define H2C_CMD_RSSI_MONITOR 0x42
|
||||
|
||||
#define SET_H2C_CMD_ID_CLASS(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(7, 0))
|
||||
|
||||
#define MEDIA_STATUS_RPT_SET_OP_MODE(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
|
||||
#define MEDIA_STATUS_RPT_SET_MACID(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
|
||||
|
||||
#define SET_PWR_MODE_SET_MODE(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(14, 8))
|
||||
#define SET_PWR_MODE_SET_RLBM(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(19, 16))
|
||||
#define SET_PWR_MODE_SET_SMART_PS(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 20))
|
||||
#define SET_PWR_MODE_SET_AWAKE_INTERVAL(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24))
|
||||
#define SET_PWR_MODE_SET_PORT_ID(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 5))
|
||||
#define SET_PWR_MODE_SET_PWR_STATE(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 8))
|
||||
#define SET_RSSI_INFO_MACID(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8))
|
||||
#define SET_RSSI_INFO_RSSI(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24))
|
||||
#define SET_RSSI_INFO_STBC(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, BIT(1))
|
||||
#define SET_RA_INFO_MACID(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8))
|
||||
#define SET_RA_INFO_RATE_ID(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(20, 16))
|
||||
#define SET_RA_INFO_INIT_RA_LVL(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(22, 21))
|
||||
#define SET_RA_INFO_SGI_EN(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(23))
|
||||
#define SET_RA_INFO_BW_MODE(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(25, 24))
|
||||
#define SET_RA_INFO_LDPC(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(26))
|
||||
#define SET_RA_INFO_NO_UPDATE(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(27))
|
||||
#define SET_RA_INFO_VHT_EN(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(29, 28))
|
||||
#define SET_RA_INFO_DIS_PT(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(30))
|
||||
#define SET_RA_INFO_RA_MASK0(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 0))
|
||||
#define SET_RA_INFO_RA_MASK1(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 8))
|
||||
#define SET_RA_INFO_RA_MASK2(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(23, 16))
|
||||
#define SET_RA_INFO_RA_MASK3(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(31, 24))
|
||||
|
||||
static inline struct rtw_c2h_cmd *get_c2h_from_skb(struct sk_buff *skb)
|
||||
{
|
||||
u32 pkt_offset;
|
||||
|
||||
pkt_offset = *((u32 *)skb->cb);
|
||||
return (struct rtw_c2h_cmd *)(skb->data + pkt_offset);
|
||||
}
|
||||
|
||||
void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb);
|
||||
void rtw_fw_send_general_info(struct rtw_dev *rtwdev);
|
||||
void rtw_fw_send_phydm_info(struct rtw_dev *rtwdev);
|
||||
|
||||
void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para);
|
||||
void rtw_fw_set_pwr_mode(struct rtw_dev *rtwdev);
|
||||
void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si);
|
||||
void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si);
|
||||
void rtw_fw_media_status_report(struct rtw_dev *rtwdev, u8 mac_id, bool conn);
|
||||
void rtw_add_rsvd_page(struct rtw_dev *rtwdev, enum rtw_rsvd_packet_type type,
|
||||
bool txdesc);
|
||||
int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr,
|
||||
u8 *buf, u32 size);
|
||||
void rtw_reset_rsvd_page(struct rtw_dev *rtwdev);
|
||||
int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev,
|
||||
struct ieee80211_vif *vif);
|
||||
void rtw_send_rsvd_page_h2c(struct rtw_dev *rtwdev);
|
||||
int rtw_dump_drv_rsvd_page(struct rtw_dev *rtwdev,
|
||||
u32 offset, u32 size, u32 *buf);
|
||||
#endif
|
||||
211
drivers/net/wireless/realtek/rtw88/hci.h
Normal file
211
drivers/net/wireless/realtek/rtw88/hci.h
Normal file
@@ -0,0 +1,211 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#ifndef __RTW_HCI_H__
|
||||
#define __RTW_HCI_H__
|
||||
|
||||
/* ops for PCI, USB and SDIO */
|
||||
struct rtw_hci_ops {
|
||||
int (*tx)(struct rtw_dev *rtwdev,
|
||||
struct rtw_tx_pkt_info *pkt_info,
|
||||
struct sk_buff *skb);
|
||||
int (*setup)(struct rtw_dev *rtwdev);
|
||||
int (*start)(struct rtw_dev *rtwdev);
|
||||
void (*stop)(struct rtw_dev *rtwdev);
|
||||
|
||||
int (*write_data_rsvd_page)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
|
||||
int (*write_data_h2c)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
|
||||
|
||||
u8 (*read8)(struct rtw_dev *rtwdev, u32 addr);
|
||||
u16 (*read16)(struct rtw_dev *rtwdev, u32 addr);
|
||||
u32 (*read32)(struct rtw_dev *rtwdev, u32 addr);
|
||||
void (*write8)(struct rtw_dev *rtwdev, u32 addr, u8 val);
|
||||
void (*write16)(struct rtw_dev *rtwdev, u32 addr, u16 val);
|
||||
void (*write32)(struct rtw_dev *rtwdev, u32 addr, u32 val);
|
||||
};
|
||||
|
||||
static inline int rtw_hci_tx(struct rtw_dev *rtwdev,
|
||||
struct rtw_tx_pkt_info *pkt_info,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
return rtwdev->hci.ops->tx(rtwdev, pkt_info, skb);
|
||||
}
|
||||
|
||||
static inline int rtw_hci_setup(struct rtw_dev *rtwdev)
|
||||
{
|
||||
return rtwdev->hci.ops->setup(rtwdev);
|
||||
}
|
||||
|
||||
static inline int rtw_hci_start(struct rtw_dev *rtwdev)
|
||||
{
|
||||
return rtwdev->hci.ops->start(rtwdev);
|
||||
}
|
||||
|
||||
static inline void rtw_hci_stop(struct rtw_dev *rtwdev)
|
||||
{
|
||||
rtwdev->hci.ops->stop(rtwdev);
|
||||
}
|
||||
|
||||
static inline int
|
||||
rtw_hci_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, u32 size)
|
||||
{
|
||||
return rtwdev->hci.ops->write_data_rsvd_page(rtwdev, buf, size);
|
||||
}
|
||||
|
||||
static inline int
|
||||
rtw_hci_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size)
|
||||
{
|
||||
return rtwdev->hci.ops->write_data_h2c(rtwdev, buf, size);
|
||||
}
|
||||
|
||||
static inline u8 rtw_read8(struct rtw_dev *rtwdev, u32 addr)
|
||||
{
|
||||
return rtwdev->hci.ops->read8(rtwdev, addr);
|
||||
}
|
||||
|
||||
static inline u16 rtw_read16(struct rtw_dev *rtwdev, u32 addr)
|
||||
{
|
||||
return rtwdev->hci.ops->read16(rtwdev, addr);
|
||||
}
|
||||
|
||||
static inline u32 rtw_read32(struct rtw_dev *rtwdev, u32 addr)
|
||||
{
|
||||
return rtwdev->hci.ops->read32(rtwdev, addr);
|
||||
}
|
||||
|
||||
static inline void rtw_write8(struct rtw_dev *rtwdev, u32 addr, u8 val)
|
||||
{
|
||||
rtwdev->hci.ops->write8(rtwdev, addr, val);
|
||||
}
|
||||
|
||||
static inline void rtw_write16(struct rtw_dev *rtwdev, u32 addr, u16 val)
|
||||
{
|
||||
rtwdev->hci.ops->write16(rtwdev, addr, val);
|
||||
}
|
||||
|
||||
static inline void rtw_write32(struct rtw_dev *rtwdev, u32 addr, u32 val)
|
||||
{
|
||||
rtwdev->hci.ops->write32(rtwdev, addr, val);
|
||||
}
|
||||
|
||||
static inline void rtw_write8_set(struct rtw_dev *rtwdev, u32 addr, u8 bit)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
val = rtw_read8(rtwdev, addr);
|
||||
rtw_write8(rtwdev, addr, val | bit);
|
||||
}
|
||||
|
||||
static inline void rtw_writ16_set(struct rtw_dev *rtwdev, u32 addr, u16 bit)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
val = rtw_read16(rtwdev, addr);
|
||||
rtw_write16(rtwdev, addr, val | bit);
|
||||
}
|
||||
|
||||
static inline void rtw_write32_set(struct rtw_dev *rtwdev, u32 addr, u32 bit)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = rtw_read32(rtwdev, addr);
|
||||
rtw_write32(rtwdev, addr, val | bit);
|
||||
}
|
||||
|
||||
static inline void rtw_write8_clr(struct rtw_dev *rtwdev, u32 addr, u8 bit)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
val = rtw_read8(rtwdev, addr);
|
||||
rtw_write8(rtwdev, addr, val & ~bit);
|
||||
}
|
||||
|
||||
static inline void rtw_write16_clr(struct rtw_dev *rtwdev, u32 addr, u16 bit)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
val = rtw_read16(rtwdev, addr);
|
||||
rtw_write16(rtwdev, addr, val & ~bit);
|
||||
}
|
||||
|
||||
static inline void rtw_write32_clr(struct rtw_dev *rtwdev, u32 addr, u32 bit)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = rtw_read32(rtwdev, addr);
|
||||
rtw_write32(rtwdev, addr, val & ~bit);
|
||||
}
|
||||
|
||||
static inline u32
|
||||
rtw_read_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
|
||||
u32 addr, u32 mask)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
spin_lock_irqsave(&rtwdev->rf_lock, flags);
|
||||
val = rtwdev->chip->ops->read_rf(rtwdev, rf_path, addr, mask);
|
||||
spin_unlock_irqrestore(&rtwdev->rf_lock, flags);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void
|
||||
rtw_write_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
|
||||
u32 addr, u32 mask, u32 data)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rtwdev->rf_lock, flags);
|
||||
rtwdev->chip->ops->write_rf(rtwdev, rf_path, addr, mask, data);
|
||||
spin_unlock_irqrestore(&rtwdev->rf_lock, flags);
|
||||
}
|
||||
|
||||
static inline u32
|
||||
rtw_read32_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask)
|
||||
{
|
||||
u32 shift = __ffs(mask);
|
||||
u32 orig;
|
||||
u32 ret;
|
||||
|
||||
orig = rtw_read32(rtwdev, addr);
|
||||
ret = (orig & mask) >> shift;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void
|
||||
rtw_write32_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data)
|
||||
{
|
||||
u32 shift = __ffs(mask);
|
||||
u32 orig;
|
||||
u32 set;
|
||||
|
||||
WARN(addr & 0x3, "should be 4-byte aligned, addr = 0x%08x\n", addr);
|
||||
|
||||
orig = rtw_read32(rtwdev, addr);
|
||||
set = (orig & ~mask) | ((data << shift) & mask);
|
||||
rtw_write32(rtwdev, addr, set);
|
||||
}
|
||||
|
||||
static inline void
|
||||
rtw_write8_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u8 data)
|
||||
{
|
||||
u32 shift;
|
||||
u8 orig, set;
|
||||
|
||||
mask &= 0xff;
|
||||
shift = __ffs(mask);
|
||||
|
||||
orig = rtw_read8(rtwdev, addr);
|
||||
set = (orig & ~mask) | ((data << shift) & mask);
|
||||
rtw_write8(rtwdev, addr, set);
|
||||
}
|
||||
|
||||
static inline enum rtw_hci_type rtw_hci_type(struct rtw_dev *rtwdev)
|
||||
{
|
||||
return rtwdev->hci.type;
|
||||
}
|
||||
|
||||
#endif
|
||||
965
drivers/net/wireless/realtek/rtw88/mac.c
Normal file
965
drivers/net/wireless/realtek/rtw88/mac.c
Normal file
File diff suppressed because it is too large
Load Diff
35
drivers/net/wireless/realtek/rtw88/mac.h
Normal file
35
drivers/net/wireless/realtek/rtw88/mac.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#ifndef __RTW_MAC_H__
|
||||
#define __RTW_MAC_H__
|
||||
|
||||
#define RTW_HW_PORT_NUM 5
|
||||
#define cut_version_to_mask(cut) (0x1 << ((cut) + 1))
|
||||
#define SDIO_LOCAL_OFFSET 0x10250000
|
||||
#define DDMA_POLLING_COUNT 1000
|
||||
#define C2H_PKT_BUF 256
|
||||
#define PHY_STATUS_SIZE 4
|
||||
#define ILLEGAL_KEY_GROUP 0xFAAAAA00
|
||||
|
||||
/* HW memory address */
|
||||
#define OCPBASE_TXBUF_88XX 0x18780000
|
||||
#define OCPBASE_DMEM_88XX 0x00200000
|
||||
#define OCPBASE_EMEM_88XX 0x00100000
|
||||
|
||||
#define RSVD_PG_DRV_NUM 16
|
||||
#define RSVD_PG_H2C_EXTRAINFO_NUM 24
|
||||
#define RSVD_PG_H2C_STATICINFO_NUM 8
|
||||
#define RSVD_PG_H2CQ_NUM 8
|
||||
#define RSVD_PG_CPU_INSTRUCTION_NUM 0
|
||||
#define RSVD_PG_FW_TXBUF_NUM 4
|
||||
|
||||
void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw,
|
||||
u8 primary_ch_idx);
|
||||
int rtw_mac_power_on(struct rtw_dev *rtwdev);
|
||||
void rtw_mac_power_off(struct rtw_dev *rtwdev);
|
||||
int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw);
|
||||
int rtw_mac_init(struct rtw_dev *rtwdev);
|
||||
|
||||
#endif
|
||||
481
drivers/net/wireless/realtek/rtw88/mac80211.c
Normal file
481
drivers/net/wireless/realtek/rtw88/mac80211.c
Normal file
@@ -0,0 +1,481 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#include "main.h"
|
||||
#include "sec.h"
|
||||
#include "tx.h"
|
||||
#include "fw.h"
|
||||
#include "mac.h"
|
||||
#include "ps.h"
|
||||
#include "reg.h"
|
||||
#include "debug.h"
|
||||
|
||||
static void rtw_ops_tx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_tx_control *control,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
struct rtw_tx_pkt_info pkt_info = {0};
|
||||
|
||||
if (!rtw_flag_check(rtwdev, RTW_FLAG_RUNNING))
|
||||
goto out;
|
||||
|
||||
rtw_tx_pkt_info_update(rtwdev, &pkt_info, control, skb);
|
||||
if (rtw_hci_tx(rtwdev, &pkt_info, skb))
|
||||
goto out;
|
||||
|
||||
return;
|
||||
|
||||
out:
|
||||
ieee80211_free_txskb(hw, skb);
|
||||
}
|
||||
|
||||
static int rtw_ops_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
ret = rtw_core_start(rtwdev);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rtw_ops_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtw_core_stop(rtwdev);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
}
|
||||
|
||||
static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_IDLE) {
|
||||
if (hw->conf.flags & IEEE80211_CONF_IDLE) {
|
||||
rtw_enter_ips(rtwdev);
|
||||
} else {
|
||||
ret = rtw_leave_ips(rtwdev);
|
||||
if (ret) {
|
||||
rtw_err(rtwdev, "failed to leave idle state\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_CHANNEL)
|
||||
rtw_set_channel(rtwdev);
|
||||
|
||||
out:
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct rtw_vif_port rtw_vif_port[] = {
|
||||
[0] = {
|
||||
.mac_addr = {.addr = 0x0610},
|
||||
.bssid = {.addr = 0x0618},
|
||||
.net_type = {.addr = 0x0100, .mask = 0x30000},
|
||||
.aid = {.addr = 0x06a8, .mask = 0x7ff},
|
||||
},
|
||||
[1] = {
|
||||
.mac_addr = {.addr = 0x0700},
|
||||
.bssid = {.addr = 0x0708},
|
||||
.net_type = {.addr = 0x0100, .mask = 0xc0000},
|
||||
.aid = {.addr = 0x0710, .mask = 0x7ff},
|
||||
},
|
||||
[2] = {
|
||||
.mac_addr = {.addr = 0x1620},
|
||||
.bssid = {.addr = 0x1628},
|
||||
.net_type = {.addr = 0x1100, .mask = 0x3},
|
||||
.aid = {.addr = 0x1600, .mask = 0x7ff},
|
||||
},
|
||||
[3] = {
|
||||
.mac_addr = {.addr = 0x1630},
|
||||
.bssid = {.addr = 0x1638},
|
||||
.net_type = {.addr = 0x1100, .mask = 0xc},
|
||||
.aid = {.addr = 0x1604, .mask = 0x7ff},
|
||||
},
|
||||
[4] = {
|
||||
.mac_addr = {.addr = 0x1640},
|
||||
.bssid = {.addr = 0x1648},
|
||||
.net_type = {.addr = 0x1100, .mask = 0x30},
|
||||
.aid = {.addr = 0x1608, .mask = 0x7ff},
|
||||
},
|
||||
};
|
||||
|
||||
static int rtw_ops_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
|
||||
enum rtw_net_type net_type;
|
||||
u32 config = 0;
|
||||
u8 port = 0;
|
||||
|
||||
rtwvif->port = port;
|
||||
rtwvif->vif = vif;
|
||||
rtwvif->stats.tx_unicast = 0;
|
||||
rtwvif->stats.rx_unicast = 0;
|
||||
rtwvif->stats.tx_cnt = 0;
|
||||
rtwvif->stats.rx_cnt = 0;
|
||||
rtwvif->in_lps = false;
|
||||
rtwvif->conf = &rtw_vif_port[port];
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
net_type = RTW_NET_AP_MODE;
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
net_type = RTW_NET_AD_HOC;
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
default:
|
||||
net_type = RTW_NET_NO_LINK;
|
||||
break;
|
||||
}
|
||||
|
||||
ether_addr_copy(rtwvif->mac_addr, vif->addr);
|
||||
config |= PORT_SET_MAC_ADDR;
|
||||
rtwvif->net_type = net_type;
|
||||
config |= PORT_SET_NET_TYPE;
|
||||
rtw_vif_port_config(rtwdev, rtwvif, config);
|
||||
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
rtw_info(rtwdev, "start vif %pM on port %d\n", vif->addr, rtwvif->port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtw_ops_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
|
||||
u32 config = 0;
|
||||
|
||||
rtw_info(rtwdev, "stop vif %pM on port %d\n", vif->addr, rtwvif->port);
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
|
||||
eth_zero_addr(rtwvif->mac_addr);
|
||||
config |= PORT_SET_MAC_ADDR;
|
||||
rtwvif->net_type = RTW_NET_NO_LINK;
|
||||
config |= PORT_SET_NET_TYPE;
|
||||
rtw_vif_port_config(rtwdev, rtwvif, config);
|
||||
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
}
|
||||
|
||||
static void rtw_ops_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *new_flags,
|
||||
u64 multicast)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
|
||||
*new_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_FCSFAIL |
|
||||
FIF_BCN_PRBRESP_PROMISC;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
|
||||
if (changed_flags & FIF_ALLMULTI) {
|
||||
if (*new_flags & FIF_ALLMULTI)
|
||||
rtwdev->hal.rcr |= BIT_AM | BIT_AB;
|
||||
else
|
||||
rtwdev->hal.rcr &= ~(BIT_AM | BIT_AB);
|
||||
}
|
||||
if (changed_flags & FIF_FCSFAIL) {
|
||||
if (*new_flags & FIF_FCSFAIL)
|
||||
rtwdev->hal.rcr |= BIT_ACRC32;
|
||||
else
|
||||
rtwdev->hal.rcr &= ~(BIT_ACRC32);
|
||||
}
|
||||
if (changed_flags & FIF_OTHER_BSS) {
|
||||
if (*new_flags & FIF_OTHER_BSS)
|
||||
rtwdev->hal.rcr |= BIT_AAP;
|
||||
else
|
||||
rtwdev->hal.rcr &= ~(BIT_AAP);
|
||||
}
|
||||
if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
|
||||
if (*new_flags & FIF_BCN_PRBRESP_PROMISC)
|
||||
rtwdev->hal.rcr &= ~(BIT_CBSSID_BCN | BIT_CBSSID_DATA);
|
||||
else
|
||||
rtwdev->hal.rcr |= BIT_CBSSID_BCN;
|
||||
}
|
||||
|
||||
rtw_dbg(rtwdev, RTW_DBG_RX,
|
||||
"config rx filter, changed=0x%08x, new=0x%08x, rcr=0x%08x\n",
|
||||
changed_flags, *new_flags, rtwdev->hal.rcr);
|
||||
|
||||
rtw_write32(rtwdev, REG_RCR, rtwdev->hal.rcr);
|
||||
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
}
|
||||
|
||||
static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *conf,
|
||||
u32 changed)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
|
||||
u32 config = 0;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
|
||||
if (changed & BSS_CHANGED_ASSOC) {
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
enum rtw_net_type net_type;
|
||||
|
||||
if (conf->assoc) {
|
||||
net_type = RTW_NET_MGD_LINKED;
|
||||
chip->ops->do_iqk(rtwdev);
|
||||
|
||||
rtwvif->aid = conf->aid;
|
||||
rtw_add_rsvd_page(rtwdev, RSVD_PS_POLL, true);
|
||||
rtw_add_rsvd_page(rtwdev, RSVD_QOS_NULL, true);
|
||||
rtw_add_rsvd_page(rtwdev, RSVD_NULL, true);
|
||||
rtw_fw_download_rsvd_page(rtwdev, vif);
|
||||
rtw_send_rsvd_page_h2c(rtwdev);
|
||||
} else {
|
||||
net_type = RTW_NET_NO_LINK;
|
||||
rtwvif->aid = 0;
|
||||
rtw_reset_rsvd_page(rtwdev);
|
||||
}
|
||||
|
||||
rtwvif->net_type = net_type;
|
||||
config |= PORT_SET_NET_TYPE;
|
||||
config |= PORT_SET_AID;
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_BSSID) {
|
||||
ether_addr_copy(rtwvif->bssid, conf->bssid);
|
||||
config |= PORT_SET_BSSID;
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON)
|
||||
rtw_fw_download_rsvd_page(rtwdev, vif);
|
||||
|
||||
rtw_vif_port_config(rtwdev, rtwvif, config);
|
||||
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
}
|
||||
|
||||
static u8 rtw_acquire_macid(struct rtw_dev *rtwdev)
|
||||
{
|
||||
unsigned long mac_id;
|
||||
|
||||
mac_id = find_first_zero_bit(rtwdev->mac_id_map, RTW_MAX_MAC_ID_NUM);
|
||||
if (mac_id < RTW_MAX_MAC_ID_NUM)
|
||||
set_bit(mac_id, rtwdev->mac_id_map);
|
||||
|
||||
return mac_id;
|
||||
}
|
||||
|
||||
static void rtw_release_macid(struct rtw_dev *rtwdev, u8 mac_id)
|
||||
{
|
||||
clear_bit(mac_id, rtwdev->mac_id_map);
|
||||
}
|
||||
|
||||
static int rtw_ops_sta_add(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
|
||||
si->mac_id = rtw_acquire_macid(rtwdev);
|
||||
if (si->mac_id >= RTW_MAX_MAC_ID_NUM) {
|
||||
ret = -ENOSPC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
si->sta = sta;
|
||||
si->vif = vif;
|
||||
si->init_ra_lv = 1;
|
||||
ewma_rssi_init(&si->avg_rssi);
|
||||
|
||||
rtw_update_sta_info(rtwdev, si);
|
||||
rtw_fw_media_status_report(rtwdev, si->mac_id, true);
|
||||
|
||||
rtwdev->sta_cnt++;
|
||||
|
||||
rtw_info(rtwdev, "sta %pM joined with macid %d\n",
|
||||
sta->addr, si->mac_id);
|
||||
|
||||
out:
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rtw_ops_sta_remove(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
|
||||
rtw_release_macid(rtwdev, si->mac_id);
|
||||
rtw_fw_media_status_report(rtwdev, si->mac_id, false);
|
||||
|
||||
rtwdev->sta_cnt--;
|
||||
|
||||
rtw_info(rtwdev, "sta %pM with macid %d left\n",
|
||||
sta->addr, si->mac_id);
|
||||
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtw_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
struct rtw_sec_desc *sec = &rtwdev->sec;
|
||||
u8 hw_key_type;
|
||||
u8 hw_key_idx;
|
||||
int ret = 0;
|
||||
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_WEP40:
|
||||
hw_key_type = RTW_CAM_WEP40;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
hw_key_type = RTW_CAM_WEP104;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
hw_key_type = RTW_CAM_TKIP;
|
||||
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
hw_key_type = RTW_CAM_AES;
|
||||
key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
|
||||
/* suppress error messages */
|
||||
return -EOPNOTSUPP;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
|
||||
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
|
||||
hw_key_idx = rtw_sec_get_free_cam(sec);
|
||||
} else {
|
||||
/* multiple interfaces? */
|
||||
hw_key_idx = key->keyidx;
|
||||
}
|
||||
|
||||
if (hw_key_idx > sec->total_cam_num) {
|
||||
ret = -ENOSPC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case SET_KEY:
|
||||
/* need sw generated IV */
|
||||
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
|
||||
key->hw_key_idx = hw_key_idx;
|
||||
rtw_sec_write_cam(rtwdev, sec, sta, key,
|
||||
hw_key_type, hw_key_idx);
|
||||
break;
|
||||
case DISABLE_KEY:
|
||||
rtw_sec_clear_cam(rtwdev, sec, key->hw_key_idx);
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rtw_ops_ampdu_action(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_ampdu_params *params)
|
||||
{
|
||||
struct ieee80211_sta *sta = params->sta;
|
||||
u16 tid = params->tid;
|
||||
|
||||
switch (params->action) {
|
||||
case IEEE80211_AMPDU_TX_START:
|
||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
||||
case IEEE80211_AMPDU_RX_START:
|
||||
case IEEE80211_AMPDU_RX_STOP:
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtw_ops_sw_scan_start(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
const u8 *mac_addr)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
|
||||
|
||||
rtw_leave_lps(rtwdev, rtwvif);
|
||||
|
||||
rtw_flag_set(rtwdev, RTW_FLAG_DIG_DISABLE);
|
||||
rtw_flag_set(rtwdev, RTW_FLAG_SCANNING);
|
||||
}
|
||||
|
||||
static void rtw_ops_sw_scan_complete(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
|
||||
rtw_flag_clear(rtwdev, RTW_FLAG_SCANNING);
|
||||
rtw_flag_clear(rtwdev, RTW_FLAG_DIG_DISABLE);
|
||||
}
|
||||
|
||||
const struct ieee80211_ops rtw_ops = {
|
||||
.tx = rtw_ops_tx,
|
||||
.start = rtw_ops_start,
|
||||
.stop = rtw_ops_stop,
|
||||
.config = rtw_ops_config,
|
||||
.add_interface = rtw_ops_add_interface,
|
||||
.remove_interface = rtw_ops_remove_interface,
|
||||
.configure_filter = rtw_ops_configure_filter,
|
||||
.bss_info_changed = rtw_ops_bss_info_changed,
|
||||
.sta_add = rtw_ops_sta_add,
|
||||
.sta_remove = rtw_ops_sta_remove,
|
||||
.set_key = rtw_ops_set_key,
|
||||
.ampdu_action = rtw_ops_ampdu_action,
|
||||
.sw_scan_start = rtw_ops_sw_scan_start,
|
||||
.sw_scan_complete = rtw_ops_sw_scan_complete,
|
||||
};
|
||||
EXPORT_SYMBOL(rtw_ops);
|
||||
1211
drivers/net/wireless/realtek/rtw88/main.c
Normal file
1211
drivers/net/wireless/realtek/rtw88/main.c
Normal file
File diff suppressed because it is too large
Load Diff
1104
drivers/net/wireless/realtek/rtw88/main.h
Normal file
1104
drivers/net/wireless/realtek/rtw88/main.h
Normal file
File diff suppressed because it is too large
Load Diff
1211
drivers/net/wireless/realtek/rtw88/pci.c
Normal file
1211
drivers/net/wireless/realtek/rtw88/pci.c
Normal file
File diff suppressed because it is too large
Load Diff
237
drivers/net/wireless/realtek/rtw88/pci.h
Normal file
237
drivers/net/wireless/realtek/rtw88/pci.h
Normal file
@@ -0,0 +1,237 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#ifndef __RTK_PCI_H_
|
||||
#define __RTK_PCI_H_
|
||||
|
||||
#define RTK_PCI_DEVICE(vend, dev, hw_config) \
|
||||
PCI_DEVICE(vend, dev), \
|
||||
.driver_data = (kernel_ulong_t)&(hw_config),
|
||||
|
||||
#define RTK_DEFAULT_TX_DESC_NUM 128
|
||||
#define RTK_BEQ_TX_DESC_NUM 256
|
||||
|
||||
#define RTK_MAX_RX_DESC_NUM 512
|
||||
/* 8K + rx desc size */
|
||||
#define RTK_PCI_RX_BUF_SIZE (8192 + 24)
|
||||
|
||||
#define RTK_PCI_CTRL 0x300
|
||||
#define BIT_RST_TRXDMA_INTF BIT(20)
|
||||
#define BIT_RX_TAG_EN BIT(15)
|
||||
#define REG_DBI_WDATA_V1 0x03E8
|
||||
#define REG_DBI_FLAG_V1 0x03F0
|
||||
#define REG_MDIO_V1 0x03F4
|
||||
#define REG_PCIE_MIX_CFG 0x03F8
|
||||
#define BIT_MDIO_WFLAG_V1 BIT(5)
|
||||
|
||||
#define BIT_PCI_BCNQ_FLAG BIT(4)
|
||||
#define RTK_PCI_TXBD_DESA_BCNQ 0x308
|
||||
#define RTK_PCI_TXBD_DESA_H2CQ 0x1320
|
||||
#define RTK_PCI_TXBD_DESA_MGMTQ 0x310
|
||||
#define RTK_PCI_TXBD_DESA_BKQ 0x330
|
||||
#define RTK_PCI_TXBD_DESA_BEQ 0x328
|
||||
#define RTK_PCI_TXBD_DESA_VIQ 0x320
|
||||
#define RTK_PCI_TXBD_DESA_VOQ 0x318
|
||||
#define RTK_PCI_TXBD_DESA_HI0Q 0x340
|
||||
#define RTK_PCI_RXBD_DESA_MPDUQ 0x338
|
||||
|
||||
/* BCNQ is specialized for rsvd page, does not need to specify a number */
|
||||
#define RTK_PCI_TXBD_NUM_H2CQ 0x1328
|
||||
#define RTK_PCI_TXBD_NUM_MGMTQ 0x380
|
||||
#define RTK_PCI_TXBD_NUM_BKQ 0x38A
|
||||
#define RTK_PCI_TXBD_NUM_BEQ 0x388
|
||||
#define RTK_PCI_TXBD_NUM_VIQ 0x386
|
||||
#define RTK_PCI_TXBD_NUM_VOQ 0x384
|
||||
#define RTK_PCI_TXBD_NUM_HI0Q 0x38C
|
||||
#define RTK_PCI_RXBD_NUM_MPDUQ 0x382
|
||||
#define RTK_PCI_TXBD_IDX_H2CQ 0x132C
|
||||
#define RTK_PCI_TXBD_IDX_MGMTQ 0x3B0
|
||||
#define RTK_PCI_TXBD_IDX_BKQ 0x3AC
|
||||
#define RTK_PCI_TXBD_IDX_BEQ 0x3A8
|
||||
#define RTK_PCI_TXBD_IDX_VIQ 0x3A4
|
||||
#define RTK_PCI_TXBD_IDX_VOQ 0x3A0
|
||||
#define RTK_PCI_TXBD_IDX_HI0Q 0x3B8
|
||||
#define RTK_PCI_RXBD_IDX_MPDUQ 0x3B4
|
||||
|
||||
#define RTK_PCI_TXBD_RWPTR_CLR 0x39C
|
||||
#define RTK_PCI_TXBD_H2CQ_CSR 0x1330
|
||||
|
||||
#define BIT_CLR_H2CQ_HOST_IDX BIT(16)
|
||||
#define BIT_CLR_H2CQ_HW_IDX BIT(8)
|
||||
|
||||
#define RTK_PCI_HIMR0 0x0B0
|
||||
#define RTK_PCI_HISR0 0x0B4
|
||||
#define RTK_PCI_HIMR1 0x0B8
|
||||
#define RTK_PCI_HISR1 0x0BC
|
||||
#define RTK_PCI_HIMR2 0x10B0
|
||||
#define RTK_PCI_HISR2 0x10B4
|
||||
#define RTK_PCI_HIMR3 0x10B8
|
||||
#define RTK_PCI_HISR3 0x10BC
|
||||
/* IMR 0 */
|
||||
#define IMR_TIMER2 BIT(31)
|
||||
#define IMR_TIMER1 BIT(30)
|
||||
#define IMR_PSTIMEOUT BIT(29)
|
||||
#define IMR_GTINT4 BIT(28)
|
||||
#define IMR_GTINT3 BIT(27)
|
||||
#define IMR_TBDER BIT(26)
|
||||
#define IMR_TBDOK BIT(25)
|
||||
#define IMR_TSF_BIT32_TOGGLE BIT(24)
|
||||
#define IMR_BCNDMAINT0 BIT(20)
|
||||
#define IMR_BCNDOK0 BIT(16)
|
||||
#define IMR_HSISR_IND_ON_INT BIT(15)
|
||||
#define IMR_BCNDMAINT_E BIT(14)
|
||||
#define IMR_ATIMEND BIT(12)
|
||||
#define IMR_HISR1_IND_INT BIT(11)
|
||||
#define IMR_C2HCMD BIT(10)
|
||||
#define IMR_CPWM2 BIT(9)
|
||||
#define IMR_CPWM BIT(8)
|
||||
#define IMR_HIGHDOK BIT(7)
|
||||
#define IMR_MGNTDOK BIT(6)
|
||||
#define IMR_BKDOK BIT(5)
|
||||
#define IMR_BEDOK BIT(4)
|
||||
#define IMR_VIDOK BIT(3)
|
||||
#define IMR_VODOK BIT(2)
|
||||
#define IMR_RDU BIT(1)
|
||||
#define IMR_ROK BIT(0)
|
||||
/* IMR 1 */
|
||||
#define IMR_TXFIFO_TH_INT BIT(30)
|
||||
#define IMR_BTON_STS_UPDATE BIT(29)
|
||||
#define IMR_MCUERR BIT(28)
|
||||
#define IMR_BCNDMAINT7 BIT(27)
|
||||
#define IMR_BCNDMAINT6 BIT(26)
|
||||
#define IMR_BCNDMAINT5 BIT(25)
|
||||
#define IMR_BCNDMAINT4 BIT(24)
|
||||
#define IMR_BCNDMAINT3 BIT(23)
|
||||
#define IMR_BCNDMAINT2 BIT(22)
|
||||
#define IMR_BCNDMAINT1 BIT(21)
|
||||
#define IMR_BCNDOK7 BIT(20)
|
||||
#define IMR_BCNDOK6 BIT(19)
|
||||
#define IMR_BCNDOK5 BIT(18)
|
||||
#define IMR_BCNDOK4 BIT(17)
|
||||
#define IMR_BCNDOK3 BIT(16)
|
||||
#define IMR_BCNDOK2 BIT(15)
|
||||
#define IMR_BCNDOK1 BIT(14)
|
||||
#define IMR_ATIMEND_E BIT(13)
|
||||
#define IMR_ATIMEND BIT(12)
|
||||
#define IMR_TXERR BIT(11)
|
||||
#define IMR_RXERR BIT(10)
|
||||
#define IMR_TXFOVW BIT(9)
|
||||
#define IMR_RXFOVW BIT(8)
|
||||
#define IMR_CPU_MGQ_TXDONE BIT(5)
|
||||
#define IMR_PS_TIMER_C BIT(4)
|
||||
#define IMR_PS_TIMER_B BIT(3)
|
||||
#define IMR_PS_TIMER_A BIT(2)
|
||||
#define IMR_CPUMGQ_TX_TIMER BIT(1)
|
||||
/* IMR 3 */
|
||||
#define IMR_H2CDOK BIT(16)
|
||||
|
||||
/* one element is reserved to know if the ring is closed */
|
||||
static inline int avail_desc(u32 wp, u32 rp, u32 len)
|
||||
{
|
||||
if (rp > wp)
|
||||
return rp - wp - 1;
|
||||
else
|
||||
return len - wp + rp - 1;
|
||||
}
|
||||
|
||||
#define RTK_PCI_TXBD_OWN_OFFSET 15
|
||||
#define RTK_PCI_TXBD_BCN_WORK 0x383
|
||||
|
||||
struct rtw_pci_tx_buffer_desc {
|
||||
__le16 buf_size;
|
||||
__le16 psb_len;
|
||||
__le32 dma;
|
||||
};
|
||||
|
||||
struct rtw_pci_tx_data {
|
||||
dma_addr_t dma;
|
||||
u8 sn;
|
||||
};
|
||||
|
||||
struct rtw_pci_ring {
|
||||
u8 *head;
|
||||
dma_addr_t dma;
|
||||
|
||||
u8 desc_size;
|
||||
|
||||
u32 len;
|
||||
u32 wp;
|
||||
u32 rp;
|
||||
};
|
||||
|
||||
struct rtw_pci_tx_ring {
|
||||
struct rtw_pci_ring r;
|
||||
struct sk_buff_head queue;
|
||||
bool queue_stopped;
|
||||
};
|
||||
|
||||
struct rtw_pci_rx_buffer_desc {
|
||||
__le16 buf_size;
|
||||
__le16 total_pkt_size;
|
||||
__le32 dma;
|
||||
};
|
||||
|
||||
struct rtw_pci_rx_ring {
|
||||
struct rtw_pci_ring r;
|
||||
struct sk_buff *buf[RTK_MAX_RX_DESC_NUM];
|
||||
};
|
||||
|
||||
#define RX_TAG_MAX 8192
|
||||
|
||||
struct rtw_pci {
|
||||
struct pci_dev *pdev;
|
||||
|
||||
/* used for pci interrupt */
|
||||
spinlock_t irq_lock;
|
||||
u32 irq_mask[4];
|
||||
bool irq_enabled;
|
||||
|
||||
u16 rx_tag;
|
||||
struct rtw_pci_tx_ring tx_rings[RTK_MAX_TX_QUEUE_NUM];
|
||||
struct rtw_pci_rx_ring rx_rings[RTK_MAX_RX_QUEUE_NUM];
|
||||
|
||||
void __iomem *mmap;
|
||||
};
|
||||
|
||||
static u32 max_num_of_tx_queue(u8 queue)
|
||||
{
|
||||
u32 max_num;
|
||||
|
||||
switch (queue) {
|
||||
case RTW_TX_QUEUE_BE:
|
||||
max_num = RTK_BEQ_TX_DESC_NUM;
|
||||
break;
|
||||
case RTW_TX_QUEUE_BCN:
|
||||
max_num = 1;
|
||||
break;
|
||||
default:
|
||||
max_num = RTK_DEFAULT_TX_DESC_NUM;
|
||||
break;
|
||||
}
|
||||
|
||||
return max_num;
|
||||
}
|
||||
|
||||
static inline struct
|
||||
rtw_pci_tx_data *rtw_pci_get_tx_data(struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct rtw_pci_tx_data) >
|
||||
sizeof(info->status.status_driver_data));
|
||||
|
||||
return (struct rtw_pci_tx_data *)info->status.status_driver_data;
|
||||
}
|
||||
|
||||
static inline
|
||||
struct rtw_pci_tx_buffer_desc *get_tx_buffer_desc(struct rtw_pci_tx_ring *ring,
|
||||
u32 size)
|
||||
{
|
||||
u8 *buf_desc;
|
||||
|
||||
buf_desc = ring->r.head + ring->r.wp * size;
|
||||
return (struct rtw_pci_tx_buffer_desc *)buf_desc;
|
||||
}
|
||||
|
||||
#endif
|
||||
1724
drivers/net/wireless/realtek/rtw88/phy.c
Normal file
1724
drivers/net/wireless/realtek/rtw88/phy.c
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user