mirror of
				https://github.com/Telecominfraproject/wlan-ap.git
				synced 2025-10-30 01:52:51 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			613 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			613 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 47728424bea22cb0dc646be2cec95fec51710e01 Mon Sep 17 00:00:00 2001
 | |
| From: John Crispin <john@phrozen.org>
 | |
| Date: Fri, 22 Nov 2024 06:37:44 +0100
 | |
| Subject: [PATCH] ucode: multi radio support
 | |
| 
 | |
| Signed-off-by: John Crispin <john@phrozen.org>
 | |
| ---
 | |
|  package/utils/ucode/patches/0001-fixes.patch  |  21 +-
 | |
|  ...ess-to-tb-array-out-of-uc_nl_convert.patch | 341 ++++++++++++++++++
 | |
|  ...d-support-for-multi-attribute-arrays.patch |  94 +++++
 | |
|  ...l80211-add-wiphy-multi-radio-support.patch |  50 +++
 | |
|  ...w-attributes-for-multi-radio-support.patch |  30 ++
 | |
|  5 files changed, 528 insertions(+), 8 deletions(-)
 | |
|  create mode 100644 package/utils/ucode/patches/110-nl80211-move-access-to-tb-array-out-of-uc_nl_convert.patch
 | |
|  create mode 100644 package/utils/ucode/patches/111-nl80211-add-support-for-multi-attribute-arrays.patch
 | |
|  create mode 100644 package/utils/ucode/patches/112-nl80211-add-wiphy-multi-radio-support.patch
 | |
|  create mode 100644 package/utils/ucode/patches/113-nl80211-add-new-attributes-for-multi-radio-support.patch
 | |
| 
 | |
| diff --git a/package/utils/ucode/patches/0001-fixes.patch b/package/utils/ucode/patches/0001-fixes.patch
 | |
| index a8f96fc71d..1f60bdd656 100644
 | |
| --- a/package/utils/ucode/patches/0001-fixes.patch
 | |
| +++ b/package/utils/ucode/patches/0001-fixes.patch
 | |
| @@ -8,11 +8,9 @@ Subject: [PATCH] fixes
 | |
|   lib/rtnl.c    |  1 +
 | |
|   2 files changed, 87 insertions(+), 6 deletions(-)
 | |
|  
 | |
| -Index: ucode-2023-06-06-c7d84aae/lib/nl80211.c
 | |
| -===================================================================
 | |
| ---- ucode-2023-06-06-c7d84aae.orig/lib/nl80211.c
 | |
| -+++ ucode-2023-06-06-c7d84aae/lib/nl80211.c
 | |
| -@@ -56,6 +56,26 @@ limitations under the License.
 | |
| +--- a/lib/nl80211.c
 | |
| ++++ b/lib/nl80211.c
 | |
| +@@ -57,6 +57,33 @@ limitations under the License.
 | |
|   
 | |
|   #define NL80211_CMDS_BITMAP_SIZE	DIV_ROUND_UP(NL80211_CMD_MAX + 1, 32)
 | |
|   
 | |
| @@ -33,13 +31,20 @@ Index: ucode-2023-06-06-c7d84aae/lib/nl80211.c
 | |
|  +#ifndef QCA_WIFI_7
 | |
|  +#define NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC NL80211_ATTR_NOT_IMPLEMENTED
 | |
|  +#define NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY NL80211_ATTR_NOT_IMPLEMENTED
 | |
| ++#define NL80211_WIPHY_RADIO_FREQ_ATTR_START NL80211_ATTR_NOT_IMPLEMENTED
 | |
| ++#define NL80211_WIPHY_RADIO_FREQ_ATTR_END NL80211_ATTR_NOT_IMPLEMENTED
 | |
| ++#define NL80211_WIPHY_RADIO_ATTR_INDEX NL80211_ATTR_NOT_IMPLEMENTED
 | |
| ++#define NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE NL80211_ATTR_NOT_IMPLEMENTED
 | |
| ++#define NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION NL80211_ATTR_NOT_IMPLEMENTED
 | |
| ++#define NL80211_ATTR_WIPHY_RADIOS NL80211_ATTR_NOT_IMPLEMENTED
 | |
| ++#define NL80211_ATTR_VIF_RADIO_MASK NL80211_ATTR_NOT_IMPLEMENTED
 | |
|  +#endif
 | |
|  +
 | |
|  +
 | |
|   static struct {
 | |
|   	int code;
 | |
|   	char *msg;
 | |
| -@@ -560,7 +580,7 @@ static const uc_nl_nested_spec_t nl80211
 | |
| +@@ -561,7 +588,7 @@ static const uc_nl_nested_spec_t nl80211
 | |
|   
 | |
|   static const uc_nl_nested_spec_t nl80211_wiphy_bands_iftype_data_nla = {
 | |
|   	.headsize = 0,
 | |
| @@ -47,8 +52,8 @@ Index: ucode-2023-06-06-c7d84aae/lib/nl80211.c
 | |
|  +	.nattrs = 9,
 | |
|   	.attrs = {
 | |
|   		{ NL80211_BAND_IFTYPE_ATTR_IFTYPES, "iftypes", DT_NESTED, 0, &nl80211_ifcomb_limit_types_nla },
 | |
| - 		{ NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC, "he_cap_mac", DT_U16, DF_ARRAY, NULL },
 | |
| -@@ -569,6 +589,8 @@ static const uc_nl_nested_spec_t nl80211
 | |
| + 		{ NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC, "he_cap_mac", DT_U8, DF_ARRAY, NULL },
 | |
| +@@ -570,6 +597,8 @@ static const uc_nl_nested_spec_t nl80211
 | |
|   		{ NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE, "he_cap_ppe", DT_U8, DF_ARRAY, NULL },
 | |
|   		{ NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA, "he_6ghz_capa", DT_U16, 0, NULL },
 | |
|   		{ NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS, "vendor_elems", DT_STRING, DF_BINARY, NULL },
 | |
| diff --git a/package/utils/ucode/patches/110-nl80211-move-access-to-tb-array-out-of-uc_nl_convert.patch b/package/utils/ucode/patches/110-nl80211-move-access-to-tb-array-out-of-uc_nl_convert.patch
 | |
| new file mode 100644
 | |
| index 0000000000..7e9d07e01e
 | |
| --- /dev/null
 | |
| +++ b/package/utils/ucode/patches/110-nl80211-move-access-to-tb-array-out-of-uc_nl_convert.patch
 | |
| @@ -0,0 +1,341 @@
 | |
| +From: Felix Fietkau <nbd@nbd.name>
 | |
| +Date: Sat, 29 Jun 2024 12:03:21 +0200
 | |
| +Subject: [PATCH] nl80211: move access to tb array out of uc_nl_convert_attr
 | |
| + and below
 | |
| +
 | |
| +Only one place needs access to another attribute from the tb array
 | |
| +(HE MCS rates). In order to make that access possible, add a flag to indicate
 | |
| +a second attribute dependency via auxdata.
 | |
| +
 | |
| +Signed-off-by: Felix Fietkau <nbd@nbd.name>
 | |
| +---
 | |
| +
 | |
| +--- a/lib/nl80211.c
 | |
| ++++ b/lib/nl80211.c
 | |
| +@@ -197,6 +197,7 @@ enum {
 | |
| + 	DF_OFFSET1 = (1 << 4),
 | |
| + 	DF_ARRAY = (1 << 5),
 | |
| + 	DF_BINARY = (1 << 6),
 | |
| ++	DF_RELATED = (1 << 7),
 | |
| + };
 | |
| + 
 | |
| + typedef struct uc_nl_attr_spec {
 | |
| +@@ -215,6 +216,7 @@ typedef struct uc_nl_nested_spec {
 | |
| + 
 | |
| + #define SIZE(type) (void *)(uintptr_t)sizeof(struct type)
 | |
| + #define MEMBER(type, field) (void *)(uintptr_t)offsetof(struct type, field)
 | |
| ++#define ATTRID(id) (void *)(uintptr_t)(id)
 | |
| + 
 | |
| + static const uc_nl_nested_spec_t nl80211_cqm_nla = {
 | |
| + 	.headsize = 0,
 | |
| +@@ -593,7 +595,7 @@ static const uc_nl_nested_spec_t nl80211
 | |
| + 		{ NL80211_BAND_IFTYPE_ATTR_IFTYPES, "iftypes", DT_NESTED, 0, &nl80211_ifcomb_limit_types_nla },
 | |
| + 		{ NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC, "he_cap_mac", DT_U8, DF_ARRAY, NULL },
 | |
| + 		{ NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY, "he_cap_phy", DT_U8, DF_ARRAY, NULL },
 | |
| +-		{ NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET, "he_cap_mcs_set", DT_HE_MCS, 0, NULL },
 | |
| ++		{ NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET, "he_cap_mcs_set", DT_HE_MCS, DF_RELATED, ATTRID(NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY) },
 | |
| + 		{ NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE, "he_cap_ppe", DT_U8, DF_ARRAY, NULL },
 | |
| + 		{ NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA, "he_6ghz_capa", DT_U16, 0, NULL },
 | |
| + 		{ NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS, "vendor_elems", DT_STRING, DF_BINARY, NULL },
 | |
| +@@ -1065,12 +1067,12 @@ static bool
 | |
| + uc_nl_parse_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base, uc_vm_t *vm, uc_value_t *val, size_t idx);
 | |
| + 
 | |
| + static uc_value_t *
 | |
| +-uc_nl_convert_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base, struct nlattr **tb, uc_vm_t *vm);
 | |
| ++uc_nl_convert_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base, struct nlattr *attr, struct nlattr *attr2, uc_vm_t *vm);
 | |
| + 
 | |
| + static bool
 | |
| + uc_nl_convert_attrs(struct nl_msg *msg, void *buf, size_t buflen, size_t headsize, const uc_nl_attr_spec_t *attrs, size_t nattrs, uc_vm_t *vm, uc_value_t *obj)
 | |
| + {
 | |
| +-	struct nlattr **tb, *nla, *nla_nest;
 | |
| ++	struct nlattr **tb, *nla, *nla2, *nla_nest;
 | |
| + 	size_t i, type, maxattr = 0;
 | |
| + 	uc_value_t *v, *arr;
 | |
| + 	int rem;
 | |
| +@@ -1106,9 +1108,7 @@ uc_nl_convert_attrs(struct nl_msg *msg,
 | |
| + 				    attrs[i].auxdata && nla_type(nla) != (intptr_t)attrs[i].auxdata)
 | |
| + 					continue;
 | |
| + 
 | |
| +-				tb[attrs[i].attr] = nla;
 | |
| +-
 | |
| +-				v = uc_nl_convert_attr(&attrs[i], msg, (char *)buf, tb, vm);
 | |
| ++				v = uc_nl_convert_attr(&attrs[i], msg, (char *)buf, nla, NULL, vm);
 | |
| + 
 | |
| + 				if (!v)
 | |
| + 					continue;
 | |
| +@@ -1128,7 +1128,12 @@ uc_nl_convert_attrs(struct nl_msg *msg,
 | |
| + 			v = arr;
 | |
| + 		}
 | |
| + 		else {
 | |
| +-			v = uc_nl_convert_attr(&attrs[i], msg, (char *)buf, tb, vm);
 | |
| ++			if (attrs[i].flags & DF_RELATED)
 | |
| ++				nla2 = tb[(uintptr_t)attrs[i].auxdata];
 | |
| ++			else
 | |
| ++				nla2 = NULL;
 | |
| ++
 | |
| ++			v = uc_nl_convert_attr(&attrs[i], msg, (char *)buf, tb[attrs[i].attr], nla2, vm);
 | |
| + 
 | |
| + 			if (!v)
 | |
| + 				continue;
 | |
| +@@ -1218,7 +1223,7 @@ uc_nl_parse_rta_nested(const uc_nl_attr_
 | |
| + }
 | |
| + 
 | |
| + static uc_value_t *
 | |
| +-uc_nl_convert_rta_nested(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr **tb, uc_vm_t *vm)
 | |
| ++uc_nl_convert_rta_nested(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr *attr, uc_vm_t *vm)
 | |
| + {
 | |
| + 	const uc_nl_nested_spec_t *nest = spec->auxdata;
 | |
| + 	uc_value_t *nested_obj;
 | |
| +@@ -1227,13 +1232,13 @@ uc_nl_convert_rta_nested(const uc_nl_att
 | |
| + 	if (!nest)
 | |
| + 		return NULL;
 | |
| + 
 | |
| +-	if (!nla_check_len(tb[spec->attr], nest->headsize))
 | |
| ++	if (!nla_check_len(attr, nest->headsize))
 | |
| + 		return NULL;
 | |
| + 
 | |
| + 	nested_obj = ucv_object_new(vm);
 | |
| + 
 | |
| + 	rv = uc_nl_convert_attrs(msg,
 | |
| +-		nla_data(tb[spec->attr]), nla_len(tb[spec->attr]), nest->headsize,
 | |
| ++		nla_data(attr), nla_len(attr), nest->headsize,
 | |
| + 		nest->attrs, nest->nattrs,
 | |
| + 		vm, nested_obj);
 | |
| + 
 | |
| +@@ -1247,17 +1252,17 @@ uc_nl_convert_rta_nested(const uc_nl_att
 | |
| + }
 | |
| + 
 | |
| + static uc_value_t *
 | |
| +-uc_nl_convert_rta_ht_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr **tb, uc_vm_t *vm)
 | |
| ++uc_nl_convert_rta_ht_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr *attr, uc_vm_t *vm)
 | |
| + {
 | |
| + 	uc_value_t *mcs_obj, *mcs_idx;
 | |
| + 	uint16_t max_rate = 0;
 | |
| + 	uint8_t *mcs;
 | |
| + 	size_t i;
 | |
| + 
 | |
| +-	if (!nla_check_len(tb[spec->attr], 16))
 | |
| ++	if (!nla_check_len(attr, 16))
 | |
| + 		return NULL;
 | |
| + 
 | |
| +-	mcs = nla_data(tb[spec->attr]);
 | |
| ++	mcs = nla_data(attr);
 | |
| + 	mcs_obj = ucv_object_new(vm);
 | |
| + 
 | |
| + 	max_rate = (mcs[10] | ((mcs[11] & 0x3) << 8));
 | |
| +@@ -1282,16 +1287,16 @@ uc_nl_convert_rta_ht_mcs(const uc_nl_att
 | |
| + }
 | |
| + 
 | |
| + static uc_value_t *
 | |
| +-uc_nl_convert_rta_ht_cap(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr **tb, uc_vm_t *vm)
 | |
| ++uc_nl_convert_rta_ht_cap(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr *attr, uc_vm_t *vm)
 | |
| + {
 | |
| + 	uc_value_t *cap_obj, *mcs_obj, *rx_mask;
 | |
| + 	struct ieee80211_ht_cap *cap;
 | |
| + 	size_t i;
 | |
| + 
 | |
| +-	if (!nla_check_len(tb[spec->attr], sizeof(*cap)))
 | |
| ++	if (!nla_check_len(attr, sizeof(*cap)))
 | |
| + 		return NULL;
 | |
| + 
 | |
| +-	cap = nla_data(tb[spec->attr]);
 | |
| ++	cap = nla_data(attr);
 | |
| + 	cap_obj = ucv_object_new(vm);
 | |
| + 
 | |
| + 	ucv_object_add(cap_obj, "cap_info", ucv_uint64_new(le16toh(cap->cap_info)));
 | |
| +@@ -1316,17 +1321,17 @@ uc_nl_convert_rta_ht_cap(const uc_nl_att
 | |
| + }
 | |
| + 
 | |
| + static uc_value_t *
 | |
| +-uc_nl_convert_rta_vht_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr **tb, uc_vm_t *vm)
 | |
| ++uc_nl_convert_rta_vht_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr *attr, uc_vm_t *vm)
 | |
| + {
 | |
| + 	uc_value_t *mcs_obj, *mcs_set, *mcs_entry, *mcs_idx;
 | |
| + 	size_t i, j, max_idx;
 | |
| + 	uint16_t u16;
 | |
| + 	uint8_t *mcs;
 | |
| + 
 | |
| +-	if (!nla_check_len(tb[spec->attr], 8))
 | |
| ++	if (!nla_check_len(attr, 8))
 | |
| + 		return NULL;
 | |
| + 
 | |
| +-	mcs = nla_data(tb[spec->attr]);
 | |
| ++	mcs = nla_data(attr);
 | |
| + 	mcs_obj = ucv_object_new(vm);
 | |
| + 
 | |
| + 	u16 = mcs[0] | (mcs[1] << 8);
 | |
| +@@ -1387,7 +1392,7 @@ uc_nl_convert_rta_vht_mcs(const uc_nl_at
 | |
| + }
 | |
| + 
 | |
| + static uc_value_t *
 | |
| +-uc_nl_convert_rta_he_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr **tb, uc_vm_t *vm)
 | |
| ++uc_nl_convert_rta_he_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr *attr, struct nlattr *phy_attr, uc_vm_t *vm)
 | |
| + {
 | |
| + 	uint8_t bw_support_mask[] = { (1 << 1) | (1 << 2), (1 << 3), (1 << 4) };
 | |
| + 	uc_value_t *mcs_set, *mcs_bw, *mcs_dir, *mcs_entry, *mcs_idx;
 | |
| +@@ -1395,13 +1400,13 @@ uc_nl_convert_rta_he_mcs(const uc_nl_att
 | |
| + 	uint16_t u16, phy_cap_0 = 0;
 | |
| + 	size_t i, j, k, l, max_idx;
 | |
| + 
 | |
| +-	if (!nla_check_len(tb[spec->attr], sizeof(mcs)))
 | |
| ++	if (!nla_check_len(attr, sizeof(mcs)))
 | |
| + 		return NULL;
 | |
| + 
 | |
| +-	if (nla_check_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY], sizeof(phy_cap_0)))
 | |
| +-		phy_cap_0 = nla_get_u16(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]);
 | |
| ++	if (nla_check_len(phy_attr, sizeof(phy_cap_0)))
 | |
| ++		phy_cap_0 = nla_get_u16(phy_attr);
 | |
| + 
 | |
| +-	memcpy(mcs, nla_data(tb[spec->attr]), sizeof(mcs));
 | |
| ++	memcpy(mcs, nla_data(attr), sizeof(mcs));
 | |
| + 
 | |
| + 	mcs_set = ucv_array_new_length(vm, 3);
 | |
| + 
 | |
| +@@ -1458,14 +1463,14 @@ uc_nl_convert_rta_he_mcs(const uc_nl_att
 | |
| + }
 | |
| + 
 | |
| + static uc_value_t *
 | |
| +-uc_nl_convert_rta_ie(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr **tb, uc_vm_t *vm)
 | |
| ++uc_nl_convert_rta_ie(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr *attr, uc_vm_t *vm)
 | |
| + {
 | |
| + 	uc_value_t *ie_arr, *ie_obj;
 | |
| + 	uint8_t *ie;
 | |
| + 	size_t len;
 | |
| + 
 | |
| +-	len = nla_len(tb[spec->attr]);
 | |
| +-	ie = nla_data(tb[spec->attr]);
 | |
| ++	len = nla_len(attr);
 | |
| ++	ie = nla_data(attr);
 | |
| + 
 | |
| + 	if (len < 2)
 | |
| + 		return NULL;
 | |
| +@@ -1734,7 +1739,7 @@ uc_nl_convert_numval(const uc_nl_attr_sp
 | |
| + }
 | |
| + 
 | |
| + static uc_value_t *
 | |
| +-uc_nl_convert_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base, struct nlattr **tb, uc_vm_t *vm)
 | |
| ++uc_nl_convert_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base, struct nlattr *attr, struct nlattr *attr2, uc_vm_t *vm)
 | |
| + {
 | |
| + 	union { uint8_t u8; uint16_t u16; uint32_t u32; uint64_t u64; size_t sz; } t = { 0 };
 | |
| + 	char buf[sizeof("FF:FF:FF:FF:FF:FF")];
 | |
| +@@ -1751,17 +1756,17 @@ uc_nl_convert_attr(const uc_nl_attr_spec
 | |
| + 	case DT_U64:
 | |
| + 		if (spec->flags & DF_ARRAY) {
 | |
| + 			assert(spec->attr != 0);
 | |
| +-			assert((nla_len(tb[spec->attr]) % dt_sizes[spec->type]) == 0);
 | |
| ++			assert((nla_len(attr) % dt_sizes[spec->type]) == 0);
 | |
| + 
 | |
| +-			v = ucv_array_new_length(vm, nla_len(tb[spec->attr]) / dt_sizes[spec->type]);
 | |
| ++			v = ucv_array_new_length(vm, nla_len(attr) / dt_sizes[spec->type]);
 | |
| + 
 | |
| +-			for (i = 0; i < nla_len(tb[spec->attr]); i += dt_sizes[spec->type])
 | |
| +-				ucv_array_push(v, uc_nl_convert_numval(spec, nla_data(tb[spec->attr]) + i));
 | |
| ++			for (i = 0; i < nla_len(attr); i += dt_sizes[spec->type])
 | |
| ++				ucv_array_push(v, uc_nl_convert_numval(spec, nla_data(attr) + i));
 | |
| + 
 | |
| + 			return v;
 | |
| + 		}
 | |
| +-		else if (nla_check_len(tb[spec->attr], dt_sizes[spec->type])) {
 | |
| +-			return uc_nl_convert_numval(spec, nla_data(tb[spec->attr]));
 | |
| ++		else if (nla_check_len(attr, dt_sizes[spec->type])) {
 | |
| ++			return uc_nl_convert_numval(spec, nla_data(attr));
 | |
| + 		}
 | |
| + 
 | |
| + 		return NULL;
 | |
| +@@ -1769,15 +1774,15 @@ uc_nl_convert_attr(const uc_nl_attr_spec
 | |
| + 	case DT_BOOL:
 | |
| + 		if (spec->attr == 0)
 | |
| + 			t.u8 = uc_nl_get_struct_member_u8(base, spec->auxdata);
 | |
| +-		else if (nla_check_len(tb[spec->attr], sizeof(t.u8)))
 | |
| +-			t.u8 = nla_get_u8(tb[spec->attr]);
 | |
| ++		else if (nla_check_len(attr, sizeof(t.u8)))
 | |
| ++			t.u8 = nla_get_u8(attr);
 | |
| + 
 | |
| + 		return ucv_boolean_new(t.u8 != 0);
 | |
| + 
 | |
| + 	case DT_FLAG:
 | |
| + 		if (spec->attr == 0)
 | |
| + 			t.u8 = uc_nl_get_struct_member_u8(base, spec->auxdata);
 | |
| +-		else if (tb[spec->attr] != NULL)
 | |
| ++		else if (attr != NULL)
 | |
| + 			t.u8 = 1;
 | |
| + 
 | |
| + 		return ucv_boolean_new(t.u8 != 0);
 | |
| +@@ -1785,21 +1790,21 @@ uc_nl_convert_attr(const uc_nl_attr_spec
 | |
| + 	case DT_STRING:
 | |
| + 		assert(spec->attr != 0);
 | |
| + 
 | |
| +-		if (!nla_check_len(tb[spec->attr], 1))
 | |
| ++		if (!nla_check_len(attr, 1))
 | |
| + 			return NULL;
 | |
| + 
 | |
| +-		t.sz = nla_len(tb[spec->attr]);
 | |
| ++		t.sz = nla_len(attr);
 | |
| + 
 | |
| + 		if (!(spec->flags & DF_BINARY))
 | |
| + 			t.sz -= 1;
 | |
| + 
 | |
| +-		return ucv_string_new_length(nla_data(tb[spec->attr]), t.sz);
 | |
| ++		return ucv_string_new_length(nla_data(attr), t.sz);
 | |
| + 
 | |
| + 	case DT_NETDEV:
 | |
| + 		if (spec->attr == 0)
 | |
| + 			t.u32 = uc_nl_get_struct_member_u32(base, spec->auxdata);
 | |
| +-		else if (nla_check_len(tb[spec->attr], sizeof(t.u32)))
 | |
| +-			t.u32 = nla_get_u32(tb[spec->attr]);
 | |
| ++		else if (nla_check_len(attr, sizeof(t.u32)))
 | |
| ++			t.u32 = nla_get_u32(attr);
 | |
| + 
 | |
| + 		if (if_indextoname(t.u32, buf))
 | |
| + 			return ucv_string_new(buf);
 | |
| +@@ -1809,10 +1814,10 @@ uc_nl_convert_attr(const uc_nl_attr_spec
 | |
| + 	case DT_LLADDR:
 | |
| + 		assert(spec->attr != 0);
 | |
| + 
 | |
| +-		if (!nla_check_len(tb[spec->attr], sizeof(*ea)))
 | |
| ++		if (!nla_check_len(attr, sizeof(*ea)))
 | |
| + 			return NULL;
 | |
| + 
 | |
| +-		ea = nla_data(tb[spec->attr]);
 | |
| ++		ea = nla_data(attr);
 | |
| + 
 | |
| + 		snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
 | |
| + 			ea->ether_addr_octet[0], ea->ether_addr_octet[1],
 | |
| +@@ -1824,29 +1829,29 @@ uc_nl_convert_attr(const uc_nl_attr_spec
 | |
| + 	case DT_INADDR:
 | |
| + 		assert(spec->attr != 0);
 | |
| + 
 | |
| +-		if (!nla_check_len(tb[spec->attr], sizeof(struct in_addr)) ||
 | |
| +-		    !inet_ntop(AF_INET, nla_data(tb[spec->attr]), buf, sizeof(buf)))
 | |
| ++		if (!nla_check_len(attr, sizeof(struct in_addr)) ||
 | |
| ++		    !inet_ntop(AF_INET, nla_data(attr), buf, sizeof(buf)))
 | |
| + 			return NULL;
 | |
| + 
 | |
| + 		return ucv_string_new(buf);
 | |
| + 
 | |
| + 	case DT_NESTED:
 | |
| +-		return uc_nl_convert_rta_nested(spec, msg, tb, vm);
 | |
| ++		return uc_nl_convert_rta_nested(spec, msg, attr, vm);
 | |
| + 
 | |
| + 	case DT_HT_MCS:
 | |
| +-		return uc_nl_convert_rta_ht_mcs(spec, msg, tb, vm);
 | |
| ++		return uc_nl_convert_rta_ht_mcs(spec, msg, attr, vm);
 | |
| + 
 | |
| + 	case DT_HT_CAP:
 | |
| +-		return uc_nl_convert_rta_ht_cap(spec, msg, tb, vm);
 | |
| ++		return uc_nl_convert_rta_ht_cap(spec, msg, attr, vm);
 | |
| + 
 | |
| + 	case DT_VHT_MCS:
 | |
| +-		return uc_nl_convert_rta_vht_mcs(spec, msg, tb, vm);
 | |
| ++		return uc_nl_convert_rta_vht_mcs(spec, msg, attr, vm);
 | |
| + 
 | |
| + 	case DT_HE_MCS:
 | |
| +-		return uc_nl_convert_rta_he_mcs(spec, msg, tb, vm);
 | |
| ++		return uc_nl_convert_rta_he_mcs(spec, msg, attr, attr2, vm);
 | |
| + 
 | |
| + 	case DT_IE:
 | |
| +-		return uc_nl_convert_rta_ie(spec, msg, tb, vm);
 | |
| ++		return uc_nl_convert_rta_ie(spec, msg, attr, vm);
 | |
| + 
 | |
| + 	default:
 | |
| + 		assert(0);
 | |
| diff --git a/package/utils/ucode/patches/111-nl80211-add-support-for-multi-attribute-arrays.patch b/package/utils/ucode/patches/111-nl80211-add-support-for-multi-attribute-arrays.patch
 | |
| new file mode 100644
 | |
| index 0000000000..517d882850
 | |
| --- /dev/null
 | |
| +++ b/package/utils/ucode/patches/111-nl80211-add-support-for-multi-attribute-arrays.patch
 | |
| @@ -0,0 +1,94 @@
 | |
| +From: Felix Fietkau <nbd@nbd.name>
 | |
| +Date: Sat, 29 Jun 2024 12:05:29 +0200
 | |
| +Subject: [PATCH] nl80211: add support for multi-attribute arrays
 | |
| +
 | |
| +For newly added attributes, the kernel prefers to no longer add a nesting
 | |
| +container attribute. Instead, an attribute with the element type is simply
 | |
| +added multiple times within the outer container.
 | |
| +Add support for this array style, which will be used in the pending wiphy
 | |
| +multi radio support.
 | |
| +
 | |
| +Signed-off-by: Felix Fietkau <nbd@nbd.name>
 | |
| +---
 | |
| +
 | |
| +--- a/lib/nl80211.c
 | |
| ++++ b/lib/nl80211.c
 | |
| +@@ -198,6 +198,7 @@ enum {
 | |
| + 	DF_ARRAY = (1 << 5),
 | |
| + 	DF_BINARY = (1 << 6),
 | |
| + 	DF_RELATED = (1 << 7),
 | |
| ++	DF_REPEATED = (1 << 8),
 | |
| + };
 | |
| + 
 | |
| + typedef struct uc_nl_attr_spec {
 | |
| +@@ -1043,26 +1044,6 @@ uc_nl_get_struct_member_u32(char *base,
 | |
| + 	return u32;
 | |
| + }
 | |
| + 
 | |
| +-static void
 | |
| +-uc_nl_nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len)
 | |
| +-{
 | |
| +-	struct nlattr *nla;
 | |
| +-	int rem;
 | |
| +-
 | |
| +-	memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
 | |
| +-
 | |
| +-	nla_for_each_attr(nla, head, len, rem) {
 | |
| +-		int type = nla_type(nla);
 | |
| +-
 | |
| +-		if (type <= maxtype)
 | |
| +-			tb[type] = nla;
 | |
| +-	}
 | |
| +-
 | |
| +-	if (rem > 0)
 | |
| +-		fprintf(stderr, "netlink: %d bytes leftover after parsing attributes.\n", rem);
 | |
| +-}
 | |
| +-
 | |
| +-
 | |
| + static bool
 | |
| + uc_nl_parse_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base, uc_vm_t *vm, uc_value_t *val, size_t idx);
 | |
| + 
 | |
| +@@ -1086,12 +1067,10 @@ uc_nl_convert_attrs(struct nl_msg *msg,
 | |
| + 	if (!tb)
 | |
| + 		return false;
 | |
| + 
 | |
| +-	uc_nl_nla_parse(tb, maxattr, buf + headsize, buflen - headsize);
 | |
| +-
 | |
| + 	nla_for_each_attr(nla, buf + headsize, buflen - headsize, rem) {
 | |
| + 		type = nla_type(nla);
 | |
| + 
 | |
| +-		if (type <= maxattr)
 | |
| ++		if (type <= maxattr && !tb[type])
 | |
| + 			tb[type] = nla;
 | |
| + 	}
 | |
| + 
 | |
| +@@ -1099,7 +1078,28 @@ uc_nl_convert_attrs(struct nl_msg *msg,
 | |
| + 		if (attrs[i].attr != 0 && !tb[attrs[i].attr])
 | |
| + 			continue;
 | |
| + 
 | |
| +-		if (attrs[i].flags & DF_MULTIPLE) {
 | |
| ++		if (attrs[i].flags & DF_REPEATED) {
 | |
| ++			arr = ucv_array_new(vm);
 | |
| ++
 | |
| ++			nla = tb[attrs[i].attr];
 | |
| ++			rem = buflen - ((void *)nla - buf);
 | |
| ++			for (; nla_ok(nla, rem); nla = nla_next(nla, &rem)) {
 | |
| ++				if (nla_type(nla) != (int)attrs[i].attr)
 | |
| ++					break;
 | |
| ++				v = uc_nl_convert_attr(&attrs[i], msg, (char *)buf, nla, NULL, vm);
 | |
| ++				if (!v)
 | |
| ++					continue;
 | |
| ++
 | |
| ++				ucv_array_push(arr, v);
 | |
| ++			}
 | |
| ++			if (!ucv_array_length(arr)) {
 | |
| ++				ucv_put(arr);
 | |
| ++				continue;
 | |
| ++			}
 | |
| ++
 | |
| ++			v = arr;
 | |
| ++		}
 | |
| ++		else if (attrs[i].flags & DF_MULTIPLE) {
 | |
| + 			arr = ucv_array_new(vm);
 | |
| + 			nla_nest = tb[attrs[i].attr];
 | |
| + 
 | |
| diff --git a/package/utils/ucode/patches/112-nl80211-add-wiphy-multi-radio-support.patch b/package/utils/ucode/patches/112-nl80211-add-wiphy-multi-radio-support.patch
 | |
| new file mode 100644
 | |
| index 0000000000..588e9a5e72
 | |
| --- /dev/null
 | |
| +++ b/package/utils/ucode/patches/112-nl80211-add-wiphy-multi-radio-support.patch
 | |
| @@ -0,0 +1,50 @@
 | |
| +From: Felix Fietkau <nbd@nbd.name>
 | |
| +Date: Tue, 9 Jul 2024 17:53:30 +0200
 | |
| +Subject: [PATCH] nl80211: add wiphy multi-radio support
 | |
| +
 | |
| +Support new attributes that describe multiple radios belonging to a single
 | |
| +wiphy.
 | |
| +
 | |
| +Signed-off-by: Felix Fietkau <nbd@nbd.name>
 | |
| +---
 | |
| +
 | |
| +--- a/lib/nl80211.c
 | |
| ++++ b/lib/nl80211.c
 | |
| +@@ -842,9 +842,28 @@ static const uc_nl_nested_spec_t nl80211
 | |
| + 	}
 | |
| + };
 | |
| + 
 | |
| ++static const uc_nl_nested_spec_t nl80211_radio_freq_range_nla = {
 | |
| ++	.headsize = 0,
 | |
| ++	.nattrs = 2,
 | |
| ++	.attrs = {
 | |
| ++		{ NL80211_WIPHY_RADIO_FREQ_ATTR_START, "start", DT_U32, 0, NULL },
 | |
| ++		{ NL80211_WIPHY_RADIO_FREQ_ATTR_END, "end", DT_U32, 0, NULL },
 | |
| ++	}
 | |
| ++};
 | |
| ++
 | |
| ++static const uc_nl_nested_spec_t nl80211_wiphy_radio_nla = {
 | |
| ++	.headsize = 0,
 | |
| ++	.nattrs = 3,
 | |
| ++	.attrs = {
 | |
| ++		{ NL80211_WIPHY_RADIO_ATTR_INDEX, "index", DT_U32, 0, NULL },
 | |
| ++		{ NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE, "freq_ranges", DT_NESTED, DF_REPEATED, &nl80211_radio_freq_range_nla },
 | |
| ++		{ NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION, "interface_combinations", DT_NESTED, DF_REPEATED, &nl80211_ifcomb_nla },
 | |
| ++	}
 | |
| ++};
 | |
| ++
 | |
| + static const uc_nl_nested_spec_t nl80211_msg = {
 | |
| + 	.headsize = 0,
 | |
| +-	.nattrs = 128,
 | |
| ++	.nattrs = 129,
 | |
| + 	.attrs = {
 | |
| + 		{ NL80211_ATTR_4ADDR, "4addr", DT_U8, 0, NULL },
 | |
| + 		{ NL80211_ATTR_AIRTIME_WEIGHT, "airtime_weight", DT_U16, 0, NULL },
 | |
| +@@ -974,6 +993,7 @@ static const uc_nl_nested_spec_t nl80211
 | |
| + 		{ NL80211_ATTR_SOFTWARE_IFTYPES, "software_iftypes", DT_NESTED, 0, &nl80211_ifcomb_limit_types_nla },
 | |
| + 		{ NL80211_ATTR_MAX_AP_ASSOC_STA, "max_ap_assoc", DT_U16, 0, NULL },
 | |
| + 		{ NL80211_ATTR_SURVEY_INFO, "survey_info", DT_NESTED, 0, &nl80211_survey_info_nla },
 | |
| ++		{ NL80211_ATTR_WIPHY_RADIOS, "radios", DT_NESTED, DF_MULTIPLE|DF_AUTOIDX, &nl80211_wiphy_radio_nla },
 | |
| + 	}
 | |
| + };
 | |
| + 
 | |
| diff --git a/package/utils/ucode/patches/113-nl80211-add-new-attributes-for-multi-radio-support.patch b/package/utils/ucode/patches/113-nl80211-add-new-attributes-for-multi-radio-support.patch
 | |
| new file mode 100644
 | |
| index 0000000000..15e5047510
 | |
| --- /dev/null
 | |
| +++ b/package/utils/ucode/patches/113-nl80211-add-new-attributes-for-multi-radio-support.patch
 | |
| @@ -0,0 +1,30 @@
 | |
| +From: Felix Fietkau <nbd@nbd.name>
 | |
| +Date: Wed, 23 Oct 2024 18:50:10 +0200
 | |
| +Subject: [PATCH] nl80211: add new attributes for multi-radio support
 | |
| +
 | |
| +- vif radio mask: used to assign vifs to specific radios
 | |
| +- monitor skip_tx flag: do not pass locally transmitted packets on the monitor interface
 | |
| +- radio antenna mask: radio specific part of the phy antenna mask
 | |
| +
 | |
| +Signed-off-by: Felix Fietkau <nbd@nbd.name>
 | |
| +---
 | |
| +
 | |
| +--- a/lib/nl80211.c
 | |
| ++++ b/lib/nl80211.c
 | |
| +@@ -863,7 +863,7 @@ static const uc_nl_nested_spec_t nl80211
 | |
| + 
 | |
| + static const uc_nl_nested_spec_t nl80211_msg = {
 | |
| + 	.headsize = 0,
 | |
| +-	.nattrs = 129,
 | |
| ++	.nattrs = 130,
 | |
| + 	.attrs = {
 | |
| + 		{ NL80211_ATTR_4ADDR, "4addr", DT_U8, 0, NULL },
 | |
| + 		{ NL80211_ATTR_AIRTIME_WEIGHT, "airtime_weight", DT_U16, 0, NULL },
 | |
| +@@ -994,6 +994,7 @@ static const uc_nl_nested_spec_t nl80211
 | |
| + 		{ NL80211_ATTR_MAX_AP_ASSOC_STA, "max_ap_assoc", DT_U16, 0, NULL },
 | |
| + 		{ NL80211_ATTR_SURVEY_INFO, "survey_info", DT_NESTED, 0, &nl80211_survey_info_nla },
 | |
| + 		{ NL80211_ATTR_WIPHY_RADIOS, "radios", DT_NESTED, DF_MULTIPLE|DF_AUTOIDX, &nl80211_wiphy_radio_nla },
 | |
| ++		{ NL80211_ATTR_VIF_RADIO_MASK, "vif_radio_mask", DT_U32, 0, NULL },
 | |
| + 	}
 | |
| + };
 | |
| + 
 | |
| -- 
 | |
| 2.34.1
 | |
| 
 | 
