Skip to content

Commit

Permalink
rtw89: update Realtek's rtw89 driver.
Browse files Browse the repository at this point in the history
This adds support for the Realtek 8922AE PCI
wireless network (Wi-Fi 7) adapter.

This version is based on
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
98f7e32f20d28ec452afb208f9cffc08448a2652 ( tag: v6.11 ).

Sponsored by:   The FreeBSD Foundation

(cherry picked from commit 6d67aabd63555ab62a2f2b7f52a75ef100a2fe75)
  • Loading branch information
Bjoern A. Zeeb authored and fichtner committed Feb 18, 2025
1 parent c296eeb commit 43d7574
Show file tree
Hide file tree
Showing 76 changed files with 45,373 additions and 8,472 deletions.
19 changes: 19 additions & 0 deletions sys/contrib/dev/rtw89/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,18 @@ config RTW89_8851B
config RTW89_8852A
tristate

config RTW89_8852B_COMMON
tristate

config RTW89_8852B
tristate

config RTW89_8852C
tristate

config RTW89_8922A
tristate

config RTW89_8851BE
tristate "Realtek 8851BE PCI wireless network (Wi-Fi 6) adapter"
depends on PCI
Expand Down Expand Up @@ -56,6 +62,7 @@ config RTW89_8852BE
select RTW89_CORE
select RTW89_PCI
select RTW89_8852B
select RTW89_8852B_COMMON
help
Select this option will enable support for 8852BE chipset

Expand All @@ -72,6 +79,18 @@ config RTW89_8852CE

802.11ax PCIe wireless network (Wi-Fi 6E) adapter

config RTW89_8922AE
tristate "Realtek 8922AE PCI wireless network (Wi-Fi 7) adapter"
depends on PCI
select RTW89_CORE
select RTW89_PCI
select RTW89_8922A
help
Select this option will enable support for 8922AE chipset

802.11be PCIe wireless network (Wi-Fi 7) adapter
supporting 2x2 2GHz/5GHz/6GHz 4096-QAM 160MHz channels.

config RTW89_DEBUG
bool

Expand Down
18 changes: 16 additions & 2 deletions sys/contrib/dev/rtw89/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@ obj-$(CONFIG_RTW89_CORE) += rtw89_core.o
rtw89_core-y += core.o \
mac80211.o \
mac.o \
mac_be.o \
phy.o \
phy_be.o \
fw.o \
cam.o \
efuse.o \
efuse_be.o \
regd.o \
sar.o \
coex.o \
ps.o \
chan.o \
ser.o \
acpi.o
acpi.o \
util.o

rtw89_core-$(CONFIG_PM) += wow.o

Expand All @@ -36,6 +40,9 @@ rtw89_8852a-objs := rtw8852a.o \
obj-$(CONFIG_RTW89_8852AE) += rtw89_8852ae.o
rtw89_8852ae-objs := rtw8852ae.o

obj-$(CONFIG_RTW89_8852B_COMMON) += rtw89_8852b_common.o
rtw89_8852b_common-objs := rtw8852b_common.o

obj-$(CONFIG_RTW89_8852B) += rtw89_8852b.o
rtw89_8852b-objs := rtw8852b.o \
rtw8852b_table.o \
Expand All @@ -54,8 +61,15 @@ rtw89_8852c-objs := rtw8852c.o \
obj-$(CONFIG_RTW89_8852CE) += rtw89_8852ce.o
rtw89_8852ce-objs := rtw8852ce.o

obj-$(CONFIG_RTW89_8922A) += rtw89_8922a.o
rtw89_8922a-objs := rtw8922a.o \
rtw8922a_rfk.o

obj-$(CONFIG_RTW89_8922AE) += rtw89_8922ae.o
rtw89_8922ae-objs := rtw8922ae.o

rtw89_core-$(CONFIG_RTW89_DEBUG) += debug.o

obj-$(CONFIG_RTW89_PCI) += rtw89_pci.o
rtw89_pci-y := pci.o
rtw89_pci-y := pci.o pci_be.o

131 changes: 115 additions & 16 deletions sys/contrib/dev/rtw89/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,47 +13,146 @@ static const guid_t rtw89_guid = GUID_INIT(0xD2A8C3E8, 0x4B69, 0x4F00,
0x82, 0xBD, 0xFE, 0x86,
0x07, 0x80, 0x3A, 0xA7);

static int rtw89_acpi_dsm_get(struct rtw89_dev *rtwdev, union acpi_object *obj,
u8 *value)
static
int rtw89_acpi_dsm_get_value(struct rtw89_dev *rtwdev, union acpi_object *obj,
u8 *value)
{
switch (obj->type) {
case ACPI_TYPE_INTEGER:
*value = (u8)obj->integer.value;
break;
case ACPI_TYPE_BUFFER:
*value = obj->buffer.pointer[0];
break;
default:
rtw89_debug(rtwdev, RTW89_DBG_UNEXP,
"acpi dsm return unhandled type: %d\n", obj->type);
if (obj->type != ACPI_TYPE_INTEGER) {
rtw89_debug(rtwdev, RTW89_DBG_ACPI,
"acpi: expect integer but type: %d\n", obj->type);
return -EINVAL;
}

*value = (u8)obj->integer.value;
return 0;
}

static bool chk_acpi_policy_6ghz_sig(const struct rtw89_acpi_policy_6ghz *p)
{
return p->signature[0] == 0x00 &&
p->signature[1] == 0xE0 &&
p->signature[2] == 0x4C;
}

static
int rtw89_acpi_dsm_get_policy_6ghz(struct rtw89_dev *rtwdev,
union acpi_object *obj,
struct rtw89_acpi_policy_6ghz **policy_6ghz)
{
const struct rtw89_acpi_policy_6ghz *ptr;
u32 expect_len;
u32 len;

if (obj->type != ACPI_TYPE_BUFFER) {
rtw89_debug(rtwdev, RTW89_DBG_ACPI,
"acpi: expect buffer but type: %d\n", obj->type);
return -EINVAL;
}

len = obj->buffer.length;
if (len < sizeof(*ptr)) {
rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
__func__, len);
return -EINVAL;
}

ptr = (typeof(ptr))obj->buffer.pointer;
if (!chk_acpi_policy_6ghz_sig(ptr)) {
rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: bad signature\n", __func__);
return -EINVAL;
}

expect_len = struct_size(ptr, country_list, ptr->country_count);
if (len < expect_len) {
rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: expect %u but length: %u\n",
__func__, expect_len, len);
return -EINVAL;
}

*policy_6ghz = kmemdup(ptr, expect_len, GFP_KERNEL);
if (!*policy_6ghz)
return -ENOMEM;

rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "policy_6ghz: ", *policy_6ghz,
expect_len);
return 0;
}

static bool chk_acpi_policy_6ghz_sp_sig(const struct rtw89_acpi_policy_6ghz_sp *p)
{
return p->signature[0] == 0x52 &&
p->signature[1] == 0x54 &&
p->signature[2] == 0x4B &&
p->signature[3] == 0x07;
}

static
int rtw89_acpi_dsm_get_policy_6ghz_sp(struct rtw89_dev *rtwdev,
union acpi_object *obj,
struct rtw89_acpi_policy_6ghz_sp **policy)
{
const struct rtw89_acpi_policy_6ghz_sp *ptr;
u32 buf_len;

if (obj->type != ACPI_TYPE_BUFFER) {
rtw89_debug(rtwdev, RTW89_DBG_ACPI,
"acpi: expect buffer but type: %d\n", obj->type);
return -EINVAL;
}

buf_len = obj->buffer.length;
if (buf_len < sizeof(*ptr)) {
rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
__func__, buf_len);
return -EINVAL;
}

ptr = (typeof(ptr))obj->buffer.pointer;
if (!chk_acpi_policy_6ghz_sp_sig(ptr)) {
rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: bad signature\n", __func__);
return -EINVAL;
}

*policy = kmemdup(ptr, sizeof(*ptr), GFP_KERNEL);
if (!*policy)
return -ENOMEM;

rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "policy_6ghz_sp: ", *policy,
sizeof(*ptr));
return 0;
}

int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
enum rtw89_acpi_dsm_func func, u8 *value)
enum rtw89_acpi_dsm_func func,
struct rtw89_acpi_dsm_result *res)
{
union acpi_object *obj;
int ret;

obj = acpi_evaluate_dsm(ACPI_HANDLE(rtwdev->dev), &rtw89_guid,
0, func, NULL);
if (!obj) {
rtw89_debug(rtwdev, RTW89_DBG_UNEXP,
rtw89_debug(rtwdev, RTW89_DBG_ACPI,
"acpi dsm fail to evaluate func: %d\n", func);
return -ENOENT;
}

ret = rtw89_acpi_dsm_get(rtwdev, obj, value);
if (func == RTW89_ACPI_DSM_FUNC_6G_BP)
ret = rtw89_acpi_dsm_get_policy_6ghz(rtwdev, obj,
&res->u.policy_6ghz);
else if (func == RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP)
ret = rtw89_acpi_dsm_get_policy_6ghz_sp(rtwdev, obj,
&res->u.policy_6ghz_sp);
else
ret = rtw89_acpi_dsm_get_value(rtwdev, obj, &res->u.value);

ACPI_FREE(obj);
return ret;
}
#elif defined(__FreeBSD__)
int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
enum rtw89_acpi_dsm_func func, u8 *value)
enum rtw89_acpi_dsm_func func,
struct rtw89_acpi_dsm_result *res)
{
return -ENOENT;
}
Expand Down
53 changes: 51 additions & 2 deletions sys/contrib/dev/rtw89/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,59 @@ enum rtw89_acpi_dsm_func {
RTW89_ACPI_DSM_FUNC_6G_DIS = 3,
RTW89_ACPI_DSM_FUNC_6G_BP = 4,
RTW89_ACPI_DSM_FUNC_TAS_EN = 5,
RTW89_ACPI_DSM_FUNC_59G_EN = 6,
RTW89_ACPI_DSM_FUNC_UNII4_SUP = 6,
RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP = 7,
};

enum rtw89_acpi_conf_unii4 {
RTW89_ACPI_CONF_UNII4_FCC = BIT(0),
RTW89_ACPI_CONF_UNII4_IC = BIT(1),
};

enum rtw89_acpi_policy_mode {
RTW89_ACPI_POLICY_BLOCK = 0,
RTW89_ACPI_POLICY_ALLOW = 1,
};

struct rtw89_acpi_country_code {
/* below are allowed:
* * ISO alpha2 country code
* * EU for countries in Europe
*/
char alpha2[2];
} __packed;

struct rtw89_acpi_policy_6ghz {
u8 signature[3];
u8 rsvd;
u8 policy_mode;
u8 country_count;
struct rtw89_acpi_country_code country_list[] __counted_by(country_count);
} __packed;

enum rtw89_acpi_conf_6ghz_sp {
RTW89_ACPI_CONF_6GHZ_SP_US = BIT(0),
};

struct rtw89_acpi_policy_6ghz_sp {
u8 signature[4];
u8 revision;
u8 override;
u8 conf;
u8 rsvd;
} __packed;

struct rtw89_acpi_dsm_result {
union {
u8 value;
/* caller needs to free it after using */
struct rtw89_acpi_policy_6ghz *policy_6ghz;
struct rtw89_acpi_policy_6ghz_sp *policy_6ghz_sp;
} u;
};

int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
enum rtw89_acpi_dsm_func func, u8 *value);
enum rtw89_acpi_dsm_func func,
struct rtw89_acpi_dsm_result *res);

#endif
Loading

0 comments on commit 43d7574

Please sign in to comment.