diff --git a/.github/config/config.stock.udm b/.github/config/config.stock.udm index 3a28906a7c4b..490d84ff6298 100644 --- a/.github/config/config.stock.udm +++ b/.github/config/config.stock.udm @@ -19,7 +19,7 @@ CONFIG_THREAD_INFO_IN_TASK=y # CONFIG_INIT_ENV_ARG_LIMIT=32 # CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="-v1.11.4.3940-e66d85f" +CONFIG_LOCALVERSION="-v1.12.22.4309-4105ace" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_BUILD_SALT="" CONFIG_DEFAULT_HOSTNAME="(none)" @@ -811,7 +811,7 @@ CONFIG_NETFILTER_NETLINK=y CONFIG_NETFILTER_FAMILY_BRIDGE=y # CONFIG_NETFILTER_NETLINK_ACCT is not set CONFIG_NETFILTER_NETLINK_QUEUE=y -# CONFIG_NETFILTER_NETLINK_LOG is not set +CONFIG_NETFILTER_NETLINK_LOG=m # CONFIG_NETFILTER_NETLINK_OSF is not set CONFIG_NF_CONNTRACK=y CONFIG_NF_LOG_COMMON=m @@ -876,7 +876,7 @@ CONFIG_NETFILTER_XT_TARGET_LOG=m CONFIG_NETFILTER_XT_TARGET_MARK=y CONFIG_NETFILTER_XT_NAT=y CONFIG_NETFILTER_XT_TARGET_NETMAP=y -# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set +CONFIG_NETFILTER_XT_TARGET_NFLOG=m CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y # CONFIG_NETFILTER_XT_TARGET_RATEEST is not set CONFIG_NETFILTER_XT_TARGET_REDIRECT=y @@ -933,7 +933,7 @@ CONFIG_NETFILTER_XT_MATCH_SOCKET=m # CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set # CONFIG_NETFILTER_XT_MATCH_STRING is not set # CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set -# CONFIG_NETFILTER_XT_MATCH_TIME is not set +CONFIG_NETFILTER_XT_MATCH_TIME=y # CONFIG_NETFILTER_XT_MATCH_U32 is not set CONFIG_IP_SET=y CONFIG_IP_SET_MAX=256 @@ -1560,6 +1560,7 @@ CONFIG_SCSI_PROC_FS=y # SCSI support type (disk, tape, CD-ROM) # CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_UBNT_STATIC_BOOT_DEV=y # CONFIG_CHR_DEV_ST is not set # CONFIG_CHR_DEV_OSST is not set # CONFIG_BLK_DEV_SR is not set @@ -2032,7 +2033,7 @@ CONFIG_FIXED_PHY=y # CONFIG_MICROSEMI_PHY is not set # CONFIG_NATIONAL_PHY is not set # CONFIG_QSEMI_PHY is not set -# CONFIG_REALTEK_PHY is not set +CONFIG_REALTEK_PHY=y # CONFIG_RENESAS_PHY is not set # CONFIG_ROCKCHIP_PHY is not set # CONFIG_SMSC_PHY is not set diff --git a/arch/arm64/include/asm/checksum.h b/arch/arm64/include/asm/checksum.h index fd11e0d70e44..1672ed418bc5 100644 --- a/arch/arm64/include/asm/checksum.h +++ b/arch/arm64/include/asm/checksum.h @@ -47,6 +47,9 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) } #define ip_fast_csum ip_fast_csum +extern unsigned int do_csum(const unsigned char *buff, int len); +#define do_csum do_csum + #include #endif /* __ASM_CHECKSUM_H */ diff --git a/arch/arm64/lib/Makefile b/arch/arm64/lib/Makefile index 5df2d611b77d..56c50d82148c 100644 --- a/arch/arm64/lib/Makefile +++ b/arch/arm64/lib/Makefile @@ -3,7 +3,7 @@ lib-y := clear_user.o delay.o copy_from_user.o \ copy_to_user.o copy_in_user.o copy_page.o \ clear_page.o memchr.o memcpy.o memmove.o memset.o \ memcmp.o strcmp.o strncmp.o strlen.o strnlen.o \ - strchr.o strrchr.o tishift.o + strchr.o strrchr.o tishift.o csum.o # Tell the compiler to treat all general purpose registers (with the # exception of the IP registers, which are already handled by the caller diff --git a/arch/arm64/lib/csum.S b/arch/arm64/lib/csum.S new file mode 100644 index 000000000000..534e2ebdc426 --- /dev/null +++ b/arch/arm64/lib/csum.S @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2019 Linaro, Ltd. + */ + +#include +#include + +ENTRY(do_csum) + adds x2, xzr, xzr // clear x2 and C flag + + // 64 bytes at a time + lsr x3, x1, #6 + and x1, x1, #63 + cbz x3, 1f + + // Eight 64-bit adds per iteration +0: ldp x4, x5, [x0], #64 + ldp x6, x7, [x0, #-48] + ldp x8, x9, [x0, #-32] + ldp x10, x11, [x0, #-16] + adcs x2, x2, x4 + sub x3, x3, #1 + adcs x2, x2, x5 + adcs x2, x2, x6 + adcs x2, x2, x7 + adcs x2, x2, x8 + adcs x2, x2, x9 + adcs x2, x2, x10 + adcs x2, x2, x11 + cbnz x3, 0b + adc x2, x2, xzr + + cbz x1, 7f + bic x3, x1, #1 + add x12, x0, x1 + add x0, x0, x3 + neg x3, x3 + add x3, x3, #64 + lsl x3, x3, #3 + + // Handle remaining 63 bytes or less using an overlapping 64-byte load + // and a branchless code path to complete the calculation + ldp x4, x5, [x0, #-64] + ldp x6, x7, [x0, #-48] + ldp x8, x9, [x0, #-32] + ldp x10, x11, [x0, #-16] + ldrb w12, [x12, #-1] + + .irp reg, x4, x5, x6, x7, x8, x9, x10, x11 + cmp x3, #64 + csel \reg, \reg, xzr, lt + ccmp x3, xzr, #0, lt + csel x13, x3, xzr, gt + sub x3, x3, #64 +CPU_LE( lsr \reg, \reg, x13 ) +CPU_BE( lsl \reg, \reg, x13 ) + .endr + + adds x2, x2, x4 + adcs x2, x2, x5 + adcs x2, x2, x6 + adcs x2, x2, x7 + adcs x2, x2, x8 + adcs x2, x2, x9 + adcs x2, x2, x10 + adcs x2, x2, x11 + adc x2, x2, xzr + +CPU_LE( adds x12, x2, x12 ) +CPU_BE( adds x12, x2, x12, lsl #8 ) + adc x12, x12, xzr + tst x1, #1 + csel x2, x2, x12, eq + +7: lsr x1, x2, #32 + adds w2, w2, w1 + adc w2, w2, wzr + + lsr w1, w2, #16 + uxth w2, w2 + add w2, w2, w1 + + lsr w1, w2, #16 // handle the carry by hand + add w2, w2, w1 + + uxth w0, w2 + ret + + // Handle 63 bytes or less +1: tbz x1, #5, 2f + ldp x4, x5, [x0], #32 + ldp x6, x7, [x0, #-16] + adds x2, x2, x4 + adcs x2, x2, x5 + adcs x2, x2, x6 + adcs x2, x2, x7 + adc x2, x2, xzr + +2: tbz x1, #4, 3f + ldp x4, x5, [x0], #16 + adds x2, x2, x4 + adcs x2, x2, x5 + adc x2, x2, xzr + +3: tbz x1, #3, 4f + ldr x4, [x0], #8 + adds x2, x2, x4 + adc x2, x2, xzr + +4: tbz x1, #2, 5f + ldr w4, [x0], #4 + adds x2, x2, x4 + adc x2, x2, xzr + +5: tbz x1, #1, 6f + ldrh w4, [x0], #2 + adds x2, x2, x4 + adc x2, x2, xzr + +6: tbz x1, #0, 7b + ldrb w4, [x0] +CPU_LE( adds x2, x2, x4 ) +CPU_BE( adds x2, x2, x4, lsl #8 ) + adc x2, x2, xzr + b 7b +ENDPROC(do_csum) diff --git a/drivers/net/ethernet/al/al_eth.c b/drivers/net/ethernet/al/al_eth.c index 8038d58a9f64..db92783e6180 100644 --- a/drivers/net/ethernet/al/al_eth.c +++ b/drivers/net/ethernet/al/al_eth.c @@ -45,6 +45,7 @@ #include #include #include +#include "../../../gpio/gpiolib.h" #ifdef CONFIG_ARCH_ALPINE #include #include @@ -509,6 +510,19 @@ struct al_mod_eth_epe_control_entry parser_control_udp_dis_end_of_parse_entry = /* ports 1 & 3 are STD */ static const int eth_v4_adv_port_map[4] = {0, 2, 4, 5}; +const char *al_mod_gpio_of_names[AL_ETH_GPIO_MAX] = { + "mod-def0", + "los", + "tx-fault", + "tx-disable", +}; +const enum gpiod_flags al_mode_gpio_flags[AL_ETH_GPIO_MAX] = { + GPIOD_IN, + GPIOD_IN, + GPIOD_IN, + GPIOD_OUT_LOW, +}; + /** Forward declarations */ #ifdef CONFIG_ARCH_ALPINE static void al_mod_eth_serdes_mode_set(struct al_mod_eth_adapter *adapter); @@ -936,27 +950,60 @@ static int al_mod_eth_board_of_led(struct al_mod_eth_adapter *adapter, struct a return 0; } -static int al_mod_eth_board_of_sfp_probing(struct al_mod_eth_adapter *adapter, struct al_mod_eth_board_params* params, struct device_node *np) +static int al_mod_eth_board_of_lm(struct al_mod_eth_adapter *adapter, struct al_mod_eth_board_params* params, struct device_node *np) { - struct device_node *np_10g; - #define OF_NODE_NAME_10G "10g-serial" - #define OF_PROP_NAME_PROBE_1G "sfp_probe_1g" - #define OF_PROP_NAME_PROBE_10G "sfp_probe_10g" + int i = 0, rc; + struct gpio_desc *desc; + char of_gpio_name[32]; + enum of_gpio_flags; + struct device_node *np_lm; + #define OF_NODE_NAME_LM "link_manager" + #define OF_PROP_NAME_PROBE_1G "sfp-probe-1g" + #define OF_PROP_NAME_PROBE_10G "sfp-probe-10g" + #define OF_PROP_NAME_ELINK_DET "enhanced-link-detection" if (NULL == adapter || NULL == np || NULL == params) { return -EINVAL; } - np_10g = of_find_child_by_name(np, OF_NODE_NAME_10G); - if (!np_10g) { - netdev_dbg(adapter->netdev, "Unable to find matching node (%s)\n", OF_NODE_NAME_10G); + np_lm = of_find_child_by_name(np, OF_NODE_NAME_LM); + if (!np_lm) { + netdev_dbg(adapter->netdev, "Unable to find matching node (%s)\n", OF_NODE_NAME_LM); return -EINVAL; } - adapter->sfp_probe_1g = (of_property_match_string(np_10g, OF_PROP_NAME_PROBE_1G, "disabled") < 0); - adapter->sfp_probe_10g = (of_property_match_string(np_10g, OF_PROP_NAME_PROBE_10G, "disabled") < 0); + adapter->sfp_enhanced_link_detection = + !(of_property_match_string(np_lm, OF_PROP_NAME_ELINK_DET, "enabled") < 0); + + rc = 0; + for (i = 0; i < AL_ETH_GPIO_MAX; ++i) { + snprintf(of_gpio_name, sizeof(of_gpio_name), "%s-gpios", al_mod_gpio_of_names[i]); + + desc = gpiod_get_from_of_node(np_lm, of_gpio_name, 0, al_mode_gpio_flags[i], + al_mod_gpio_of_names[i]); + if (IS_ERR(desc)) + break; - of_node_put(np_10g); + adapter->sfp_gpio_list[i] = desc; + } + + if (IS_ERR(desc)) { + int err_idx = i; + pr_debug("Unable to get %s GPIO (rc %ld)\n", al_mod_gpio_of_names[i], PTR_ERR(desc)); + adapter->sfp_gpio_init = AL_FALSE; + if (err_idx) + for (i = 0; i < err_idx; ++i) + gpiod_put(adapter->sfp_gpio_list[i]); + + } else { + adapter->sfp_gpio_init = AL_TRUE; + pr_info("SFP GPIOs initialized successfully"); + } + + adapter->sfp_probe_1g = (of_property_match_string(np_lm, OF_PROP_NAME_PROBE_1G, "disabled") < 0); + adapter->sfp_probe_10g = (of_property_match_string(np_lm, OF_PROP_NAME_PROBE_10G, "disabled") < 0); + + of_node_put(np_lm); return 0; } @@ -997,6 +1044,8 @@ static void al_mod_eth_board_params_of_defaults(struct al_mod_eth_adapter *adapt adapter->sfp_probe_1g = true; adapter->sfp_probe_10g = true; + /* Disable enhanced link detection by default */ + adapter->sfp_enhanced_link_detection = false; } static int al_mod_eth_board_params_of_init(struct al_mod_eth_adapter *adapter, struct al_mod_eth_board_params* params) { @@ -1030,7 +1079,7 @@ static int al_mod_eth_board_params_of_init(struct al_mod_eth_adapter *adapter, s al_mod_eth_board_of_led(adapter, params, np_port); /* LM SFP probing */ - al_mod_eth_board_of_sfp_probing(adapter, params, np_port); + al_mod_eth_board_of_lm(adapter, params, np_port); /* Free resources */ of_node_put(np_port); @@ -6253,12 +6302,12 @@ static int al_mod_set_features(struct net_device *dev, #if defined(CONFIG_ARCH_ALPINE) static int al_mod_eth_i2c_data_read(void *context, uint8_t bus_id, uint8_t i2c_addr, uint8_t reg_addr, - uint8_t *val, size_t len, al_mod_bool seq) + uint8_t *val, size_t len, size_t block_size) { struct i2c_adapter *i2c_adapter; struct al_mod_eth_adapter *adapter = context; struct i2c_msg msgs[2] = { 0 }; - size_t i2c_ops_cnt; + size_t this_len; int rc = 0; msgs[0].addr = i2c_addr; @@ -6268,14 +6317,7 @@ static int al_mod_eth_i2c_data_read(void *context, uint8_t bus_id, uint8_t i2c_a msgs[1].addr = i2c_addr; msgs[1].flags = I2C_M_RD; msgs[1].buf = val; - - if (likely(seq)) { - msgs[1].len = len; - i2c_ops_cnt = 1; - } else { - msgs[1].len = 1; - i2c_ops_cnt = len; - } + msgs[1].len = len; i2c_adapter = i2c_get_adapter(bus_id); @@ -6288,48 +6330,49 @@ static int al_mod_eth_i2c_data_read(void *context, uint8_t bus_id, uint8_t i2c_a return -EINVAL; } - for (; i2c_ops_cnt--; msgs[1].buf++, reg_addr++) { + while (len) { + this_len = len; + if (this_len > block_size) + this_len = block_size; + + msgs[1].len = this_len; + if (i2c_transfer(i2c_adapter, msgs, ARRAY_SIZE(msgs)) != ARRAY_SIZE(msgs)) { netdev_dbg(adapter->netdev, "Failed to write sfp+ parameters\n"); rc = -ETIMEDOUT; break; } + + msgs[1].buf += this_len; + reg_addr += this_len; + len -= this_len; } i2c_put_adapter(i2c_adapter); return rc; } -static int al_mod_eth_i2c_data_write(void *context, uint8_t bus_id, uint8_t i2c_addr, uint8_t reg_addr, uint8_t *val, size_t len, al_mod_bool seq) +static int al_mod_eth_i2c_data_write(void *context, uint8_t bus_id, uint8_t i2c_addr, uint8_t reg_addr, uint8_t *val, size_t len, size_t block_size) { struct i2c_adapter *i2c_adapter; struct al_mod_eth_adapter *adapter = context; struct i2c_msg msgs[1] = { 0 }; - uint8_t data_s[2] = { 0 }, *data_d = NULL; - size_t i2c_ops_cnt; int rc = 0; msgs[0].addr = i2c_addr; msgs[0].flags = 0; - if (likely(seq)) { - data_d = kmalloc(1 + len, GFP_KERNEL); - if (NULL == data_d) { - netdev_err(adapter->netdev, "Unable to allocate i2c msg.\n"); - return -ENOMEM; - } - msgs[0].len = (1 + len); - msgs[0].buf = data_d; - i2c_ops_cnt = 1; - } else { - msgs[0].len = (1 + 1); - msgs[0].buf = &data_s[0]; - i2c_ops_cnt = len; + msgs[0].len = (1 + len); + msgs[0].buf = kmalloc(1 + len, GFP_KERNEL); + + if (NULL == msgs[0].buf) { + netdev_err(adapter->netdev, "Unable to allocate i2c msg.\n"); + return -ENOMEM; } i2c_adapter = i2c_get_adapter(bus_id); if (i2c_adapter == NULL) { - kfree(data_d); + kfree(msgs[0].buf); netdev_err( adapter->netdev, "Failed to get i2c adapter. " @@ -6338,40 +6381,30 @@ static int al_mod_eth_i2c_data_write(void *context, uint8_t bus_id, uint8_t i2c_ return -EINVAL; } - while (i2c_ops_cnt--) { - if (likely(seq)) { - /* sequential access*/ - msgs[0].buf[0] = reg_addr; - memcpy(&msgs[0].buf[1], val, len); - } else { - /* byte-per-byte access */ - msgs[0].buf[0] = reg_addr++; - msgs[0].buf[1] = *val++; - } + rc = i2c_transfer(i2c_adapter, msgs, ARRAY_SIZE(msgs)); - if (i2c_transfer(i2c_adapter, msgs, ARRAY_SIZE(msgs)) != ARRAY_SIZE(msgs)) { - netdev_dbg(adapter->netdev, "Failed to write sfp+ parameters\n"); - rc = -ETIMEDOUT; - break; - } - } + kfree(msgs[0].buf); i2c_put_adapter(i2c_adapter); - kfree(data_d); - return rc; + if (rc < 0) { + netdev_dbg(adapter->netdev, "Failed to write sfp+ parameters\n"); + return rc; + } + + return rc == ARRAY_SIZE(msgs) ? len : 0; } static int al_mod_eth_i2c_byte_read(void *context, uint8_t bus_id, uint8_t i2c_addr, uint8_t reg_addr, uint8_t *val) { - return al_mod_eth_i2c_data_read(context, bus_id, i2c_addr, reg_addr, val, 1, AL_TRUE); + return al_mod_eth_i2c_data_read(context, bus_id, i2c_addr, reg_addr, val, 1, 1); } static int al_mod_eth_i2c_byte_write(void *context, uint8_t bus_id, uint8_t i2c_addr, uint8_t reg_addr, uint8_t val) { - return al_mod_eth_i2c_data_write(context, bus_id, i2c_addr, reg_addr, &val, 1, AL_TRUE); + return al_mod_eth_i2c_data_write(context, bus_id, i2c_addr, reg_addr, &val, 1, 1); } static uint8_t al_mod_eth_get_rand_byte(void) @@ -6747,6 +6780,10 @@ static void al_mod_eth_lm_config(struct al_mod_eth_adapter *adapter) params.get_msec = al_mod_eth_systime_msec_get; params.led_config = &al_mod_eth_lm_led_config; + params.sfp_enhanced_link_detection = adapter->sfp_enhanced_link_detection; + params.sfp_gpio_init = adapter->sfp_gpio_init; + params.sfp_gpio_list = adapter->sfp_gpio_list; + if (adapter->gpio_sfp_present) { err = gpio_request_one(adapter->gpio_sfp_present, GPIOF_IN, "sfp_present"); if (err) { @@ -9767,6 +9804,12 @@ al_mod_eth_remove(struct pci_dev *pdev) struct al_mod_eth_adapter *adapter = pci_get_drvdata(pdev); struct net_device *dev = adapter->netdev; + if (adapter->sfp_gpio_init) { + int i; + for (i = 0; i < AL_ETH_GPIO_MAX; ++i) + gpiod_put(adapter->sfp_gpio_list[i]); + + } #ifdef CONFIG_ARCH_ALPINE /* * adapter->lm_context.lock was initialized in al_mod_eth_probe diff --git a/drivers/net/ethernet/al/al_eth.h b/drivers/net/ethernet/al/al_eth.h index 442eb45b9a75..c40392c070c0 100644 --- a/drivers/net/ethernet/al/al_eth.h +++ b/drivers/net/ethernet/al/al_eth.h @@ -656,6 +656,10 @@ struct al_mod_eth_adapter { unsigned int gpio_spd_10g; unsigned int gpio_spd_25g; unsigned int gpio_sfp_present; + /* enable enhanced SFP link detection */ + bool sfp_enhanced_link_detection; + al_mod_bool sfp_gpio_init; + struct gpio_desc *sfp_gpio_list[AL_ETH_GPIO_MAX]; al_mod_bool kr_fec_enable; struct work_struct reset_task; diff --git a/drivers/net/ethernet/al/al_mod_eth_sysfs.c b/drivers/net/ethernet/al/al_mod_eth_sysfs.c index 11680f8c0637..7a491239551a 100644 --- a/drivers/net/ethernet/al/al_mod_eth_sysfs.c +++ b/drivers/net/ethernet/al/al_mod_eth_sysfs.c @@ -256,6 +256,50 @@ static struct device_attribute dev_attr_sfp_probe_10g = { .store = al_mod_eth_store_sfp_probe_10g, }; +static ssize_t al_mod_eth_show_sfp_enhanced_link_detection(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct al_mod_eth_adapter *adapter = dev_get_drvdata(dev); + + if (NULL == adapter) { + dev_warn(dev, "%s drvdata are not initialized\n", __func__); + return -EINVAL; + } + + return sprintf(buf, "%d\n", !!adapter->sfp_enhanced_link_detection); +} + +static ssize_t al_mod_eth_store_sfp_enhanced_link_detection(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct al_mod_eth_adapter *adapter = dev_get_drvdata(dev); + unsigned long enable; + int err; + + if (NULL == adapter) { + dev_warn(dev, "%s drvdata are not initialized\n", __func__); + return -EINVAL; + } + + + err = kstrtoul(buf, 10, &enable); + if (err < 0) + return err; + + adapter->sfp_enhanced_link_detection = !!enable; + + if (adapter->up) + dev_warn(dev, "%s this action will take place in the next activation (up)\n", + __func__); + return len; +} + +static struct device_attribute dev_attr_sfp_enhanced_link_detection = { + .attr = { .name = "sfp_enhanced_link_detection", .mode = (S_IRUGO | S_IWUSR) }, + .show = al_mod_eth_show_sfp_enhanced_link_detection, + .store = al_mod_eth_store_sfp_enhanced_link_detection, +}; + static ssize_t al_mod_eth_store_force_1000_base_x(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) @@ -1306,6 +1350,9 @@ int al_mod_eth_sysfs_init( if (device_create_file(dev, &dev_attr_sfp_probe_10g)) dev_info(dev, "failed to create sfp_probe_10g sysfs entry"); + if (device_create_file(dev, &dev_attr_sfp_enhanced_link_detection)) + dev_info(dev, "failed to create dev_attr_sfp_enhanced_link_detection sysfs entry"); + if (device_create_file(dev, &dev_attr_force_1000_base_x)) dev_info(dev, "failed to create force_1000_base_x sysfs entry"); @@ -1428,6 +1475,7 @@ void al_mod_eth_sysfs_terminate( device_remove_file(dev, &dev_attr_link_training_enable); device_remove_file(dev, &dev_attr_sfp_probe_1g); device_remove_file(dev, &dev_attr_sfp_probe_10g); + device_remove_file(dev, &dev_attr_sfp_enhanced_link_detection); device_remove_file(dev, &dev_attr_force_1000_base_x); device_remove_file(dev, &dev_attr_intr_moderation_restore_default); device_remove_file(dev, &dev_attr_flow_steer_config); diff --git a/drivers/net/ethernet/al/al_mod_hal_eth_mac.h b/drivers/net/ethernet/al/al_mod_hal_eth_mac.h index e88c26b3d66a..0c36d75d73c6 100644 --- a/drivers/net/ethernet/al/al_mod_hal_eth_mac.h +++ b/drivers/net/ethernet/al/al_mod_hal_eth_mac.h @@ -930,6 +930,14 @@ struct al_mod_eth_mac_obj { al_mod_bool rx, al_mod_bool tx_start, al_mod_bool rx_start); + + /** + * check if 10GBase-KR is live and kicking. + * @param adapter pointer to the private structure. + * + * @return false if cannot detect 10GBase-KR medium is set. true otherwise + */ + int (*check_10g_base_kr)(struct al_mod_eth_mac_obj *obj); }; /** Ethernet MAC handle initialization parameters */ diff --git a/drivers/net/ethernet/al/al_mod_hal_eth_mac_v1_v2.c b/drivers/net/ethernet/al/al_mod_hal_eth_mac_v1_v2.c index a11abe65f80b..35c0384a92ef 100644 --- a/drivers/net/ethernet/al/al_mod_hal_eth_mac_v1_v2.c +++ b/drivers/net/ethernet/al/al_mod_hal_eth_mac_v1_v2.c @@ -591,6 +591,13 @@ static int link_status_get(struct al_mod_eth_mac_obj *obj, if ((reg & AL_BIT(5)) == 0) status->link_up = AL_FALSE; + + /* + * There is no interframe signalization for SGMII. + * Avoid using uninitialized values for local/remote fault. + */ + status->local_fault = AL_FALSE; + status->remote_fault = AL_FALSE; break; case AL_ETH_MAC_MODE_RGMII: diff --git a/drivers/net/ethernet/al/al_mod_hal_eth_mac_v3.c b/drivers/net/ethernet/al/al_mod_hal_eth_mac_v3.c index 4d54f044f645..1fe1c5fa9e59 100644 --- a/drivers/net/ethernet/al/al_mod_hal_eth_mac_v3.c +++ b/drivers/net/ethernet/al/al_mod_hal_eth_mac_v3.c @@ -1175,6 +1175,13 @@ static int link_status_get(struct al_mod_eth_mac_obj *obj, if ((reg & AL_BIT(5)) == 0) status->link_up = AL_FALSE; + /* + * There is no interframe signalization for SGMII. + * Avoid using uninitialized values for local/remote fault. + */ + status->local_fault = AL_FALSE; + status->remote_fault = AL_FALSE; + break; case AL_ETH_MAC_MODE_XLG_LL_25G: @@ -1494,6 +1501,18 @@ static void iofic_attrs_get_non_fatal(struct al_mod_eth_mac_obj *obj __attribute *mac_d_mask = 0; } +static int check_10g_base_kr(struct al_mod_eth_mac_obj *obj) +{ + struct al_mod_eth_mac_regs *mac_reg = obj->mac_regs_base; + uint32_t reg; + + al_mod_reg_write32(&mac_reg->kr.pcs_addr, ETH_MAC_KR_PCS_BASE_R_STATUS2); + reg = al_mod_reg_read32(&mac_reg->kr.pcs_data); + if (reg & AL_BIT(15)) + return 1; + return 0; +} + int al_mod_eth_mac_v3_handle_init(struct al_mod_eth_mac_obj *obj, __attribute__((unused)) struct al_mod_eth_mac_obj_init_params *params) { @@ -1524,6 +1543,7 @@ int al_mod_eth_mac_v3_handle_init(struct al_mod_eth_mac_obj *obj, obj->iofic_attrs_get_transient = iofic_attrs_get_transient; obj->iofic_attrs_get_non_fatal = iofic_attrs_get_non_fatal; obj->mac_start_stop_adv = mac_start_stop_adv; + obj->check_10g_base_kr = check_10g_base_kr; return 0; } diff --git a/drivers/net/ethernet/al/al_mod_init_eth_lm.c b/drivers/net/ethernet/al/al_mod_init_eth_lm.c index 4a30d4f51b6f..1a4680ff0845 100644 --- a/drivers/net/ethernet/al/al_mod_init_eth_lm.c +++ b/drivers/net/ethernet/al/al_mod_init_eth_lm.c @@ -46,6 +46,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "al_mod_serdes.h" #include "al_mod_hal_eth.h" #include "al_mod_init_eth_kr.h" +#include "al_mod_hal_eth_mac_regs.h" /* delay before checking link status with new serdes parameters (uSec) */ #define AL_ETH_LM_LINK_STATUS_DELAY 1000 @@ -64,6 +65,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define MODULE_IDENTIFIER_SFP 0x3 #define MODULE_IDENTIFIER_QSFP 0xd +#define SFP_DEFAULT_T_STARTUP (300) +#define SFP_OPTIONS_LOS_INVERTED BIT(2) +#define SFP_OPTIONS_LOS_NORMAL BIT(1) #define SFP_PRESENT 0 #define SFP_NOT_PRESENT 1 @@ -105,6 +109,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define SFP_SFF8472_LENGTH_FIELD_4_COPPER (4) +#define UF_SFP_POLLING_TIMEOUT 3500 + enum al_mod_eth_lm_step_detection_state { LM_STEP_DETECTION_INIT, LM_STEP_DETECTION_RETIMER_RX_ADAPT_WAIT, @@ -140,6 +146,8 @@ enum al_mod_eth_lm_step_retimer_wfl_state { static int retimer_full_config(struct al_mod_eth_lm_context *lm_context); static int al_mod_eth_lm_retimer_25g_rx_adaptation_step(struct al_mod_eth_lm_context *lm_context); +extern const enum gpiod_flags al_mode_gpio_flags[AL_ETH_GPIO_MAX]; +extern const char* al_mod_gpio_of_names[AL_ETH_GPIO_MAX]; struct _al_eth_lm_retimer { int (*rx_adaptation)(struct al_mod_eth_lm_context *lm_context); @@ -177,6 +185,99 @@ static inline al_mod_bool elapsed_time_msec(unsigned int current_time, return AL_FALSE; } +static unsigned int al_mod_eth_sfp_gpio_get_state(struct al_mod_eth_lm_context *lm_context) +{ + unsigned int i, state, v; + + for (i = 0, state = 0; i < AL_ETH_GPIO_MAX; ++i) { + if (al_mode_gpio_flags[i] != GPIOD_IN || !lm_context->sfp_gpio_list[i]) + continue; + v = gpiod_get_value_cansleep(lm_context->sfp_gpio_list[i]); + if (v) + state |= BIT(i); + } + + return state; +} + +static void al_mod_eth_sfp_gpio_state_update(struct al_mod_eth_lm_context *lm_context) +{ + unsigned int state, i, changed; + + state = al_mod_eth_sfp_gpio_get_state(lm_context); + + changed = state ^ lm_context->sfp_gpio_state; + changed &= SFP_F_PRESENT | SFP_F_LOS | SFP_F_TX_FAULT; + + for (i = 0; i < AL_ETH_GPIO_MAX; i++) + if (changed & BIT(i)) + lm_debug("%s:%s %u -> %u\n", __func__, al_mod_gpio_of_names[i], + !!(lm_context->sfp_gpio_state & BIT(i)), !!(state & BIT(i))); + + state |= lm_context->sfp_gpio_state & SFP_F_TX_DISABLE; + lm_context->sfp_gpio_state = state; +} + +static bool al_mod_eth_sfp_los_check_los(struct al_mod_eth_lm_context *lm_context) +{ + const __be16 los_inverted = cpu_to_be16(SFP_OPTIONS_LOS_INVERTED); + const __be16 los_normal = cpu_to_be16(SFP_OPTIONS_LOS_NORMAL); + __be16 los_options; + bool los = false; + + do { + if (!lm_context->sfp_id_valid) + break; + + mutex_lock(&lm_context->lock); + los_options = lm_context->sfp_id.ext.options & (los_inverted | los_normal); + mutex_unlock(&lm_context->lock); + + /* + * If neither SFP_OPTIONS_LOS_INVERTED nor SFP_OPTIONS_LOS_NORMAL + * are set, we assume that no LOS signal is available. If both are + * set, we assume LOS is not implemented (and is meaningless.) + */ + if (los_options == los_inverted) + los = !(lm_context->sfp_gpio_state & SFP_F_LOS); + else if (los_options == los_normal) + los = !!(lm_context->sfp_gpio_state & SFP_F_LOS); + + } while (0); + + return los; +} + +static int al_mod_eth_lm_link_status_get(struct al_mod_eth_lm_context *lm_context, + struct al_mod_eth_link_status *status) +{ + int rc; + + rc = al_mod_eth_link_status_get(lm_context->adapter, status); + if (rc) { + al_mod_err("%s: Error getting link status from MAC\n", __func__); + return rc; + } + + if (lm_context->sfp_enhanced_link_detection) { + if (lm_context->sfp_gpio_init) { + al_mod_eth_sfp_gpio_state_update(lm_context); + lm_debug("check_los %d los %d txfault %d det %d", + al_mod_eth_sfp_los_check_los(lm_context), + !!(lm_context->sfp_gpio_state & SFP_F_LOS), + !!(lm_context->sfp_gpio_state & SFP_F_TX_FAULT), + !!(lm_context->sfp_gpio_state & SFP_F_PRESENT)); + + status->remote_fault |= al_mod_eth_sfp_los_check_los(lm_context); + status->local_fault |= !!(lm_context->sfp_gpio_state & SFP_F_TX_FAULT); + } + } + + lm_debug("remote_fault %d local_fault %d link %d", !!status->remote_fault, + !!status->local_fault, !!status->link_up); + return 0; +} + static unsigned int al_mod_eth_sfp_crc(void *buf, size_t len) { uint8_t *p, check; @@ -187,6 +288,19 @@ static unsigned int al_mod_eth_sfp_crc(void *buf, size_t len) return check; } +static bool al_mod_eth_sfp_is_10GBaseT(struct sfp_eeprom_id *id) +{ + const char *UF_RJ45_10G = "UF-RJ45-10G"; + + if (id->base.br_nominal == 103) { + if (id->base.connector == SFP_CONNECTOR_RJ45) + return true; + if (!memcmp(id->base.vendor_pn, UF_RJ45_10G, strlen(UF_RJ45_10G))) + return true; // UBNT SFP EEPROM broken as usual + } + return false; +} + static bool al_mod_eth_sfp_is_10g(struct sfp_eeprom_id *id) { return (id->base.e10g_base_er || id->base.e10g_base_lrm || id->base.e10g_base_lr || @@ -216,19 +330,34 @@ static bool al_mod_eth_sfp_is_1g(struct sfp_eeprom_id *id) return false; } +static inline unsigned long al_mod_eth_sfp_quirk_flags_get(struct al_mod_eth_lm_context *lm_context) +{ + unsigned long sfp_quirk_flags = 0; + + al_mod_assert(lm_context); + + mutex_lock(&lm_context->lock); + sfp_quirk_flags = lm_context->sfp_quirk_flags; + mutex_unlock(&lm_context->lock); + + return sfp_quirk_flags; +} + static int al_mod_eth_sfp_mii_read(struct al_mod_eth_lm_context *lm_context, int addr, uint16_t *val) { uint8_t data[2] = {0}; int rc = 0; + unsigned long sfp_quirk_flags = 0; al_mod_assert(val); al_mod_assert(lm_context); al_mod_assert(lm_context->i2c_read_data); - rc = lm_context->i2c_read_data( - lm_context->i2c_context, lm_context->sfp_bus_id, SFP_I2C_ADDR_PHY, addr, data, - sizeof(data), - !test_bit(AL_MOD_SFP_QUIRK_NO_SEQ_READING, &lm_context->sfp_quirk_flags)); + sfp_quirk_flags = al_mod_eth_sfp_quirk_flags_get(lm_context); + + rc = lm_context->i2c_read_data(lm_context->i2c_context, lm_context->sfp_bus_id, + SFP_I2C_ADDR_PHY, addr, data, sizeof(data), + lm_context->sfp_i2c_block_size); if (rc) return rc; @@ -258,62 +387,91 @@ static int al_mod_eth_sfp_phy_id(struct al_mod_eth_lm_context *lm_context, int * *phy_id |= phy_reg; return 0; } -static const struct al_mod_sfp_fixup_entry al_mod_sfp_fixup_list[] = { -#define X(_pn, _sfp_quirk_flags, _delay_init_s) \ - { .pn = _pn, .sfp_quirk_flags = _sfp_quirk_flags, .delay_init_s = _delay_init_s }, +static const struct al_mod_sfp_quirk_entry al_mod_sfp_fixup_list[] = { +#define X(_pn, _flags, _delay_init_ms) \ + { .pn = _pn, .flags = _flags, .delay_init_ms = _delay_init_ms }, AL_MOD_SFP_FIXUP_LIST(X) #undef X }; +static bool al_mod_eth_sfp_needs_byte_io(struct al_mod_eth_lm_context *lm_context, void *buf, size_t len) +{ + size_t i, block_size = lm_context->sfp_i2c_block_size; + + /* Already using byte IO */ + if (block_size == 1) + return false; + + for (i = 1; i < len; i += block_size) { + if (memchr_inv(buf + i, '\0', min(block_size - 1, len - i))) + return false; + } + return true; +} + static int al_mod_eth_sfp_detect(struct al_mod_eth_lm_context *lm_context, enum al_mod_eth_lm_link_mode *new_mode) { /* SFP module inserted - read I2C data */ + const char *uc_dac_sfp_pn = "UC-DAC-SFP+"; + const char *uf_rj45_1g_sfp_pn = "UF-RJ45-1G"; struct sfp_eeprom_id id; uint8_t cc = 0; int rc = 0, phy_id, i; - uint32_t sfp_quirk_flags = 0; + unsigned long sfp_quirk_flags = 0; + const struct al_mod_sfp_quirk_entry *sfp_quirk = NULL; + unsigned sfp_t_start_ms; + al_mod_assert(lm_context->i2c_read_data); lm_context->sfp_has_phyreg = AL_FALSE; + /* + * Some SFP modules and also some Linux I2C drivers do not like reads + * longer than 16 bytes, so read the EEPROM in chunks of 16 bytes at + * a time. + */ + lm_context->sfp_i2c_block_size = SFP_I2C_MAX_BLOCK_SIZE; + do { rc = lm_context->i2c_read_data(lm_context->i2c_context, lm_context->sfp_bus_id, - lm_context->sfp_i2c_addr, - offsetof(struct sfp_eeprom_base, vendor_pn), - (uint8_t *)&id.base.vendor_pn, - sizeof(id.base.vendor_pn), AL_FALSE); + lm_context->sfp_i2c_addr, 0, (uint8_t *)&id.base, + sizeof(id.base), lm_context->sfp_i2c_block_size); if (rc) break; + if (al_mod_eth_sfp_needs_byte_io(lm_context, &id.base, sizeof(id.base))) { + lm_debug("%s: Switching to reading EEPROM to one byte at a time", __func__); + + lm_context->sfp_i2c_block_size = 1; + + rc = lm_context->i2c_read_data(lm_context->i2c_context, + lm_context->sfp_bus_id, + lm_context->sfp_i2c_addr, 0, + (uint8_t *)&id.base, sizeof(id.base), + lm_context->sfp_i2c_block_size); + if (rc) + break; + } + lm_debug("%s: SFP detected (PN \"%.*s\")", __func__, (int)sizeof(id.base.vendor_pn), id.base.vendor_pn); for (i = 0; i < ARRAY_SIZE(al_mod_sfp_fixup_list); ++i) { if (!strncmp(id.base.vendor_pn, al_mod_sfp_fixup_list[i].pn, strlen(al_mod_sfp_fixup_list[i].pn))) { - sfp_quirk_flags = al_mod_sfp_fixup_list[i].sfp_quirk_flags; - /* delay init by n seconds - some modules need this */ - msleep(al_mod_sfp_fixup_list[i].delay_init_s * 1000); + sfp_quirk = &al_mod_sfp_fixup_list[i]; + sfp_quirk_flags = sfp_quirk->flags; break; } } - mutex_lock(&lm_context->lock); - lm_context->sfp_quirk_flags = sfp_quirk_flags; - mutex_unlock(&lm_context->lock); - - /* continue detection */ - rc = lm_context->i2c_read_data( - lm_context->i2c_context, lm_context->sfp_bus_id, lm_context->sfp_i2c_addr, - 0, (uint8_t *)&id, sizeof(id), - !test_bit(AL_MOD_SFP_QUIRK_NO_SEQ_READING, &lm_context->sfp_quirk_flags)); - if (rc) - break; + sfp_t_start_ms = (sfp_quirk && sfp_quirk->delay_init_ms > 0) ? + sfp_quirk->delay_init_ms : + SFP_DEFAULT_T_STARTUP; cc = al_mod_eth_sfp_crc(&id.base, sizeof(id.base) - 1); if (cc != id.base.cc_base) { - const char *uc_dac_sfp_pn = "UC-DAC-SFP+"; lm_debug("%s: EEPROM base structure checksum failure (0x%02x != 0x%02x)", __func__, cc, id.base.cc_base); /** @@ -330,25 +488,51 @@ static int al_mod_eth_sfp_detect(struct al_mod_eth_lm_context *lm_context, /* Set len to 1 meter */ id.base.link_len[SFP_SFF8472_LENGTH_FIELD_4_COPPER] = 1; /* As data are faulty, deny the access to EEPROM */ - lm_context->sfp_quirk_flags |= + sfp_quirk_flags |= BIT(AL_MOD_SFP_QUIRK_NO_EEPROM_ACCESS); break; } } + rc = lm_context->i2c_read_data(lm_context->i2c_context, lm_context->sfp_bus_id, + lm_context->sfp_i2c_addr, + offsetof(struct sfp_eeprom_id, ext), + (uint8_t *)&id.ext, sizeof(id.ext), + lm_context->sfp_i2c_block_size); + if (rc) + break; + cc = al_mod_eth_sfp_crc(&id.ext, sizeof(id.ext) - 1); if (cc != id.ext.cc_ext) { lm_debug("%s: EEPROM extended structure checksum failure: 0x%02x != 0x%02x", __func__, cc, id.ext.cc_ext); memset(&id.ext, 0, sizeof(id.ext)); } + /* + * UF-RJ45-1G's EEPROM shows no support for LOS, but PHY fully supports + * it. Fix LOS option for UF-RJ45-1G to get better link detection. + */ + if (!strncmp(id.base.vendor_pn, uf_rj45_1g_sfp_pn, + strlen(uf_rj45_1g_sfp_pn)) && !id.ext.options) { + id.ext.options |= cpu_to_be16(SFP_OPTIONS_LOS_NORMAL); + } - if (!test_bit(AL_MOD_SFP_QUIRK_NO_PHY_DETECTION, &lm_context->sfp_quirk_flags) && - !al_mod_eth_sfp_phy_id(lm_context, &phy_id)) { + if (test_bit(AL_MOD_SFP_QUIRK_ENHANCED_LINK_DETECTION, + &sfp_quirk_flags)) { + lm_context->sfp_enhanced_link_detection = true; + } else { + lm_context->sfp_enhanced_link_detection = + lm_context->sfp_enhanced_link_detection_default; + } + + /* Note: Keep PHY ID reading for debugging purposes */ + if (lm_context->debug && !al_mod_eth_sfp_phy_id(lm_context, &phy_id)) { lm_debug("%s: SFP module has PHY with ID 0x%08x", __func__, phy_id); - lm_context->sfp_has_phyreg = AL_TRUE; } + + /* t_init/t_start_up (SFF-8472/SFF-8431) delay in ms */ + msleep(sfp_t_start_ms); } while (0); if (rc) { @@ -380,6 +564,59 @@ static int al_mod_eth_sfp_detect(struct al_mod_eth_lm_context *lm_context, } /* for active direct attached need to use len 0 in the retimer configuration */ lm_context->da_len = (id.base.sfp_ct_passive) ? id.base.link_len[SFP_SFF8472_LENGTH_FIELD_4_COPPER] : 0; + } else if (lm_context->sfp_probe_10g && al_mod_eth_sfp_is_10GBaseT(&id)) { + struct al_mod_eth_mac_obj *mac_obj = &lm_context->adapter->mac_obj; + struct al_mod_eth_link_status status; + unsigned long diff; + + /* When we connect 10G module to 1G interface, bit-15 gets + * cleared (most likely bit indicated established 10G-KR link). + * It's set when cable's dangling or connected to 10G-KR medium. + * Note: bit-15 logic stolen from: link_status_get(). + */ + switch (lm_context->mode) { + case AL_ETH_LM_MODE_10G_OPTIC: + *new_mode = AL_ETH_LM_MODE_10G_OPTIC; + + if (!mac_obj->check_10g_base_kr) + break; // not supported + + if (mac_obj->check_10g_base_kr(mac_obj)) { + lm_context->RJ45_10G_jiffies = jiffies; + } else { + diff = jiffies - lm_context->RJ45_10G_jiffies; + if (jiffies_to_msecs(diff) > UF_SFP_POLLING_TIMEOUT) { + *new_mode = AL_ETH_LM_MODE_1G; + lm_context->RJ45_10G_jiffies = jiffies; + } + } + break; + case AL_ETH_LM_MODE_1G: + *new_mode = AL_ETH_LM_MODE_1G; + + rc = al_mod_eth_lm_link_status_get(lm_context, &status); + if (rc || !status.local_fault || !status.remote_fault) { + diff = jiffies - lm_context->RJ45_10G_jiffies; + if (jiffies_to_msecs(diff) > UF_SFP_POLLING_TIMEOUT) { + *new_mode = AL_ETH_LM_MODE_10G_OPTIC; + lm_context->RJ45_10G_jiffies = jiffies; + } + } else { + lm_context->RJ45_10G_jiffies = jiffies; + } + break; + default: + lm_context->RJ45_10G_jiffies = jiffies; + *new_mode = AL_ETH_LM_MODE_10G_OPTIC; + break; + } + + if (lm_context->mode == AL_ETH_LM_MODE_DISCONNECTED) { + if (*new_mode == AL_ETH_LM_MODE_1G) + lm_debug("%s: 1G SGMII detected\n", __func__); + else + lm_debug("%s: 10G-KR detected\n", __func__); + } } else if (lm_context->sfp_probe_10g && al_mod_eth_sfp_is_10g(&id)) { *new_mode = AL_ETH_LM_MODE_10G_OPTIC; if ((lm_context->mode != *new_mode) && @@ -416,6 +653,10 @@ static int al_mod_eth_sfp_detect(struct al_mod_eth_lm_context *lm_context, mutex_lock(&lm_context->lock); lm_context->sfp_id = id; + lm_context->sfp_quirk = sfp_quirk; + lm_context->sfp_quirk_flags = sfp_quirk_flags; + lm_context->sfp_id_valid = AL_TRUE; + if (*new_mode != AL_ETH_LM_MODE_DISCONNECTED) { if (lm_context->link_conf.speed > SPEED_10 && lm_context->link_conf.speed <= SPEED_1000) { @@ -427,12 +668,11 @@ static int al_mod_eth_sfp_detect(struct al_mod_eth_lm_context *lm_context, lm_context->mode = *new_mode; lm_debug( - "%s: (mode %s) SFP inserted -> Vendor:%.*s,PN:%.*s, REV:%.*s, SERIAL:%.*s PHY : %s quirks : %x", + "%s: (mode %s) SFP inserted -> Vendor:%.*s,PN:%.*s, REV:%.*s, SERIAL:%.*s, quirks : %lx", __func__, al_mod_eth_lm_mode_convert_to_str(lm_context->mode), (int)sizeof(id.base.vendor_name), id.base.vendor_name, (int)sizeof(id.base.vendor_pn), id.base.vendor_pn, (int)sizeof(id.base.vendor_rev), - id.base.vendor_rev, (int)sizeof(id.ext.vendor_sn), id.ext.vendor_sn, - lm_context->sfp_has_phyreg ? "yes" : "no", lm_context->sfp_quirk_flags); + id.base.vendor_rev, (int)sizeof(id.ext.vendor_sn), id.ext.vendor_sn, sfp_quirk_flags); mutex_unlock(&lm_context->lock); @@ -507,32 +747,38 @@ static int al_mod_eth_module_detect(struct al_mod_eth_lm_context *lm_context, al_mod_bool use_gpio_present = AL_FALSE; al_mod_bool bounce_detected = AL_FALSE; - if ((lm_context->gpio_get) && (lm_context->gpio_present != 0)) { - int sfp_present_debounce; - - use_gpio_present = AL_TRUE; - sfp_present = lm_context->gpio_get(lm_context->gpio_present); - for (i = 0; i < SFP_PRESENT_GPIO_DEBOUNCE_ITERS; i++) { - al_mod_udelay(1); - sfp_present_debounce = lm_context->gpio_get(lm_context->gpio_present); - if (sfp_present_debounce != sfp_present) { - bounce_detected = AL_TRUE; - break; + if (lm_context->sfp_gpio_init) { + al_mod_eth_sfp_gpio_state_update(lm_context); + sfp_present = !!(lm_context->sfp_gpio_state & SFP_F_PRESENT) ? SFP_PRESENT : + SFP_NOT_PRESENT; + } else { + if ((lm_context->gpio_get) && (lm_context->gpio_present != 0)) { + int sfp_present_debounce; + + use_gpio_present = AL_TRUE; + sfp_present = lm_context->gpio_get(lm_context->gpio_present); + for (i = 0; i < SFP_PRESENT_GPIO_DEBOUNCE_ITERS; i++) { + al_mod_udelay(1); + sfp_present_debounce = lm_context->gpio_get(lm_context->gpio_present); + if (sfp_present_debounce != sfp_present) { + bounce_detected = AL_TRUE; + break; + } } } - } - if (bounce_detected) { - *new_mode = lm_context->mode; + if (bounce_detected) { + *new_mode = lm_context->mode; - return 0; + return 0; + } } if (sfp_present == SFP_NOT_PRESENT) { if (lm_context->mode != AL_ETH_LM_MODE_DISCONNECTED) lm_debug("%s: SFP not present\n", __func__); *new_mode = AL_ETH_LM_MODE_DISCONNECTED; - + lm_context->sfp_id_valid = AL_FALSE; return 0; } else if (use_gpio_present && lm_context->sfp_detect_force_mode) { if (lm_context->mode == AL_ETH_LM_MODE_DISCONNECTED) @@ -1129,36 +1375,17 @@ static int al_mod_eth_lm_retimer_25g_rx_adaptation_step(struct al_mod_eth_lm_con static int al_mod_eth_lm_check_for_link(struct al_mod_eth_lm_context *lm_context, al_mod_bool *link_up) { - struct al_mod_eth_link_status status; + struct al_mod_eth_link_status status = {0}; int ret = 0; - uint16_t mii_bmsr = 0; al_mod_eth_link_status_clear(lm_context->adapter); - al_mod_eth_link_status_get(lm_context->adapter, &status); - - if(lm_context->sfp_has_phyreg) { - /* Read link and autonegotiation status */ - ret = al_mod_eth_sfp_mii_read(lm_context, MII_BMSR, &mii_bmsr); - if(ret) { - lm_debug("%s: unable to read MII_BMSR\n", __func__); - return ret; - } - status.link_up = status.link_up && (mii_bmsr & BMSR_LSTATUS); - lm_debug("%s: >>>> PHY link state %s autoneg %s\n", __func__, - (mii_bmsr & BMSR_LSTATUS) ? "UP" : "DOWN", - (mii_bmsr & BMSR_ANEGCOMPLETE) ? "DONE" : "IN PROGRESS"); - } - - if (status.link_up == AL_TRUE) { - lm_debug("%s: >>>> Link state DOWN ==> UP\n", __func__); - al_mod_eth_led_set(lm_context->adapter, AL_TRUE); - lm_context->link_state = AL_ETH_LM_LINK_UP; - *link_up = AL_TRUE; + al_mod_eth_lm_link_status_get(lm_context, &status); - return 0; - } else if (status.local_fault) { + if (!lm_context->sfp_enhanced_link_detection && status.link_up == AL_TRUE) { + goto link_is_up; + } else if (status.local_fault) { + lm_debug("%s: >>>> Link state DOWN\n", __func__); lm_context->link_state = AL_ETH_LM_LINK_DOWN; - al_mod_eth_led_set(lm_context->adapter, AL_FALSE); /* TODO -> EOSN-385 * if ((lm_context->mode == AL_ETH_LM_MODE_25G) && lm_context->auto_fec_enable) * lm_debug("%s: Failed to establish link\n", __func__); @@ -1166,16 +1393,30 @@ static int al_mod_eth_lm_check_for_link(struct al_mod_eth_lm_context *lm_context * al_mod_err("%s: Failed to establish link\n", __func__); */ ret = -1; - } else { + } else if (status.remote_fault) { lm_debug("%s: >>>> Link state DOWN ==> DOWN_RF\n", __func__); lm_context->link_state = AL_ETH_LM_LINK_DOWN_RF; - al_mod_eth_led_set(lm_context->adapter, AL_FALSE); - ret = 0; + } else if (status.link_up == AL_TRUE) { + goto link_is_up; + } else { + lm_debug("%s: >>>> Link state DOWN\n", __func__); + lm_context->link_state = AL_ETH_LM_LINK_DOWN; + ret = -1; } + /* Link is down */ + al_mod_eth_led_set(lm_context->adapter, AL_FALSE); *link_up = AL_FALSE; return ret; + +link_is_up: + lm_debug("%s: >>>> Link state DOWN ==> UP\n", __func__); + lm_context->link_state = AL_ETH_LM_LINK_UP; + al_mod_eth_led_set(lm_context->adapter, AL_TRUE); + *link_up = AL_TRUE; + + return 0; } static int al_mod_eth_lm_link_state_check_for_detection(struct al_mod_eth_lm_context *lm_context, @@ -1184,37 +1425,44 @@ static int al_mod_eth_lm_link_state_check_for_detection(struct al_mod_eth_lm_con { switch (lm_context->link_state) { case AL_ETH_LM_LINK_UP: - al_mod_eth_link_status_get(lm_context->adapter, status); + al_mod_eth_lm_link_status_get(lm_context, status); - if (status->link_up) { + if (!lm_context->sfp_enhanced_link_detection && status->link_up) { if (link_fault) *link_fault = AL_FALSE; - al_mod_eth_led_set(lm_context->adapter, AL_TRUE); - return 0; } else if (status->local_fault) { lm_debug("%s: >>>> Link state UP ==> DOWN\n", __func__); lm_context->link_state = AL_ETH_LM_LINK_DOWN; - } else { + } else if (status->remote_fault) { lm_debug("%s: >>>> Link state UP ==> DOWN_RF\n", __func__); lm_context->link_state = AL_ETH_LM_LINK_DOWN_RF; - } + } else if (status->link_up) { + if (link_fault) + *link_fault = AL_FALSE; + return 0; + } else { + lm_context->link_state = AL_ETH_LM_LINK_DOWN; + } break; case AL_ETH_LM_LINK_DOWN_RF: - al_mod_eth_link_status_get(lm_context->adapter, status); + al_mod_eth_lm_link_status_get(lm_context, status); if (status->local_fault) { lm_debug("%s: >>>> Link state DOWN_RF ==> DOWN\n", __func__); lm_context->link_state = AL_ETH_LM_LINK_DOWN; break; - } else if (status->remote_fault == AL_FALSE) { + } else if (status->remote_fault == AL_FALSE && status->link_up) { lm_debug("%s: >>>> Link state DOWN_RF ==> UP\n", __func__); lm_context->link_state = AL_ETH_LM_LINK_UP; + } else if (status->remote_fault) { + /* in case of remote fault only no need to check SFP again */ + } else { + lm_context->link_state = AL_ETH_LM_LINK_DOWN; } - /* in case of remote fault only no need to check SFP again */ return 0; case AL_ETH_LM_LINK_DOWN: break; @@ -1292,10 +1540,15 @@ static int al_mod_eth_lm_retimer_i2c_write(void *i2c_context, int al_mod_eth_lm_get_module_info(struct al_mod_eth_lm_context *lm_context, struct ethtool_modinfo *modinfo) { + unsigned long sfp_quirk_flags = 0; + al_mod_assert(lm_context); al_mod_assert(modinfo); - if (test_bit(AL_MOD_SFP_QUIRK_NO_EEPROM_ACCESS, &lm_context->sfp_quirk_flags)) { + sfp_quirk_flags = al_mod_eth_sfp_quirk_flags_get(lm_context); + + if (test_bit(AL_MOD_SFP_QUIRK_NO_EEPROM_ACCESS, &sfp_quirk_flags) || + !lm_context->sfp_id_valid) { modinfo->eeprom_len = 0; return 0; } @@ -1319,6 +1572,7 @@ int al_mod_eth_lm_get_module_eeprom(struct al_mod_eth_lm_context *lm_context, unsigned int first, last, len; int rc; + unsigned long sfp_quirk_flags = 0; al_mod_assert(lm_context); al_mod_assert(eeprom); @@ -1328,10 +1582,12 @@ int al_mod_eth_lm_get_module_eeprom(struct al_mod_eth_lm_context *lm_context, if (eeprom->len == 0) return -EINVAL; - if (test_bit(AL_MOD_SFP_QUIRK_NO_EEPROM_ACCESS, &lm_context->sfp_quirk_flags)) { + sfp_quirk_flags = al_mod_eth_sfp_quirk_flags_get(lm_context); + + if (test_bit(AL_MOD_SFP_QUIRK_NO_EEPROM_ACCESS, &sfp_quirk_flags)) { return 0; } - + memset(data, 0, eeprom->len); first = eeprom->offset; @@ -1341,8 +1597,7 @@ int al_mod_eth_lm_get_module_eeprom(struct al_mod_eth_lm_context *lm_context, len -= first; rc = lm_context->i2c_read_data(lm_context->i2c_context, lm_context->sfp_bus_id, SFP_I2C_ADDR, first, data, len, - !test_bit(AL_MOD_SFP_QUIRK_NO_SEQ_READING, - &lm_context->sfp_quirk_flags)); + lm_context->sfp_i2c_block_size); if (rc) return rc; @@ -1355,8 +1610,7 @@ int al_mod_eth_lm_get_module_eeprom(struct al_mod_eth_lm_context *lm_context, first -= ETH_MODULE_SFF_8079_LEN; rc = lm_context->i2c_read_data(lm_context->i2c_context, lm_context->sfp_bus_id, SFP_I2C_ADDR_A2, first, data, len, - !test_bit(AL_MOD_SFP_QUIRK_NO_SEQ_READING, - &lm_context->sfp_quirk_flags)); + lm_context->sfp_i2c_block_size); if (rc) return rc; } @@ -1494,7 +1748,13 @@ int al_mod_eth_lm_init(struct al_mod_eth_lm_context *lm_context, mutex_init(&lm_context->lock); #endif lm_context->sfp_has_phyreg = AL_FALSE; + lm_context->sfp_quirk = NULL; lm_context->sfp_quirk_flags = 0; + lm_context->sfp_i2c_block_size = SFP_I2C_MAX_BLOCK_SIZE; + lm_context->sfp_enhanced_link_detection_default = + params->sfp_enhanced_link_detection; + lm_context->sfp_gpio_init = params->sfp_gpio_init; + lm_context->sfp_gpio_list = params->sfp_gpio_list; return 0; } @@ -2169,24 +2429,30 @@ int al_mod_eth_lm_link_check(struct al_mod_eth_lm_context *lm_context, struct al_mod_eth_link_status status; int rc; - rc = al_mod_eth_link_status_get(lm_context->adapter, &status); + rc = al_mod_eth_lm_link_status_get(lm_context, &status); if (rc) { al_mod_err("%s: Error getting link status from MAC\n", __func__); return rc; } - if (status.link_up) + if (!lm_context->sfp_enhanced_link_detection && status.link_up) *link_state = AL_ETH_LM_LINK_UP; else if (status.local_fault) *link_state = AL_ETH_LM_LINK_DOWN; else if (status.remote_fault) *link_state = AL_ETH_LM_LINK_DOWN_RF; + else if (status.link_up) + *link_state = AL_ETH_LM_LINK_UP; else { - al_mod_err("%s: Invalid link state!\n", __func__); + /** + * SGMII mode doesn't support such thing as local/remote fault detection + * thus this is completely VALID state. Set link_state to AL_ETH_LM_LINK_DOWN. + */ + *link_state = AL_ETH_LM_LINK_DOWN; return -EIO; } - al_mod_dbg("%s: link_state is %s\n", __func__, + lm_debug("%s: link_state is %s\n", __func__, ((*link_state == AL_ETH_LM_LINK_DOWN) ? "DOWN" : ((*link_state == AL_ETH_LM_LINK_DOWN_RF) ? "DOWN_RF" : ((*link_state == AL_ETH_LM_LINK_UP) ? "UP" : "UNKNOWN")))); diff --git a/drivers/net/ethernet/al/al_mod_init_eth_lm.h b/drivers/net/ethernet/al/al_mod_init_eth_lm.h index d182648eac4a..d41ea497c834 100644 --- a/drivers/net/ethernet/al/al_mod_init_eth_lm.h +++ b/drivers/net/ethernet/al/al_mod_init_eth_lm.h @@ -103,15 +103,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define __AL_INIT_ETH_LM_H__ #include +#include +#include #include "al_mod_serdes.h" #include "al_mod_hal_eth.h" #include "al_mod_init_eth_kr.h" #include "al_mod_eth_lm_retimer.h" -#define SFP_I2C_ADDR (0xA0 >> 1) +#define SFP_I2C_ADDR (0xA0 >> 1) #define SFP_I2C_ADDR_A2 (0xA2 >> 1) -#define SFP_I2C_ADDR_PHY (0xAC >> 1) +#define SFP_I2C_ADDR_PHY (0xAC >> 1) +#define SFP_I2C_MAX_BLOCK_SIZE (16) + +/* Similar to GPIO enum in drivers/net/phy/sfp.c */ +enum al_mod_sfp_gpio { + AL_ETH_GPIO_MODDEF0 = 0,/* GPIO_OPTDET_N */ + AL_ETH_GPIO_LOS, /* GPIO_OPRX_LOS */ + AL_ETH_GPIO_TX_FAULT, /* GPIO_OPTX_FAULT */ + AL_ETH_GPIO_TX_DISABLE, /* GPIO_OPTX_DIS */ + AL_ETH_GPIO_MAX, + + SFP_F_PRESENT = BIT(AL_ETH_GPIO_MODDEF0), + SFP_F_LOS = BIT(AL_ETH_GPIO_LOS), + SFP_F_TX_FAULT = BIT(AL_ETH_GPIO_TX_FAULT), + SFP_F_TX_DISABLE = BIT(AL_ETH_GPIO_TX_DISABLE), +}; enum al_mod_eth_lm_link_mode { AL_ETH_LM_MODE_DISCONNECTED, @@ -164,42 +181,6 @@ enum al_mod_eth_lm_sfp_probe_type { AL_ETH_LM_SFP_PROBE_10G, }; -/** - * @brief List of quirks - */ -enum al_mod_sfp_quirks_e { - /* module does not support sequential reading */ - AL_MOD_SFP_QUIRK_NO_SEQ_READING = 0, - /* limit access to module's EEPROM */ - AL_MOD_SFP_QUIRK_NO_EEPROM_ACCESS, - /* skip PHY detection */ - AL_MOD_SFP_QUIRK_NO_PHY_DETECTION, - AL_MOD_SFP_QUIRK_COUNT -}; - -struct al_mod_sfp_fixup_entry { - const char *pn; - const unsigned long sfp_quirk_flags; - const int delay_init_s; -}; - -/** - * @brief List of modules with quirks - * - * UF-INSTANT - doesn't support sequential reading - * Alcatel 3FE46541AA & Huawei MA5671A & Alcatel Lucent G-010S-P - periodic reading of eeprom leads to jamming i2c bus - * VSOL 1GE (SFP) ONU - doesn't support sequential reading - * - * X (product number, quirk flags, number of seconds to delay SFP initialization) - */ -#define AL_MOD_SFP_FIXUP_LIST(X) \ - X("MA5671A", BIT(AL_MOD_SFP_QUIRK_NO_EEPROM_ACCESS), 10) \ - X("3FE46541AA", BIT(AL_MOD_SFP_QUIRK_NO_EEPROM_ACCESS), 10) \ - X("G010SP", BIT(AL_MOD_SFP_QUIRK_NO_EEPROM_ACCESS), 10) \ - X("UF-INSTANT", BIT(AL_MOD_SFP_QUIRK_NO_SEQ_READING), 0) \ - X("V2801F", BIT(AL_MOD_SFP_QUIRK_NO_SEQ_READING), 0) \ - X("UC-DAC-SFP+", BIT(AL_MOD_SFP_QUIRK_NO_PHY_DETECTION), 0) - struct al_mod_eth_lm_step_retimer_data { int rx_adap_state; int slc_state; @@ -230,6 +211,44 @@ struct al_mod_eth_lm_link_config { al_mod_bool autoneg; }; +/** + * @brief List of quirks + */ +enum al_mod_sfp_quirks_e { + /* limit access to module's EEPROM */ + AL_MOD_SFP_QUIRK_NO_EEPROM_ACCESS = 0, + /* use enhanced GPIO detection */ + AL_MOD_SFP_QUIRK_ENHANCED_LINK_DETECTION, + AL_MOD_SFP_QUIRK_COUNT +}; + +struct al_mod_sfp_quirk_entry { + const char *pn; + const unsigned long flags; + const int delay_init_ms; +}; + +/** + * @brief List of modules with quirks + * + * - periodic reading of eeprom leads to jamming i2c bus : + * - Alcatel 3FE46541AA + * - Huawei MA5671A + * - Alcatel Lucent G-010S-P + * - 10Gtek SFP-10G-SR + * - Cisco SFP-10G-SR + * - needs more time to initialize (~1s) : UF-RJ45-1G + * X (product number, quirk flags, number of seconds to delay SFP initialization) + */ +#define AL_MOD_SFP_FIXUP_LIST(X) \ + X("MA5671A", BIT(AL_MOD_SFP_QUIRK_NO_EEPROM_ACCESS), 10000) \ + X("3FE46541AA", BIT(AL_MOD_SFP_QUIRK_NO_EEPROM_ACCESS), 10000) \ + X("G010SP", BIT(AL_MOD_SFP_QUIRK_NO_EEPROM_ACCESS), 10000) \ + X("SFP-SR-10GB", BIT(AL_MOD_SFP_QUIRK_NO_EEPROM_ACCESS), 0) \ + X("SFP-10G-SR", BIT(AL_MOD_SFP_QUIRK_NO_EEPROM_ACCESS), 0) \ + X("UF-RJ45-1G", BIT(AL_MOD_SFP_QUIRK_ENHANCED_LINK_DETECTION), 1000) \ + X("S+RJ10", BIT(AL_MOD_SFP_QUIRK_ENHANCED_LINK_DETECTION), 0) + struct al_mod_eth_lm_context { struct al_mod_hal_eth_adapter *adapter; struct al_mod_serdes_grp_obj *serdes_obj; @@ -281,11 +300,11 @@ struct al_mod_eth_lm_context { /* services */ int (*i2c_read_data)(void *handle, uint8_t bus_id, uint8_t i2c_addr, - uint8_t reg_addr, uint8_t *val, size_t len, al_mod_bool seq); + uint8_t reg_addr, uint8_t *val, size_t len, size_t block_size); int (*i2c_read)(void *handle, uint8_t bus_id, uint8_t i2c_addr, uint8_t reg_addr, uint8_t *val); int (*i2c_write_data)(void *handle, uint8_t bus_id, uint8_t i2c_addr, - uint8_t reg_addr, uint8_t *val, size_t len, al_mod_bool seq); + uint8_t reg_addr, uint8_t *val, size_t len, size_t block_size); int (*i2c_write)(void *handle, uint8_t bus_id, uint8_t i2c_addr, uint8_t reg_addr, uint8_t val); void *i2c_context; @@ -293,6 +312,11 @@ struct al_mod_eth_lm_context { int (*gpio_get)(unsigned int gpio); uint32_t gpio_present; + al_mod_bool sfp_enhanced_link_detection_default; + al_mod_bool sfp_enhanced_link_detection; /* enable enhanced SFP detection */ + al_mod_bool sfp_gpio_init; + struct gpio_desc **sfp_gpio_list; + unsigned sfp_gpio_state; enum al_mod_eth_retimer_channel retimer_tx_channel; al_mod_bool retimer_configured; @@ -337,11 +361,15 @@ struct al_mod_eth_lm_context { /* desired link configuration */ struct al_mod_eth_lm_link_config link_conf; /* Allows to apply a special treatment for SFP module */ + const struct al_mod_sfp_quirk_entry *sfp_quirk; unsigned long sfp_quirk_flags; /* SFP A0 */ struct sfp_eeprom_id sfp_id; + size_t sfp_i2c_block_size; + al_mod_bool sfp_id_valid; /* lm context lock */ struct mutex lock; + unsigned long RJ45_10G_jiffies; }; struct al_mod_eth_lm_init_params { @@ -402,11 +430,11 @@ struct al_mod_eth_lm_init_params { * in case no eeprom is connected should return -ETIMEDOUT */ int (*i2c_read_data)(void *handle, uint8_t bus_id, uint8_t i2c_addr, - uint8_t reg_addr, uint8_t *val, size_t len, al_mod_bool seq); + uint8_t reg_addr, uint8_t *val, size_t len, size_t block_size); int (*i2c_read)(void *handle, uint8_t bus_id, uint8_t i2c_addr, uint8_t reg_addr, uint8_t *val); int (*i2c_write_data)(void *handle, uint8_t bus_id, uint8_t i2c_addr, - uint8_t reg_addr, uint8_t *val, size_t len, al_mod_bool seq); + uint8_t reg_addr, uint8_t *val, size_t len, size_t block_size); int (*i2c_write)(void *handle, uint8_t bus_id, uint8_t i2c_addr, uint8_t reg_addr, uint8_t val); void *i2c_context; @@ -452,6 +480,10 @@ struct al_mod_eth_lm_init_params { unsigned int auto_fec_initial_timeout; /* Toggle timeout (in msec) to wait before toggling FEC state */ unsigned int auto_fec_toggle_timeout; + /* enable enhanced SFP detection */ + al_mod_bool sfp_enhanced_link_detection; + al_mod_bool sfp_gpio_init; + struct gpio_desc **sfp_gpio_list; }; /** diff --git a/drivers/net/phy/ar8216.c b/drivers/net/phy/ar8216.c index f2b207ce6e70..c6f1342106d8 100644 --- a/drivers/net/phy/ar8216.c +++ b/drivers/net/phy/ar8216.c @@ -580,7 +580,7 @@ ar8216_mangle_rx(struct net_device *dev, struct sk_buff *skb) return; /* lookup port vid from local table, the switch passes an invalid vlan id */ - vlan = priv->vlan_id[priv->pvid[port]]; + vlan = priv->pvid[port]; buf[14 + 2] &= 0xf0; buf[14 + 2] |= vlan >> 8; @@ -682,7 +682,7 @@ ar8216_setup_port(struct ar8xxx_priv *priv, int port, u32 members) u32 pvid; if (priv->vlan) { - pvid = priv->vlan_id[priv->pvid[port]]; + pvid = priv->pvid[port]; if (priv->vlan_tagged & (1 << port)) egress = AR8216_OUT_ADD_VLAN; else @@ -838,7 +838,7 @@ ar8236_setup_port(struct ar8xxx_priv *priv, int port, u32 members) u32 pvid; if (priv->vlan) { - pvid = priv->vlan_id[priv->pvid[port]]; + pvid = priv->pvid[port]; if (priv->vlan_tagged & (1 << port)) egress = AR8216_OUT_ADD_VLAN; else @@ -988,6 +988,12 @@ ar8xxx_sw_set_pvid(struct switch_dev *dev, int port, int vlan) port < 0 || port >= AR8X16_MAX_PORTS) return -EINVAL; + // clear previous Native VLAN if exist + if (priv->vt[priv->pvid[port]].untagged & (1 << port)) { + priv->vt[priv->pvid[port]].untagged &= ~(1 << port); + priv->vt[priv->pvid[port]].tagged |= (1 << port); + } + priv->pvid[port] = vlan; return 0; } @@ -1004,28 +1010,6 @@ ar8xxx_sw_get_pvid(struct switch_dev *dev, int port, int *vlan) return 0; } -static int -ar8xxx_sw_set_vid(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - - if (val->port_vlan >= AR8X16_MAX_VLANS) - return -EINVAL; - - priv->vlan_id[val->port_vlan] = val->value.i; - return 0; -} - -static int -ar8xxx_sw_get_vid(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - val->value.i = priv->vlan_id[val->port_vlan]; - return 0; -} - static int ar8xxx_sw_set_ivl(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) @@ -1035,7 +1019,7 @@ ar8xxx_sw_set_ivl(struct switch_dev *dev, const struct switch_attr *attr, if (val->port_vlan >= AR8X16_MAX_VLANS) return -EINVAL; - priv->use_ivl[val->port_vlan] = val->value.i; + priv->vt[val->port_vlan].use_ivl = val->value.i; return 0; } @@ -1044,7 +1028,7 @@ ar8xxx_sw_get_ivl(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) { struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - val->value.i = priv->use_ivl[val->port_vlan]; + val->value.i = priv->vt[val->port_vlan].use_ivl; return 0; } @@ -1068,7 +1052,7 @@ ar8xxx_sw_get_ports(struct switch_dev *dev, struct switch_val *val) if (val->port_vlan >= AR8X16_MAX_VLANS) return -EINVAL; - ports = priv->vlan_table[val->port_vlan]; + ports = priv->vt[val->port_vlan].vlan_entry; val->len = 0; for (i = 0; i < dev->ports; i++) { struct switch_port *p; @@ -1090,29 +1074,21 @@ static int ar8xxx_sw_set_ports(struct switch_dev *dev, struct switch_val *val) { struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - u8 *vt = &priv->vlan_table[val->port_vlan]; - int i, j; + int i; - *vt = 0; for (i = 0; i < val->len; i++) { struct switch_port *p = &val->value.ports[i]; if (p->flags & (1 << SWITCH_PORT_FLAG_TAGGED)) { priv->vlan_tagged |= (1 << p->id); + priv->vt[val->port_vlan].tagged |= (1 << p->id); + priv->vt[val->port_vlan].untagged &= ~(1 << p->id); } else { priv->vlan_tagged &= ~(1 << p->id); + priv->vt[val->port_vlan].tagged &= ~(1 << p->id); + priv->vt[val->port_vlan].untagged |= (1 << p->id); priv->pvid[p->id] = val->port_vlan; - - /* make sure that an untagged port does not - * appear in other vlans */ - for (j = 0; j < AR8X16_MAX_VLANS; j++) { - if (j == val->port_vlan) - continue; - priv->vlan_table[j] &= ~(1 << p->id); - } } - - *vt |= 1 << p->id; } return 0; } @@ -1185,7 +1161,7 @@ ar8xxx_sw_hw_apply(struct switch_dev *dev) /* calculate the port destination masks and load vlans * into the vlan translation unit */ for (j = 0; j < AR8X16_MAX_VLANS; j++) { - u8 vp = priv->vlan_table[j]; + u8 vp = priv->vt[j].tagged | priv->vt[j].untagged; if (!vp) continue; @@ -1196,8 +1172,7 @@ ar8xxx_sw_hw_apply(struct switch_dev *dev) portmask[i] |= vp & ~mask; } - chip->vtu_load_vlan(priv, priv->vlan_id[j], - priv->vlan_table[j]); + chip->vtu_load_vlan(priv, j, vp); } } else { /* vlan disabled: @@ -1237,9 +1212,6 @@ ar8xxx_sw_reset_switch(struct switch_dev *dev) memset(&priv->vlan, 0, sizeof(struct ar8xxx_priv) - offsetof(struct ar8xxx_priv, vlan)); - for (i = 0; i < AR8X16_MAX_VLANS; i++) - priv->vlan_id[i] = i; - /* Configure all ports */ for (i = 0; i < dev->ports; i++) chip->init_port(priv, i); @@ -1731,14 +1703,6 @@ const struct switch_attr ar8xxx_sw_attr_port[] = { }; const struct switch_attr ar8xxx_sw_attr_vlan[] = { - { - .type = SWITCH_TYPE_INT, - .name = "vid", - .description = "VLAN ID (0-4094)", - .set = ar8xxx_sw_set_vid, - .get = ar8xxx_sw_get_vid, - .max = 4094, - }, { .type = SWITCH_TYPE_INT, .name = "enable_ivl", diff --git a/drivers/net/phy/ar8216.h b/drivers/net/phy/ar8216.h index 36646954bce9..7140aff29b3b 100644 --- a/drivers/net/phy/ar8216.h +++ b/drivers/net/phy/ar8216.h @@ -424,7 +424,7 @@ struct ar8xxx_chip { void (*get_arl_entry)(struct ar8xxx_priv *priv, struct arl_entry *a, u32 *status, enum arl_op op); int (*sw_hw_apply)(struct switch_dev *dev); - void (*phy_rgmii_set)(struct ar8xxx_priv *priv, struct phy_device *phydev); + void (*phy_rgmii_set)(struct ar8xxx_priv *priv, struct phy_device *phydev); int (*phyaddr_to_portno)(int phy_addr); int (*portno_to_phyno)(int portno); @@ -489,12 +489,24 @@ struct ar8xxx_priv { unsigned int use_count; /* all fields below are cleared on reset */ + /* vlan: per port mask. port bit set ? SECURE MODE : PORT MODE */ uint32_t vlan; - u16 vlan_id[AR8X16_MAX_VLANS]; - u8 vlan_table[AR8X16_MAX_VLANS]; - u8 use_ivl[AR8X16_MAX_VLANS]; /* independent VLAN learning */ + /* vlan_tagged: per port mask. port bit set ? SECURE MODE : PORT MODE */ u8 vlan_tagged; + /* pvid: native VLANs per port */ u16 pvid[AR8X16_MAX_PORTS]; + struct VLAN_table { + union { + struct { + /* tagged: port mask for tagged egress */ + u8 tagged; + /* untagged: port mask for untagged egress */ + u8 untagged; + } __packed; + u16 vlan_entry; + }; + u8 use_ivl; + } vt[AR8X16_MAX_VLANS]; int arl_age_time; /* mirroring */ diff --git a/drivers/net/phy/ar8327.c b/drivers/net/phy/ar8327.c index 32aed254460f..a1c3b5c34c7c 100644 --- a/drivers/net/phy/ar8327.c +++ b/drivers/net/phy/ar8327.c @@ -26,12 +26,13 @@ #include #include #include +#include #include "ar8216.h" #include "ar8327.h" extern const struct ar8xxx_mib_desc ar8236_mibs[41]; -extern const struct switch_attr ar8xxx_sw_attr_vlan[2]; +extern const struct switch_attr ar8xxx_sw_attr_vlan[1]; static u32 ar8327_get_pad_cfg(struct ar8327_pad_cfg *cfg) @@ -205,6 +206,31 @@ ar8327_phy_fixup(struct ar8xxx_priv *priv, int phy) */ } +static int +ar8327_sw_phy_write16(struct switch_dev *dev, int port, u8 reg, u16 value) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + int phyno = ar8327_portno_to_phyno(port); + if (phyno < 0) + return phyno; + return mdiobus_write(priv->mii_bus, phyno, reg, value); +} + +static int +ar8327_sw_phy_read16(struct switch_dev *dev, int port, u8 reg, u16 *value) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + int val; + int phyno = ar8327_portno_to_phyno(port); + if (phyno < 0) + return phyno; + val = mdiobus_read(priv->mii_bus, phyno, reg); + if (val < 0) + return val; + *value = val; + return 0; +} + static int ar8327_sw_set_port_link (struct switch_dev *sw_dev, int port, struct switch_port_link *link) @@ -214,47 +240,16 @@ ar8327_sw_set_port_link (struct switch_dev *sw_dev, int port, int rc = 0; /* don't allow to control MAC of CPU ports */ - if(AR8337_HAS_NO_PHY(port)) { + if (AR8337_HAS_NO_PHY(port)) { return -ENOTSUPP; } /* Handle PHY */ - if((rc = switch_generic_set_link(sw_dev, port-1, link))) { + if ((rc = switch_generic_set_link(sw_dev, port, link))) { return rc; } - /* Handle MAC */ -#ifdef CONFIG_SWCONFIG_UBNT_EXT - if(!link->power_down) -#endif - { - status = AR8216_PORT_STATUS_TXMAC | AR8216_PORT_STATUS_RXMAC; - if(link->aneg) { - status |= AR8216_PORT_STATUS_LINK_AUTO | AR8216_PORT_STATUS_FLOW_CONTROL; - } else { - switch (link->speed) { - case SWITCH_PORT_SPEED_10: - status |= AR8216_PORT_SPEED_10M; - break; - case SWITCH_PORT_SPEED_100: - status |= AR8216_PORT_SPEED_100M; - break; - case SWITCH_PORT_SPEED_1000: - status |= AR8216_PORT_SPEED_1000M; - break; - default: - return -ENOTSUPP; - } - status |= link->duplex ? AR8216_PORT_STATUS_DUPLEX : 0; - status |= link->rx_flow ? AR8216_PORT_STATUS_RXFLOW : 0; - status |= link->tx_flow ? AR8216_PORT_STATUS_TXFLOW : 0; - } - } - - ar8xxx_write(priv, AR8327_REG_PORT_STATUS(port), 0); - msleep(100); - ar8xxx_write(priv, AR8327_REG_PORT_STATUS(port), status); - + /* MAC can detect speed from PHY by default. */ return 0; } @@ -1106,20 +1101,20 @@ ar8327_vtu_load_vlan(struct ar8xxx_priv *priv, u32 vid, u32 port_mask) op = AR8327_VTU_FUNC1_OP_LOAD | (vid << AR8327_VTU_FUNC1_VID_S); val = AR8327_VTU_FUNC0_VALID; - if (priv->use_ivl[vid]) + if (priv->vt[vid].use_ivl) val |= AR8327_VTU_FUNC0_IVL; for (i = 0; i < AR8327_NUM_PORTS; i++) { u32 mode; - if ((port_mask & BIT(i)) == 0) - mode = AR8327_VTU_FUNC0_EG_MODE_NOT; - else if (priv->vlan == 0) + if (priv->vlan == 0) // port VLAN, not VT mode = AR8327_VTU_FUNC0_EG_MODE_KEEP; - else if ((priv->vlan_tagged & BIT(i)) || (priv->vlan_id[priv->pvid[i]] != vid)) + else if (priv->vt[vid].tagged & BIT(i)) mode = AR8327_VTU_FUNC0_EG_MODE_TAG; - else + else if (priv->vt[vid].untagged & BIT(i)) mode = AR8327_VTU_FUNC0_EG_MODE_UNTAG; + else + mode = AR8327_VTU_FUNC0_EG_MODE_NOT; val |= mode << AR8327_VTU_FUNC0_EG_MODE_S(i); } @@ -1132,7 +1127,7 @@ ar8327_setup_port(struct ar8xxx_priv *priv, int port, u32 members) struct ar8327_data *data = priv->chip_data; u32 t; u32 egress, ingress; - u32 pvid = priv->vlan_id[priv->pvid[port]]; + u32 pvid = priv->pvid[port]; egress = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH; @@ -1261,22 +1256,27 @@ static int ar8327_sw_get_ports(struct switch_dev *dev, struct switch_val *val) { struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - u8 ports = priv->vlan_table[val->port_vlan]; + + u8 p_t = priv->vt[val->port_vlan].tagged; + u8 p_u = priv->vt[val->port_vlan].untagged; int i; val->len = 0; - for (i = 0; i < dev->ports; i++) { - struct switch_port *p; - - if (!(ports & (1 << i))) - continue; + for (i = 0; (p_t | p_u) >= (1 << i); i++) { + struct switch_port *p = &val->value.ports[val->len]; - p = &val->value.ports[val->len++]; - p->id = i; - if ((priv->vlan_tagged & (1 << i)) || (priv->pvid[i] != val->port_vlan)) - p->flags = (1 << SWITCH_PORT_FLAG_TAGGED); - else - p->flags = 0; + if ((p_t & (1 << i)) || (p_u & (1 << i))) { + if (p_t & (1 << i)) { + p->flags = (1 << SWITCH_PORT_FLAG_TAGGED); + } else { + if (priv->pvid[i] != val->port_vlan) + p->flags = (1 << SWITCH_PORT_FLAG_UNTAGGED); + else + p->flags = 0; + } + p->id = i; + val->len++; + } } return 0; } @@ -1285,24 +1285,23 @@ static int ar8327_sw_set_ports(struct switch_dev *dev, struct switch_val *val) { struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - u8 *vt = &priv->vlan_table[val->port_vlan]; int i; - *vt = 0; + priv->vt[val->port_vlan].vlan_entry = 0; for (i = 0; i < val->len; i++) { struct switch_port *p = &val->value.ports[i]; if (p->flags & (1 << SWITCH_PORT_FLAG_TAGGED)) { - if (val->port_vlan == priv->pvid[p->id]) { - priv->vlan_tagged |= (1 << p->id); - } + priv->vt[val->port_vlan].tagged |= (1 << p->id); + priv->vt[val->port_vlan].untagged &= ~(1 << p->id); } else { - priv->vlan_tagged &= ~(1 << p->id); - priv->pvid[p->id] = val->port_vlan; + priv->vt[val->port_vlan].untagged |= (1 << p->id); + priv->vt[val->port_vlan].tagged &= ~(1 << p->id); + if (!(p->flags & (1 << SWITCH_PORT_FLAG_UNTAGGED))) + priv->pvid[p->id] = val->port_vlan; } - - *vt |= 1 << p->id; } + return 0; } @@ -2248,6 +2247,203 @@ static void ar8327_acl_hw_destroy(struct acl_hw *hw) } } +static int +ar8xxx_hw_get_arl_table(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ +#define ARL_TABLE_SIZE 2048 + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + struct mii_bus *bus = priv->mii_bus; + char *buf = priv->arl_buf; + int i, k, n, rc; + int total = 0, len = sizeof(priv->arl_buf); + u16 r2, page; + u16 r1_func, r1_data0, r1_data1, r1_data2; + struct arl_table *arl; + + arl = vmalloc(sizeof(struct arl_table) * ARL_TABLE_SIZE); + if (arl == NULL) { + pr_err("[ARL] OOM\n"); + return -1; + } + + mutex_lock(&priv->reg_mutex); + mutex_lock(&bus->mdio_lock); + + split_addr(AR8327_REG_ATU_DATA0, &r1_data0, &r2, &page); + r2 |= 0x10; + r1_data1 = (AR8327_REG_ATU_DATA1 >> 1) & 0x1e; + r1_data2 = (AR8327_REG_ATU_DATA2 >> 1) & 0x1e; + r1_func = (AR8327_REG_ATU_FUNC >> 1) & 0x1e; + /* all ATU registers are on the same page + * therefore set page only once + */ + bus->write(bus, 0x18, 0, page); + wait_for_page_switch(); + ar8327_wait_atu_ready(priv, r2, r1_func); + ar8xxx_mii_write32(priv, r2, r1_data0, 0); + ar8xxx_mii_write32(priv, r2, r1_data1, 0); + ar8xxx_mii_write32(priv, r2, r1_data2, 0); + + // read whole bunch + for (i = 0; i < ARL_TABLE_SIZE; i++) { + ar8xxx_mii_write32(priv, r2, r1_func, + AR8327_ATU_FUNC_OP_GET_NEXT | + AR8327_ATU_FUNC_BUSY); + ar8327_wait_atu_ready(priv, r2, r1_func); + + arl[total]._w[0] = ar8xxx_mii_read32(priv, r2, r1_data0); + arl[total]._w[1] = ar8xxx_mii_read32(priv, r2, r1_data1); + arl[total]._w[2] = ar8xxx_mii_read32(priv, r2, r1_data2); + + if (!arl[total].status) + break; + total++; + } + mutex_unlock(&bus->mdio_lock); + + for (i = 0, n = -1; i < total; i++) { + // skip hole + if (!arl[i].status) { + if (n == -1) + n = i; + continue; + } + // glue entries + for (k = i + 1; k < total; k++) { + if (!arl[k].status) + continue; + if (!memcmp(arl[i].mac, arl[k].mac, 6) && + arl[i].vid == arl[k].vid) { + arl[k].status = 0; + arl[i].portmap |= arl[k].portmap; + } + } + // pack entries + if (n >= 0) { + arl[n] = arl[i]; + arl[i].status = 0; + n++; + } + } + if (n >= 0) // n < 0 -> all entries are unique + total = n; + + rc = snprintf(buf, len, "ARL table\n"); + for (i = 0; i < total; i++) { + if (rc <= 0 || len < 64) { + *buf = '\0'; + break; + } + buf += rc; + len -= rc; + + for (k = 0; k < AR8327_NUM_PORTS; k++) { + if (arl[i].portmap & (1 << k)) + *buf++ = '0' + k; + else + *buf++ = '-'; + } + len -= k; + rc = snprintf(buf, len, " %02x:%02x:%02x:%02x:%02x:%02x %d\n", + arl[i].mac[5], arl[i].mac[4], arl[i].mac[3], + arl[i].mac[2], arl[i].mac[1], arl[i].mac[0], + arl[i].vid); + } + val->value.s = priv->arl_buf; + val->len = sizeof(priv->arl_buf) - len; + + mutex_unlock(&priv->reg_mutex); + vfree(arl); + return 0; +} + +static int +ar8xxx_hw_eddit_arl_table(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + struct mii_bus *bus = priv->mii_bus; + const char *cmd = val->value.s; + u16 r2, page; + u16 r1_func, r1_data0, r1_data1, r1_data2; + u32 ports; + struct arl_table arl = {._w = {0x00, 0x00, 0x00}}; + struct atu_func_reg afr = {._w = 0x00}; + + while (cmd) { + while (isblank(*cmd)) + cmd++; + if (!*cmd) // EOF + break; + + if (!memcmp(cmd, "add", strlen("add"))) { + cmd += strlen("add"); + afr.at_func = 0x2; + arl.status = 7; // max age time, but not static + } else if (!memcmp(cmd, "rem", strlen("rem"))) { + cmd += strlen("rem"); + afr.at_func = 0x3; + } else if (!memcmp(cmd, "flush", strlen("flush"))) { + cmd += strlen("flush"); + afr.at_func = 0x1; + } else if (!memcmp(cmd, "ports", strlen("ports"))) { + cmd += strlen("ports"); + cmd = acl_parse_bitmask(cmd, &ports); + arl.portmap = ports; + } + else if (!memcmp(cmd, "mac", strlen("mac"))) { + cmd += strlen("mac"); + if (sscanf(cmd, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", + &arl.mac[5], &arl.mac[4], &arl.mac[3], + &arl.mac[2], &arl.mac[1], &arl.mac[0]) != 6) { + cmd = NULL; + break; + } + cmd = strchr(cmd, ':'); + while (isgraph(*cmd)) + cmd++; + } + else if (!memcmp(cmd, "vid", strlen("vid"))) { + uint16_t vid; + cmd += strlen("vid"); + cmd = acl_parse_value(cmd, &vid); + arl.vid = vid; + } else { + pr_err("[ARL] Unknown cmd: '%s'\n", cmd); + return -1; + } + } + if (cmd == NULL || afr.at_func == 0x0) { + pr_err("[ARL] Failed to parse: '%s'\n", val->value.s); + return -1; + } + arl.svl = 0; // IVL + afr.busy = 1; + + split_addr(AR8327_REG_ATU_DATA0, &r1_data0, &r2, &page); + r2 |= 0x10; + r1_data1 = (AR8327_REG_ATU_DATA1 >> 1) & 0x1e; + r1_data2 = (AR8327_REG_ATU_DATA2 >> 1) & 0x1e; + r1_func = (AR8327_REG_ATU_FUNC >> 1) & 0x1e; + /* all ATU registers are on the same page + * therefore set page only once + */ + mutex_lock(&bus->mdio_lock); + bus->write(bus, 0x18, 0, page); + wait_for_page_switch(); + ar8327_wait_atu_ready(priv, r2, r1_func); + ar8xxx_mii_write32(priv, r2, r1_data0, arl._w[0]); + ar8xxx_mii_write32(priv, r2, r1_data1, arl._w[1]); + ar8xxx_mii_write32(priv, r2, r1_data2, arl._w[2]); + ar8xxx_mii_write32(priv, r2, r1_func, afr._w); // commit + + mutex_unlock(&bus->mdio_lock); + return 0; +} + static const struct switch_attr ar8327_sw_attr_globals[] = { { .type = SWITCH_TYPE_NOVAL, @@ -2297,9 +2493,9 @@ static const struct switch_attr ar8327_sw_attr_globals[] = { { .type = SWITCH_TYPE_STRING, .name = "arl_table", - .description = "Get ARL table", - .set = NULL, - .get = ar8xxx_sw_get_arl_table, + .description = "Get/Set ARL table", + .set = ar8xxx_hw_eddit_arl_table, + .get = ar8xxx_hw_get_arl_table, }, { .type = SWITCH_TYPE_NOVAL, @@ -2351,6 +2547,10 @@ static const struct switch_attr ar8327_sw_attr_globals[] = { .get = ar8327_sw_get_acl, .max = 1 }, +#if 0 +/* HW IGMP Snooping will de-header VLAN from IGMP Reports, which will result + * in non-working IGMP Proxy. + */ { .type = SWITCH_TYPE_INT, .name = "igmp_snooping", @@ -2359,6 +2559,7 @@ static const struct switch_attr ar8327_sw_attr_globals[] = { .get = ar8327_sw_get_igmp_snooping, .max = 1 }, +#endif { .type = SWITCH_TYPE_INT, .name = "igmp_v3", @@ -2468,7 +2669,8 @@ static const struct switch_dev_ops ar8327_sw_ops = { }, #endif .set_port_link = ar8327_sw_set_port_link, - .phy_write16 = ar8xxx_sw_phy_write16, + .phy_write16 = ar8327_sw_phy_write16, + .phy_read16 = ar8327_sw_phy_read16, }; /** diff --git a/drivers/net/phy/ar8327.h b/drivers/net/phy/ar8327.h index 1260207056ec..52883a466772 100644 --- a/drivers/net/phy/ar8327.h +++ b/drivers/net/phy/ar8327.h @@ -599,6 +599,53 @@ struct ar8327_data { u32 port_isolation[AR8327_NUM_PORTS]; }; +struct arl_table { + union { + struct { + uint8_t mac[6]; // : 48 + uint32_t portmap : 7; + uint32_t port_cross : 1; + uint32_t priority : 3; + uint32_t svl : 1; + uint32_t pri_en : 1; + uint32_t mirror : 1; + uint32_t drop : 1; + uint32_t reserved0 : 1; /* ATU hash ? */ + uint32_t status : 4; /* h1-7: ~40s, hF: static, 0: none */ + uint32_t leaky : 1; + uint32_t rdr_to_cpu : 1; + uint32_t cpy_to_cpu : 1; + uint32_t reserved1 : 1; + uint32_t vid : 12; + uint32_t white_list : 1; + /* reserved */ + } __attribute__((packed)); + uint32_t _w[3]; + }; +} __attribute__((packed)); + +struct atu_func_reg { + union { + struct { + uint32_t at_func : 4; + uint32_t flush_static : 1; + uint32_t atu_type : 1; + uint32_t reserved0 : 2; + uint32_t port_num : 4; + uint32_t at_full_vio : 1; + uint32_t at_multi_en : 1; + uint32_t at_port_en : 1; + uint32_t at_vid_en : 1; + uint32_t atu_index : 5; + uint32_t reserved1 : 1; + uint32_t trunk_port : 3; + uint32_t reserved2 : 6; + uint32_t busy : 1; + } __attribute__((packed)); + uint32_t _w; + }; +} __attribute__((packed)); + /* register functions */ #define SW_BIT_MASK_U32(nr) (~(0xFFFFFFFF << (nr))) #define SW_FIELD_MASK_U32(offset, len) ((SW_BIT_MASK_U32(len) << (offset))) diff --git a/drivers/net/phy/rtl8370.c b/drivers/net/phy/rtl8370.c index d5be9cef18cd..68c971a84bde 100644 --- a/drivers/net/phy/rtl8370.c +++ b/drivers/net/phy/rtl8370.c @@ -36,6 +36,7 @@ #include "rtl83xx_api/acl.h" #include "rtl83xx_api/led.h" #include "rtl83xx_api/l2.h" +#include "rtl83xx_api/igmp.h" #include "rtl8370.h" @@ -413,12 +414,10 @@ static int rtl8370_vlan_apply(struct rtl8370_priv *priv) RTK_PORTMASK_CLEAR(vlan_cfg.untag); RTK_PORTMASK_CLEAR(vlan_cfg.mbr); for (j = 0; j < priv->swdev.ports; j++) { - if (!(priv->vlan_table[i].members & BIT(j))) - continue; - - RTK_PORTMASK_PORT_SET(vlan_cfg.mbr, _rtl_port_p2l(priv, j)); - /* untag ports with pvid - port based vlans */ - if (!(priv->pvid_tagged & BIT(j)) && (priv->pvid_table[j] == i)) { + if (priv->vlan_table[i].tagged & BIT(j)) { + RTK_PORTMASK_PORT_SET(vlan_cfg.mbr, _rtl_port_p2l(priv, j)); + } else if (priv->vlan_table[i].untagged & BIT(j)) { + RTK_PORTMASK_PORT_SET(vlan_cfg.mbr, _rtl_port_p2l(priv, j)); RTK_PORTMASK_PORT_SET(vlan_cfg.untag, _rtl_port_p2l(priv, j)); } } @@ -865,7 +864,11 @@ static int rtl8370_setup(struct rtl8370_priv *priv, bool hard_reset) return rc; } - if((rc = rtl8370_l2_init(priv))){ + if ((rc = rtl8370_l2_init(priv))) { + return rc; + } + + if ((rc = rtk_igmp_init())) { return rc; } @@ -1049,15 +1052,14 @@ static int rtl8370_sw_get_vlan_info(struct switch_dev *dev, const struct switch_ BUF_APPEND_PRINTF("VLAN %d: Ports: '", val->port_vlan); for (i = 0; i < dev->ports; ++i) { - if (!(priv->vlan_table[val->port_vlan].members & BIT(i))) { - continue; + if (priv->vlan_table[val->port_vlan].tagged & BIT(i)) { + BUF_APPEND_PRINTF("%dt ", i); + } else if (priv->vlan_table[val->port_vlan].untagged & BIT(i)) { + if (val->port_vlan != priv->pvid_table[i]) + BUF_APPEND_PRINTF("%du ", i); + else + BUF_APPEND_PRINTF("%d ", i); } - - BUF_APPEND_PRINTF("%d%s", i, - (priv->pvid_tagged & BIT(i) || - val->port_vlan != priv->pvid_table[i]) ? - "t" : - ""); } str[str_max - 1] = '\0'; @@ -1177,7 +1179,7 @@ static int rtl8370_sw_get_ivl(struct switch_dev *dev, const struct switch_attr * static int rtl8370_sw_get_vlan_ports(struct switch_dev *dev, struct switch_val *val) { struct rtl8370_priv *priv = sw_to_rtl8370(dev); - uint16_t ports = priv->vlan_table[val->port_vlan].members; + uint16_t ports; int i; val->len = 0; @@ -1186,6 +1188,9 @@ static int rtl8370_sw_get_vlan_ports(struct switch_dev *dev, struct switch_val * return -EINVAL; } + ports = priv->vlan_table[val->port_vlan].tagged | + priv->vlan_table[val->port_vlan].untagged; + for (i = 0; i < dev->ports; i++) { struct switch_port *p; @@ -1194,9 +1199,14 @@ static int rtl8370_sw_get_vlan_ports(struct switch_dev *dev, struct switch_val * p = &val->value.ports[val->len++]; p->id = i; - p->flags = ((priv->pvid_tagged & BIT(i)) || val->port_vlan != priv->pvid_table[i]) ? - BIT(SWITCH_PORT_FLAG_TAGGED) : - 0; + if (priv->vlan_table[val->port_vlan].tagged & BIT(i)) { + p->flags = BIT(SWITCH_PORT_FLAG_TAGGED); + } else { + if (priv->pvid_table[i] != val->port_vlan) + p->flags = BIT(SWITCH_PORT_FLAG_UNTAGGED); + else + p->flags = 0; + } } return 0; @@ -1212,29 +1222,26 @@ static int rtl8370_sw_get_vlan_ports(struct switch_dev *dev, struct switch_val * static int rtl8370_sw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val) { struct rtl8370_priv *priv = sw_to_rtl8370(dev); - struct switch_port *port; - int i = 0; + int i; if (rtl8370_vlan_valid(dev, val->port_vlan)) { return -EINVAL; } priv->vlan_table[val->port_vlan].members = 0; - port = &val->value.ports[0]; - for (i = 0; i < val->len; ++i, ++port) { + for (i = 0; i < val->len; i++) { + struct switch_port *p = &val->value.ports[i]; - if ((port->flags & BIT(SWITCH_PORT_FLAG_TAGGED)) && - (val->port_vlan == priv->pvid_table[port->id])) { - priv->pvid_tagged |= BIT(port->id); + if (p->flags & BIT(SWITCH_PORT_FLAG_TAGGED)) { + priv->vlan_table[val->port_vlan].tagged |= BIT(p->id); + } else if ((p->flags & BIT(SWITCH_PORT_FLAG_UNTAGGED))) { + priv->vlan_table[val->port_vlan].untagged |= BIT(p->id); } else { - priv->pvid_tagged &= ~BIT(port->id); + // Native VLAN + priv->pvid_table[p->id] = val->port_vlan; + priv->vlan_table[val->port_vlan].untagged |= BIT(p->id); } - if (!(port->flags & BIT(SWITCH_PORT_FLAG_TAGGED))) { - /* Update the pvid to the vid we are untagging */ - priv->pvid_table[port->id] = val->port_vlan; - } - priv->vlan_table[val->port_vlan].members |= BIT(port->id); } return 0; @@ -1600,6 +1607,12 @@ static int rtl8370_sw_set_port_pvid(struct switch_dev *dev, int port, int pvid) return -EINVAL; } + // clear previous Native VLAN if exist + if (priv->vlan_table[priv->pvid_table[port]].untagged & (1 << port)) { + priv->vlan_table[priv->pvid_table[port]].untagged &= ~(1 << port); + priv->vlan_table[priv->pvid_table[port]].tagged |= (1 << port); + } + priv->pvid_table[port] = pvid; return 0; @@ -1656,6 +1669,30 @@ static int rtl8370_sw_phy_write16(struct switch_dev *dev, int port, uint8_t reg, return 0; } +/** + * @brief Read data from PHY + * + * @param dev - switch control structure + * @param addr - port number (physical) + * @param reg - PHY register + * @param value - data to store + * @return int - error from errno.h, 0 on success + */ +static int rtl8370_sw_phy_read16(struct switch_dev *dev, int port, uint8_t reg, uint16_t *value) +{ + struct rtl8370_priv *priv = sw_to_rtl8370(dev); + rtk_port_phy_data_t val; + rtk_api_ret_t rc; + + rc = rtk_port_phyReg_get(_rtl_port_p2l(priv, port), reg, &val); + if (RT_ERR_OK != rc) { + rtl_err(rc, "%s: Unable to write into port's PHY register", __func__); + return -ENODATA; + } + *value = (uint16_t)val; + return 0; +} + /** * @brief Set a port link status * @@ -1866,6 +1903,7 @@ static int rtl8370_acl_rule_sw_to_hw(struct acl_hw *hw, acl_entry_t *entry, /* Destination port */ act->actEnable[FILTER_ENACT_REDIRECT] = TRUE; RTK_PORTMASK_ALLPORT_SET(cfg->activeport.mask); + RTK_PORTMASK_CLEAR(act->filterPortmask); cfg->invert = FALSE; for (i = 0; i < hw->max_ports; ++i) { @@ -1878,6 +1916,13 @@ static int rtl8370_acl_rule_sw_to_hw(struct acl_hw *hw, acl_entry_t *entry, RTK_PORTMASK_PORT_SET(cfg->activeport.value, _rtl_port_p2l(priv, i)); } } + if (entry->vlan_dst) { + /* INGRESS not EGRESS, otherwise it messes up + * ARL table - will be registred w/ PVID in ARL. + */ + act->actEnable[FILTER_ENACT_CVLAN_INGRESS] = TRUE; + act->filterCvlanVid = entry->vlan_dst; + } break; case ACL_RULE_VLAN_ASSIGNMENT: @@ -1918,6 +1963,7 @@ static int rtl8370_acl_rule_sw_to_hw(struct acl_hw *hw, acl_entry_t *entry, default: return -EOPNOTSUPP; } + return 0; } @@ -2519,6 +2565,55 @@ static int rtl8370_arl_age_time_apply(struct rtl8370_priv *priv) return 0; } +static int +rtl8370_sw_set_igmp_snooping(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rtl8370_priv *priv = sw_to_rtl8370(dev); + int rc; + rtk_port_t port; + rtk_portmask_t portmask = {0}; + rtk_igmp_action_t act = val->value.i ? IGMP_ACTION_ASIC : + IGMP_ACTION_FORWARD; + + if (val->value.i) { + RTK_PORTMASK_PORT_SET(portmask, EXT_PORT0); + RTK_PORTMASK_PORT_SET(portmask, EXT_PORT1); + } + rc = rtk_igmp_static_router_port_set(&portmask); + if (rc) { + rtl_err(rc, "rtk_igmp_static_router_port_set()"); + return -1; + } + + for (port = UTP_PORT0; port <= UTP_PORT7; port++) { + rc = rtk_igmp_protocol_set(port, PROTOCOL_IGMPv2, act); + if (rc) { + rtl_err(rc, "rtk_igmp_protocol_set()"); + return -1; + } + rc = rtk_igmp_protocol_set(port, PROTOCOL_IGMPv3, act); + if (rc) { + rtl_err(rc, "rtk_igmp_protocol_set()"); + return -1; + } + } + + priv->igmp_snooping = val->value.i; + return 0; +} + +static int +rtl8370_sw_get_igmp_snooping(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rtl8370_priv *priv = sw_to_rtl8370(dev); + val->value.i = priv->igmp_snooping; + return 0; +} + /** * @brief Apply configuration * @@ -2627,7 +2722,15 @@ static struct switch_attr rtl8370_globals[] = { .description = "Get ARL table", .set = NULL, .get = rtl8370_sw_get_arl_table - } + }, + { + .type = SWITCH_TYPE_INT, + .name = "igmp_snooping", + .description = "Get/Set IGMP Snooping", + .set = rtl8370_sw_set_igmp_snooping, + .get = rtl8370_sw_get_igmp_snooping, + .max = 1 + }, }; /** @@ -2769,6 +2872,7 @@ static const struct switch_dev_ops rtl8370_sw_ops = { #endif .set_port_link = rtl8370_sw_set_port_link, .phy_write16 = rtl8370_sw_phy_write16, + .phy_read16 = rtl8370_sw_phy_read16, }; /** diff --git a/drivers/net/phy/rtl8370.h b/drivers/net/phy/rtl8370.h index 3d42d0620745..5c9de9cdf5be 100644 --- a/drivers/net/phy/rtl8370.h +++ b/drivers/net/phy/rtl8370.h @@ -192,7 +192,13 @@ struct rtl8370_port_mapping { }; struct rtl8370_vlan_entry { - uint16_t members; + union { + struct { + uint16_t tagged; + uint16_t untagged; + } __packed; + uint32_t members; + }; uint8_t fid; bool ivl_enabled; }; @@ -212,13 +218,13 @@ struct rtl8370_priv { uint8_t efid_table[RTL8370_PORT_MAX_PHY]; struct rtl8370_vlan_entry vlan_table[RTL8370_NUM_VIDS]; struct rtl8370_svlan_table svlan_table; - uint16_t pvid_tagged; uint16_t pvid_table[RTL8370_PORT_MAX_PHY]; /* array of port isolation masks */ rtk_portmask_t port_isolation[RTL8370_PORT_MAX_PHY]; struct rtl8370_mac_mode mac_mode[RTL8370_PORT_MAX_CPU]; const struct rtl8370_port_mapping *port_map; int reset_pin; + int igmp_snooping; }; #define RTL8370_INTERPRET_API_ERRORS diff --git a/drivers/net/phy/rtl83xx_api/igmp.c b/drivers/net/phy/rtl83xx_api/igmp.c index c676d2c6cc3c..a87726089ca9 100644 --- a/drivers/net/phy/rtl83xx_api/igmp.c +++ b/drivers/net/phy/rtl83xx_api/igmp.c @@ -42,16 +42,16 @@ static rtk_api_ret_t _rtk_igmp_init(void) RTK_SCAN_ALL_PHY_PORTMASK(port) { - if ((retVal = rtl8367c_setAsicIGMPv1Opeartion(port, PROTOCOL_OP_ASIC)) != RT_ERR_OK) + if ((retVal = rtl8367c_setAsicIGMPv1Opeartion(port, PROTOCOL_OP_DROP)) != RT_ERR_OK) return retVal; - if ((retVal = rtl8367c_setAsicIGMPv2Opeartion(port, PROTOCOL_OP_ASIC)) != RT_ERR_OK) + if ((retVal = rtl8367c_setAsicIGMPv2Opeartion(port, PROTOCOL_OP_FLOOD)) != RT_ERR_OK) return retVal; if ((retVal = rtl8367c_setAsicIGMPv3Opeartion(port, PROTOCOL_OP_FLOOD)) != RT_ERR_OK) return retVal; - if ((retVal = rtl8367c_setAsicMLDv1Opeartion(port, PROTOCOL_OP_ASIC)) != RT_ERR_OK) + if ((retVal = rtl8367c_setAsicMLDv1Opeartion(port, PROTOCOL_OP_FLOOD)) != RT_ERR_OK) return retVal; if ((retVal = rtl8367c_setAsicMLDv2Opeartion(port, PROTOCOL_OP_FLOOD)) != RT_ERR_OK) diff --git a/drivers/net/phy/swconfig.c b/drivers/net/phy/swconfig.c index 02d84201d9cc..e8af537bedd7 100644 --- a/drivers/net/phy/swconfig.c +++ b/drivers/net/phy/swconfig.c @@ -95,7 +95,8 @@ swconfig_set_vlan_ports(struct switch_dev *dev, const struct switch_attr *attr, return -EINVAL; if (ops->set_port_pvid && - !(ports[i].flags & (1 << SWITCH_PORT_FLAG_TAGGED))) + !(ports[i].flags & (1 << SWITCH_PORT_FLAG_TAGGED)) && + !(ports[i].flags & (1 << SWITCH_PORT_FLAG_UNTAGGED))) ops->set_port_pvid(dev, ports[i].id, val->port_vlan); } @@ -362,6 +363,7 @@ static const struct nla_policy switch_policy[SWITCH_ATTR_MAX+1] = { static const struct nla_policy port_policy[SWITCH_PORT_ATTR_MAX+1] = { [SWITCH_PORT_ID] = { .type = NLA_U32 }, [SWITCH_PORT_FLAG_TAGGED] = { .type = NLA_FLAG }, + [SWITCH_PORT_FLAG_UNTAGGED] = { .type = NLA_FLAG }, }; static struct nla_policy link_policy[SWITCH_LINK_ATTR_MAX] = { @@ -710,6 +712,8 @@ swconfig_parse_ports(struct sk_buff *msg, struct nlattr *head, port->id = nla_get_u32(tb[SWITCH_PORT_ID]); if (tb[SWITCH_PORT_FLAG_TAGGED]) port->flags |= (1 << SWITCH_PORT_FLAG_TAGGED); + if (tb[SWITCH_PORT_FLAG_UNTAGGED]) + port->flags |= (1 << SWITCH_PORT_FLAG_UNTAGGED); val->len++; } @@ -849,6 +853,10 @@ swconfig_send_port(struct swconfig_callback *cb, void *arg) if (nla_put_flag(cb->msg, SWITCH_PORT_FLAG_TAGGED)) goto nla_put_failure; } + if (port->flags & (1 << SWITCH_PORT_FLAG_UNTAGGED)) { + if (nla_put_flag(cb->msg, SWITCH_PORT_FLAG_UNTAGGED)) + goto nla_put_failure; + } nla_nest_end(cb->msg, p); return 0; @@ -1354,10 +1362,58 @@ unregister_switch(struct switch_dev *dev) } EXPORT_SYMBOL_GPL(unregister_switch); +static int +set_phy_adv_to_max(struct switch_dev *dev, int port) +{ + int rc = 0; + u16 status; // contains port capabilities + u16 adv; // contains advertised capabilities + + // set to max 10M and 100M capabilities + rc |= dev->ops->phy_read16(dev, port, MII_BMSR, &status); + rc |= dev->ops->phy_read16(dev, port, MII_ADVERTISE, &adv); + status = (status >> 6) & (0x1F << 5); + adv &= ~(0x1F << 5); + adv |= status; + rc |= dev->ops->phy_write16(dev, port, MII_ADVERTISE, adv); + + // set to max 1G capabilities + rc |= dev->ops->phy_read16(dev, port, MII_ESTATUS, &status); + rc |= dev->ops->phy_read16(dev, port, MII_CTRL1000, &adv); + status = (status >> 4) & (0x03 << 8); + adv &= ~(0x03 << 8); + adv |= status; + rc |= dev->ops->phy_write16(dev, port, MII_CTRL1000, adv); + return rc; +} + +static int +set_phy_adv_to_1G(struct switch_dev *dev, int port) +{ + int rc = 0; + u16 status; // contains port capabilities + u16 adv; // contains advertised capabilities + + // reset 10M and 100M capabilities + rc |= dev->ops->phy_read16(dev, port, MII_ADVERTISE, &adv); + adv &= ~(0x1F << 5); + rc |= dev->ops->phy_write16(dev, port, MII_ADVERTISE, adv); + + // set to max 1G capabilities + rc |= dev->ops->phy_read16(dev, port, MII_ESTATUS, &status); + rc |= dev->ops->phy_read16(dev, port, MII_CTRL1000, &adv); + status = (status >> 4) & (0x03 << 8); + adv &= ~(0x03 << 8); + adv |= status; + rc |= dev->ops->phy_write16(dev, port, MII_CTRL1000, adv); + return rc; +} + int switch_generic_set_link(struct switch_dev *dev, int port, struct switch_port_link *link) { + int rc; if (WARN_ON(!dev->ops->phy_write16)) return -ENOTSUPP; @@ -1369,6 +1425,11 @@ switch_generic_set_link(struct switch_dev *dev, int port, { /* Generic implementation */ if (link->aneg) { + rc = set_phy_adv_to_max(dev, port); + if (rc) { + pr_err("Failed to set A-NEG to max\n"); + return -EFAULT; + } dev->ops->phy_write16(dev, port, MII_BMCR, 0x0000); dev->ops->phy_write16(dev, port, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); } else { @@ -1384,7 +1445,16 @@ switch_generic_set_link(struct switch_dev *dev, int port, bmcr |= BMCR_SPEED100; break; case SWITCH_PORT_SPEED_1000: - bmcr |= BMCR_SPEED1000; + /* According to IEEE, 1G and above always should + * have autoneg On. If only 1G is desired then + * only advertisement should be set accordingly. + */ + rc = set_phy_adv_to_1G(dev, port); + if (rc) { + pr_err("Failed to set A-NEG to 1G\n"); + return -EFAULT; + } + bmcr = BMCR_ANENABLE | BMCR_ANRESTART; break; default: return -ENOTSUPP; diff --git a/drivers/net/phy/ubnt_acl.c b/drivers/net/phy/ubnt_acl.c index a325fb441870..b193febe9fbc 100644 --- a/drivers/net/phy/ubnt_acl.c +++ b/drivers/net/phy/ubnt_acl.c @@ -334,15 +334,7 @@ static const char *acl_parse_mac(const char *rule, u8 mac[6]) return rule; } -/** - * @brief Parse the HEX/DEC value and store result in `value`. - * - * @param rule - value to be parsed, value starting with `0x` considered HEX. - * @param value - stored result. - * @return char* - string after value or NULL on error. - * @note single quote tolerant. - */ -static const char *acl_parse_value(const char *rule, uint16_t *value) +const char *acl_parse_value(const char *rule, uint16_t *value) { while (isblank(*rule) || *rule == '\'') rule++; @@ -359,15 +351,7 @@ static const char *acl_parse_value(const char *rule, uint16_t *value) return rule; } -/** - * @brief Parse the bit tuple and store result in as bitmask in `mask`. - * - * @param rule - value to be parsed. - * @param mask - stored result. - * @return char* - string after value or NULL on error. - * @note single quote tolerant. - */ -static const char *acl_parse_bitmask(const char *rule, u32 *mask) +const char *acl_parse_bitmask(const char *rule, u32 *mask) { u32 value; @@ -623,6 +607,10 @@ int ubnt_acl_get_acl_table(struct acl_hw *hw) } BUF_APPEND_PRINTF("%d ", i); } + + if (entry->vlan_dst) { + BUF_APPEND_PRINTF("\nVLAN_DST %d\n", entry->vlan_dst); + } break; case ACL_RULE_VLAN_ASSIGNMENT: BUF_APPEND_PRINTF("ETHER_TYPE: 0x%04X\n", entry->ether_type); diff --git a/drivers/net/phy/ubnt_acl.h b/drivers/net/phy/ubnt_acl.h index 12f08ba5f9d5..7446cee93eed 100644 --- a/drivers/net/phy/ubnt_acl.h +++ b/drivers/net/phy/ubnt_acl.h @@ -221,6 +221,26 @@ int ubnt_acl_enable_set(struct acl_hw *hw, int enable); */ int ubnt_mac_zero_addr(acl_mac_t *mac); +/** + * @brief Parse the bit tuple and store result in as bitmask in `mask`. + * + * @param rule - value to be parsed. + * @param mask - stored result. + * @return char* - string after value or NULL on error. + * @note single quote tolerant. + */ +const char *acl_parse_bitmask(const char *rule, u32 *mask); + +/** + * @brief Parse the HEX/DEC value and store result in `value`. + * + * @param rule - value to be parsed, value starting with `0x` considered HEX. + * @param value - stored result. + * @return char* - string after value or NULL on error. + * @note single quote tolerant. + */ +const char *acl_parse_value(const char *rule, uint16_t *value); + // same as std::isblank() static inline int isblank(int c) { diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 7cb6e2b9e180..d75b9886606c 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -94,6 +94,13 @@ config BLK_DEV_SD In this case, do not compile the driver for your SCSI host adapter (below) as a module either. +config SCSI_UBNT_STATIC_BOOT_DEV + bool "UBNT static boot flash name" + depends on BLK_DEV_SD + ---help--- + When the SCSI host type is an usb storage and the vendor name is "Generic ", + this option will name a static disk name (/dev/boot) for that device. + config CHR_DEV_ST tristate "SCSI tape support" depends on SCSI diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index bab46c228c30..6936c1ba314f 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -3435,10 +3435,23 @@ static int sd_probe(struct device *dev) goto out_put; } - error = sd_format_disk_name("sd", index, gd->disk_name, DISK_NAME_LEN); - if (error) { - sdev_printk(KERN_WARNING, sdp, "SCSI disk (sd) name length exceeded.\n"); - goto out_free_index; +#ifdef CONFIG_SCSI_UBNT_STATIC_BOOT_DEV + /* + * Fix the disk name to "boot" if the host type is an usb storage and + * the vendor name is "Generic " for Genesys GL3224E or "Generic-" for + * Realtek RTS5315 (2nd source). + */ + if (strcmp(sdp->host->hostt->proc_name, "usb-storage") == 0 && + strncmp(sdp->vendor, "Generic", 7) == 0) { + strcpy(gd->disk_name, "boot"); + } else +#endif + { + error = sd_format_disk_name("sd", index, gd->disk_name, DISK_NAME_LEN); + if (error) { + sdev_printk(KERN_WARNING, sdp, "SCSI disk (sd) name length exceeded.\n"); + goto out_free_index; + } } sdkp->device = sdp; diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 1ca147b3c26a..bb9be78ec791 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -11,7 +11,7 @@ * Copyright 2008 Jouni Malinen * Copyright 2008 Colin McCabe * Copyright 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018-2020 Intel Corporation * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -52,6 +52,11 @@ #define NL80211_MULTICAST_GROUP_NAN "nan" #define NL80211_MULTICAST_GROUP_TESTMODE "testmode" +#define NL80211_EDMG_BW_CONFIG_MIN 4 +#define NL80211_EDMG_BW_CONFIG_MAX 15 +#define NL80211_EDMG_CHANNELS_MIN 1 +#define NL80211_EDMG_CHANNELS_MAX 0x3c /* 0b00111100 */ + /** * DOC: Station handling * @@ -178,18 +183,27 @@ * * By setting @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK flag drivers * can indicate they support offloading EAPOL handshakes for WPA/WPA2 - * preshared key authentication. In %NL80211_CMD_CONNECT the preshared - * key should be specified using %NL80211_ATTR_PMK. Drivers supporting - * this offload may reject the %NL80211_CMD_CONNECT when no preshared - * key material is provided, for example when that driver does not - * support setting the temporal keys through %CMD_NEW_KEY. + * preshared key authentication in station mode. In %NL80211_CMD_CONNECT + * the preshared key should be specified using %NL80211_ATTR_PMK. Drivers + * supporting this offload may reject the %NL80211_CMD_CONNECT when no + * preshared key material is provided, for example when that driver does + * not support setting the temporal keys through %NL80211_CMD_NEW_KEY. * * Similarly @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X flag can be * set by drivers indicating offload support of the PTK/GTK EAPOL - * handshakes during 802.1X authentication. In order to use the offload - * the %NL80211_CMD_CONNECT should have %NL80211_ATTR_WANT_1X_4WAY_HS - * attribute flag. Drivers supporting this offload may reject the - * %NL80211_CMD_CONNECT when the attribute flag is not present. + * handshakes during 802.1X authentication in station mode. In order to + * use the offload the %NL80211_CMD_CONNECT should have + * %NL80211_ATTR_WANT_1X_4WAY_HS attribute flag. Drivers supporting this + * offload may reject the %NL80211_CMD_CONNECT when the attribute flag is + * not present. + * + * By setting @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK flag drivers + * can indicate they support offloading EAPOL handshakes for WPA/WPA2 + * preshared key authentication in AP mode. In %NL80211_CMD_START_AP + * the preshared key should be specified using %NL80211_ATTR_PMK. Drivers + * supporting this offload may reject the %NL80211_CMD_START_AP when no + * preshared key material is provided, for example when that driver does + * not support setting the temporal keys through %NL80211_CMD_NEW_KEY. * * For 802.1X the PMK or PMK-R0 are set by providing %NL80211_ATTR_PMK * using %NL80211_CMD_SET_PMK. For offloaded FT support also @@ -234,6 +248,58 @@ * use in a FILS shared key connection with PMKSA caching. */ +/** + * DOC: SAE authentication offload + * + * By setting @NL80211_EXT_FEATURE_SAE_OFFLOAD flag drivers can indicate they + * support offloading SAE authentication for WPA3-Personal networks in station + * mode. Similarly @NL80211_EXT_FEATURE_SAE_OFFLOAD_AP flag can be set by + * drivers indicating the offload support in AP mode. + * + * The password for SAE should be specified using %NL80211_ATTR_SAE_PASSWORD in + * %NL80211_CMD_CONNECT and %NL80211_CMD_START_AP for station and AP mode + * respectively. + */ + +/** + * DOC: VLAN offload support for setting group keys and binding STAs to VLANs + * + * By setting @NL80211_EXT_FEATURE_VLAN_OFFLOAD flag drivers can indicate they + * support offloading VLAN functionality in a manner where the driver exposes a + * single netdev that uses VLAN tagged frames and separate VLAN-specific netdevs + * can then be added using RTM_NEWLINK/IFLA_VLAN_ID similarly to the Ethernet + * case. Frames received from stations that are not assigned to any VLAN are + * delivered on the main netdev and frames to such stations can be sent through + * that main netdev. + * + * %NL80211_CMD_NEW_KEY (for group keys), %NL80211_CMD_NEW_STATION, and + * %NL80211_CMD_SET_STATION will optionally specify vlan_id using + * %NL80211_ATTR_VLAN_ID. + */ + +/** + * DOC: TID configuration + * + * TID config support can be checked in the %NL80211_ATTR_TID_CONFIG + * attribute given in wiphy capabilities. + * + * The necessary configuration parameters are mentioned in + * &enum nl80211_tid_config_attr and it will be passed to the + * %NL80211_CMD_SET_TID_CONFIG command in %NL80211_ATTR_TID_CONFIG. + * + * If the configuration needs to be applied for specific peer then the MAC + * address of the peer needs to be passed in %NL80211_ATTR_MAC, otherwise the + * configuration will be applied for all the connected peers in the vif except + * any peers that have peer specific configuration for the TID by default; if + * the %NL80211_TID_CONFIG_ATTR_OVERRIDE flag is set, peer specific values + * will be overwritten. + * + * All this configuration is valid only for STA's current connection + * i.e. the configuration will be reset to default when the STA connects back + * after disconnection/roaming, and this configuration will be cleared when + * the interface goes down. + */ + /** * enum nl80211_commands - supported nl80211 commands * @@ -243,13 +309,14 @@ * to get a list of all present wiphys. * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME, - * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ (and the - * attributes determining the channel width; this is used for setting - * monitor mode channel), %NL80211_ATTR_WIPHY_RETRY_SHORT, - * %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD, - * and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD. - * However, for setting the channel, see %NL80211_CMD_SET_CHANNEL - * instead, the support here is for backward compatibility only. + * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ, + * %NL80211_ATTR_WIPHY_FREQ_OFFSET (and the attributes determining the + * channel width; this is used for setting monitor mode channel), + * %NL80211_ATTR_WIPHY_RETRY_SHORT, %NL80211_ATTR_WIPHY_RETRY_LONG, + * %NL80211_ATTR_WIPHY_FRAG_THRESHOLD, and/or + * %NL80211_ATTR_WIPHY_RTS_THRESHOLD. However, for setting the channel, + * see %NL80211_CMD_SET_CHANNEL instead, the support here is for backward + * compatibility only. * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request * or rename notification. Has attributes %NL80211_ATTR_WIPHY and * %NL80211_ATTR_WIPHY_NAME. @@ -298,7 +365,8 @@ * %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_INACTIVITY_TIMEOUT, * %NL80211_ATTR_ACL_POLICY and %NL80211_ATTR_MAC_ADDRS. * The channel to use can be set on the interface or be given using the - * %NL80211_ATTR_WIPHY_FREQ and the attributes determining channel width. + * %NL80211_ATTR_WIPHY_FREQ and %NL80211_ATTR_WIPHY_FREQ_OFFSET, and the + * attributes determining channel width. * @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP * @NL80211_CMD_STOP_AP: Stop AP operation on the given interface * @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP @@ -308,7 +376,7 @@ * @NL80211_CMD_SET_STATION: Set station attributes for station identified by * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. * @NL80211_CMD_NEW_STATION: Add a station with given attributes to the - * the interface identified by %NL80211_ATTR_IFINDEX. + * interface identified by %NL80211_ATTR_IFINDEX. * @NL80211_CMD_DEL_STATION: Remove a station identified by %NL80211_ATTR_MAC * or, if no MAC address given, all stations, on the interface identified * by %NL80211_ATTR_IFINDEX. %NL80211_ATTR_MGMT_SUBTYPE and @@ -328,7 +396,7 @@ * @NL80211_CMD_DEL_MPATH: Delete a mesh path to the destination given by * %NL80211_ATTR_MAC. * @NL80211_CMD_NEW_PATH: Add a mesh path with given attributes to the - * the interface identified by %NL80211_ATTR_IFINDEX. + * interface identified by %NL80211_ATTR_IFINDEX. * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC * or, if no MAC address given, all mesh paths, on the interface identified * by %NL80211_ATTR_IFINDEX. @@ -483,11 +551,12 @@ * interface. %NL80211_ATTR_MAC is used to specify PeerSTAAddress (and * BSSID in case of station mode). %NL80211_ATTR_SSID is used to specify * the SSID (mainly for association, but is included in authentication - * request, too, to help BSS selection. %NL80211_ATTR_WIPHY_FREQ is used - * to specify the frequence of the channel in MHz. %NL80211_ATTR_AUTH_TYPE - * is used to specify the authentication type. %NL80211_ATTR_IE is used to - * define IEs (VendorSpecificInfo, but also including RSN IE and FT IEs) - * to be added to the frame. + * request, too, to help BSS selection. %NL80211_ATTR_WIPHY_FREQ + + * %NL80211_ATTR_WIPHY_FREQ_OFFSET is used to specify the frequence of the + * channel in MHz. %NL80211_ATTR_AUTH_TYPE is used to specify the + * authentication type. %NL80211_ATTR_IE is used to define IEs + * (VendorSpecificInfo, but also including RSN IE and FT IEs) to be added + * to the frame. * When used as an event, this reports reception of an Authentication * frame in station and IBSS modes when the local MLME processed the * frame, i.e., it was for the local STA and was received in correct @@ -542,8 +611,9 @@ * requests to connect to a specified network but without separating * auth and assoc steps. For this, you need to specify the SSID in a * %NL80211_ATTR_SSID attribute, and can optionally specify the association - * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_USE_MFP, - * %NL80211_ATTR_MAC, %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT, + * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, + * %NL80211_ATTR_USE_MFP, %NL80211_ATTR_MAC, %NL80211_ATTR_WIPHY_FREQ, + * %NL80211_ATTR_WIPHY_FREQ_OFFSET, %NL80211_ATTR_CONTROL_PORT, * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT, * %NL80211_ATTR_CONTROL_PORT_OVER_NL80211, %NL80211_ATTR_MAC_HINT, and @@ -557,6 +627,14 @@ * set of BSSID,frequency parameters is used (i.e., either the enforcing * %NL80211_ATTR_MAC,%NL80211_ATTR_WIPHY_FREQ or the less strict * %NL80211_ATTR_MAC_HINT and %NL80211_ATTR_WIPHY_FREQ_HINT). + * Driver shall not modify the IEs specified through %NL80211_ATTR_IE if + * %NL80211_ATTR_MAC is included. However, if %NL80211_ATTR_MAC_HINT is + * included, these IEs through %NL80211_ATTR_IE are specified by the user + * space based on the best possible BSS selected. Thus, if the driver ends + * up selecting a different BSS, it can modify these IEs accordingly (e.g. + * userspace asks the driver to perform PMKSA caching with BSS1 and the + * driver ends up selecting BSS2 with different PMKSA cache entry; RSNIE + * has to get updated with the apt PMKID). * %NL80211_ATTR_PREV_BSSID can be used to request a reassociation within * the ESS in case the device is already associated and an association with * a different BSS is desired. @@ -573,14 +651,13 @@ * authentication/association or not receiving a response from the AP. * Non-zero %NL80211_ATTR_STATUS_CODE value is indicated in that case as * well to remain backwards compatible. - * When establishing a security association, drivers that support 4 way - * handshake offload should send %NL80211_CMD_PORT_AUTHORIZED event when - * the 4 way handshake is completed successfully. * @NL80211_CMD_ROAM: Notification indicating the card/driver roamed by itself. - * When a security association was established with the new AP (e.g. if - * the FT protocol was used for roaming or the driver completed the 4 way - * handshake), this event should be followed by an + * When a security association was established on an 802.1X network using + * fast transition, this event should be followed by an * %NL80211_CMD_PORT_AUTHORIZED event. + * Following a %NL80211_CMD_ROAM event userspace can issue + * %NL80211_CMD_GET_SCAN in order to obtain the scan information for the + * new BSS the card/driver roamed to. * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify * userspace that a connection was dropped by the AP or due to other * reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and @@ -626,6 +703,10 @@ * four bytes for vendor frames including the OUI. The registration * cannot be dropped, but is removed automatically when the netlink * socket is closed. Multiple registrations can be made. + * The %NL80211_ATTR_RECEIVE_MULTICAST flag attribute can be given if + * %NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS is available, in which + * case the registration can also be modified to include/exclude the + * flag, rather than requiring unregistration to change it. * @NL80211_CMD_REGISTER_ACTION: Alias for @NL80211_CMD_REGISTER_FRAME for * backward compatibility * @NL80211_CMD_FRAME: Management frame TX request and RX notification. This @@ -648,7 +729,9 @@ * is used during CSA period. * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this * command may be used with the corresponding cookie to cancel the wait - * time if it is known that it is no longer necessary. + * time if it is known that it is no longer necessary. This command is + * also sent as an event whenever the driver has completed the off-channel + * wait time. * @NL80211_CMD_ACTION: Alias for @NL80211_CMD_FRAME for backward compatibility. * @NL80211_CMD_FRAME_TX_STATUS: Report TX status of a management frame * transmitted with %NL80211_CMD_FRAME. %NL80211_ATTR_COOKIE identifies @@ -677,7 +760,8 @@ * of any other interfaces, and other interfaces will again take * precedence when they are used. * - * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface. + * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface + * (no longer supported). * * @NL80211_CMD_SET_MULTICAST_TO_UNICAST: Configure if this AP should perform * multicast to unicast conversion. When enabled, all multicast packets @@ -723,7 +807,7 @@ * various triggers. These triggers can be configured through this * command with the %NL80211_ATTR_WOWLAN_TRIGGERS attribute. For * more background information, see - * http://wireless.kernel.org/en/users/Documentation/WoWLAN. + * https://wireless.wiki.kernel.org/en/users/Documentation/WoWLAN. * The @NL80211_CMD_SET_WOWLAN command can also be used as a notification * from the driver reporting the wakeup reason. In this case, the * @NL80211_ATTR_WOWLAN_TRIGGERS attribute will contain the reason @@ -863,7 +947,7 @@ * @NL80211_CMD_SET_COALESCE: Configure coalesce rules or clear existing rules. * * @NL80211_CMD_CHANNEL_SWITCH: Perform a channel switch by announcing the - * the new channel information (Channel Switch Announcement - CSA) + * new channel information (Channel Switch Announcement - CSA) * in the beacon for some time (as defined in the * %NL80211_ATTR_CH_SWITCH_COUNT parameter) and then change to the * new channel. Userspace provides the new channel information (using @@ -987,13 +1071,11 @@ * @NL80211_CMD_DEL_PMK: For offloaded 4-Way handshake, delete the previously * configured PMK for the authenticator address identified by * %NL80211_ATTR_MAC. - * @NL80211_CMD_PORT_AUTHORIZED: An event that indicates that the 4 way - * handshake was completed successfully by the driver. The BSSID is - * specified with %NL80211_ATTR_MAC. Drivers that support 4 way handshake - * offload should send this event after indicating 802.11 association with - * %NL80211_CMD_CONNECT or %NL80211_CMD_ROAM. If the 4 way handshake failed - * %NL80211_CMD_DISCONNECT should be indicated instead. - * + * @NL80211_CMD_PORT_AUTHORIZED: An event that indicates an 802.1X FT roam was + * completed successfully. Drivers that support 4 way handshake offload + * should send this event after indicating 802.1X FT assocation with + * %NL80211_CMD_ROAM. If the 4 way handshake failed %NL80211_CMD_DISCONNECT + * should be indicated instead. * @NL80211_CMD_CONTROL_PORT_FRAME: Control Port (e.g. PAE) frame TX request * and RX notification. This command is used both as a request to transmit * a control port frame and as a notification that a control port frame @@ -1033,6 +1115,76 @@ * %NL80211_ATTR_CHANNEL_WIDTH,%NL80211_ATTR_NSS attributes with its * address(specified in %NL80211_ATTR_MAC). * + * @NL80211_CMD_GET_FTM_RESPONDER_STATS: Retrieve FTM responder statistics, in + * the %NL80211_ATTR_FTM_RESPONDER_STATS attribute. + * + * @NL80211_CMD_PEER_MEASUREMENT_START: start a (set of) peer measurement(s) + * with the given parameters, which are encapsulated in the nested + * %NL80211_ATTR_PEER_MEASUREMENTS attribute. Optionally, MAC address + * randomization may be enabled and configured by specifying the + * %NL80211_ATTR_MAC and %NL80211_ATTR_MAC_MASK attributes. + * If a timeout is requested, use the %NL80211_ATTR_TIMEOUT attribute. + * A u64 cookie for further %NL80211_ATTR_COOKIE use is returned in + * the netlink extended ack message. + * + * To cancel a measurement, close the socket that requested it. + * + * Measurement results are reported to the socket that requested the + * measurement using @NL80211_CMD_PEER_MEASUREMENT_RESULT when they + * become available, so applications must ensure a large enough socket + * buffer size. + * + * Depending on driver support it may or may not be possible to start + * multiple concurrent measurements. + * @NL80211_CMD_PEER_MEASUREMENT_RESULT: This command number is used for the + * result notification from the driver to the requesting socket. + * @NL80211_CMD_PEER_MEASUREMENT_COMPLETE: Notification only, indicating that + * the measurement completed, using the measurement cookie + * (%NL80211_ATTR_COOKIE). + * + * @NL80211_CMD_NOTIFY_RADAR: Notify the kernel that a radar signal was + * detected and reported by a neighboring device on the channel + * indicated by %NL80211_ATTR_WIPHY_FREQ and other attributes + * determining the width and type. + * + * @NL80211_CMD_UPDATE_OWE_INFO: This interface allows the host driver to + * offload OWE processing to user space. This intends to support + * OWE AKM by the host drivers that implement SME but rely + * on the user space for the cryptographic/DH IE processing in AP mode. + * + * @NL80211_CMD_PROBE_MESH_LINK: The requirement for mesh link metric + * refreshing, is that from one mesh point we be able to send some data + * frames to other mesh points which are not currently selected as a + * primary traffic path, but which are only 1 hop away. The absence of + * the primary path to the chosen node makes it necessary to apply some + * form of marking on a chosen packet stream so that the packets can be + * properly steered to the selected node for testing, and not by the + * regular mesh path lookup. Further, the packets must be of type data + * so that the rate control (often embedded in firmware) is used for + * rate selection. + * + * Here attribute %NL80211_ATTR_MAC is used to specify connected mesh + * peer MAC address and %NL80211_ATTR_FRAME is used to specify the frame + * content. The frame is ethernet data. + * + * @NL80211_CMD_SET_TID_CONFIG: Data frame TID specific configuration + * is passed using %NL80211_ATTR_TID_CONFIG attribute. + * + * @NL80211_CMD_UNPROT_BEACON: Unprotected or incorrectly protected Beacon + * frame. This event is used to indicate that a received Beacon frame was + * dropped because it did not include a valid MME MIC while beacon + * protection was enabled (BIGTK configured in station mode). + * + * @NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS: Report TX status of a control + * port frame transmitted with %NL80211_CMD_CONTROL_PORT_FRAME. + * %NL80211_ATTR_COOKIE identifies the TX command and %NL80211_ATTR_FRAME + * includes the contents of the frame. %NL80211_ATTR_ACK flag is included + * if the recipient acknowledged the frame. + * + * @NL80211_CMD_SET_SAR_SPECS: SAR power limitation configuration is + * passed using %NL80211_ATTR_SAR_SPEC. %NL80211_ATTR_WIPHY is used to + * specify the wiphy index to be applied to. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -1245,6 +1397,26 @@ enum nl80211_commands { NL80211_CMD_CONTROL_PORT_FRAME, + NL80211_CMD_GET_FTM_RESPONDER_STATS, + + NL80211_CMD_PEER_MEASUREMENT_START, + NL80211_CMD_PEER_MEASUREMENT_RESULT, + NL80211_CMD_PEER_MEASUREMENT_COMPLETE, + + NL80211_CMD_NOTIFY_RADAR, + + NL80211_CMD_UPDATE_OWE_INFO, + + NL80211_CMD_PROBE_MESH_LINK, + + NL80211_CMD_SET_TID_CONFIG, + + NL80211_CMD_UNPROT_BEACON, + + NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS, + + NL80211_CMD_SET_SAR_SPECS, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -1290,7 +1462,8 @@ enum nl80211_commands { * of &enum nl80211_chan_width, describing the channel width. See the * documentation of the enum for more information. * @NL80211_ATTR_CENTER_FREQ1: Center frequency of the first part of the - * channel, used for anything but 20 MHz bandwidth + * channel, used for anything but 20 MHz bandwidth. In S1G this is the + * operating channel center frequency. * @NL80211_ATTR_CENTER_FREQ2: Center frequency of the second part of the * channel, used only for 80+80 MHz bandwidth * @NL80211_ATTR_WIPHY_CHANNEL_TYPE: included with NL80211_ATTR_WIPHY_FREQ @@ -1355,7 +1528,7 @@ enum nl80211_commands { * rates as defined by IEEE 802.11 7.3.2.2 but without the length * restriction (at most %NL80211_MAX_SUPP_RATES). * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station - * to, or the AP interface the station was originally added to to. + * to, or the AP interface the station was originally added to. * @NL80211_ATTR_STA_INFO: information about a station, part of station info * given for %NL80211_CMD_GET_STATION, nested attribute containing * info as possible, see &enum nl80211_sta_info. @@ -1500,7 +1673,8 @@ enum nl80211_commands { * flag is included, then control port frames are sent over NL80211 instead * using %CMD_CONTROL_PORT_FRAME. If control port routing over NL80211 is * to be used then userspace must also use the %NL80211_ATTR_SOCKET_OWNER - * flag. + * flag. When used with %NL80211_ATTR_CONTROL_PORT_NO_PREAUTH, pre-auth + * frames are not forwared over the control port. * * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver. * We recommend using nested, driver-specific attributes within this. @@ -1525,6 +1699,12 @@ enum nl80211_commands { * (a u32 with flags from &enum nl80211_wpa_versions). * @NL80211_ATTR_AKM_SUITES: Used with CONNECT, ASSOCIATE, and NEW_BEACON to * indicate which key management algorithm(s) to use (an array of u32). + * This attribute is also sent in response to @NL80211_CMD_GET_WIPHY, + * indicating the supported AKM suites, intended for specific drivers which + * implement SME and have constraints on which AKMs are supported and also + * the cases where an AKM support is offloaded to the driver/firmware. + * If there is no such notification from the driver, user space should + * assume the driver supports all the AKM suites. * * @NL80211_ATTR_REQ_IE: (Re)association request information elements as * sent out by the card, for ROAM and successful CONNECT events. @@ -1580,8 +1760,9 @@ enum nl80211_commands { * specify just a single bitrate, which is to be used for the beacon. * The driver must also specify support for this with the extended * features NL80211_EXT_FEATURE_BEACON_RATE_LEGACY, - * NL80211_EXT_FEATURE_BEACON_RATE_HT and - * NL80211_EXT_FEATURE_BEACON_RATE_VHT. + * NL80211_EXT_FEATURE_BEACON_RATE_HT, + * NL80211_EXT_FEATURE_BEACON_RATE_VHT and + * NL80211_EXT_FEATURE_BEACON_RATE_HE. * * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain * at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME. @@ -1701,7 +1882,7 @@ enum nl80211_commands { * the values passed in @NL80211_ATTR_SCAN_SSIDS (eg. if an SSID * is included in the probe request, but the match attributes * will never let it go through), -EINVAL may be returned. - * If ommited, no filtering is done. + * If omitted, no filtering is done. * * @NL80211_ATTR_INTERFACE_COMBINATIONS: Nested attribute listing the supported * interface combinations. In each nested item, it contains attributes @@ -1785,8 +1966,15 @@ enum nl80211_commands { * @NL80211_ATTR_PROBE_RESP: Probe Response template data. Contains the entire * probe-response frame. The DA field in the 802.11 header is zero-ed out, * to be filled by the FW. - * @NL80211_ATTR_DISABLE_HT: Force HT capable interfaces to disable - * this feature. Currently, only supported in mac80211 drivers. + * @NL80211_ATTR_DISABLE_HT: Force HT capable interfaces to disable + * this feature during association. This is a flag attribute. + * Currently only supported in mac80211 drivers. + * @NL80211_ATTR_DISABLE_VHT: Force VHT capable interfaces to disable + * this feature during association. This is a flag attribute. + * Currently only supported in mac80211 drivers. + * @NL80211_ATTR_DISABLE_HE: Force HE capable interfaces to disable + * this feature during association. This is a flag attribute. + * Currently only supported in mac80211 drivers. * @NL80211_ATTR_HT_CAPABILITY_MASK: Specify which bits of the * ATTR_HT_CAPABILITY to which attention should be paid. * Currently, only mac80211 NICs support this feature. @@ -1806,7 +1994,7 @@ enum nl80211_commands { * * @NL80211_ATTR_INACTIVITY_TIMEOUT: timeout value in seconds, this can be * used by the drivers which has MLME in firmware and does not have support - * to report per station tx/rx activity to free up the staion entry from + * to report per station tx/rx activity to free up the station entry from * the list. This needs to be used when the driver advertises the * capability to timeout the stations. * @@ -1907,13 +2095,14 @@ enum nl80211_commands { * until the channel switch event. * @NL80211_ATTR_CH_SWITCH_BLOCK_TX: flag attribute specifying that transmission * must be blocked on the current channel (before the channel switch - * operation). + * operation). Also included in the channel switch started event if quiet + * was requested by the AP. * @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information * for the time while performing a channel switch. - * @NL80211_ATTR_CSA_C_OFF_BEACON: An array of offsets (u16) to the channel - * switch counters in the beacons tail (%NL80211_ATTR_BEACON_TAIL). - * @NL80211_ATTR_CSA_C_OFF_PRESP: An array of offsets (u16) to the channel - * switch counters in the probe response (%NL80211_ATTR_PROBE_RESP). + * @NL80211_ATTR_CNTDWN_OFFS_BEACON: An array of offsets (u16) to the channel + * switch or color change counters in the beacons tail (%NL80211_ATTR_BEACON_TAIL). + * @NL80211_ATTR_CNTDWN_OFFS_PRESP: An array of offsets (u16) to the channel + * switch or color change counters in the probe response (%NL80211_ATTR_PROBE_RESP). * * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32. * As specified in the &enum nl80211_rxmgmt_flags. @@ -1921,7 +2110,7 @@ enum nl80211_commands { * @NL80211_ATTR_STA_SUPPORTED_CHANNELS: array of supported channels. * * @NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES: array of supported - * supported operating classes. + * operating classes. * * @NL80211_ATTR_HANDLE_DFS: A flag indicating whether user space * controls DFS operation in IBSS mode. If the flag is included in @@ -2167,7 +2356,7 @@ enum nl80211_commands { * * @NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST: When present the RSSI level for BSSs in * the specified band is to be adjusted before doing - * %NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI based comparision to figure out + * %NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI based comparison to figure out * better BSSs. The attribute value is a packed structure * value as specified by &struct nl80211_bss_select_rssi_adjust. * @@ -2199,10 +2388,11 @@ enum nl80211_commands { * * @NL80211_ATTR_PMK: attribute for passing PMK key material. Used with * %NL80211_CMD_SET_PMKSA for the PMKSA identified by %NL80211_ATTR_PMKID. - * For %NL80211_CMD_CONNECT it is used to provide PSK for offloading 4-way - * handshake for WPA/WPA2-PSK networks. For 802.1X authentication it is - * used with %NL80211_CMD_SET_PMK. For offloaded FT support this attribute - * specifies the PMK-R0 if NL80211_ATTR_PMKR0_NAME is included as well. + * For %NL80211_CMD_CONNECT and %NL80211_CMD_START_AP it is used to provide + * PSK for offloading 4-way handshake for WPA/WPA2-PSK networks. For 802.1X + * authentication it is used with %NL80211_CMD_SET_PMK. For offloaded FT + * support this attribute specifies the PMK-R0 if NL80211_ATTR_PMKR0_NAME + * is included as well. * * @NL80211_ATTR_SCHED_SCAN_MULTI: flag attribute which user-space shall use to * indicate that it supports multiple active scheduled scan requests. @@ -2220,10 +2410,10 @@ enum nl80211_commands { * &enum nl80211_external_auth_action value). This is used with the * %NL80211_CMD_EXTERNAL_AUTH request event. * @NL80211_ATTR_EXTERNAL_AUTH_SUPPORT: Flag attribute indicating that the user - * space supports external authentication. This attribute shall be used - * only with %NL80211_CMD_CONNECT request. The driver may offload - * authentication processing to user space if this capability is indicated - * in NL80211_CMD_CONNECT requests from the user space. + * space supports external authentication. This attribute shall be used + * with %NL80211_CMD_CONNECT and %NL80211_CMD_START_AP request. The driver + * may offload authentication processing to user space if this capability + * is indicated in the respective requests from the user space. * * @NL80211_ATTR_NSS: Station's New/updated RX_NSS value notified using this * u8 attribute. This is used with %NL80211_CMD_STA_OPMODE_CHANGED. @@ -2232,7 +2422,7 @@ enum nl80211_commands { * nl80211_txq_stats) * @NL80211_ATTR_TXQ_LIMIT: Total packet limit for the TXQ queues for this phy. * The smaller of this and the memory limit is enforced. - * @NL80211_ATTR_TXQ_MEMORY_LIMIT: Total memory memory limit (in bytes) for the + * @NL80211_ATTR_TXQ_MEMORY_LIMIT: Total memory limit (in bytes) for the * TXQ queues for this phy. The smaller of this and the packet limit is * enforced. * @NL80211_ATTR_TXQ_QUANTUM: TXQ scheduler quantum (bytes). Number of bytes @@ -2241,6 +2431,135 @@ enum nl80211_commands { * association request when used with NL80211_CMD_NEW_STATION). Can be set * only if %NL80211_STA_FLAG_WME is set. * + * @NL80211_ATTR_FTM_RESPONDER: nested attribute which user-space can include + * in %NL80211_CMD_START_AP or %NL80211_CMD_SET_BEACON for fine timing + * measurement (FTM) responder functionality and containing parameters as + * possible, see &enum nl80211_ftm_responder_attr + * + * @NL80211_ATTR_FTM_RESPONDER_STATS: Nested attribute with FTM responder + * statistics, see &enum nl80211_ftm_responder_stats. + * + * @NL80211_ATTR_TIMEOUT: Timeout for the given operation in milliseconds (u32), + * if the attribute is not given no timeout is requested. Note that 0 is an + * invalid value. + * + * @NL80211_ATTR_PEER_MEASUREMENTS: peer measurements request (and result) + * data, uses nested attributes specified in + * &enum nl80211_peer_measurement_attrs. + * This is also used for capability advertisement in the wiphy information, + * with the appropriate sub-attributes. + * + * @NL80211_ATTR_AIRTIME_WEIGHT: Station's weight when scheduled by the airtime + * scheduler. + * + * @NL80211_ATTR_STA_TX_POWER_SETTING: Transmit power setting type (u8) for + * station associated with the AP. See &enum nl80211_tx_power_setting for + * possible values. + * @NL80211_ATTR_STA_TX_POWER: Transmit power level (s16) in dBm units. This + * allows to set Tx power for a station. If this attribute is not included, + * the default per-interface tx power setting will be overriding. Driver + * should be picking up the lowest tx power, either tx power per-interface + * or per-station. + * + * @NL80211_ATTR_SAE_PASSWORD: attribute for passing SAE password material. It + * is used with %NL80211_CMD_CONNECT to provide password for offloading + * SAE authentication for WPA3-Personal networks. + * + * @NL80211_ATTR_TWT_RESPONDER: Enable target wait time responder support. + * + * @NL80211_ATTR_HE_OBSS_PD: nested attribute for OBSS Packet Detection + * functionality. + * + * @NL80211_ATTR_WIPHY_EDMG_CHANNELS: bitmap that indicates the 2.16 GHz + * channel(s) that are allowed to be used for EDMG transmissions. + * Defined by IEEE P802.11ay/D4.0 section 9.4.2.251. (u8 attribute) + * @NL80211_ATTR_WIPHY_EDMG_BW_CONFIG: Channel BW Configuration subfield encodes + * the allowed channel bandwidth configurations. (u8 attribute) + * Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13. + * + * @NL80211_ATTR_VLAN_ID: VLAN ID (1..4094) for the station and VLAN group key + * (u16). + * + * @NL80211_ATTR_HE_BSS_COLOR: nested attribute for BSS Color Settings. + * + * @NL80211_ATTR_IFTYPE_AKM_SUITES: nested array attribute, with each entry + * using attributes from &enum nl80211_iftype_akm_attributes. This + * attribute is sent in a response to %NL80211_CMD_GET_WIPHY indicating + * supported AKM suites capability per interface. AKMs advertised in + * %NL80211_ATTR_AKM_SUITES are default capabilities if AKM suites not + * advertised for a specific interface type. + * + * @NL80211_ATTR_TID_CONFIG: TID specific configuration in a + * nested attribute with &enum nl80211_tid_config_attr sub-attributes; + * on output (in wiphy attributes) it contains only the feature sub- + * attributes. + * + * @NL80211_ATTR_CONTROL_PORT_NO_PREAUTH: disable preauth frame rx on control + * port in order to forward/receive them as ordinary data frames. + * + * @NL80211_ATTR_PMK_LIFETIME: Maximum lifetime for PMKSA in seconds (u32, + * dot11RSNAConfigPMKReauthThreshold; 0 is not a valid value). + * An optional parameter configured through %NL80211_CMD_SET_PMKSA. + * Drivers that trigger roaming need to know the lifetime of the + * configured PMKSA for triggering the full vs. PMKSA caching based + * authentication. This timeout helps authentication methods like SAE, + * where PMK gets updated only by going through a full (new SAE) + * authentication instead of getting updated during an association for EAP + * authentication. No new full authentication within the PMK expiry shall + * result in a disassociation at the end of the lifetime. + * + * @NL80211_ATTR_PMK_REAUTH_THRESHOLD: Reauthentication threshold time, in + * terms of percentage of %NL80211_ATTR_PMK_LIFETIME + * (u8, dot11RSNAConfigPMKReauthThreshold, 1..100). This is an optional + * parameter configured through %NL80211_CMD_SET_PMKSA. Requests the + * driver to trigger a full authentication roam (without PMKSA caching) + * after the reauthentication threshold time, but before the PMK lifetime + * has expired. + * + * Authentication methods like SAE need to be able to generate a new PMKSA + * entry without having to force a disconnection after the PMK timeout. If + * no roaming occurs between the reauth threshold and PMK expiration, + * disassociation is still forced. + * @NL80211_ATTR_RECEIVE_MULTICAST: multicast flag for the + * %NL80211_CMD_REGISTER_FRAME command, see the description there. + * @NL80211_ATTR_WIPHY_FREQ_OFFSET: offset of the associated + * %NL80211_ATTR_WIPHY_FREQ in positive KHz. Only valid when supplied with + * an %NL80211_ATTR_WIPHY_FREQ_OFFSET. + * @NL80211_ATTR_CENTER_FREQ1_OFFSET: Center frequency offset in KHz for the + * first channel segment specified in %NL80211_ATTR_CENTER_FREQ1. + * @NL80211_ATTR_SCAN_FREQ_KHZ: nested attribute with KHz frequencies + * + * @NL80211_ATTR_HE_6GHZ_CAPABILITY: HE 6 GHz Band Capability element (from + * association request when used with NL80211_CMD_NEW_STATION). + * + * @NL80211_ATTR_FILS_DISCOVERY: Optional parameter to configure FILS + * discovery. It is a nested attribute, see + * &enum nl80211_fils_discovery_attributes. + * + * @NL80211_ATTR_UNSOL_BCAST_PROBE_RESP: Optional parameter to configure + * unsolicited broadcast probe response. It is a nested attribute, see + * &enum nl80211_unsol_bcast_probe_resp_attributes. + * + * @NL80211_ATTR_S1G_CAPABILITY: S1G Capability information element (from + * association request when used with NL80211_CMD_NEW_STATION) + * @NL80211_ATTR_S1G_CAPABILITY_MASK: S1G Capability Information element + * override mask. Used with NL80211_ATTR_S1G_CAPABILITY in + * NL80211_CMD_ASSOCIATE or NL80211_CMD_CONNECT. + * + * @NL80211_ATTR_SAE_PWE: Indicates the mechanism(s) allowed for SAE PWE + * derivation in WPA3-Personal networks which are using SAE authentication. + * This is a u8 attribute that encapsulates one of the values from + * &enum nl80211_sae_pwe_mechanism. + * + * @NL80211_ATTR_SAR_SPEC: SAR power limitation specification when + * used with %NL80211_CMD_SET_SAR_SPECS. The message contains fields + * of %nl80211_sar_attrs which specifies the sar type and related + * sar specs. Sar specs contains array of %nl80211_sar_specs_attrs. + * + * @NL80211_ATTR_RECONNECT_REQUESTED: flag attribute, used with deauth and + * disassoc events to indicate that an immediate reconnect to the AP + * is desired. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2547,8 +2866,8 @@ enum nl80211_attrs { NL80211_ATTR_CH_SWITCH_COUNT, NL80211_ATTR_CH_SWITCH_BLOCK_TX, NL80211_ATTR_CSA_IES, - NL80211_ATTR_CSA_C_OFF_BEACON, - NL80211_ATTR_CSA_C_OFF_PRESP, + NL80211_ATTR_CNTDWN_OFFS_BEACON, + NL80211_ATTR_CNTDWN_OFFS_PRESP, NL80211_ATTR_RXMGMT_FLAGS, @@ -2682,8 +3001,65 @@ enum nl80211_attrs { NL80211_ATTR_HE_CAPABILITY, - /* NOTE: Make sure this is in sync with hostap's nl80211_copy.h */ - NL80211_ATTR_STA_ROAMED = 277, + NL80211_ATTR_FTM_RESPONDER, + + NL80211_ATTR_FTM_RESPONDER_STATS, + + NL80211_ATTR_TIMEOUT, + + NL80211_ATTR_PEER_MEASUREMENTS, + + NL80211_ATTR_AIRTIME_WEIGHT, + NL80211_ATTR_STA_TX_POWER_SETTING, + NL80211_ATTR_STA_TX_POWER, + + NL80211_ATTR_SAE_PASSWORD, + + NL80211_ATTR_TWT_RESPONDER, + + NL80211_ATTR_HE_OBSS_PD, + + NL80211_ATTR_WIPHY_EDMG_CHANNELS, + NL80211_ATTR_WIPHY_EDMG_BW_CONFIG, + + NL80211_ATTR_VLAN_ID, + + NL80211_ATTR_HE_BSS_COLOR, + + NL80211_ATTR_IFTYPE_AKM_SUITES, + + NL80211_ATTR_TID_CONFIG, + + NL80211_ATTR_CONTROL_PORT_NO_PREAUTH, + + NL80211_ATTR_PMK_LIFETIME, + NL80211_ATTR_PMK_REAUTH_THRESHOLD, + + NL80211_ATTR_RECEIVE_MULTICAST, + NL80211_ATTR_WIPHY_FREQ_OFFSET, + NL80211_ATTR_CENTER_FREQ1_OFFSET, + NL80211_ATTR_SCAN_FREQ_KHZ, + + NL80211_ATTR_HE_6GHZ_CAPABILITY, + + NL80211_ATTR_FILS_DISCOVERY, + + NL80211_ATTR_UNSOL_BCAST_PROBE_RESP, + + NL80211_ATTR_S1G_CAPABILITY, + NL80211_ATTR_S1G_CAPABILITY_MASK, + + NL80211_ATTR_SAE_PWE, + + NL80211_ATTR_RECONNECT_REQUESTED, + + NL80211_ATTR_SAR_SPEC, + + NL80211_ATTR_DISABLE_HE, + + /* UBNT Attributes + * include userspace $(STAGING_DIR)/usr/include/linux/nl80211_actual.h */ + NL80211_ATTR_STA_ROAMED, /* add attributes here, update the policy in nl80211.c */ @@ -2697,6 +3073,8 @@ enum nl80211_attrs { #define NL80211_ATTR_MESH_PARAMS NL80211_ATTR_MESH_CONFIG #define NL80211_ATTR_IFACE_SOCKET_OWNER NL80211_ATTR_SOCKET_OWNER #define NL80211_ATTR_SAE_DATA NL80211_ATTR_AUTH_DATA +#define NL80211_ATTR_CSA_C_OFF_BEACON NL80211_ATTR_CNTDWN_OFFS_BEACON +#define NL80211_ATTR_CSA_C_OFF_PRESP NL80211_ATTR_CNTDWN_OFFS_PRESP /* * Allow user space programs to use #ifdef on new attributes by defining them @@ -2728,7 +3106,7 @@ enum nl80211_attrs { #define NL80211_MAX_SUPP_RATES 32 #define NL80211_MAX_SUPP_HT_RATES 77 -#define NL80211_MAX_SUPP_REG_RULES 64 +#define NL80211_MAX_SUPP_REG_RULES 128 #define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0 #define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 #define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 @@ -2874,6 +3252,18 @@ enum nl80211_he_gi { NL80211_RATE_INFO_HE_GI_3_2, }; +/** + * enum nl80211_he_ltf - HE long training field + * @NL80211_RATE_INFO_HE_1xLTF: 3.2 usec + * @NL80211_RATE_INFO_HE_2xLTF: 6.4 usec + * @NL80211_RATE_INFO_HE_4xLTF: 12.8 usec + */ +enum nl80211_he_ltf { + NL80211_RATE_INFO_HE_1XLTF, + NL80211_RATE_INFO_HE_2XLTF, + NL80211_RATE_INFO_HE_4XLTF, +}; + /** * enum nl80211_he_ru_alloc - HE RU allocation values * @NL80211_RATE_INFO_HE_RU_ALLOC_26: 26-tone RU allocation @@ -3053,8 +3443,23 @@ enum nl80211_sta_bss_param { * received from the station (u64, usec) * @NL80211_STA_INFO_PAD: attribute used for padding for 64-bit alignment * @NL80211_STA_INFO_ACK_SIGNAL: signal strength of the last ACK frame(u8, dBm) - * @NL80211_STA_INFO_DATA_ACK_SIGNAL_AVG: avg signal strength of (data) - * ACK frame (s8, dBm) + * @NL80211_STA_INFO_ACK_SIGNAL_AVG: avg signal strength of ACK frames (s8, dBm) + * @NL80211_STA_INFO_RX_MPDUS: total number of received packets (MPDUs) + * (u32, from this station) + * @NL80211_STA_INFO_FCS_ERROR_COUNT: total number of packets (MPDUs) received + * with an FCS error (u32, from this station). This count may not include + * some packets with an FCS error due to TA corruption. Hence this counter + * might not be fully accurate. + * @NL80211_STA_INFO_CONNECTED_TO_GATE: set to true if STA has a path to a + * mesh gate (u8, 0 or 1) + * @NL80211_STA_INFO_TX_DURATION: aggregate PPDU duration for all frames + * sent to the station (u64, usec) + * @NL80211_STA_INFO_AIRTIME_WEIGHT: current airtime weight for station (u16) + * @NL80211_STA_INFO_AIRTIME_LINK_METRIC: airtime link metric for mesh station + * @NL80211_STA_INFO_ASSOC_AT_BOOTTIME: Timestamp (CLOCK_BOOTTIME, nanoseconds) + * of STA's association + * @NL80211_STA_INFO_CONNECTED_TO_AS: set to true if STA has a path to a + * authentication server (u8, 0 or 1) * @__NL80211_STA_INFO_AFTER_LAST: internal * @NL80211_STA_INFO_MAX: highest possible station info attribute */ @@ -3094,13 +3499,25 @@ enum nl80211_sta_info { NL80211_STA_INFO_RX_DURATION, NL80211_STA_INFO_PAD, NL80211_STA_INFO_ACK_SIGNAL, - NL80211_STA_INFO_DATA_ACK_SIGNAL_AVG, + NL80211_STA_INFO_ACK_SIGNAL_AVG, + NL80211_STA_INFO_RX_MPDUS, + NL80211_STA_INFO_FCS_ERROR_COUNT, + NL80211_STA_INFO_CONNECTED_TO_GATE, + NL80211_STA_INFO_TX_DURATION, + NL80211_STA_INFO_AIRTIME_WEIGHT, + NL80211_STA_INFO_AIRTIME_LINK_METRIC, + NL80211_STA_INFO_ASSOC_AT_BOOTTIME, + NL80211_STA_INFO_CONNECTED_TO_AS, /* keep last */ __NL80211_STA_INFO_AFTER_LAST, NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1 }; +/* we renamed this - stay compatible */ +#define NL80211_STA_INFO_DATA_ACK_SIGNAL_AVG NL80211_STA_INFO_ACK_SIGNAL_AVG + + /** * enum nl80211_tid_stats - per TID statistics attributes * @__NL80211_TID_STATS_INVALID: attribute number 0 is reserved @@ -3200,8 +3617,10 @@ enum nl80211_mpath_flags { * &enum nl80211_mpath_flags; * @NL80211_MPATH_INFO_DISCOVERY_TIMEOUT: total path discovery timeout, in msec * @NL80211_MPATH_INFO_DISCOVERY_RETRIES: mesh path discovery retries + * @NL80211_MPATH_INFO_HOP_COUNT: hop count to destination + * @NL80211_MPATH_INFO_PATH_CHANGE: total number of path changes to destination * @NL80211_MPATH_INFO_MAX: highest mesh path information attribute number - * currently defind + * currently defined * @__NL80211_MPATH_INFO_AFTER_LAST: internal use */ enum nl80211_mpath_info { @@ -3213,6 +3632,8 @@ enum nl80211_mpath_info { NL80211_MPATH_INFO_FLAGS, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT, NL80211_MPATH_INFO_DISCOVERY_RETRIES, + NL80211_MPATH_INFO_HOP_COUNT, + NL80211_MPATH_INFO_PATH_CHANGE, /* keep last */ __NL80211_MPATH_INFO_AFTER_LAST, @@ -3235,6 +3656,8 @@ enum nl80211_mpath_info { * defined in HE capabilities IE * @NL80211_BAND_IFTYPE_ATTR_MAX: highest band HE capability attribute currently * defined + * @NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA: HE 6GHz band capabilities (__le16), + * given for all 6 GHz band channels * @__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST: internal use */ enum nl80211_band_iftype_attr { @@ -3245,6 +3668,7 @@ enum nl80211_band_iftype_attr { NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE, + NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA, /* keep last */ __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST, @@ -3268,6 +3692,12 @@ enum nl80211_band_iftype_attr { * @NL80211_BAND_ATTR_VHT_CAPA: VHT capabilities, as in the HT information IE * @NL80211_BAND_ATTR_IFTYPE_DATA: nested array attribute, with each entry using * attributes from &enum nl80211_band_iftype_attr + * @NL80211_BAND_ATTR_EDMG_CHANNELS: bitmap that indicates the 2.16 GHz + * channel(s) that are allowed to be used for EDMG transmissions. + * Defined by IEEE P802.11ay/D4.0 section 9.4.2.251. + * @NL80211_BAND_ATTR_EDMG_BW_CONFIG: Channel BW Configuration subfield encodes + * the allowed channel bandwidth configurations. + * Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13. * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined * @__NL80211_BAND_ATTR_AFTER_LAST: internal use */ @@ -3285,6 +3715,9 @@ enum nl80211_band_attr { NL80211_BAND_ATTR_VHT_CAPA, NL80211_BAND_ATTR_IFTYPE_DATA, + NL80211_BAND_ATTR_EDMG_CHANNELS, + NL80211_BAND_ATTR_EDMG_BW_CONFIG, + /* keep last */ __NL80211_BAND_ATTR_AFTER_LAST, NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1 @@ -3367,6 +3800,19 @@ enum nl80211_wmm_rule { * @NL80211_FREQUENCY_ATTR_WMM: this channel has wmm limitations. * This is a nested attribute that contains the wmm limitation per AC. * (see &enum nl80211_wmm_rule) + * @NL80211_FREQUENCY_ATTR_NO_HE: HE operation is not allowed on this channel + * in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_OFFSET: frequency offset in KHz + * @NL80211_FREQUENCY_ATTR_1MHZ: 1 MHz operation is allowed + * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_2MHZ: 2 MHz operation is allowed + * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_4MHZ: 4 MHz operation is allowed + * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_8MHZ: 8 MHz operation is allowed + * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_16MHZ: 16 MHz operation is allowed + * on this channel in current regulatory domain. * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number * currently defined * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use @@ -3396,6 +3842,13 @@ enum nl80211_frequency_attr { NL80211_FREQUENCY_ATTR_NO_20MHZ, NL80211_FREQUENCY_ATTR_NO_10MHZ, NL80211_FREQUENCY_ATTR_WMM, + NL80211_FREQUENCY_ATTR_NO_HE, + NL80211_FREQUENCY_ATTR_OFFSET, + NL80211_FREQUENCY_ATTR_1MHZ, + NL80211_FREQUENCY_ATTR_2MHZ, + NL80211_FREQUENCY_ATTR_4MHZ, + NL80211_FREQUENCY_ATTR_8MHZ, + NL80211_FREQUENCY_ATTR_16MHZ, /* keep last */ __NL80211_FREQUENCY_ATTR_AFTER_LAST, @@ -3541,6 +3994,14 @@ enum nl80211_reg_rule_attr { * value as specified by &struct nl80211_bss_select_rssi_adjust. * @NL80211_SCHED_SCAN_MATCH_ATTR_BSSID: BSSID to be used for matching * (this cannot be used together with SSID). + * @NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI: Nested attribute that carries the + * band specific minimum rssi thresholds for the bands defined in + * enum nl80211_band. The minimum rssi threshold value(s32) specific to a + * band shall be encapsulated in attribute with type value equals to one + * of the NL80211_BAND_* defined in enum nl80211_band. For example, the + * minimum rssi threshold value for 2.4GHZ band shall be encapsulated + * within an attribute of type NL80211_BAND_2GHZ. And one or more of such + * attributes will be nested within this attribute. * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter * attribute number currently defined * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use @@ -3553,6 +4014,7 @@ enum nl80211_sched_scan_match_attr { NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI, NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST, NL80211_SCHED_SCAN_MATCH_ATTR_BSSID, + NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI, /* keep last */ __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST, @@ -3584,6 +4046,7 @@ enum nl80211_sched_scan_match_attr { * @NL80211_RRF_NO_HT40PLUS: channels can't be used in HT40+ operation * @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed * @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed + * @NL80211_RRF_NO_HE: HE operation not allowed */ enum nl80211_reg_rule_flags { NL80211_RRF_NO_OFDM = 1<<0, @@ -3601,6 +4064,7 @@ enum nl80211_reg_rule_flags { NL80211_RRF_NO_HT40PLUS = 1<<14, NL80211_RRF_NO_80MHZ = 1<<15, NL80211_RRF_NO_160MHZ = 1<<16, + NL80211_RRF_NO_HE = 1<<17, }; #define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR @@ -3674,8 +4138,11 @@ enum nl80211_user_reg_hint_type { * @NL80211_SURVEY_INFO_TIME_SCAN: time the radio spent for scan * (on this channel or globally) * @NL80211_SURVEY_INFO_PAD: attribute used for padding for 64-bit alignment + * @NL80211_SURVEY_INFO_TIME_BSS_RX: amount of time the radio spent + * receiving frames destined to the local BSS * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number * currently defined + * @NL80211_SURVEY_INFO_FREQUENCY_OFFSET: center frequency offset in KHz * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use */ enum nl80211_survey_info { @@ -3690,6 +4157,8 @@ enum nl80211_survey_info { NL80211_SURVEY_INFO_TIME_TX, NL80211_SURVEY_INFO_TIME_SCAN, NL80211_SURVEY_INFO_PAD, + NL80211_SURVEY_INFO_TIME_BSS_RX, + NL80211_SURVEY_INFO_FREQUENCY_OFFSET, /* keep last */ __NL80211_SURVEY_INFO_AFTER_LAST, @@ -3870,6 +4339,21 @@ enum nl80211_mesh_power_mode { * remove it from the STA's list of peers. You may set this to 0 to disable * the removal of the STA. Default is 30 minutes. * + * @NL80211_MESHCONF_CONNECTED_TO_GATE: If set to true then this mesh STA + * will advertise that it is connected to a gate in the mesh formation + * field. If left unset then the mesh formation field will only + * advertise such if there is an active root mesh path. + * + * @NL80211_MESHCONF_NOLEARN: Try to avoid multi-hop path discovery (e.g. + * PREQ/PREP for HWMP) if the destination is a direct neighbor. Note that + * this might not be the optimal decision as a multi-hop route might be + * better. So if using this setting you will likely also want to disable + * dot11MeshForwarding and use another mesh routing protocol on top. + * + * @NL80211_MESHCONF_CONNECTED_TO_AS: If set to true then this mesh STA + * will advertise that it is connected to a authentication server + * in the mesh formation field. + * * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use */ enum nl80211_meshconf_params { @@ -3902,6 +4386,9 @@ enum nl80211_meshconf_params { NL80211_MESHCONF_POWER_MODE, NL80211_MESHCONF_AWAKE_WINDOW, NL80211_MESHCONF_PLINK_TIMEOUT, + NL80211_MESHCONF_CONNECTED_TO_GATE, + NL80211_MESHCONF_NOLEARN, + NL80211_MESHCONF_CONNECTED_TO_AS, /* keep last */ __NL80211_MESHCONF_ATTR_AFTER_LAST, @@ -4031,6 +4518,27 @@ enum nl80211_channel_type { NL80211_CHAN_HT40PLUS }; +/** + * enum nl80211_key_mode - Key mode + * + * @NL80211_KEY_RX_TX: (Default) + * Key can be used for Rx and Tx immediately + * + * The following modes can only be selected for unicast keys and when the + * driver supports @NL80211_EXT_FEATURE_EXT_KEY_ID: + * + * @NL80211_KEY_NO_TX: Only allowed in combination with @NL80211_CMD_NEW_KEY: + * Unicast key can only be used for Rx, Tx not allowed, yet + * @NL80211_KEY_SET_TX: Only allowed in combination with @NL80211_CMD_SET_KEY: + * The unicast key identified by idx and mac is cleared for Tx and becomes + * the preferred Tx key for the station. + */ +enum nl80211_key_mode { + NL80211_KEY_RX_TX, + NL80211_KEY_NO_TX, + NL80211_KEY_SET_TX +}; + /** * enum nl80211_chan_width - channel width definitions * @@ -4049,6 +4557,11 @@ enum nl80211_channel_type { * attribute must be provided as well * @NL80211_CHAN_WIDTH_5: 5 MHz OFDM channel * @NL80211_CHAN_WIDTH_10: 10 MHz OFDM channel + * @NL80211_CHAN_WIDTH_1: 1 MHz OFDM channel + * @NL80211_CHAN_WIDTH_2: 2 MHz OFDM channel + * @NL80211_CHAN_WIDTH_4: 4 MHz OFDM channel + * @NL80211_CHAN_WIDTH_8: 8 MHz OFDM channel + * @NL80211_CHAN_WIDTH_16: 16 MHz OFDM channel */ enum nl80211_chan_width { NL80211_CHAN_WIDTH_20_NOHT, @@ -4059,6 +4572,11 @@ enum nl80211_chan_width { NL80211_CHAN_WIDTH_160, NL80211_CHAN_WIDTH_5, NL80211_CHAN_WIDTH_10, + NL80211_CHAN_WIDTH_1, + NL80211_CHAN_WIDTH_2, + NL80211_CHAN_WIDTH_4, + NL80211_CHAN_WIDTH_8, + NL80211_CHAN_WIDTH_16, }; /** @@ -4069,11 +4587,15 @@ enum nl80211_chan_width { * @NL80211_BSS_CHAN_WIDTH_20: control channel is 20 MHz wide or compatible * @NL80211_BSS_CHAN_WIDTH_10: control channel is 10 MHz wide * @NL80211_BSS_CHAN_WIDTH_5: control channel is 5 MHz wide + * @NL80211_BSS_CHAN_WIDTH_1: control channel is 1 MHz wide + * @NL80211_BSS_CHAN_WIDTH_2: control channel is 2 MHz wide */ enum nl80211_bss_scan_width { NL80211_BSS_CHAN_WIDTH_20, NL80211_BSS_CHAN_WIDTH_10, NL80211_BSS_CHAN_WIDTH_5, + NL80211_BSS_CHAN_WIDTH_1, + NL80211_BSS_CHAN_WIDTH_2, }; /** @@ -4125,6 +4647,7 @@ enum nl80211_bss_scan_width { * @NL80211_BSS_CHAIN_SIGNAL: per-chain signal strength of last BSS update. * Contains a nested array of signal strength attributes (u8, dBm), * using the nesting index as the antenna number. + * @NL80211_BSS_FREQUENCY_OFFSET: frequency offset in KHz * @__NL80211_BSS_AFTER_LAST: internal * @NL80211_BSS_MAX: highest BSS attribute */ @@ -4149,6 +4672,7 @@ enum nl80211_bss { NL80211_BSS_PARENT_TSF, NL80211_BSS_PARENT_BSSID, NL80211_BSS_CHAIN_SIGNAL, + NL80211_BSS_FREQUENCY_OFFSET, /* keep last */ __NL80211_BSS_AFTER_LAST, @@ -4236,6 +4760,7 @@ enum nl80211_mfp { enum nl80211_wpa_versions { NL80211_WPA_VERSION_1 = 1 << 0, NL80211_WPA_VERSION_2 = 1 << 1, + NL80211_WPA_VERSION_3 = 1 << 2, }; /** @@ -4274,6 +4799,10 @@ enum nl80211_key_default_types { * @NL80211_KEY_DEFAULT_TYPES: A nested attribute containing flags * attributes, specifying what a key should be set as default as. * See &enum nl80211_key_default_types. + * @NL80211_KEY_MODE: the mode from enum nl80211_key_mode. + * Defaults to @NL80211_KEY_RX_TX. + * @NL80211_KEY_DEFAULT_BEACON: flag indicating default Beacon frame key + * * @__NL80211_KEY_AFTER_LAST: internal * @NL80211_KEY_MAX: highest key attribute */ @@ -4287,6 +4816,8 @@ enum nl80211_key_attributes { NL80211_KEY_DEFAULT_MGMT, NL80211_KEY_TYPE, NL80211_KEY_DEFAULT_TYPES, + NL80211_KEY_MODE, + NL80211_KEY_DEFAULT_BEACON, /* keep last */ __NL80211_KEY_AFTER_LAST, @@ -4305,6 +4836,10 @@ enum nl80211_key_attributes { * @NL80211_TXRATE_VHT: VHT rates allowed for TX rate selection, * see &struct nl80211_txrate_vht * @NL80211_TXRATE_GI: configure GI, see &enum nl80211_txrate_gi + * @NL80211_TXRATE_HE: HE rates allowed for TX rate selection, + * see &struct nl80211_txrate_he + * @NL80211_TXRATE_HE_GI: configure HE GI, 0.8us, 1.6us and 3.2us. + * @NL80211_TXRATE_HE_LTF: configure HE LTF, 1XLTF, 2XLTF and 4XLTF. * @__NL80211_TXRATE_AFTER_LAST: internal * @NL80211_TXRATE_MAX: highest TX rate attribute */ @@ -4314,6 +4849,9 @@ enum nl80211_tx_rate_attributes { NL80211_TXRATE_HT, NL80211_TXRATE_VHT, NL80211_TXRATE_GI, + NL80211_TXRATE_HE, + NL80211_TXRATE_HE_GI, + NL80211_TXRATE_HE_LTF, /* keep last */ __NL80211_TXRATE_AFTER_LAST, @@ -4331,6 +4869,15 @@ struct nl80211_txrate_vht { __u16 mcs[NL80211_VHT_NSS_MAX]; }; +#define NL80211_HE_NSS_MAX 8 +/** + * struct nl80211_txrate_he - HE MCS/NSS txrate bitmap + * @mcs: MCS bitmap table for each NSS (array index 0 for 1 stream, etc.) + */ +struct nl80211_txrate_he { + __u16 mcs[NL80211_HE_NSS_MAX]; +}; + enum nl80211_txrate_gi { NL80211_TXRATE_DEFAULT_GI, NL80211_TXRATE_FORCE_SGI, @@ -4341,7 +4888,9 @@ enum nl80211_txrate_gi { * enum nl80211_band - Frequency band * @NL80211_BAND_2GHZ: 2.4 GHz ISM band * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) - * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 64.80 GHz) + * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 69.12 GHz) + * @NL80211_BAND_6GHZ: around 6 GHz band (5.9 - 7.2 GHz) + * @NL80211_BAND_S1GHZ: around 900MHz, supported by S1G PHYs * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace * since newer kernel versions may support more bands */ @@ -4349,6 +4898,8 @@ enum nl80211_band { NL80211_BAND_2GHZ, NL80211_BAND_5GHZ, NL80211_BAND_60GHZ, + NL80211_BAND_6GHZ, + NL80211_BAND_S1GHZ, NUM_NL80211_BANDS, }; @@ -4440,6 +4991,92 @@ enum nl80211_tx_power_setting { NL80211_TX_POWER_FIXED, }; +/** + * enum nl80211_tid_config - TID config state + * @NL80211_TID_CONFIG_ENABLE: Enable config for the TID + * @NL80211_TID_CONFIG_DISABLE: Disable config for the TID + */ +enum nl80211_tid_config { + NL80211_TID_CONFIG_ENABLE, + NL80211_TID_CONFIG_DISABLE, +}; + +/* enum nl80211_tx_rate_setting - TX rate configuration type + * @NL80211_TX_RATE_AUTOMATIC: automatically determine TX rate + * @NL80211_TX_RATE_LIMITED: limit the TX rate by the TX rate parameter + * @NL80211_TX_RATE_FIXED: fix TX rate to the TX rate parameter + */ +enum nl80211_tx_rate_setting { + NL80211_TX_RATE_AUTOMATIC, + NL80211_TX_RATE_LIMITED, + NL80211_TX_RATE_FIXED, +}; + +/* enum nl80211_tid_config_attr - TID specific configuration. + * @NL80211_TID_CONFIG_ATTR_PAD: pad attribute for 64-bit values + * @NL80211_TID_CONFIG_ATTR_VIF_SUPP: a bitmap (u64) of attributes supported + * for per-vif configuration; doesn't list the ones that are generic + * (%NL80211_TID_CONFIG_ATTR_TIDS, %NL80211_TID_CONFIG_ATTR_OVERRIDE). + * @NL80211_TID_CONFIG_ATTR_PEER_SUPP: same as the previous per-vif one, but + * per peer instead. + * @NL80211_TID_CONFIG_ATTR_OVERRIDE: flag attribue, if set indicates + * that the new configuration overrides all previous peer + * configurations, otherwise previous peer specific configurations + * should be left untouched. + * @NL80211_TID_CONFIG_ATTR_TIDS: a bitmask value of TIDs (bit 0 to 7) + * Its type is u16. + * @NL80211_TID_CONFIG_ATTR_NOACK: Configure ack policy for the TID. + * specified in %NL80211_TID_CONFIG_ATTR_TID. see %enum nl80211_tid_config. + * Its type is u8. + * @NL80211_TID_CONFIG_ATTR_RETRY_SHORT: Number of retries used with data frame + * transmission, user-space sets this configuration in + * &NL80211_CMD_SET_TID_CONFIG. It is u8 type, min value is 1 and + * the max value is advertised by the driver in this attribute on + * output in wiphy capabilities. + * @NL80211_TID_CONFIG_ATTR_RETRY_LONG: Number of retries used with data frame + * transmission, user-space sets this configuration in + * &NL80211_CMD_SET_TID_CONFIG. Its type is u8, min value is 1 and + * the max value is advertised by the driver in this attribute on + * output in wiphy capabilities. + * @NL80211_TID_CONFIG_ATTR_AMPDU_CTRL: Enable/Disable MPDU aggregation + * for the TIDs specified in %NL80211_TID_CONFIG_ATTR_TIDS. + * Its type is u8, using the values from &nl80211_tid_config. + * @NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL: Enable/Disable RTS_CTS for the TIDs + * specified in %NL80211_TID_CONFIG_ATTR_TIDS. It is u8 type, using + * the values from &nl80211_tid_config. + * @NL80211_TID_CONFIG_ATTR_AMSDU_CTRL: Enable/Disable MSDU aggregation + * for the TIDs specified in %NL80211_TID_CONFIG_ATTR_TIDS. + * Its type is u8, using the values from &nl80211_tid_config. + * @NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE: This attribute will be useful + * to notfiy the driver that what type of txrate should be used + * for the TIDs specified in %NL80211_TID_CONFIG_ATTR_TIDS. using + * the values form &nl80211_tx_rate_setting. + * @NL80211_TID_CONFIG_ATTR_TX_RATE: Data frame TX rate mask should be applied + * with the parameters passed through %NL80211_ATTR_TX_RATES. + * configuration is applied to the data frame for the tid to that connected + * station. + */ +enum nl80211_tid_config_attr { + __NL80211_TID_CONFIG_ATTR_INVALID, + NL80211_TID_CONFIG_ATTR_PAD, + NL80211_TID_CONFIG_ATTR_VIF_SUPP, + NL80211_TID_CONFIG_ATTR_PEER_SUPP, + NL80211_TID_CONFIG_ATTR_OVERRIDE, + NL80211_TID_CONFIG_ATTR_TIDS, + NL80211_TID_CONFIG_ATTR_NOACK, + NL80211_TID_CONFIG_ATTR_RETRY_SHORT, + NL80211_TID_CONFIG_ATTR_RETRY_LONG, + NL80211_TID_CONFIG_ATTR_AMPDU_CTRL, + NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL, + NL80211_TID_CONFIG_ATTR_AMSDU_CTRL, + NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE, + NL80211_TID_CONFIG_ATTR_TX_RATE, + + /* keep last */ + __NL80211_TID_CONFIG_ATTR_AFTER_LAST, + NL80211_TID_CONFIG_ATTR_MAX = __NL80211_TID_CONFIG_ATTR_AFTER_LAST - 1 +}; + /** * enum nl80211_packet_pattern_attr - packet pattern attribute * @__NL80211_PKTPAT_INVALID: invalid number for nested attribute @@ -4834,7 +5471,7 @@ enum nl80211_iface_limit_attrs { * numbers = [ #{STA} <= 1, #{P2P-client,P2P-GO} <= 3 ], max = 4 * => allows a STA plus three P2P interfaces * - * The list of these four possiblities could completely be contained + * The list of these four possibilities could completely be contained * within the %NL80211_ATTR_INTERFACE_COMBINATIONS attribute to indicate * that any of these groups must match. * @@ -4864,7 +5501,7 @@ enum nl80211_if_combination_attrs { * enum nl80211_plink_state - state of a mesh peer link finite state machine * * @NL80211_PLINK_LISTEN: initial state, considered the implicit - * state of non existant mesh peer links + * state of non existent mesh peer links * @NL80211_PLINK_OPN_SNT: mesh plink open frame has been sent to * this mesh peer * @NL80211_PLINK_OPN_RCVD: mesh plink open frame has been received @@ -4911,6 +5548,8 @@ enum plink_actions { #define NL80211_KCK_LEN 16 #define NL80211_KEK_LEN 16 +#define NL80211_KCK_EXT_LEN 24 +#define NL80211_KEK_EXT_LEN 32 #define NL80211_REPLAY_CTR_LEN 8 /** @@ -4919,6 +5558,7 @@ enum plink_actions { * @NL80211_REKEY_DATA_KEK: key encryption key (binary) * @NL80211_REKEY_DATA_KCK: key confirmation key (binary) * @NL80211_REKEY_DATA_REPLAY_CTR: replay counter (binary) + * @NL80211_REKEY_DATA_AKM: AKM data (OUI, suite type) * @NUM_NL80211_REKEY_DATA: number of rekey attributes (internal) * @MAX_NL80211_REKEY_DATA: highest rekey attribute (internal) */ @@ -4927,6 +5567,7 @@ enum nl80211_rekey_data { NL80211_REKEY_DATA_KEK, NL80211_REKEY_DATA_KCK, NL80211_REKEY_DATA_REPLAY_CTR, + NL80211_REKEY_DATA_AKM, /* keep last */ NUM_NL80211_REKEY_DATA, @@ -5140,14 +5781,14 @@ enum nl80211_feature_flags { NL80211_FEATURE_TDLS_CHANNEL_SWITCH = 1 << 28, NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR = 1 << 29, NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR = 1 << 30, - NL80211_FEATURE_ND_RANDOM_MAC_ADDR = 1 << 31, + NL80211_FEATURE_ND_RANDOM_MAC_ADDR = 1U << 31, }; /** * enum nl80211_ext_feature_index - bit index of extended features. * @NL80211_EXT_FEATURE_VHT_IBSS: This driver supports IBSS with VHT datarates. * @NL80211_EXT_FEATURE_RRM: This driver supports RRM. When featured, user can - * can request to use RRM (see %NL80211_ATTR_USE_RRM) with + * request to use RRM (see %NL80211_ATTR_USE_RRM) with * %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests, which will set * the ASSOC_REQ_USE_RRM flag in the association request even if * NL80211_FEATURE_QUIET is not advertized. @@ -5216,9 +5857,8 @@ enum nl80211_feature_flags { * "radar detected" event. * @NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211: Driver supports sending and * receiving control port frames over nl80211 instead of the netdevice. - * @NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT: This Driver support data ack - * rssi if firmware support, this flag is to intimate about ack rssi - * support to nl80211. + * @NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT: This driver/device supports + * (average) ACK signal strength reporting. * @NL80211_EXT_FEATURE_TXQS: Driver supports FQ-CoDel-enabled intermediate * TXQs. * @NL80211_EXT_FEATURE_SCAN_RANDOM_SN: Driver/device supports randomizing the @@ -5226,6 +5866,93 @@ enum nl80211_feature_flags { * @NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT: Driver/device can omit all data * except for supported rates from the probe request content if requested * by the %NL80211_SCAN_FLAG_MIN_PREQ_CONTENT flag. + * @NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER: Driver supports enabling fine + * timing measurement responder role. + * + * @NL80211_EXT_FEATURE_CAN_REPLACE_PTK0: Driver/device confirm that they are + * able to rekey an in-use key correctly. Userspace must not rekey PTK keys + * if this flag is not set. Ignoring this can leak clear text packets and/or + * freeze the connection. + * @NL80211_EXT_FEATURE_EXT_KEY_ID: Driver supports "Extended Key ID for + * Individually Addressed Frames" from IEEE802.11-2016. + * + * @NL80211_EXT_FEATURE_AIRTIME_FAIRNESS: Driver supports getting airtime + * fairness for transmitted packets and has enabled airtime fairness + * scheduling. + * + * @NL80211_EXT_FEATURE_AP_PMKSA_CACHING: Driver/device supports PMKSA caching + * (set/del PMKSA operations) in AP mode. + * + * @NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD: Driver supports + * filtering of sched scan results using band specific RSSI thresholds. + * + * @NL80211_EXT_FEATURE_STA_TX_PWR: This driver supports controlling tx power + * to a station. + * + * @NL80211_EXT_FEATURE_SAE_OFFLOAD: Device wants to do SAE authentication in + * station mode (SAE password is passed as part of the connect command). + * + * @NL80211_EXT_FEATURE_VLAN_OFFLOAD: The driver supports a single netdev + * with VLAN tagged frames and separate VLAN-specific netdevs added using + * vconfig similarly to the Ethernet case. + * + * @NL80211_EXT_FEATURE_AQL: The driver supports the Airtime Queue Limit (AQL) + * feature, which prevents bufferbloat by using the expected transmission + * time to limit the amount of data buffered in the hardware. + * + * @NL80211_EXT_FEATURE_BEACON_PROTECTION: The driver supports Beacon protection + * and can receive key configuration for BIGTK using key indexes 6 and 7. + * @NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT: The driver supports Beacon + * protection as a client only and cannot transmit protected beacons. + * + * @NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH: The driver can disable the + * forwarding of preauth frames over the control port. They are then + * handled as ordinary data frames. + * + * @NL80211_EXT_FEATURE_PROTECTED_TWT: Driver supports protected TWT frames + * + * @NL80211_EXT_FEATURE_DEL_IBSS_STA: The driver supports removing stations + * in IBSS mode, essentially by dropping their state. + * + * @NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS: management frame registrations + * are possible for multicast frames and those will be reported properly. + * + * @NL80211_EXT_FEATURE_SCAN_FREQ_KHZ: This driver supports receiving and + * reporting scan request with %NL80211_ATTR_SCAN_FREQ_KHZ. In order to + * report %NL80211_ATTR_SCAN_FREQ_KHZ, %NL80211_SCAN_FLAG_FREQ_KHZ must be + * included in the scan request. + * + * @NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS: The driver + * can report tx status for control port over nl80211 tx operations. + * + * @NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION: Driver supports Operating + * Channel Validation (OCV) when using driver's SME for RSNA handshakes. + * + * @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK: Device wants to do 4-way + * handshake with PSK in AP mode (PSK is passed as part of the start AP + * command). + * + * @NL80211_EXT_FEATURE_SAE_OFFLOAD_AP: Device wants to do SAE authentication + * in AP mode (SAE password is passed as part of the start AP command). + * + * @NL80211_EXT_FEATURE_FILS_DISCOVERY: Driver/device supports FILS discovery + * frames transmission + * + * @NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP: Driver/device supports + * unsolicited broadcast probe response transmission + * + * @NL80211_EXT_FEATURE_BEACON_RATE_HE: Driver supports beacon rate + * configuration (AP/mesh) with HE rates. + * + * @NL80211_EXT_FEATURE_SECURE_LTF: Device supports secure LTF measurement + * exchange protocol. + * + * @NL80211_EXT_FEATURE_SECURE_RTT: Device supports secure RTT measurement + * exchange protocol. + * + * @NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE: Device supports management + * frame protection for all management frames exchanged during the + * negotiation and range measurement procedure. * * @NUM_NL80211_EXT_FEATURES: number of extended features. * @MAX_NL80211_EXT_FEATURES: highest extended feature index. @@ -5258,10 +5985,39 @@ enum nl80211_ext_feature_index { NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN, NL80211_EXT_FEATURE_DFS_OFFLOAD, NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211, - NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT, + NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT, + /* we renamed this - stay compatible */ + NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT = NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT, NL80211_EXT_FEATURE_TXQS, NL80211_EXT_FEATURE_SCAN_RANDOM_SN, NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT, + NL80211_EXT_FEATURE_CAN_REPLACE_PTK0, + NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER, + NL80211_EXT_FEATURE_AIRTIME_FAIRNESS, + NL80211_EXT_FEATURE_AP_PMKSA_CACHING, + NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD, + NL80211_EXT_FEATURE_EXT_KEY_ID, + NL80211_EXT_FEATURE_STA_TX_PWR, + NL80211_EXT_FEATURE_SAE_OFFLOAD, + NL80211_EXT_FEATURE_VLAN_OFFLOAD, + NL80211_EXT_FEATURE_AQL, + NL80211_EXT_FEATURE_BEACON_PROTECTION, + NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH, + NL80211_EXT_FEATURE_PROTECTED_TWT, + NL80211_EXT_FEATURE_DEL_IBSS_STA, + NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS, + NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT, + NL80211_EXT_FEATURE_SCAN_FREQ_KHZ, + NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS, + NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION, + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK, + NL80211_EXT_FEATURE_SAE_OFFLOAD_AP, + NL80211_EXT_FEATURE_FILS_DISCOVERY, + NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP, + NL80211_EXT_FEATURE_BEACON_RATE_HE, + NL80211_EXT_FEATURE_SECURE_LTF, + NL80211_EXT_FEATURE_SECURE_RTT, + NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE, /* add new features before the definition below */ NUM_NL80211_EXT_FEATURES, @@ -5346,7 +6102,7 @@ enum nl80211_timeout_reason { * request parameters IE in the probe request * @NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP: accept broadcast probe responses * @NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE: send probe request frames at - * rate of at least 5.5M. In case non OCE AP is dicovered in the channel, + * rate of at least 5.5M. In case non OCE AP is discovered in the channel, * only the first probe req in the channel will be sent in high rate. * @NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION: allow probe request * tx deferral (dot11FILSProbeDelay shall be set to 15ms) @@ -5373,6 +6129,11 @@ enum nl80211_timeout_reason { * @NL80211_SCAN_FLAG_MIN_PREQ_CONTENT: minimize probe request content to * only have supported rates and no additional capabilities (unless * added by userspace explicitly.) + * @NL80211_SCAN_FLAG_FREQ_KHZ: report scan results with + * %NL80211_ATTR_SCAN_FREQ_KHZ. This also means + * %NL80211_ATTR_SCAN_FREQUENCIES will not be included. + * @NL80211_SCAN_FLAG_COLOCATED_6GHZ: scan for colocated APs reported by + * 2.4/5 GHz APs */ enum nl80211_scan_flags { NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0, @@ -5388,6 +6149,8 @@ enum nl80211_scan_flags { NL80211_SCAN_FLAG_HIGH_ACCURACY = 1<<10, NL80211_SCAN_FLAG_RANDOM_SN = 1<<11, NL80211_SCAN_FLAG_MIN_PREQ_CONTENT = 1<<12, + NL80211_SCAN_FLAG_FREQ_KHZ = 1<<13, + NL80211_SCAN_FLAG_COLOCATED_6GHZ = 1<<14, }; /** @@ -5475,7 +6238,7 @@ enum nl80211_dfs_state { }; /** - * enum enum nl80211_protocol_features - nl80211 protocol features + * enum nl80211_protocol_features - nl80211 protocol features * @NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP: nl80211 supports splitting * wiphy dumps (if requested by the application with the attribute * %NL80211_ATTR_SPLIT_WIPHY_DUMP. Also supported is filtering the @@ -5513,9 +6276,14 @@ enum nl80211_crit_proto_id { * Used by cfg80211_rx_mgmt() * * @NL80211_RXMGMT_FLAG_ANSWERED: frame was answered by device/driver. + * @NL80211_RXMGMT_FLAG_EXTERNAL_AUTH: Host driver intends to offload + * the authentication. Exclusively defined for host drivers that + * advertises the SME functionality but would like the userspace + * to handle certain authentication algorithms (e.g. SAE). */ enum nl80211_rxmgmt_flags { NL80211_RXMGMT_FLAG_ANSWERED = 1 << 0, + NL80211_RXMGMT_FLAG_EXTERNAL_AUTH = 1 << 1, }; /* @@ -5547,11 +6315,13 @@ struct nl80211_vendor_cmd_info { * @NL80211_TDLS_PEER_HT: TDLS peer is HT capable. * @NL80211_TDLS_PEER_VHT: TDLS peer is VHT capable. * @NL80211_TDLS_PEER_WMM: TDLS peer is WMM capable. + * @NL80211_TDLS_PEER_HE: TDLS peer is HE capable. */ enum nl80211_tdls_peer_capability { NL80211_TDLS_PEER_HT = 1<<0, NL80211_TDLS_PEER_VHT = 1<<1, NL80211_TDLS_PEER_WMM = 1<<2, + NL80211_TDLS_PEER_HE = 1<<3, }; /** @@ -5801,4 +6571,736 @@ enum nl80211_external_auth_action { NL80211_EXTERNAL_AUTH_ABORT, }; +/** + * enum nl80211_ftm_responder_attributes - fine timing measurement + * responder attributes + * @__NL80211_FTM_RESP_ATTR_INVALID: Invalid + * @NL80211_FTM_RESP_ATTR_ENABLED: FTM responder is enabled + * @NL80211_FTM_RESP_ATTR_LCI: The content of Measurement Report Element + * (9.4.2.22 in 802.11-2016) with type 8 - LCI (9.4.2.22.10), + * i.e. starting with the measurement token + * @NL80211_FTM_RESP_ATTR_CIVIC: The content of Measurement Report Element + * (9.4.2.22 in 802.11-2016) with type 11 - Civic (Section 9.4.2.22.13), + * i.e. starting with the measurement token + * @__NL80211_FTM_RESP_ATTR_LAST: Internal + * @NL80211_FTM_RESP_ATTR_MAX: highest FTM responder attribute. + */ +enum nl80211_ftm_responder_attributes { + __NL80211_FTM_RESP_ATTR_INVALID, + + NL80211_FTM_RESP_ATTR_ENABLED, + NL80211_FTM_RESP_ATTR_LCI, + NL80211_FTM_RESP_ATTR_CIVICLOC, + + /* keep last */ + __NL80211_FTM_RESP_ATTR_LAST, + NL80211_FTM_RESP_ATTR_MAX = __NL80211_FTM_RESP_ATTR_LAST - 1, +}; + +/* + * enum nl80211_ftm_responder_stats - FTM responder statistics + * + * These attribute types are used with %NL80211_ATTR_FTM_RESPONDER_STATS + * when getting FTM responder statistics. + * + * @__NL80211_FTM_STATS_INVALID: attribute number 0 is reserved + * @NL80211_FTM_STATS_SUCCESS_NUM: number of FTM sessions in which all frames + * were ssfully answered (u32) + * @NL80211_FTM_STATS_PARTIAL_NUM: number of FTM sessions in which part of the + * frames were successfully answered (u32) + * @NL80211_FTM_STATS_FAILED_NUM: number of failed FTM sessions (u32) + * @NL80211_FTM_STATS_ASAP_NUM: number of ASAP sessions (u32) + * @NL80211_FTM_STATS_NON_ASAP_NUM: number of non-ASAP sessions (u32) + * @NL80211_FTM_STATS_TOTAL_DURATION_MSEC: total sessions durations - gives an + * indication of how much time the responder was busy (u64, msec) + * @NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM: number of unknown FTM triggers - + * triggers from initiators that didn't finish successfully the negotiation + * phase with the responder (u32) + * @NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM: number of FTM reschedule requests + * - initiator asks for a new scheduling although it already has scheduled + * FTM slot (u32) + * @NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM: number of FTM triggers out of + * scheduled window (u32) + * @NL80211_FTM_STATS_PAD: used for padding, ignore + * @__NL80211_TXQ_ATTR_AFTER_LAST: Internal + * @NL80211_FTM_STATS_MAX: highest possible FTM responder stats attribute + */ +enum nl80211_ftm_responder_stats { + __NL80211_FTM_STATS_INVALID, + NL80211_FTM_STATS_SUCCESS_NUM, + NL80211_FTM_STATS_PARTIAL_NUM, + NL80211_FTM_STATS_FAILED_NUM, + NL80211_FTM_STATS_ASAP_NUM, + NL80211_FTM_STATS_NON_ASAP_NUM, + NL80211_FTM_STATS_TOTAL_DURATION_MSEC, + NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM, + NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM, + NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM, + NL80211_FTM_STATS_PAD, + + /* keep last */ + __NL80211_FTM_STATS_AFTER_LAST, + NL80211_FTM_STATS_MAX = __NL80211_FTM_STATS_AFTER_LAST - 1 +}; + +/** + * enum nl80211_preamble - frame preamble types + * @NL80211_PREAMBLE_LEGACY: legacy (HR/DSSS, OFDM, ERP PHY) preamble + * @NL80211_PREAMBLE_HT: HT preamble + * @NL80211_PREAMBLE_VHT: VHT preamble + * @NL80211_PREAMBLE_DMG: DMG preamble + * @NL80211_PREAMBLE_HE: HE preamble + */ +enum nl80211_preamble { + NL80211_PREAMBLE_LEGACY, + NL80211_PREAMBLE_HT, + NL80211_PREAMBLE_VHT, + NL80211_PREAMBLE_DMG, + NL80211_PREAMBLE_HE, +}; + +/** + * enum nl80211_peer_measurement_type - peer measurement types + * @NL80211_PMSR_TYPE_INVALID: invalid/unused, needed as we use + * these numbers also for attributes + * + * @NL80211_PMSR_TYPE_FTM: flight time measurement + * + * @NUM_NL80211_PMSR_TYPES: internal + * @NL80211_PMSR_TYPE_MAX: highest type number + */ +enum nl80211_peer_measurement_type { + NL80211_PMSR_TYPE_INVALID, + + NL80211_PMSR_TYPE_FTM, + + NUM_NL80211_PMSR_TYPES, + NL80211_PMSR_TYPE_MAX = NUM_NL80211_PMSR_TYPES - 1 +}; + +/** + * enum nl80211_peer_measurement_status - peer measurement status + * @NL80211_PMSR_STATUS_SUCCESS: measurement completed successfully + * @NL80211_PMSR_STATUS_REFUSED: measurement was locally refused + * @NL80211_PMSR_STATUS_TIMEOUT: measurement timed out + * @NL80211_PMSR_STATUS_FAILURE: measurement failed, a type-dependent + * reason may be available in the response data + */ +enum nl80211_peer_measurement_status { + NL80211_PMSR_STATUS_SUCCESS, + NL80211_PMSR_STATUS_REFUSED, + NL80211_PMSR_STATUS_TIMEOUT, + NL80211_PMSR_STATUS_FAILURE, +}; + +/** + * enum nl80211_peer_measurement_req - peer measurement request attributes + * @__NL80211_PMSR_REQ_ATTR_INVALID: invalid + * + * @NL80211_PMSR_REQ_ATTR_DATA: This is a nested attribute with measurement + * type-specific request data inside. The attributes used are from the + * enums named nl80211_peer_measurement__req. + * @NL80211_PMSR_REQ_ATTR_GET_AP_TSF: include AP TSF timestamp, if supported + * (flag attribute) + * + * @NUM_NL80211_PMSR_REQ_ATTRS: internal + * @NL80211_PMSR_REQ_ATTR_MAX: highest attribute number + */ +enum nl80211_peer_measurement_req { + __NL80211_PMSR_REQ_ATTR_INVALID, + + NL80211_PMSR_REQ_ATTR_DATA, + NL80211_PMSR_REQ_ATTR_GET_AP_TSF, + + /* keep last */ + NUM_NL80211_PMSR_REQ_ATTRS, + NL80211_PMSR_REQ_ATTR_MAX = NUM_NL80211_PMSR_REQ_ATTRS - 1 +}; + +/** + * enum nl80211_peer_measurement_resp - peer measurement response attributes + * @__NL80211_PMSR_RESP_ATTR_INVALID: invalid + * + * @NL80211_PMSR_RESP_ATTR_DATA: This is a nested attribute with measurement + * type-specific results inside. The attributes used are from the enums + * named nl80211_peer_measurement__resp. + * @NL80211_PMSR_RESP_ATTR_STATUS: u32 value with the measurement status + * (using values from &enum nl80211_peer_measurement_status.) + * @NL80211_PMSR_RESP_ATTR_HOST_TIME: host time (%CLOCK_BOOTTIME) when the + * result was measured; this value is not expected to be accurate to + * more than 20ms. (u64, nanoseconds) + * @NL80211_PMSR_RESP_ATTR_AP_TSF: TSF of the AP that the interface + * doing the measurement is connected to when the result was measured. + * This shall be accurately reported if supported and requested + * (u64, usec) + * @NL80211_PMSR_RESP_ATTR_FINAL: If results are sent to the host partially + * (*e.g. with FTM per-burst data) this flag will be cleared on all but + * the last result; if all results are combined it's set on the single + * result. + * @NL80211_PMSR_RESP_ATTR_PAD: padding for 64-bit attributes, ignore + * + * @NUM_NL80211_PMSR_RESP_ATTRS: internal + * @NL80211_PMSR_RESP_ATTR_MAX: highest attribute number + */ +enum nl80211_peer_measurement_resp { + __NL80211_PMSR_RESP_ATTR_INVALID, + + NL80211_PMSR_RESP_ATTR_DATA, + NL80211_PMSR_RESP_ATTR_STATUS, + NL80211_PMSR_RESP_ATTR_HOST_TIME, + NL80211_PMSR_RESP_ATTR_AP_TSF, + NL80211_PMSR_RESP_ATTR_FINAL, + NL80211_PMSR_RESP_ATTR_PAD, + + /* keep last */ + NUM_NL80211_PMSR_RESP_ATTRS, + NL80211_PMSR_RESP_ATTR_MAX = NUM_NL80211_PMSR_RESP_ATTRS - 1 +}; + +/** + * enum nl80211_peer_measurement_peer_attrs - peer attributes for measurement + * @__NL80211_PMSR_PEER_ATTR_INVALID: invalid + * + * @NL80211_PMSR_PEER_ATTR_ADDR: peer's MAC address + * @NL80211_PMSR_PEER_ATTR_CHAN: channel definition, nested, using top-level + * attributes like %NL80211_ATTR_WIPHY_FREQ etc. + * @NL80211_PMSR_PEER_ATTR_REQ: This is a nested attribute indexed by + * measurement type, with attributes from the + * &enum nl80211_peer_measurement_req inside. + * @NL80211_PMSR_PEER_ATTR_RESP: This is a nested attribute indexed by + * measurement type, with attributes from the + * &enum nl80211_peer_measurement_resp inside. + * + * @NUM_NL80211_PMSR_PEER_ATTRS: internal + * @NL80211_PMSR_PEER_ATTR_MAX: highest attribute number + */ +enum nl80211_peer_measurement_peer_attrs { + __NL80211_PMSR_PEER_ATTR_INVALID, + + NL80211_PMSR_PEER_ATTR_ADDR, + NL80211_PMSR_PEER_ATTR_CHAN, + NL80211_PMSR_PEER_ATTR_REQ, + NL80211_PMSR_PEER_ATTR_RESP, + + /* keep last */ + NUM_NL80211_PMSR_PEER_ATTRS, + NL80211_PMSR_PEER_ATTR_MAX = NUM_NL80211_PMSR_PEER_ATTRS - 1, +}; + +/** + * enum nl80211_peer_measurement_attrs - peer measurement attributes + * @__NL80211_PMSR_ATTR_INVALID: invalid + * + * @NL80211_PMSR_ATTR_MAX_PEERS: u32 attribute used for capability + * advertisement only, indicates the maximum number of peers + * measurements can be done with in a single request + * @NL80211_PMSR_ATTR_REPORT_AP_TSF: flag attribute in capability + * indicating that the connected AP's TSF can be reported in + * measurement results + * @NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR: flag attribute in capability + * indicating that MAC address randomization is supported. + * @NL80211_PMSR_ATTR_TYPE_CAPA: capabilities reported by the device, + * this contains a nesting indexed by measurement type, and + * type-specific capabilities inside, which are from the enums + * named nl80211_peer_measurement__capa. + * @NL80211_PMSR_ATTR_PEERS: nested attribute, the nesting index is + * meaningless, just a list of peers to measure with, with the + * sub-attributes taken from + * &enum nl80211_peer_measurement_peer_attrs. + * + * @NUM_NL80211_PMSR_ATTR: internal + * @NL80211_PMSR_ATTR_MAX: highest attribute number + */ +enum nl80211_peer_measurement_attrs { + __NL80211_PMSR_ATTR_INVALID, + + NL80211_PMSR_ATTR_MAX_PEERS, + NL80211_PMSR_ATTR_REPORT_AP_TSF, + NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR, + NL80211_PMSR_ATTR_TYPE_CAPA, + NL80211_PMSR_ATTR_PEERS, + + /* keep last */ + NUM_NL80211_PMSR_ATTR, + NL80211_PMSR_ATTR_MAX = NUM_NL80211_PMSR_ATTR - 1 +}; + +/** + * enum nl80211_peer_measurement_ftm_capa - FTM capabilities + * @__NL80211_PMSR_FTM_CAPA_ATTR_INVALID: invalid + * + * @NL80211_PMSR_FTM_CAPA_ATTR_ASAP: flag attribute indicating ASAP mode + * is supported + * @NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP: flag attribute indicating non-ASAP + * mode is supported + * @NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI: flag attribute indicating if LCI + * data can be requested during the measurement + * @NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC: flag attribute indicating if civic + * location data can be requested during the measurement + * @NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES: u32 bitmap attribute of bits + * from &enum nl80211_preamble. + * @NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS: bitmap of values from + * &enum nl80211_chan_width indicating the supported channel + * bandwidths for FTM. Note that a higher channel bandwidth may be + * configured to allow for other measurements types with different + * bandwidth requirement in the same measurement. + * @NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT: u32 attribute indicating + * the maximum bursts exponent that can be used (if not present anything + * is valid) + * @NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST: u32 attribute indicating + * the maximum FTMs per burst (if not present anything is valid) + * @NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED: flag attribute indicating if + * trigger based ranging measurement is supported + * @NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED: flag attribute indicating + * if non trigger based ranging measurement is supported + * + * @NUM_NL80211_PMSR_FTM_CAPA_ATTR: internal + * @NL80211_PMSR_FTM_CAPA_ATTR_MAX: highest attribute number + */ +enum nl80211_peer_measurement_ftm_capa { + __NL80211_PMSR_FTM_CAPA_ATTR_INVALID, + + NL80211_PMSR_FTM_CAPA_ATTR_ASAP, + NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP, + NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI, + NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC, + NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES, + NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS, + NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT, + NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST, + NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED, + NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED, + + /* keep last */ + NUM_NL80211_PMSR_FTM_CAPA_ATTR, + NL80211_PMSR_FTM_CAPA_ATTR_MAX = NUM_NL80211_PMSR_FTM_CAPA_ATTR - 1 +}; + +/** + * enum nl80211_peer_measurement_ftm_req - FTM request attributes + * @__NL80211_PMSR_FTM_REQ_ATTR_INVALID: invalid + * + * @NL80211_PMSR_FTM_REQ_ATTR_ASAP: ASAP mode requested (flag) + * @NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE: preamble type (see + * &enum nl80211_preamble), optional for DMG (u32) + * @NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP: number of bursts exponent as in + * 802.11-2016 9.4.2.168 "Fine Timing Measurement Parameters element" + * (u8, 0-15, optional with default 15 i.e. "no preference") + * @NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD: interval between bursts in units + * of 100ms (u16, optional with default 0) + * @NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION: burst duration, as in 802.11-2016 + * Table 9-257 "Burst Duration field encoding" (u8, 0-15, optional with + * default 15 i.e. "no preference") + * @NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST: number of successful FTM frames + * requested per burst + * (u8, 0-31, optional with default 0 i.e. "no preference") + * @NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES: number of FTMR frame retries + * (u8, default 3) + * @NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI: request LCI data (flag) + * @NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC: request civic location data + * (flag) + * @NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED: request trigger based ranging + * measurement (flag). + * This attribute and %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED are + * mutually exclusive. + * if neither %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED nor + * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set, EDCA based + * ranging will be used. + * @NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED: request non trigger based + * ranging measurement (flag) + * This attribute and %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED are + * mutually exclusive. + * if neither %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED nor + * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set, EDCA based + * ranging will be used. + * @NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK: negotiate for LMR feedback. Only + * valid if either %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED or + * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set. + * + * @NUM_NL80211_PMSR_FTM_REQ_ATTR: internal + * @NL80211_PMSR_FTM_REQ_ATTR_MAX: highest attribute number + */ +enum nl80211_peer_measurement_ftm_req { + __NL80211_PMSR_FTM_REQ_ATTR_INVALID, + + NL80211_PMSR_FTM_REQ_ATTR_ASAP, + NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE, + NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP, + NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD, + NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION, + NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST, + NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES, + NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI, + NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC, + NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED, + NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED, + NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK, + + /* keep last */ + NUM_NL80211_PMSR_FTM_REQ_ATTR, + NL80211_PMSR_FTM_REQ_ATTR_MAX = NUM_NL80211_PMSR_FTM_REQ_ATTR - 1 +}; + +/** + * enum nl80211_peer_measurement_ftm_failure_reasons - FTM failure reasons + * @NL80211_PMSR_FTM_FAILURE_UNSPECIFIED: unspecified failure, not used + * @NL80211_PMSR_FTM_FAILURE_NO_RESPONSE: no response from the FTM responder + * @NL80211_PMSR_FTM_FAILURE_REJECTED: FTM responder rejected measurement + * @NL80211_PMSR_FTM_FAILURE_WRONG_CHANNEL: we already know the peer is + * on a different channel, so can't measure (if we didn't know, we'd + * try and get no response) + * @NL80211_PMSR_FTM_FAILURE_PEER_NOT_CAPABLE: peer can't actually do FTM + * @NL80211_PMSR_FTM_FAILURE_INVALID_TIMESTAMP: invalid T1/T4 timestamps + * received + * @NL80211_PMSR_FTM_FAILURE_PEER_BUSY: peer reports busy, you may retry + * later (see %NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME) + * @NL80211_PMSR_FTM_FAILURE_BAD_CHANGED_PARAMS: parameters were changed + * by the peer and are no longer supported + */ +enum nl80211_peer_measurement_ftm_failure_reasons { + NL80211_PMSR_FTM_FAILURE_UNSPECIFIED, + NL80211_PMSR_FTM_FAILURE_NO_RESPONSE, + NL80211_PMSR_FTM_FAILURE_REJECTED, + NL80211_PMSR_FTM_FAILURE_WRONG_CHANNEL, + NL80211_PMSR_FTM_FAILURE_PEER_NOT_CAPABLE, + NL80211_PMSR_FTM_FAILURE_INVALID_TIMESTAMP, + NL80211_PMSR_FTM_FAILURE_PEER_BUSY, + NL80211_PMSR_FTM_FAILURE_BAD_CHANGED_PARAMS, +}; + +/** + * enum nl80211_peer_measurement_ftm_resp - FTM response attributes + * @__NL80211_PMSR_FTM_RESP_ATTR_INVALID: invalid + * + * @NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON: FTM-specific failure reason + * (u32, optional) + * @NL80211_PMSR_FTM_RESP_ATTR_BURST_INDEX: optional, if bursts are reported + * as separate results then it will be the burst index 0...(N-1) and + * the top level will indicate partial results (u32) + * @NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_ATTEMPTS: number of FTM Request frames + * transmitted (u32, optional) + * @NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_SUCCESSES: number of FTM Request frames + * that were acknowleged (u32, optional) + * @NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME: retry time received from the + * busy peer (u32, seconds) + * @NL80211_PMSR_FTM_RESP_ATTR_NUM_BURSTS_EXP: actual number of bursts exponent + * used by the responder (similar to request, u8) + * @NL80211_PMSR_FTM_RESP_ATTR_BURST_DURATION: actual burst duration used by + * the responder (similar to request, u8) + * @NL80211_PMSR_FTM_RESP_ATTR_FTMS_PER_BURST: actual FTMs per burst used + * by the responder (similar to request, u8) + * @NL80211_PMSR_FTM_RESP_ATTR_RSSI_AVG: average RSSI across all FTM action + * frames (optional, s32, 1/2 dBm) + * @NL80211_PMSR_FTM_RESP_ATTR_RSSI_SPREAD: RSSI spread across all FTM action + * frames (optional, s32, 1/2 dBm) + * @NL80211_PMSR_FTM_RESP_ATTR_TX_RATE: bitrate we used for the response to the + * FTM action frame (optional, nested, using &enum nl80211_rate_info + * attributes) + * @NL80211_PMSR_FTM_RESP_ATTR_RX_RATE: bitrate the responder used for the FTM + * action frame (optional, nested, using &enum nl80211_rate_info attrs) + * @NL80211_PMSR_FTM_RESP_ATTR_RTT_AVG: average RTT (s64, picoseconds, optional + * but one of RTT/DIST must be present) + * @NL80211_PMSR_FTM_RESP_ATTR_RTT_VARIANCE: RTT variance (u64, ps^2, note that + * standard deviation is the square root of variance, optional) + * @NL80211_PMSR_FTM_RESP_ATTR_RTT_SPREAD: RTT spread (u64, picoseconds, + * optional) + * @NL80211_PMSR_FTM_RESP_ATTR_DIST_AVG: average distance (s64, mm, optional + * but one of RTT/DIST must be present) + * @NL80211_PMSR_FTM_RESP_ATTR_DIST_VARIANCE: distance variance (u64, mm^2, note + * that standard deviation is the square root of variance, optional) + * @NL80211_PMSR_FTM_RESP_ATTR_DIST_SPREAD: distance spread (u64, mm, optional) + * @NL80211_PMSR_FTM_RESP_ATTR_LCI: LCI data from peer (binary, optional); + * this is the contents of the Measurement Report Element (802.11-2016 + * 9.4.2.22.1) starting with the Measurement Token, with Measurement + * Type 8. + * @NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC: civic location data from peer + * (binary, optional); + * this is the contents of the Measurement Report Element (802.11-2016 + * 9.4.2.22.1) starting with the Measurement Token, with Measurement + * Type 11. + * @NL80211_PMSR_FTM_RESP_ATTR_PAD: ignore, for u64/s64 padding only + * + * @NUM_NL80211_PMSR_FTM_RESP_ATTR: internal + * @NL80211_PMSR_FTM_RESP_ATTR_MAX: highest attribute number + */ +enum nl80211_peer_measurement_ftm_resp { + __NL80211_PMSR_FTM_RESP_ATTR_INVALID, + + NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON, + NL80211_PMSR_FTM_RESP_ATTR_BURST_INDEX, + NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_ATTEMPTS, + NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_SUCCESSES, + NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME, + NL80211_PMSR_FTM_RESP_ATTR_NUM_BURSTS_EXP, + NL80211_PMSR_FTM_RESP_ATTR_BURST_DURATION, + NL80211_PMSR_FTM_RESP_ATTR_FTMS_PER_BURST, + NL80211_PMSR_FTM_RESP_ATTR_RSSI_AVG, + NL80211_PMSR_FTM_RESP_ATTR_RSSI_SPREAD, + NL80211_PMSR_FTM_RESP_ATTR_TX_RATE, + NL80211_PMSR_FTM_RESP_ATTR_RX_RATE, + NL80211_PMSR_FTM_RESP_ATTR_RTT_AVG, + NL80211_PMSR_FTM_RESP_ATTR_RTT_VARIANCE, + NL80211_PMSR_FTM_RESP_ATTR_RTT_SPREAD, + NL80211_PMSR_FTM_RESP_ATTR_DIST_AVG, + NL80211_PMSR_FTM_RESP_ATTR_DIST_VARIANCE, + NL80211_PMSR_FTM_RESP_ATTR_DIST_SPREAD, + NL80211_PMSR_FTM_RESP_ATTR_LCI, + NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC, + NL80211_PMSR_FTM_RESP_ATTR_PAD, + + /* keep last */ + NUM_NL80211_PMSR_FTM_RESP_ATTR, + NL80211_PMSR_FTM_RESP_ATTR_MAX = NUM_NL80211_PMSR_FTM_RESP_ATTR - 1 +}; + +/** + * enum nl80211_obss_pd_attributes - OBSS packet detection attributes + * @__NL80211_HE_OBSS_PD_ATTR_INVALID: Invalid + * + * @NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET: the OBSS PD minimum tx power offset. + * @NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET: the OBSS PD maximum tx power offset. + * @NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET: the non-SRG OBSS PD maximum + * tx power offset. + * @NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP: bitmap that indicates the BSS color + * values used by members of the SRG. + * @NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP: bitmap that indicates the partial + * BSSID values used by members of the SRG. + * @NL80211_HE_OBSS_PD_ATTR_SR_CTRL: The SR Control field of SRP element. + * + * @__NL80211_HE_OBSS_PD_ATTR_LAST: Internal + * @NL80211_HE_OBSS_PD_ATTR_MAX: highest OBSS PD attribute. + */ +enum nl80211_obss_pd_attributes { + __NL80211_HE_OBSS_PD_ATTR_INVALID, + + NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET, + NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET, + NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET, + NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP, + NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP, + NL80211_HE_OBSS_PD_ATTR_SR_CTRL, + + /* keep last */ + __NL80211_HE_OBSS_PD_ATTR_LAST, + NL80211_HE_OBSS_PD_ATTR_MAX = __NL80211_HE_OBSS_PD_ATTR_LAST - 1, +}; + +/** + * enum nl80211_bss_color_attributes - BSS Color attributes + * @__NL80211_HE_BSS_COLOR_ATTR_INVALID: Invalid + * + * @NL80211_HE_BSS_COLOR_ATTR_COLOR: the current BSS Color. + * @NL80211_HE_BSS_COLOR_ATTR_DISABLED: is BSS coloring disabled. + * @NL80211_HE_BSS_COLOR_ATTR_PARTIAL: the AID equation to be used.. + * + * @__NL80211_HE_BSS_COLOR_ATTR_LAST: Internal + * @NL80211_HE_BSS_COLOR_ATTR_MAX: highest BSS Color attribute. + */ +enum nl80211_bss_color_attributes { + __NL80211_HE_BSS_COLOR_ATTR_INVALID, + + NL80211_HE_BSS_COLOR_ATTR_COLOR, + NL80211_HE_BSS_COLOR_ATTR_DISABLED, + NL80211_HE_BSS_COLOR_ATTR_PARTIAL, + + /* keep last */ + __NL80211_HE_BSS_COLOR_ATTR_LAST, + NL80211_HE_BSS_COLOR_ATTR_MAX = __NL80211_HE_BSS_COLOR_ATTR_LAST - 1, +}; + +/** + * enum nl80211_iftype_akm_attributes - interface type AKM attributes + * @__NL80211_IFTYPE_AKM_ATTR_INVALID: Invalid + * + * @NL80211_IFTYPE_AKM_ATTR_IFTYPES: nested attribute containing a flag + * attribute for each interface type that supports AKM suites specified in + * %NL80211_IFTYPE_AKM_ATTR_SUITES + * @NL80211_IFTYPE_AKM_ATTR_SUITES: an array of u32. Used to indicate supported + * AKM suites for the specified interface types. + * + * @__NL80211_IFTYPE_AKM_ATTR_LAST: Internal + * @NL80211_IFTYPE_AKM_ATTR_MAX: highest interface type AKM attribute. + */ +enum nl80211_iftype_akm_attributes { + __NL80211_IFTYPE_AKM_ATTR_INVALID, + + NL80211_IFTYPE_AKM_ATTR_IFTYPES, + NL80211_IFTYPE_AKM_ATTR_SUITES, + + /* keep last */ + __NL80211_IFTYPE_AKM_ATTR_LAST, + NL80211_IFTYPE_AKM_ATTR_MAX = __NL80211_IFTYPE_AKM_ATTR_LAST - 1, +}; + +/** + * enum nl80211_fils_discovery_attributes - FILS discovery configuration + * from IEEE Std 802.11ai-2016, Annex C.3 MIB detail. + * + * @__NL80211_FILS_DISCOVERY_ATTR_INVALID: Invalid + * + * @NL80211_FILS_DISCOVERY_ATTR_INT_MIN: Minimum packet interval (u32, TU). + * Allowed range: 0..10000 (TU = Time Unit) + * @NL80211_FILS_DISCOVERY_ATTR_INT_MAX: Maximum packet interval (u32, TU). + * Allowed range: 0..10000 (TU = Time Unit) + * @NL80211_FILS_DISCOVERY_ATTR_TMPL: Template data for FILS discovery action + * frame including the headers. + * + * @__NL80211_FILS_DISCOVERY_ATTR_LAST: Internal + * @NL80211_FILS_DISCOVERY_ATTR_MAX: highest attribute + */ +enum nl80211_fils_discovery_attributes { + __NL80211_FILS_DISCOVERY_ATTR_INVALID, + + NL80211_FILS_DISCOVERY_ATTR_INT_MIN, + NL80211_FILS_DISCOVERY_ATTR_INT_MAX, + NL80211_FILS_DISCOVERY_ATTR_TMPL, + + /* keep last */ + __NL80211_FILS_DISCOVERY_ATTR_LAST, + NL80211_FILS_DISCOVERY_ATTR_MAX = __NL80211_FILS_DISCOVERY_ATTR_LAST - 1 +}; + +/* + * FILS discovery template minimum length with action frame headers and + * mandatory fields. + */ +#define NL80211_FILS_DISCOVERY_TMPL_MIN_LEN 42 + +/** + * enum nl80211_unsol_bcast_probe_resp_attributes - Unsolicited broadcast probe + * response configuration. Applicable only in 6GHz. + * + * @__NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INVALID: Invalid + * + * @NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT: Maximum packet interval (u32, TU). + * Allowed range: 0..20 (TU = Time Unit). IEEE P802.11ax/D6.0 + * 26.17.2.3.2 (AP behavior for fast passive scanning). + * @NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL: Unsolicited broadcast probe response + * frame template (binary). + * + * @__NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_LAST: Internal + * @NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX: highest attribute + */ +enum nl80211_unsol_bcast_probe_resp_attributes { + __NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INVALID, + + NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT, + NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL, + + /* keep last */ + __NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_LAST, + NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX = + __NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_LAST - 1 +}; + +/** + * enum nl80211_sae_pwe_mechanism - The mechanism(s) allowed for SAE PWE + * derivation. Applicable only when WPA3-Personal SAE authentication is + * used. + * + * @NL80211_SAE_PWE_UNSPECIFIED: not specified, used internally to indicate that + * attribute is not present from userspace. + * @NL80211_SAE_PWE_HUNT_AND_PECK: hunting-and-pecking loop only + * @NL80211_SAE_PWE_HASH_TO_ELEMENT: hash-to-element only + * @NL80211_SAE_PWE_BOTH: both hunting-and-pecking loop and hash-to-element + * can be used. + */ +enum nl80211_sae_pwe_mechanism { + NL80211_SAE_PWE_UNSPECIFIED, + NL80211_SAE_PWE_HUNT_AND_PECK, + NL80211_SAE_PWE_HASH_TO_ELEMENT, + NL80211_SAE_PWE_BOTH, +}; + +/** + * enum nl80211_sar_type - type of SAR specs + * + * @NL80211_SAR_TYPE_POWER: power limitation specified in 0.25dBm unit + * + */ +enum nl80211_sar_type { + NL80211_SAR_TYPE_POWER, + + /* add new type here */ + + /* Keep last */ + NUM_NL80211_SAR_TYPE, +}; + +/** + * enum nl80211_sar_attrs - Attributes for SAR spec + * + * @NL80211_SAR_ATTR_TYPE: the SAR type as defined in &enum nl80211_sar_type. + * + * @NL80211_SAR_ATTR_SPECS: Nested array of SAR power + * limit specifications. Each specification contains a set + * of %nl80211_sar_specs_attrs. + * + * For SET operation, it contains array of %NL80211_SAR_ATTR_SPECS_POWER + * and %NL80211_SAR_ATTR_SPECS_RANGE_INDEX. + * + * For sar_capa dump, it contains array of + * %NL80211_SAR_ATTR_SPECS_START_FREQ + * and %NL80211_SAR_ATTR_SPECS_END_FREQ. + * + * @__NL80211_SAR_ATTR_LAST: Internal + * @NL80211_SAR_ATTR_MAX: highest sar attribute + * + * These attributes are used with %NL80211_CMD_SET_SAR_SPEC + */ +enum nl80211_sar_attrs { + __NL80211_SAR_ATTR_INVALID, + + NL80211_SAR_ATTR_TYPE, + NL80211_SAR_ATTR_SPECS, + + __NL80211_SAR_ATTR_LAST, + NL80211_SAR_ATTR_MAX = __NL80211_SAR_ATTR_LAST - 1, +}; + +/** + * enum nl80211_sar_specs_attrs - Attributes for SAR power limit specs + * + * @NL80211_SAR_ATTR_SPECS_POWER: Required (s32)value to specify the actual + * power limit value in units of 0.25 dBm if type is + * NL80211_SAR_TYPE_POWER. (i.e., a value of 44 represents 11 dBm). + * 0 means userspace doesn't have SAR limitation on this associated range. + * + * @NL80211_SAR_ATTR_SPECS_RANGE_INDEX: Required (u32) value to specify the + * index of exported freq range table and the associated power limitation + * is applied to this range. + * + * Userspace isn't required to set all the ranges advertised by WLAN driver, + * and userspace can skip some certain ranges. These skipped ranges don't + * have SAR limitations, and they are same as setting the + * %NL80211_SAR_ATTR_SPECS_POWER to any unreasonable high value because any + * value higher than regulatory allowed value just means SAR power + * limitation is removed, but it's required to set at least one range. + * It's not allowed to set duplicated range in one SET operation. + * + * Every SET operation overwrites previous SET operation. + * + * @NL80211_SAR_ATTR_SPECS_START_FREQ: Required (u32) value to specify the start + * frequency of this range edge when registering SAR capability to wiphy. + * It's not a channel center frequency. The unit is kHz. + * + * @NL80211_SAR_ATTR_SPECS_END_FREQ: Required (u32) value to specify the end + * frequency of this range edge when registering SAR capability to wiphy. + * It's not a channel center frequency. The unit is kHz. + * + * @__NL80211_SAR_ATTR_SPECS_LAST: Internal + * @NL80211_SAR_ATTR_SPECS_MAX: highest sar specs attribute + */ +enum nl80211_sar_specs_attrs { + __NL80211_SAR_ATTR_SPECS_INVALID, + + NL80211_SAR_ATTR_SPECS_POWER, + NL80211_SAR_ATTR_SPECS_RANGE_INDEX, + NL80211_SAR_ATTR_SPECS_START_FREQ, + NL80211_SAR_ATTR_SPECS_END_FREQ, + + __NL80211_SAR_ATTR_SPECS_LAST, + NL80211_SAR_ATTR_SPECS_MAX = __NL80211_SAR_ATTR_SPECS_LAST - 1, +}; + #endif /* __LINUX_NL80211_H */ diff --git a/include/uapi/linux/switch.h b/include/uapi/linux/switch.h index 2ace29ab5275..ca9c75993ec3 100644 --- a/include/uapi/linux/switch.h +++ b/include/uapi/linux/switch.h @@ -115,6 +115,7 @@ enum { SWITCH_PORT_UNSPEC, SWITCH_PORT_ID, SWITCH_PORT_FLAG_TAGGED, + SWITCH_PORT_FLAG_UNTAGGED, SWITCH_PORT_ATTR_MAX }; diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 39e319d04bb8..bb3722ea5d64 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -2047,7 +2047,7 @@ static int tc_dump_tclass_qdisc(struct Qdisc *q, struct sk_buff *skb, static int tc_dump_tclass_root(struct Qdisc *root, struct sk_buff *skb, struct tcmsg *tcm, struct netlink_callback *cb, - int *t_p, int s_t) + int *t_p, int s_t, bool recur) { struct Qdisc *q; int b; @@ -2058,7 +2058,7 @@ static int tc_dump_tclass_root(struct Qdisc *root, struct sk_buff *skb, if (tc_dump_tclass_qdisc(root, skb, tcm, cb, t_p, s_t) < 0) return -1; - if (!qdisc_dev(root)) + if (!qdisc_dev(root) || !recur) return 0; if (tcm->tcm_parent) { @@ -2093,13 +2093,13 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) s_t = cb->args[0]; t = 0; - if (tc_dump_tclass_root(dev->qdisc, skb, tcm, cb, &t, s_t) < 0) + if (tc_dump_tclass_root(dev->qdisc, skb, tcm, cb, &t, s_t, true) < 0) goto done; dev_queue = dev_ingress_queue(dev); if (dev_queue && tc_dump_tclass_root(dev_queue->qdisc_sleeping, skb, tcm, cb, - &t, s_t) < 0) + &t, s_t, false) < 0) goto done; done: