diff options
302 files changed, 6672 insertions, 2452 deletions
diff --git a/Documentation/devicetree/bindings/net/brcm,bcmgenet.txt b/Documentation/devicetree/bindings/net/brcm,bcmgenet.txt index 33a0d67e4ce5..0b5994fba35f 100644 --- a/Documentation/devicetree/bindings/net/brcm,bcmgenet.txt +++ b/Documentation/devicetree/bindings/net/brcm,bcmgenet.txt @@ -2,7 +2,8 @@ Required properties: - compatible: should contain one of "brcm,genet-v1", "brcm,genet-v2", - "brcm,genet-v3", "brcm,genet-v4", "brcm,genet-v5", "brcm,bcm2711-genet-v5". + "brcm,genet-v3", "brcm,genet-v4", "brcm,genet-v5", "brcm,bcm2711-genet-v5" or + "brcm,bcm7712-genet-v5". - reg: address and length of the register set for the device - interrupts and/or interrupts-extended: must be two cells, the first cell is the general purpose interrupt line, while the second cell is the diff --git a/Documentation/devicetree/bindings/net/macb.txt b/Documentation/devicetree/bindings/net/macb.txt index af9df2f01a1c..a1b06fd1962e 100644 --- a/Documentation/devicetree/bindings/net/macb.txt +++ b/Documentation/devicetree/bindings/net/macb.txt @@ -30,6 +30,10 @@ Required properties: Optional elements: 'tsu_clk' - clocks: Phandles to input clocks. +Optional properties: +- mdio: node containing PHY children. If this node is not present, then PHYs + will be direct children. + The MAC address will be determined using the optional properties defined in ethernet.txt. diff --git a/Documentation/networking/device_drivers/ethernet/mellanox/mlx5.rst b/Documentation/networking/device_drivers/ethernet/mellanox/mlx5.rst index 4b59cf2c599f..5edf50d7dbd5 100644 --- a/Documentation/networking/device_drivers/ethernet/mellanox/mlx5.rst +++ b/Documentation/networking/device_drivers/ethernet/mellanox/mlx5.rst @@ -543,6 +543,8 @@ The CR-space dump uses vsc interface which is valid even if the FW command interface is not functional, which is the case in most FW fatal errors. The recover function runs recover flow which reloads the driver and triggers fw reset if needed. +On firmware error, the health buffer is dumped into the dmesg. The log +level is derived from the error's severity (given in health buffer). User commands examples: @@ -700,3 +702,61 @@ Eswitch QoS tracepoints: $ cat /sys/kernel/debug/tracing/trace ... <...>-27418 [006] .... 76547.187258: mlx5_esw_group_qos_destroy: (0000:82:00.0) group=000000007b576bb3 tsar_ix=1 + +SF tracepoints: + +- mlx5_sf_add: trace addition of the SF port:: + + $ echo mlx5:mlx5_sf_add >> /sys/kernel/debug/tracing/set_event + $ cat /sys/kernel/debug/tracing/trace + ... + devlink-9363 [031] ..... 24610.188722: mlx5_sf_add: (0000:06:00.0) port_index=32768 controller=0 hw_id=0x8000 sfnum=88 + +- mlx5_sf_free: trace freeing of the SF port:: + + $ echo mlx5:mlx5_sf_free >> /sys/kernel/debug/tracing/set_event + $ cat /sys/kernel/debug/tracing/trace + ... + devlink-9830 [038] ..... 26300.404749: mlx5_sf_free: (0000:06:00.0) port_index=32768 controller=0 hw_id=0x8000 + +- mlx5_sf_hwc_alloc: trace allocating of the hardware SF context:: + + $ echo mlx5:mlx5_sf_hwc_alloc >> /sys/kernel/debug/tracing/set_event + $ cat /sys/kernel/debug/tracing/trace + ... + devlink-9775 [031] ..... 26296.385259: mlx5_sf_hwc_alloc: (0000:06:00.0) controller=0 hw_id=0x8000 sfnum=88 + +- mlx5_sf_hwc_free: trace freeing of the hardware SF context:: + + $ echo mlx5:mlx5_sf_hwc_free >> /sys/kernel/debug/tracing/set_event + $ cat /sys/kernel/debug/tracing/trace + ... + kworker/u128:3-9093 [046] ..... 24625.365771: mlx5_sf_hwc_free: (0000:06:00.0) hw_id=0x8000 + +- mlx5_sf_hwc_deferred_free : trace deferred freeing of the hardware SF context:: + + $ echo mlx5:mlx5_sf_hwc_deferred_free >> /sys/kernel/debug/tracing/set_event + $ cat /sys/kernel/debug/tracing/trace + ... + devlink-9519 [046] ..... 24624.400271: mlx5_sf_hwc_deferred_free: (0000:06:00.0) hw_id=0x8000 + +- mlx5_sf_vhca_event: trace SF vhca event and state:: + + $ echo mlx5:mlx5_sf_vhca_event >> /sys/kernel/debug/tracing/set_event + $ cat /sys/kernel/debug/tracing/trace + ... + kworker/u128:3-9093 [046] ..... 24625.365525: mlx5_sf_vhca_event: (0000:06:00.0) hw_id=0x8000 sfnum=88 vhca_state=1 + +- mlx5_sf_dev_add : trace SF device add event:: + + $ echo mlx5:mlx5_sf_dev_add>> /sys/kernel/debug/tracing/set_event + $ cat /sys/kernel/debug/tracing/trace + ... + kworker/u128:3-9093 [000] ..... 24616.524495: mlx5_sf_dev_add: (0000:06:00.0) sfdev=00000000fc5d96fd aux_id=4 hw_id=0x8000 sfnum=88 + +- mlx5_sf_dev_del : trace SF device delete event:: + + $ echo mlx5:mlx5_sf_dev_del >> /sys/kernel/debug/tracing/set_event + $ cat /sys/kernel/debug/tracing/trace + ... + kworker/u128:3-9093 [044] ..... 24624.400749: mlx5_sf_dev_del: (0000:06:00.0) sfdev=00000000fc5d96fd aux_id=4 hw_id=0x8000 sfnum=88 diff --git a/MAINTAINERS b/MAINTAINERS index c5aa142d4b3a..975086c5345d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13056,6 +13056,7 @@ F: include/linux/dsa/ F: include/linux/platform_data/dsa.h F: include/net/dsa.h F: net/dsa/ +F: tools/testing/selftests/drivers/net/dsa/ NETWORKING [GENERAL] M: "David S. Miller" <[email protected]> diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h index 25b5dc34db75..4b9b14b20984 100644 --- a/arch/s390/include/asm/qdio.h +++ b/arch/s390/include/asm/qdio.h @@ -349,8 +349,6 @@ extern int qdio_allocate(struct ccw_device *cdev, unsigned int no_input_qs, extern int qdio_establish(struct ccw_device *cdev, struct qdio_initialize *init_data); extern int qdio_activate(struct ccw_device *); -extern struct qaob *qdio_allocate_aob(void); -extern void qdio_release_aob(struct qaob *); extern int do_QDIO(struct ccw_device *cdev, unsigned int callflags, int q_nr, unsigned int bufnr, unsigned int count, struct qaob *aob); extern int qdio_start_irq(struct ccw_device *cdev); diff --git a/drivers/base/regmap/regmap-mdio.c b/drivers/base/regmap/regmap-mdio.c index 6a20201299f5..f7293040a2b1 100644 --- a/drivers/base/regmap/regmap-mdio.c +++ b/drivers/base/regmap/regmap-mdio.c @@ -14,7 +14,7 @@ static int regmap_mdio_read(struct mdio_device *mdio_dev, u32 reg, unsigned int { int ret; - ret = mdiobus_read(mdio_dev->bus, mdio_dev->addr, reg); + ret = mdiodev_read(mdio_dev, reg); if (ret < 0) return ret; @@ -24,7 +24,7 @@ static int regmap_mdio_read(struct mdio_device *mdio_dev, u32 reg, unsigned int static int regmap_mdio_write(struct mdio_device *mdio_dev, u32 reg, unsigned int val) { - return mdiobus_write(mdio_dev->bus, mdio_dev->addr, reg, val); + return mdiodev_write(mdio_dev, reg, val); } static int regmap_mdio_c22_read(void *context, unsigned int reg, unsigned int *val) @@ -44,7 +44,7 @@ static int regmap_mdio_c22_write(void *context, unsigned int reg, unsigned int v if (unlikely(reg & ~REGNUM_C22_MASK)) return -ENXIO; - return mdiobus_write(mdio_dev->bus, mdio_dev->addr, reg, val); + return mdiodev_write(mdio_dev, reg, val); } static const struct regmap_bus regmap_mdio_c22_bus = { diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index f37b1c56f7c4..dd335ae1122b 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -150,7 +150,7 @@ config NET_FC config IFB tristate "Intermediate Functional Block support" - depends on NET_CLS_ACT + depends on NET_ACT_MIRRED || NFT_FWD_NETDEV select NET_REDIRECT help This is an intermediate driver that allows sharing of diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 7d3752cbf761..2ec8e015c7b3 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -50,7 +50,7 @@ struct arp_pkt { #pragma pack() /* Forward declaration */ -static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[], +static void alb_send_learning_packets(struct slave *slave, const u8 mac_addr[], bool strict_match); static void rlb_purge_src_ip(struct bonding *bond, struct arp_pkt *arp); static void rlb_src_unlink(struct bonding *bond, u32 index); @@ -353,7 +353,8 @@ static struct slave *rlb_next_rx_slave(struct bonding *bond) * * Caller must hold RTNL */ -static void rlb_teach_disabled_mac_on_primary(struct bonding *bond, u8 addr[]) +static void rlb_teach_disabled_mac_on_primary(struct bonding *bond, + const u8 addr[]) { struct slave *curr_active = rtnl_dereference(bond->curr_active_slave); @@ -904,7 +905,7 @@ static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id) /*********************** tlb/rlb shared functions *********************/ -static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[], +static void alb_send_lp_vid(struct slave *slave, const u8 mac_addr[], __be16 vlan_proto, u16 vid) { struct learning_pkt pkt; @@ -940,7 +941,7 @@ static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[], struct alb_walk_data { struct bonding *bond; struct slave *slave; - u8 *mac_addr; + const u8 *mac_addr; bool strict_match; }; @@ -949,9 +950,9 @@ static int alb_upper_dev_walk(struct net_device *upper, { struct alb_walk_data *data = (struct alb_walk_data *)priv->data; bool strict_match = data->strict_match; + const u8 *mac_addr = data->mac_addr; struct bonding *bond = data->bond; struct slave *slave = data->slave; - u8 *mac_addr = data->mac_addr; struct bond_vlan_tag *tags; if (is_vlan_dev(upper) && @@ -982,7 +983,7 @@ static int alb_upper_dev_walk(struct net_device *upper, return 0; } -static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[], +static void alb_send_learning_packets(struct slave *slave, const u8 mac_addr[], bool strict_match) { struct bonding *bond = bond_get_bond_by_slave(slave); @@ -1006,14 +1007,14 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[], rcu_read_unlock(); } -static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[], +static int alb_set_slave_mac_addr(struct slave *slave, const u8 addr[], unsigned int len) { struct net_device *dev = slave->dev; struct sockaddr_storage ss; if (BOND_MODE(slave->bond) == BOND_MODE_TLB) { - memcpy(dev->dev_addr, addr, len); + __dev_addr_set(dev, addr, len); return 0; } @@ -1242,8 +1243,7 @@ static int alb_set_mac_address(struct bonding *bond, void *addr) res = dev_set_mac_address(slave->dev, addr, NULL); /* restore net_device's hw address */ - bond_hw_addr_copy(slave->dev->dev_addr, tmp_addr, - slave->dev->addr_len); + dev_addr_set(slave->dev, tmp_addr); if (res) goto unwind; @@ -1263,8 +1263,7 @@ unwind: rollback_slave->dev->addr_len); dev_set_mac_address(rollback_slave->dev, (struct sockaddr *)&ss, NULL); - bond_hw_addr_copy(rollback_slave->dev->dev_addr, tmp_addr, - rollback_slave->dev->addr_len); + dev_addr_set(rollback_slave->dev, tmp_addr); } return res; @@ -1727,8 +1726,7 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave dev_set_mac_address(new_slave->dev, (struct sockaddr *)&ss, NULL); - bond_hw_addr_copy(new_slave->dev->dev_addr, tmp_addr, - new_slave->dev->addr_len); + dev_addr_set(new_slave->dev, tmp_addr); } /* curr_active_slave must be set before calling alb_swap_mac_addr */ @@ -1761,7 +1759,7 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr) if (res) return res; - bond_hw_addr_copy(bond_dev->dev_addr, ss->__data, bond_dev->addr_len); + dev_addr_set(bond_dev, ss->__data); /* If there is no curr_active_slave there is nothing else to do. * Otherwise we'll need to pass the new address to it and handle diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 0c52612cb8e9..ff8da720a33a 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -923,7 +923,7 @@ static int bond_set_dev_addr(struct net_device *bond_dev, if (err) return err; - memcpy(bond_dev->dev_addr, slave_dev->dev_addr, slave_dev->addr_len); + __dev_addr_set(bond_dev, slave_dev->dev_addr, slave_dev->addr_len); bond_dev->addr_assign_type = NET_ADDR_STOLEN; call_netdevice_notifiers(NETDEV_CHANGEADDR, bond_dev); return 0; diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index b06af90a9964..3aea32c9b108 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -1170,9 +1170,9 @@ static ssize_t mb0_id_show(struct device *dev, struct at91_priv *priv = netdev_priv(to_net_dev(dev)); if (priv->mb0_id & CAN_EFF_FLAG) - return snprintf(buf, PAGE_SIZE, "0x%08x\n", priv->mb0_id); + return sysfs_emit(buf, "0x%08x\n", priv->mb0_id); else - return snprintf(buf, PAGE_SIZE, "0x%03x\n", priv->mb0_id); + return sysfs_emit(buf, "0x%03x\n", priv->mb0_id); } static ssize_t mb0_id_store(struct device *dev, diff --git a/drivers/net/can/dev/bittiming.c b/drivers/net/can/dev/bittiming.c index f49170eadd54..0509625c3082 100644 --- a/drivers/net/can/dev/bittiming.c +++ b/drivers/net/can/dev/bittiming.c @@ -175,27 +175,29 @@ int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, return 0; } -void can_calc_tdco(struct net_device *dev) -{ - struct can_priv *priv = netdev_priv(dev); - const struct can_bittiming *dbt = &priv->data_bittiming; - struct can_tdc *tdc = &priv->tdc; - const struct can_tdc_const *tdc_const = priv->tdc_const; +void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const, + const struct can_bittiming *dbt, + u32 *ctrlmode, u32 ctrlmode_supported) - if (!tdc_const) +{ + if (!tdc_const || !(ctrlmode_supported & CAN_CTRLMODE_TDC_AUTO)) return; + *ctrlmode &= ~CAN_CTRLMODE_TDC_MASK; + /* As specified in ISO 11898-1 section 11.3.3 "Transmitter * delay compensation" (TDC) is only applicable if data BRP is * one or two. */ if (dbt->brp == 1 || dbt->brp == 2) { - /* Reuse "normal" sample point and convert it to time quanta */ - u32 sample_point_in_tq = can_bit_time(dbt) * dbt->sample_point / 1000; - - tdc->tdco = min(sample_point_in_tq, tdc_const->tdco_max); - } else { - tdc->tdco = 0; + /* Sample point in clock periods */ + u32 sample_point_in_tc = (CAN_SYNC_SEG + dbt->prop_seg + + dbt->phase_seg1) * dbt->brp; + + if (sample_point_in_tc < tdc_const->tdco_min) + return; + tdc->tdco = min(sample_point_in_tc, tdc_const->tdco_max); + *ctrlmode |= CAN_CTRLMODE_TDC_AUTO; } } #endif /* CONFIG_CAN_CALC_BITTIMING */ @@ -209,7 +211,7 @@ static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt, const struct can_bittiming_const *btc) { struct can_priv *priv = netdev_priv(dev); - int tseg1, alltseg; + unsigned int tseg1, alltseg; u64 brp64; tseg1 = bt->prop_seg + bt->phase_seg1; diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c index 80425636049d..95cca4e5251f 100644 --- a/drivers/net/can/dev/netlink.c +++ b/drivers/net/can/dev/netlink.c @@ -2,6 +2,7 @@ /* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix * Copyright (C) 2006 Andrey Volkov, Varma Electronics * Copyright (C) 2008-2009 Wolfgang Grandegger <[email protected]> + * Copyright (C) 2021 Vincent Mailhol <[email protected]> */ #include <linux/can/dev.h> @@ -19,6 +20,19 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = { [IFLA_CAN_DATA_BITTIMING] = { .len = sizeof(struct can_bittiming) }, [IFLA_CAN_DATA_BITTIMING_CONST] = { .len = sizeof(struct can_bittiming_const) }, [IFLA_CAN_TERMINATION] = { .type = NLA_U16 }, + [IFLA_CAN_TDC] = { .type = NLA_NESTED }, +}; + +static const struct nla_policy can_tdc_policy[IFLA_CAN_TDC_MAX + 1] = { + [IFLA_CAN_TDC_TDCV_MIN] = { .type = NLA_U32 }, + [IFLA_CAN_TDC_TDCV_MAX] = { .type = NLA_U32 }, + [IFLA_CAN_TDC_TDCO_MIN] = { .type = NLA_U32 }, + [IFLA_CAN_TDC_TDCO_MAX] = { .type = NLA_U32 }, + [IFLA_CAN_TDC_TDCF_MIN] = { .type = NLA_U32 }, + [IFLA_CAN_TDC_TDCF_MAX] = { .type = NLA_U32 }, + [IFLA_CAN_TDC_TDCV] = { .type = NLA_U32 }, + [IFLA_CAN_TDC_TDCO] = { .type = NLA_U32 }, + [IFLA_CAN_TDC_TDCF] = { .type = NLA_U32 }, }; static int can_validate(struct nlattr *tb[], struct nlattr *data[], @@ -30,6 +44,7 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[], * - nominal/arbitration bittiming * - data bittiming * - control mode with CAN_CTRLMODE_FD set + * - TDC parameters are coherent (details below) */ if (!data) @@ -37,8 +52,43 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[], if (data[IFLA_CAN_CTRLMODE]) { struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]); + u32 tdc_flags = cm->flags & CAN_CTRLMODE_TDC_MASK; is_can_fd = cm->flags & cm->mask & CAN_CTRLMODE_FD; + + /* CAN_CTRLMODE_TDC_{AUTO,MANUAL} are mutually exclusive */ + if (tdc_flags == CAN_CTRLMODE_TDC_MASK) + return -EOPNOTSUPP; + /* If one of the CAN_CTRLMODE_TDC_* flag is set then + * TDC must be set and vice-versa + */ + if (!!tdc_flags != !!data[IFLA_CAN_TDC]) + return -EOPNOTSUPP; + /* If providing TDC parameters, at least TDCO is + * needed. TDCV is needed if and only if + * CAN_CTRLMODE_TDC_MANUAL is set + */ + if (data[IFLA_CAN_TDC]) { + struct nlattr *tb_tdc[IFLA_CAN_TDC_MAX + 1]; + int err; + + err = nla_parse_nested(tb_tdc, IFLA_CAN_TDC_MAX, + data[IFLA_CAN_TDC], + can_tdc_policy, extack); + if (err) + return err; + + if (tb_tdc[IFLA_CAN_TDC_TDCV]) { + if (tdc_flags & CAN_CTRLMODE_TDC_AUTO) + return -EOPNOTSUPP; + } else { + if (tdc_flags & CAN_CTRLMODE_TDC_MANUAL) + return -EOPNOTSUPP; + } + + if (!tb_tdc[IFLA_CAN_TDC_TDCO]) + return -EOPNOTSUPP; + } } if (is_can_fd) { @@ -46,7 +96,7 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[], return -EOPNOTSUPP; } - if (data[IFLA_CAN_DATA_BITTIMING]) { + if (data[IFLA_CAN_DATA_BITTIMING] || data[IFLA_CAN_TDC]) { if (!is_can_fd) return -EOPNOTSUPP; } @@ -54,11 +104,60 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[], return 0; } +static int can_tdc_changelink(struct can_priv *priv, const struct nlattr *nla, + struct netlink_ext_ack *extack) +{ + struct nlattr *tb_tdc[IFLA_CAN_TDC_MAX + 1]; + struct can_tdc tdc = { 0 }; + const struct can_tdc_const *tdc_const = priv->tdc_const; + int err; + + if (!tdc_const || !can_tdc_is_enabled(priv)) + return -EOPNOTSUPP; + + err = nla_parse_nested(tb_tdc, IFLA_CAN_TDC_MAX, nla, + can_tdc_policy, extack); + if (err) + return err; + + if (tb_tdc[IFLA_CAN_TDC_TDCV]) { + u32 tdcv = nla_get_u32(tb_tdc[IFLA_CAN_TDC_TDCV]); + + if (tdcv < tdc_const->tdcv_min || tdcv > tdc_const->tdcv_max) + return -EINVAL; + + tdc.tdcv = tdcv; + } + + if (tb_tdc[IFLA_CAN_TDC_TDCO]) { + u32 tdco = nla_get_u32(tb_tdc[IFLA_CAN_TDC_TDCO]); + + if (tdco < tdc_const->tdco_min || tdco > tdc_const->tdco_max) + return -EINVAL; + + tdc.tdco = tdco; + } + + if (tb_tdc[IFLA_CAN_TDC_TDCF]) { + u32 tdcf = nla_get_u32(tb_tdc[IFLA_CAN_TDC_TDCF]); + + if (tdcf < tdc_const->tdcf_min || tdcf > tdc_const->tdcf_max) + return -EINVAL; + + tdc.tdcf = tdcf; + } + + priv->tdc = tdc; + + return 0; +} + static int can_changelink(struct net_device *dev, struct nlattr *tb[], struct nlattr *data[], struct netlink_ext_ack *extack) { struct can_priv *priv = netdev_priv(dev); + u32 tdc_mask = 0; int err; /* We need synchronization with dev->stop() */ @@ -138,7 +237,16 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[], dev->mtu = CAN_MTU; memset(&priv->data_bittiming, 0, sizeof(priv->data_bittiming)); + priv->ctrlmode &= ~CAN_CTRLMODE_TDC_MASK; + memset(&priv->tdc, 0, sizeof(priv->tdc)); } + + tdc_mask = cm->mask & CAN_CTRLMODE_TDC_MASK; + /* CAN_CTRLMODE_TDC_{AUTO,MANUAL} are mutually + * exclusive: make sure to turn the other one off + */ + if (tdc_mask) + priv->ctrlmode &= cm->flags | ~CAN_CTRLMODE_TDC_MASK; } if (data[IFLA_CAN_RESTART_MS]) { @@ -187,9 +295,26 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[], return -EINVAL; } - memcpy(&priv->data_bittiming, &dbt, sizeof(dbt)); + memset(&priv->tdc, 0, sizeof(priv->tdc)); + if (data[IFLA_CAN_TDC]) { + /* TDC parameters are provided: use them */ + err = can_tdc_changelink(priv, data[IFLA_CAN_TDC], + extack); + if (err) { + priv->ctrlmode &= ~CAN_CTRLMODE_TDC_MASK; + return err; + } + } else if (!tdc_mask) { + /* Neither of TDC parameters nor TDC flags are + * provided: do calculation + */ + can_calc_tdco(&priv->tdc, priv->tdc_const, &priv->data_bittiming, + &priv->ctrlmode, priv->ctrlmode_supported); + } /* else: both CAN_CTRLMODE_TDC_{AUTO,MANUAL} are explicitly + * turned off. TDC is disabled: do nothing + */ - can_calc_tdco(dev); + memcpy(&priv->data_bittiming, &dbt, sizeof(dbt)); if (priv->do_set_data_bittiming) { /* Finally, set the bit-timing registers */ @@ -226,6 +351,38 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[], return 0; } +static size_t can_tdc_get_size(const struct net_device *dev) +{ + struct can_priv *priv = netdev_priv(dev); + size_t size; + + if (!priv->tdc_const) + return 0; + + size = nla_total_size(0); /* nest IFLA_CAN_TDC */ + if (priv->ctrlmode_supported & CAN_CTRLMODE_TDC_MANUAL) { + size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCV_MIN */ + size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCV_MAX */ + } + size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCO_MIN */ + size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCO_MAX */ + if (priv->tdc_const->tdcf_max) { + size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCF_MIN */ + size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCF_MAX */ + } + + if (can_tdc_is_enabled(priv)) { + if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL || + priv->do_get_auto_tdcv) + size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCV */ + size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCO */ + if (priv->tdc_const->tdcf_max) + size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCF */ + } + + return size; +} + static size_t can_get_size(const struct net_device *dev) { struct can_priv *priv = netdev_priv(dev); @@ -257,10 +414,64 @@ static size_t can_get_size(const struct net_device *dev) size += nla_total_size(sizeof(*priv->data_bitrate_const) * priv->data_bitrate_const_cnt); size += sizeof(priv->bitrate_max); /* IFLA_CAN_BITRATE_MAX */ + size += can_tdc_get_size(dev); /* IFLA_CAN_TDC */ return size; } +static int can_tdc_fill_info(struct sk_buff *skb, const struct net_device *dev) +{ + struct nlattr *nest; + struct can_priv *priv = netdev_priv(dev); + struct can_tdc *tdc = &priv->tdc; + const struct can_tdc_const *tdc_const = priv->tdc_const; + + if (!tdc_const) + return 0; + + nest = nla_nest_start(skb, IFLA_CAN_TDC); + if (!nest) + return -EMSGSIZE; + + if (priv->ctrlmode_supported & CAN_CTRLMODE_TDC_MANUAL && + (nla_put_u32(skb, IFLA_CAN_TDC_TDCV_MIN, tdc_const->tdcv_min) || + nla_put_u32(skb, IFLA_CAN_TDC_TDCV_MAX, tdc_const->tdcv_max))) + goto err_cancel; + if (nla_put_u32(skb, IFLA_CAN_TDC_TDCO_MIN, tdc_const->tdco_min) || + nla_put_u32(skb, IFLA_CAN_TDC_TDCO_MAX, tdc_const->tdco_max)) + goto err_cancel; + if (tdc_const->tdcf_max && + (nla_put_u32(skb, IFLA_CAN_TDC_TDCF_MIN, tdc_const->tdcf_min) || + nla_put_u32(skb, IFLA_CAN_TDC_TDCF_MAX, tdc_const->tdcf_max))) + goto err_cancel; + + if (can_tdc_is_enabled(priv)) { + u32 tdcv; + int err = -EINVAL; + + if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL) { + tdcv = tdc->tdcv; + err = 0; + } else if (priv->do_get_auto_tdcv) { + err = priv->do_get_auto_tdcv(dev, &tdcv); + } + if (!err && nla_put_u32(skb, IFLA_CAN_TDC_TDCV, tdcv)) + goto err_cancel; + if (nla_put_u32(skb, IFLA_CAN_TDC_TDCO, tdc->tdco)) + goto err_cancel; + if (tdc_const->tdcf_max && + nla_put_u32(skb, IFLA_CAN_TDC_TDCF, tdc->tdcf)) + goto err_cancel; + } + + nla_nest_end(skb, nest); + return 0; + +err_cancel: + nla_nest_cancel(skb, nest); + return -EMSGSIZE; +} + static int can_fill_info(struct sk_buff *skb, const struct net_device *dev) { struct can_priv *priv = netdev_priv(dev); @@ -318,7 +529,9 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev) (nla_put(skb, IFLA_CAN_BITRATE_MAX, sizeof(priv->bitrate_max), - &priv->bitrate_max)) + &priv->bitrate_max)) || + + (can_tdc_fill_info(skb, dev)) ) return -EMSGSIZE; diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index c68ad56628bd..32006dbf5abd 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -1831,7 +1831,7 @@ static ssize_t termination_show(struct device *dev, return -ETIMEDOUT; } - return snprintf(buf, PAGE_SIZE, "%u\n", mod->termination_enabled); + return sysfs_emit(buf, "%u\n", mod->termination_enabled); } static ssize_t termination_store(struct device *dev, diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index 35892c1efef0..de4ddf79ba9b 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -293,10 +293,8 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev) return -EINVAL; base = of_iomap(np, 0); - if (!base) { - dev_err(&ofdev->dev, "couldn't ioremap\n"); - return err; - } + if (!base) + return dev_err_probe(&ofdev->dev, err, "couldn't ioremap\n"); irq = irq_of_parse_and_map(np, 0); if (!irq) { diff --git a/drivers/net/can/rcar/Kconfig b/drivers/net/can/rcar/Kconfig index 56320a7f828b..c66762ef631b 100644 --- a/drivers/net/can/rcar/Kconfig +++ b/drivers/net/can/rcar/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 config CAN_RCAR tristate "Renesas R-Car and RZ/G CAN controller" - depends on ARCH_RENESAS || ARM || COMPILE_TEST + depends on ARCH_RENESAS || COMPILE_TEST help Say Y here if you want to use CAN controller found on Renesas R-Car or RZ/G SoCs. @@ -11,7 +11,7 @@ config CAN_RCAR config CAN_RCAR_CANFD tristate "Renesas R-Car CAN FD controller" - depends on ARCH_RENESAS || ARM || COMPILE_TEST + depends on ARCH_RENESAS || COMPILE_TEST help Say Y here if you want to use CAN FD controller found on Renesas R-Car SoCs. The driver puts the controller in CAN FD only diff --git a/drivers/net/can/usb/etas_es58x/es58x_fd.c b/drivers/net/can/usb/etas_es58x/es58x_fd.c index af042aa55f59..4f0cae29f4d8 100644 --- a/drivers/net/can/usb/etas_es58x/es58x_fd.c +++ b/drivers/net/can/usb/etas_es58x/es58x_fd.c @@ -428,7 +428,7 @@ static int es58x_fd_enable_channel(struct es58x_priv *priv) es58x_fd_convert_bittiming(&tx_conf_msg.data_bittiming, &priv->can.data_bittiming); - if (priv->can.tdc.tdco) { + if (can_tdc_is_enabled(&priv->can)) { tx_conf_msg.tdc_enabled = 1; tx_conf_msg.tdco = cpu_to_le16(priv->can.tdc.tdco); tx_conf_msg.tdcf = cpu_to_le16(priv->can.tdc.tdcf); @@ -505,8 +505,11 @@ static const struct can_bittiming_const es58x_fd_data_bittiming_const = { * Register" from Microchip. */ static const struct can_tdc_const es58x_tdc_const = { + .tdcv_min = 0, .tdcv_max = 0, /* Manual mode not supported. */ + .tdco_min = 0, .tdco_max = 127, + .tdcf_min = 0, .tdcf_max = 127 }; @@ -523,7 +526,7 @@ const struct es58x_parameters es58x_fd_param = { .clock = {.freq = 80 * CAN_MHZ}, .ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO | - CAN_CTRLMODE_CC_LEN8_DLC, + CAN_CTRLMODE_CC_LEN8_DLC | CAN_CTRLMODE_TDC_AUTO, .tx_start_of_frame = 0xCEFA, /* FACE in little endian */ .rx_start_of_frame = 0xFECA, /* CAFE in little endian */ .tx_urb_cmd_max_len = ES58X_FD_TX_URB_CMD_MAX_LEN, diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 5e892bef46b0..1b400de00f51 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -352,7 +352,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) } else { /* echo_id == hf->echo_id */ if (hf->echo_id >= GS_MAX_TX_URBS) { netdev_err(netdev, - "Unexpected out of range echo id %d\n", + "Unexpected out of range echo id %u\n", hf->echo_id); goto resubmit_urb; } @@ -365,7 +365,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) /* bad devices send bad echo_ids. */ if (!txc) { netdev_err(netdev, - "Unexpected unused echo id %d\n", + "Unexpected unused echo id %u\n", hf->echo_id); goto resubmit_urb; } @@ -458,7 +458,7 @@ static void gs_usb_xmit_callback(struct urb *urb) struct net_device *netdev = dev->netdev; if (urb->status) - netdev_info(netdev, "usb xmit fail %d\n", txc->echo_id); + netdev_info(netdev, "usb xmit fail %u\n", txc->echo_id); usb_free_coherent(urb->dev, urb->transfer_buffer_length, @@ -501,7 +501,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, idx = txc->echo_id; if (idx >= GS_MAX_TX_URBS) { - netdev_err(netdev, "Invalid tx context %d\n", idx); + netdev_err(netdev, "Invalid tx context %u\n", idx); goto badidx; } @@ -964,11 +964,11 @@ static int gs_usb_probe(struct usb_interface *intf, } icount = dconf->icount + 1; - dev_info(&intf->dev, "Configuring for %d interfaces\n", icount); + dev_info(&intf->dev, "Configuring for %u interfaces\n", icount); if (icount > GS_MAX_INTF) { dev_err(&intf->dev, - "Driver cannot handle more that %d CAN interfaces\n", + "Driver cannot handle more that %u CAN interfaces\n", GS_MAX_INTF); kfree(dconf); return -EINVAL; diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c index e8f43ed90b72..6107fef9f4a0 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c @@ -205,6 +205,19 @@ int peak_usb_netif_rx(struct sk_buff *skb, return netif_rx(skb); } +/* post received skb with native 64-bit hw timestamp */ +int peak_usb_netif_rx_64(struct sk_buff *skb, u32 ts_low, u32 ts_high) +{ + struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb); + u64 ns_ts; + + ns_ts = (u64)ts_high << 32 | ts_low; + ns_ts *= NSEC_PER_USEC; + hwts->hwtstamp = ns_to_ktime(ns_ts); + + return netif_rx(skb); +} + /* * callback for bulk Rx urb */ diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.h b/drivers/net/can/usb/peak_usb/pcan_usb_core.h index b00a4811bf61..daa19f57e742 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.h +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.h @@ -143,6 +143,7 @@ void peak_usb_set_ts_now(struct peak_time_ref *time_ref, u32 ts_now); void peak_usb_get_ts_time(struct peak_time_ref *time_ref, u32 ts, ktime_t *tv); int peak_usb_netif_rx(struct sk_buff *skb, struct peak_time_ref *time_ref, u32 ts_low); +int peak_usb_netif_rx_64(struct sk_buff *skb, u32 ts_low, u32 ts_high); void peak_usb_async_complete(struct urb *urb); void peak_usb_restart_complete(struct peak_usb_device *dev); diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c index 09029a3bad1a..6bd12549f101 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c @@ -515,7 +515,8 @@ static int pcan_usb_fd_decode_canmsg(struct pcan_usb_fd_if *usb_if, netdev->stats.rx_packets++; netdev->stats.rx_bytes += cfd->len; - peak_usb_netif_rx(skb, &usb_if->time_ref, le32_to_cpu(rm->ts_low)); + peak_usb_netif_rx_64(skb, le32_to_cpu(rm->ts_low), + le32_to_cpu(rm->ts_high)); return 0; } @@ -579,7 +580,8 @@ static int pcan_usb_fd_decode_status(struct pcan_usb_fd_if *usb_if, netdev->stats.rx_packets++; netdev->stats.rx_bytes += cf->len; - peak_usb_netif_rx(skb, &usb_if->time_ref, le32_to_cpu(sm->ts_low)); + peak_usb_netif_rx_64(skb, le32_to_cpu(sm->ts_low), + le32_to_cpu(sm->ts_high)); return 0; } @@ -629,7 +631,8 @@ static int pcan_usb_fd_decode_overrun(struct pcan_usb_fd_if *usb_if, cf->can_id |= CAN_ERR_CRTL; cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW; - peak_usb_netif_rx(skb, &usb_if->time_ref, le32_to_cpu(ov->ts_low)); + peak_usb_netif_rx_64(skb, le32_to_cpu(ov->ts_low), + le32_to_cpu(ov->ts_high)); netdev->stats.rx_over_errors++; netdev->stats.rx_errors++; diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 3b883e607d8b..e2b15d29d15e 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -516,8 +516,7 @@ static int xcan_chip_start(struct net_device *ndev) * @ndev: Pointer to net_device structure * @mode: Tells the mode of the driver * - * This check the drivers state and calls the - * the corresponding modes to set. + * This check the drivers state and calls the corresponding modes to set. * * Return: 0 on success and failure value on error */ @@ -982,7 +981,7 @@ static void xcan_update_error_state_after_rxtx(struct net_device *ndev) * @isr: interrupt status register value * * This is the CAN error interrupt and it will - * check the the type of error and forward the error + * check the type of error and forward the error * frame to upper layers. */ static void xcan_err_interrupt(struct net_device *ndev, u32 isr) @@ -1844,11 +1843,9 @@ err: static int xcan_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); - struct xcan_priv *priv = netdev_priv(ndev); unregister_candev(ndev); pm_runtime_disable(&pdev->dev); - netif_napi_del(&priv->napi); free_candev(ndev); return 0; diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 06279ba64cc8..af4761968733 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -1343,10 +1343,8 @@ void b53_phylink_validate(struct dsa_switch *ds, int port, phylink_set(mask, 100baseT_Full); } - bitmap_and(supported, supported, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_and(state->advertising, state->advertising, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); phylink_helper_basex_speed(state); } @@ -1544,7 +1542,7 @@ int b53_vlan_del(struct dsa_switch *ds, int port, } EXPORT_SYMBOL(b53_vlan_del); -/* Address Resolution Logic routines */ +/* Address Resolution Logic routines. Caller must hold &dev->arl_mutex. */ static int b53_arl_op_wait(struct b53_device *dev) { unsigned int timeout = 10; @@ -1709,6 +1707,7 @@ int b53_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid) { struct b53_device *priv = ds->priv; + int ret; /* 5325 and 5365 require some more massaging, but could * be supported eventually @@ -1716,7 +1715,11 @@ int b53_fdb_add(struct dsa_switch *ds, int port, if (is5325(priv) || is5365(priv)) return -EOPNOTSUPP; - return b53_arl_op(priv, 0, port, addr, vid, true); + mutex_lock(&priv->arl_mutex); + ret = b53_arl_op(priv, 0, port, addr, vid, true); + mutex_unlock(&priv->arl_mutex); + + return ret; } EXPORT_SYMBOL(b53_fdb_add); @@ -1724,8 +1727,13 @@ int b53_fdb_del(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid) { struct b53_device *priv = ds->priv; + int ret; - return b53_arl_op(priv, 0, port, addr, vid, false); + mutex_lock(&priv->arl_mutex); + ret = b53_arl_op(priv, 0, port, addr, vid, false); + mutex_unlock(&priv->arl_mutex); + + return ret; } EXPORT_SYMBOL(b53_fdb_del); @@ -1782,6 +1790,8 @@ int b53_fdb_dump(struct dsa_switch *ds, int port, int ret; u8 reg; + mutex_lock(&priv->arl_mutex); + /* Start search operation */ reg = ARL_SRCH_STDN; b53_write8(priv, B53_ARLIO_PAGE, B53_ARL_SRCH_CTL, reg); @@ -1789,18 +1799,18 @@ int b53_fdb_dump(struct dsa_switch *ds, int port, do { ret = b53_arl_search_wait(priv); if (ret) - return ret; + break; b53_arl_search_rd(priv, 0, &results[0]); ret = b53_fdb_copy(port, &results[0], cb, data); if (ret) - return ret; + break; if (priv->num_arl_bins > 2) { b53_arl_search_rd(priv, 1, &results[1]); ret = b53_fdb_copy(port, &results[1], cb, data); if (ret) - return ret; + break; if (!results[0].is_valid && !results[1].is_valid) break; @@ -1808,6 +1818,8 @@ int b53_fdb_dump(struct dsa_switch *ds, int port, } while (count++ < b53_max_arl_entries(priv) / 2); + mutex_unlock(&priv->arl_mutex); + return 0; } EXPORT_SYMBOL(b53_fdb_dump); @@ -1816,6 +1828,7 @@ int b53_mdb_add(struct dsa_switch *ds, int port, const struct switchdev_obj_port_mdb *mdb) { struct b53_device *priv = ds->priv; + int ret; /* 5325 and 5365 require some more massaging, but could * be supported eventually @@ -1823,7 +1836,11 @@ int b53_mdb_add(struct dsa_switch *ds, int port, if (is5325(priv) || is5365(priv)) return -EOPNOTSUPP; - return b53_arl_op(priv, 0, port, mdb->addr, mdb->vid, true); + mutex_lock(&priv->arl_mutex); + ret = b53_arl_op(priv, 0, port, mdb->addr, mdb->vid, true); + mutex_unlock(&priv->arl_mutex); + + return ret; } EXPORT_SYMBOL(b53_mdb_add); @@ -1833,7 +1850,9 @@ int b53_mdb_del(struct dsa_switch *ds, int port, struct b53_device *priv = ds->priv; int ret; + mutex_lock(&priv->arl_mutex); ret = b53_arl_op(priv, 0, port, mdb->addr, mdb->vid, false); + mutex_unlock(&priv->arl_mutex); if (ret) dev_err(ds->dev, "failed to delete MDB entry\n"); @@ -2670,6 +2689,7 @@ struct b53_device *b53_switch_alloc(struct device *base, mutex_init(&dev->reg_mutex); mutex_init(&dev->stats_mutex); + mutex_init(&dev->arl_mutex); return dev; } diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h index 544101e74bca..579da74ada64 100644 --- a/drivers/net/dsa/b53/b53_priv.h +++ b/drivers/net/dsa/b53/b53_priv.h @@ -107,6 +107,7 @@ struct b53_device { struct mutex reg_mutex; struct mutex stats_mutex; + struct mutex arl_mutex; const struct b53_io_ops *ops; /* chip specific data */ diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index a86ddc4bb897..13aa43b5cffd 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -685,7 +685,7 @@ static void bcm_sf2_sw_validate(struct dsa_switch *ds, int port, state->interface != PHY_INTERFACE_MODE_GMII && state->interface != PHY_INTERFACE_MODE_INTERNAL && state->interface != PHY_INTERFACE_MODE_MOCA) { - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); if (port != core_readl(priv, CORE_IMP0_PRT_ID)) dev_err(ds->dev, "Unsupported interface: %d for port %d\n", @@ -713,10 +713,8 @@ static void bcm_sf2_sw_validate(struct dsa_switch *ds, int port, phylink_set(mask, 100baseT_Half); phylink_set(mask, 100baseT_Full); - bitmap_and(supported, supported, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_and(state->advertising, state->advertising, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); } static void bcm_sf2_sw_mac_config(struct dsa_switch *ds, int port, diff --git a/drivers/net/dsa/hirschmann/hellcreek.c b/drivers/net/dsa/hirschmann/hellcreek.c index 354655f9ed00..4e0b53d94b52 100644 --- a/drivers/net/dsa/hirschmann/hellcreek.c +++ b/drivers/net/dsa/hirschmann/hellcreek.c @@ -1403,10 +1403,8 @@ static void hellcreek_phylink_validate(struct dsa_switch *ds, int port, else phylink_set(mask, 1000baseT_Full); - bitmap_and(supported, supported, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_and(state->advertising, state->advertising, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); } static int diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c index dbd4486a173f..7056d98d8177 100644 --- a/drivers/net/dsa/lantiq_gswip.c +++ b/drivers/net/dsa/lantiq_gswip.c @@ -276,6 +276,7 @@ struct gswip_priv { int num_gphy_fw; struct gswip_gphy_fw *gphy_fw; u32 port_vlan_filter; + struct mutex pce_table_lock; }; struct gswip_pce_table_entry { @@ -523,10 +524,14 @@ static int gswip_pce_table_entry_read(struct gswip_priv *priv, u16 addr_mode = tbl->key_mode ? GSWIP_PCE_TBL_CTRL_OPMOD_KSRD : GSWIP_PCE_TBL_CTRL_OPMOD_ADRD; + mutex_lock(&priv->pce_table_lock); + err = gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL, GSWIP_PCE_TBL_CTRL_BAS); - if (err) + if (err) { + mutex_unlock(&priv->pce_table_lock); return err; + } gswip_switch_w(priv, tbl->index, GSWIP_PCE_TBL_ADDR); gswip_switch_mask(priv, GSWIP_PCE_TBL_CTRL_ADDR_MASK | @@ -536,8 +541,10 @@ static int gswip_pce_table_entry_read(struct gswip_priv *priv, err = gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL, GSWIP_PCE_TBL_CTRL_BAS); - if (err) + if (err) { + mutex_unlock(&priv->pce_table_lock); return err; + } for (i = 0; i < ARRAY_SIZE(tbl->key); i++) tbl->key[i] = gswip_switch_r(priv, GSWIP_PCE_TBL_KEY(i)); @@ -553,6 +560,8 @@ static int gswip_pce_table_entry_read(struct gswip_priv *priv, tbl->valid = !!(crtl & GSWIP_PCE_TBL_CTRL_VLD); tbl->gmap = (crtl & GSWIP_PCE_TBL_CTRL_GMAP_MASK) >> 7; + mutex_unlock(&priv->pce_table_lock); + return 0; } @@ -565,10 +574,14 @@ static int gswip_pce_table_entry_write(struct gswip_priv *priv, u16 addr_mode = tbl->key_mode ? GSWIP_PCE_TBL_CTRL_OPMOD_KSWR : GSWIP_PCE_TBL_CTRL_OPMOD_ADWR; + mutex_lock(&priv->pce_table_lock); + err = gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL, GSWIP_PCE_TBL_CTRL_BAS); - if (err) + if (err) { + mutex_unlock(&priv->pce_table_lock); return err; + } gswip_switch_w(priv, tbl->index, GSWIP_PCE_TBL_ADDR); gswip_switch_mask(priv, GSWIP_PCE_TBL_CTRL_ADDR_MASK | @@ -600,8 +613,12 @@ static int gswip_pce_table_entry_write(struct gswip_priv *priv, crtl |= GSWIP_PCE_TBL_CTRL_BAS; gswip_switch_w(priv, crtl, GSWIP_PCE_TBL_CTRL); - return gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL, - GSWIP_PCE_TBL_CTRL_BAS); + err = gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL, + GSWIP_PCE_TBL_CTRL_BAS); + + mutex_unlock(&priv->pce_table_lock); + + return err; } /* Add the LAN port into a bridge with the CPU port by @@ -1447,10 +1464,8 @@ static void gswip_phylink_set_capab(unsigned long *supported, phylink_set(mask, 100baseT_Half); phylink_set(mask, 100baseT_Full); - bitmap_and(supported, supported, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_and(state->advertising, state->advertising, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); } static void gswip_xrx200_phylink_validate(struct dsa_switch *ds, int port, @@ -1478,7 +1493,7 @@ static void gswip_xrx200_phylink_validate(struct dsa_switch *ds, int port, goto unsupported; break; default: - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); dev_err(ds->dev, "Unsupported port: %i\n", port); return; } @@ -1488,7 +1503,7 @@ static void gswip_xrx200_phylink_validate(struct dsa_switch *ds, int port, return; unsupported: - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); dev_err(ds->dev, "Unsupported interface '%s' for port %d\n", phy_modes(state->interface), port); } @@ -1518,7 +1533,7 @@ static void gswip_xrx300_phylink_validate(struct dsa_switch *ds, int port, goto unsupported; break; default: - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); dev_err(ds->dev, "Unsupported port: %i\n", port); return; } @@ -1528,7 +1543,7 @@ static void gswip_xrx300_phylink_validate(struct dsa_switch *ds, int port, return; unsupported: - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); dev_err(ds->dev, "Unsupported interface '%s' for port %d\n", phy_modes(state->interface), port); } @@ -2106,6 +2121,7 @@ static int gswip_probe(struct platform_device *pdev) priv->ds->priv = priv; priv->ds->ops = priv->hw_info->ops; priv->dev = dev; + mutex_init(&priv->pce_table_lock); version = gswip_switch_r(priv, GSWIP_VERSION); np = dev->of_node; diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c index c5142f86a3c7..43fc3087aeb3 100644 --- a/drivers/net/dsa/microchip/ksz8795.c +++ b/drivers/net/dsa/microchip/ksz8795.c @@ -1542,15 +1542,13 @@ static void ksz8_validate(struct dsa_switch *ds, int port, phylink_set(mask, 100baseT_Half); phylink_set(mask, 100baseT_Full); - bitmap_and(supported, supported, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_and(state->advertising, state->advertising, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); return; unsupported: - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); dev_err(ds->dev, "Unsupported interface: %s, port: %d\n", phy_modes(state->interface), port); } diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 8dadcae93c9b..14c678a9e41b 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -674,9 +674,8 @@ static void mv88e6xxx_validate(struct dsa_switch *ds, int port, if (chip->info->ops->phylink_validate) chip->info->ops->phylink_validate(chip, port, mask, state); - bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_and(state->advertising, state->advertising, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); /* We can only operate at 2500BaseX or 1000BaseX. If requested * to advertise both, only report advertising at 2500BaseX. diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index 11b42fd812e4..45c5ec7a83ea 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -943,7 +943,7 @@ static void vsc9959_phylink_validate(struct ocelot *ocelot, int port, if (state->interface != PHY_INTERFACE_MODE_NA && state->interface != ocelot_port->phy_mode) { - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); return; } @@ -965,10 +965,8 @@ static void vsc9959_phylink_validate(struct ocelot *ocelot, int port, phylink_set(mask, 2500baseX_Full); } - bitmap_and(supported, supported, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_and(state->advertising, state->advertising, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); } static int vsc9959_prevalidate_phy_mode(struct ocelot *ocelot, int port, diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c index de1d34a1f1e4..92eae63150ea 100644 --- a/drivers/net/dsa/ocelot/seville_vsc9953.c +++ b/drivers/net/dsa/ocelot/seville_vsc9953.c @@ -999,7 +999,7 @@ static void vsc9953_phylink_validate(struct ocelot *ocelot, int port, if (state->interface != PHY_INTERFACE_MODE_NA && state->interface != ocelot_port->phy_mode) { - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); return; } @@ -1018,10 +1018,8 @@ static void vsc9953_phylink_validate(struct ocelot *ocelot, int port, phylink_set(mask, 2500baseX_Full); } - bitmap_and(supported, supported, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_and(state->advertising, state->advertising, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); } static int vsc9953_prevalidate_phy_mode(struct ocelot *ocelot, int port, diff --git a/drivers/net/dsa/qca/ar9331.c b/drivers/net/dsa/qca/ar9331.c index a6bfb6abc51a..da0d7e68643a 100644 --- a/drivers/net/dsa/qca/ar9331.c +++ b/drivers/net/dsa/qca/ar9331.c @@ -522,7 +522,7 @@ static void ar9331_sw_phylink_validate(struct dsa_switch *ds, int port, goto unsupported; break; default: - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); dev_err(ds->dev, "Unsupported port: %i\n", port); return; } @@ -536,15 +536,13 @@ static void ar9331_sw_phylink_validate(struct dsa_switch *ds, int port, phylink_set(mask, 100baseT_Half); phylink_set(mask, 100baseT_Full); - bitmap_and(supported, supported, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_and(state->advertising, state->advertising, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); return; unsupported: - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); dev_err(ds->dev, "Unsupported interface: %d, port: %d\n", state->interface, port); } diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index 808419f3b808..21dba16af097 100644 --- a/drivers/net/dsa/sja1105/sja1105.h +++ b/drivers/net/dsa/sja1105/sja1105.h @@ -261,6 +261,8 @@ struct sja1105_private { * the switch doesn't confuse them with one another. */ struct mutex mgmt_lock; + /* Serializes access to the dynamic config interface */ + struct mutex dynamic_config_lock; struct devlink_region **regions; struct sja1105_cbs_entry *cbs; struct mii_bus *mdio_base_t1; diff --git a/drivers/net/dsa/sja1105/sja1105_dynamic_config.c b/drivers/net/dsa/sja1105/sja1105_dynamic_config.c index f2049f52833c..7729d3f8b7f5 100644 --- a/drivers/net/dsa/sja1105/sja1105_dynamic_config.c +++ b/drivers/net/dsa/sja1105/sja1105_dynamic_config.c @@ -1170,6 +1170,56 @@ const struct sja1105_dynamic_table_ops sja1110_dyn_ops[BLK_IDX_MAX_DYN] = { }, }; +#define SJA1105_DYNAMIC_CONFIG_SLEEP_US 10 +#define SJA1105_DYNAMIC_CONFIG_TIMEOUT_US 100000 + +static int +sja1105_dynamic_config_poll_valid(struct sja1105_private *priv, + struct sja1105_dyn_cmd *cmd, + const struct sja1105_dynamic_table_ops *ops) +{ + u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {}; + int rc; + + /* We don't _need_ to read the full entry, just the command area which + * is a fixed SJA1105_SIZE_DYN_CMD. But our cmd_packing() API expects a + * buffer that contains the full entry too. Additionally, our API + * doesn't really know how many bytes into the buffer does the command + * area really begin. So just read back the whole entry. + */ + rc = sja1105_xfer_buf(priv, SPI_READ, ops->addr, packed_buf, + ops->packed_size); + if (rc) + return rc; + + /* Unpack the command structure, and return it to the caller in case it + * needs to perform further checks on it (VALIDENT). + */ + memset(cmd, 0, sizeof(*cmd)); + ops->cmd_packing(packed_buf, cmd, UNPACK); + + /* Hardware hasn't cleared VALID => still working on it */ + return cmd->valid ? -EAGAIN : 0; +} + +/* Poll the dynamic config entry's control area until the hardware has + * cleared the VALID bit, which means we have confirmation that it has + * finished processing the command. + */ +static int +sja1105_dynamic_config_wait_complete(struct sja1105_private *priv, + struct sja1105_dyn_cmd *cmd, + const struct sja1105_dynamic_table_ops *ops) +{ + int rc; + + return read_poll_timeout(sja1105_dynamic_config_poll_valid, + rc, rc != -EAGAIN, + SJA1105_DYNAMIC_CONFIG_SLEEP_US, + SJA1105_DYNAMIC_CONFIG_TIMEOUT_US, + false, priv, cmd, ops); +} + /* Provides read access to the settings through the dynamic interface * of the switch. * @blk_idx is used as key to select from the sja1105_dynamic_table_ops. @@ -1196,7 +1246,6 @@ int sja1105_dynamic_config_read(struct sja1105_private *priv, struct sja1105_dyn_cmd cmd = {0}; /* SPI payload buffer */ u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {0}; - int retries = 3; int rc; if (blk_idx >= BLK_IDX_MAX_DYN) @@ -1234,33 +1283,21 @@ int sja1105_dynamic_config_read(struct sja1105_private *priv, ops->entry_packing(packed_buf, entry, PACK); /* Send SPI write operation: read config table entry */ + mutex_lock(&priv->dynamic_config_lock); rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf, ops->packed_size); - if (rc < 0) + if (rc < 0) { + mutex_unlock(&priv->dynamic_config_lock); return rc; + } - /* Loop until we have confirmation that hardware has finished - * processing the command and has cleared the VALID field - */ - do { - memset(packed_buf, 0, ops->packed_size); - - /* Retrieve the read operation's result */ - rc = sja1105_xfer_buf(priv, SPI_READ, ops->addr, packed_buf, - ops->packed_size); - if (rc < 0) - return rc; - - cmd = (struct sja1105_dyn_cmd) {0}; - ops->cmd_packing(packed_buf, &cmd, UNPACK); - - if (!cmd.valident && !(ops->access & OP_VALID_ANYWAY)) - return -ENOENT; - cpu_relax(); - } while (cmd.valid && --retries); + rc = sja1105_dynamic_config_wait_complete(priv, &cmd, ops); + mutex_unlock(&priv->dynamic_config_lock); + if (rc < 0) + return rc; - if (cmd.valid) - return -ETIMEDOUT; + if (!cmd.valident && !(ops->access & OP_VALID_ANYWAY)) + return -ENOENT; /* Don't dereference possibly NULL pointer - maybe caller * only wanted to see whether the entry existed or not. @@ -1316,8 +1353,16 @@ int sja1105_dynamic_config_write(struct sja1105_private *priv, ops->entry_packing(packed_buf, entry, PACK); /* Send SPI write operation: read config table entry */ + mutex_lock(&priv->dynamic_config_lock); rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf, ops->packed_size); + if (rc < 0) { + mutex_unlock(&priv->dynamic_config_lock); + return rc; + } + + rc = sja1105_dynamic_config_wait_complete(priv, &cmd, ops); + mutex_unlock(&priv->dynamic_config_lock); if (rc < 0) return rc; diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 1832d4bd3440..c343effe2e96 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -1233,8 +1233,10 @@ static int sja1105_parse_ports_node(struct sja1105_private *priv, priv->phy_mode[index] = phy_mode; err = sja1105_parse_rgmii_delays(priv, index, child); - if (err) + if (err) { + of_node_put(child); return err; + } } return 0; @@ -1429,7 +1431,7 @@ static void sja1105_phylink_validate(struct dsa_switch *ds, int port, */ if (state->interface != PHY_INTERFACE_MODE_NA && sja1105_phy_mode_mismatch(priv, port, state->interface)) { - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); return; } @@ -1449,9 +1451,8 @@ static void sja1105_phylink_validate(struct dsa_switch *ds, int port, phylink_set(mask, 2500baseX_Full); } - bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_and(state->advertising, state->advertising, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); } static int @@ -3364,6 +3365,7 @@ static int sja1105_probe(struct spi_device *spi) priv->ds = ds; mutex_init(&priv->ptp_data.lock); + mutex_init(&priv->dynamic_config_lock); mutex_init(&priv->mgmt_lock); rc = sja1105_parse_dt(priv); diff --git a/drivers/net/dsa/xrs700x/xrs700x.c b/drivers/net/dsa/xrs700x/xrs700x.c index 469420941054..910fcb3b252b 100644 --- a/drivers/net/dsa/xrs700x/xrs700x.c +++ b/drivers/net/dsa/xrs700x/xrs700x.c @@ -456,7 +456,7 @@ static void xrs700x_phylink_validate(struct dsa_switch *ds, int port, phylink_set(mask, 1000baseT_Full); break; default: - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); dev_err(ds->dev, "Unsupported port: %i\n", port); return; } @@ -467,10 +467,8 @@ static void xrs700x_phylink_validate(struct dsa_switch *ds, int port, phylink_set(mask, 10baseT_Full); phylink_set(mask, 100baseT_Full); - bitmap_and(supported, supported, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_and(state->advertising, state->advertising, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); } static void xrs700x_mac_link_up(struct dsa_switch *ds, int port, diff --git a/drivers/net/dsa/xrs700x/xrs700x_mdio.c b/drivers/net/dsa/xrs700x/xrs700x_mdio.c index d01cf1073d49..127a677d1f39 100644 --- a/drivers/net/dsa/xrs700x/xrs700x_mdio.c +++ b/drivers/net/dsa/xrs700x/xrs700x_mdio.c @@ -31,7 +31,7 @@ static int xrs700x_mdio_reg_read(void *context, unsigned int reg, uval = (u16)FIELD_GET(GENMASK(31, 16), reg); - ret = mdiobus_write(mdiodev->bus, mdiodev->addr, XRS_MDIO_IBA1, uval); + ret = mdiodev_write(mdiodev, XRS_MDIO_IBA1, uval); if (ret < 0) { dev_err(dev, "xrs mdiobus_write returned %d\n", ret); return ret; @@ -39,13 +39,13 @@ static int xrs700x_mdio_reg_read(void *context, unsigned int reg, uval = (u16)((reg & GENMASK(15, 1)) | XRS_IB_READ); - ret = mdiobus_write(mdiodev->bus, mdiodev->addr, XRS_MDIO_IBA0, uval); + ret = mdiodev_write(mdiodev, XRS_MDIO_IBA0, uval); if (ret < 0) { dev_err(dev, "xrs mdiobus_write returned %d\n", ret); return ret; } - ret = mdiobus_read(mdiodev->bus, mdiodev->addr, XRS_MDIO_IBD); + ret = mdiodev_read(mdiodev, XRS_MDIO_IBD); if (ret < 0) { dev_err(dev, "xrs mdiobus_read returned %d\n", ret); return ret; @@ -64,7 +64,7 @@ static int xrs700x_mdio_reg_write(void *context, unsigned int reg, u16 uval; int ret; - ret = mdiobus_write(mdiodev->bus, mdiodev->addr, XRS_MDIO_IBD, (u16)val); + ret = mdiodev_write(mdiodev, XRS_MDIO_IBD, (u16)val); if (ret < 0) { dev_err(dev, "xrs mdiobus_write returned %d\n", ret); return ret; @@ -72,7 +72,7 @@ static int xrs700x_mdio_reg_write(void *context, unsigned int reg, uval = (u16)FIELD_GET(GENMASK(31, 16), reg); - ret = mdiobus_write(mdiodev->bus, mdiodev->addr, XRS_MDIO_IBA1, uval); + ret = mdiodev_write(mdiodev, XRS_MDIO_IBA1, uval); if (ret < 0) { dev_err(dev, "xrs mdiobus_write returned %d\n", ret); return ret; @@ -80,7 +80,7 @@ static int xrs700x_mdio_reg_write(void *context, unsigned int reg, uval = (u16)((reg & GENMASK(15, 1)) | XRS_IB_WRITE); - ret = mdiobus_write(mdiodev->bus, mdiodev->addr, XRS_MDIO_IBA0, uval); + ret = mdiodev_write(mdiodev, XRS_MDIO_IBA0, uval); if (ret < 0) { dev_err(dev, "xrs mdiobus_write returned %d\n", ret); return ret; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c index bafc51c34e0b..94879cf8b420 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c @@ -369,9 +369,8 @@ static int xgbe_set_link_ksettings(struct net_device *netdev, __ETHTOOL_LINK_MODE_MASK_NBITS, cmd->link_modes.advertising, __ETHTOOL_LINK_MODE_MASK_NBITS, lks->link_modes.supported); - bitmap_and(advertising, - cmd->link_modes.advertising, lks->link_modes.supported, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_and(advertising, cmd->link_modes.advertising, + lks->link_modes.supported); if ((cmd->base.autoneg == AUTONEG_ENABLE) && bitmap_empty(advertising, __ETHTOOL_LINK_MODE_MASK_NBITS)) { @@ -384,8 +383,7 @@ static int xgbe_set_link_ksettings(struct net_device *netdev, pdata->phy.autoneg = cmd->base.autoneg; pdata->phy.speed = speed; pdata->phy.duplex = cmd->base.duplex; - bitmap_copy(lks->link_modes.advertising, advertising, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_copy(lks->link_modes.advertising, advertising); if (cmd->base.autoneg == AUTONEG_ENABLE) XGBE_SET_ADV(lks, Autoneg); diff --git a/drivers/net/ethernet/asix/ax88796c_main.c b/drivers/net/ethernet/asix/ax88796c_main.c index cfc597f72e3d..4b0c5a09fd57 100644 --- a/drivers/net/ethernet/asix/ax88796c_main.c +++ b/drivers/net/ethernet/asix/ax88796c_main.c @@ -672,10 +672,10 @@ static void ax88796c_get_stats64(struct net_device *ndev, stats->tx_packets += tx_packets; stats->tx_bytes += tx_bytes; - rx_dropped += stats->rx_dropped; - tx_dropped += stats->tx_dropped; - rx_frame_errors += stats->rx_frame_errors; - rx_crc_errors += stats->rx_crc_errors; + rx_dropped += s->rx_dropped; + tx_dropped += s->tx_dropped; + rx_frame_errors += s->rx_frame_errors; + rx_crc_errors += s->rx_crc_errors; } stats->rx_dropped = rx_dropped; @@ -693,6 +693,7 @@ static void ax88796c_set_mac(struct ax88796c_device *ax_local) switch (ax_local->speed) { case SPEED_100: maccr |= MACCR_SPEED_100; + break; case SPEED_10: case SPEED_UNKNOWN: break; @@ -703,6 +704,7 @@ static void ax88796c_set_mac(struct ax88796c_device *ax_local) switch (ax_local->duplex) { case DUPLEX_FULL: maccr |= MACCR_SPEED_100; + break; case DUPLEX_HALF: case DUPLEX_UNKNOWN: break; @@ -848,11 +850,10 @@ ax88796c_open(struct net_device *ndev) /* Setup flow-control configuration */ phy_support_asym_pause(ax_local->phydev); - if (ax_local->phydev->advertising && - (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, - ax_local->phydev->advertising) || - linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, - ax_local->phydev->advertising))) + if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, + ax_local->phydev->advertising) || + linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, + ax_local->phydev->advertising)) fc |= AX_FC_ANEG; fc |= linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, diff --git a/drivers/net/ethernet/atheros/ag71xx.c b/drivers/net/ethernet/atheros/ag71xx.c index ada3a9f0c8c8..88d2ab748399 100644 --- a/drivers/net/ethernet/atheros/ag71xx.c +++ b/drivers/net/ethernet/atheros/ag71xx.c @@ -1082,14 +1082,12 @@ static void ag71xx_mac_validate(struct phylink_config *config, phylink_set(mask, 1000baseX_Full); } - bitmap_and(supported, supported, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_and(state->advertising, state->advertising, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); return; unsupported: - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); } static void ag71xx_mac_pcs_get_state(struct phylink_config *config, diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 5da9c00b43b1..226f4403cfed 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -1653,7 +1653,7 @@ static int bcmgenet_power_down(struct bcmgenet_priv *priv, /* Power down LED */ if (priv->hw_params->flags & GENET_HAS_EXT) { reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT); - if (GENET_IS_V5(priv)) + if (GENET_IS_V5(priv) && !priv->ephy_16nm) reg |= EXT_PWR_DOWN_PHY_EN | EXT_PWR_DOWN_PHY_RD | EXT_PWR_DOWN_PHY_SD | @@ -1690,7 +1690,7 @@ static void bcmgenet_power_up(struct bcmgenet_priv *priv, case GENET_POWER_PASSIVE: reg &= ~(EXT_PWR_DOWN_DLL | EXT_PWR_DOWN_BIAS | EXT_ENERGY_DET_MASK); - if (GENET_IS_V5(priv)) { + if (GENET_IS_V5(priv) && !priv->ephy_16nm) { reg &= ~(EXT_PWR_DOWN_PHY_EN | EXT_PWR_DOWN_PHY_RD | EXT_PWR_DOWN_PHY_SD | @@ -3910,6 +3910,7 @@ static void bcmgenet_set_hw_params(struct bcmgenet_priv *priv) struct bcmgenet_plat_data { enum bcmgenet_version version; u32 dma_max_burst_length; + bool ephy_16nm; }; static const struct bcmgenet_plat_data v1_plat_data = { @@ -3942,6 +3943,12 @@ static const struct bcmgenet_plat_data bcm2711_plat_data = { .dma_max_burst_length = 0x08, }; +static const struct bcmgenet_plat_data bcm7712_plat_data = { + .version = GENET_V5, + .dma_max_burst_length = DMA_MAX_BURST_LENGTH, + .ephy_16nm = true, +}; + static const struct of_device_id bcmgenet_match[] = { { .compatible = "brcm,genet-v1", .data = &v1_plat_data }, { .compatible = "brcm,genet-v2", .data = &v2_plat_data }, @@ -3949,6 +3956,7 @@ static const struct of_device_id bcmgenet_match[] = { { .compatible = "brcm,genet-v4", .data = &v4_plat_data }, { .compatible = "brcm,genet-v5", .data = &v5_plat_data }, { .compatible = "brcm,bcm2711-genet-v5", .data = &bcm2711_plat_data }, + { .compatible = "brcm,bcm7712-genet-v5", .data = &bcm7712_plat_data }, { }, }; MODULE_DEVICE_TABLE(of, bcmgenet_match); @@ -4029,6 +4037,7 @@ static int bcmgenet_probe(struct platform_device *pdev) if (pdata) { priv->version = pdata->version; priv->dma_max_burst_length = pdata->dma_max_burst_length; + priv->ephy_16nm = pdata->ephy_16nm; } else { priv->version = pd->genet_version; priv->dma_max_burst_length = DMA_MAX_BURST_LENGTH; diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h index 1cc2838e52c6..946f6e283c4e 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h @@ -329,6 +329,7 @@ struct bcmgenet_mib_counters { #define EXT_CFG_IDDQ_BIAS (1 << 0) #define EXT_CFG_PWR_DOWN (1 << 1) #define EXT_CK25_DIS (1 << 4) +#define EXT_CFG_IDDQ_GLOBAL_PWR (1 << 3) #define EXT_GPHY_RESET (1 << 5) /* DMA rings size */ @@ -612,6 +613,7 @@ struct bcmgenet_priv { phy_interface_t phy_interface; int phy_addr; int ext_phy; + bool ephy_16nm; /* Interrupt variables */ struct work_struct bcmgenet_irq_work; diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index ad56f54eda0a..5f259641437a 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c @@ -139,14 +139,15 @@ void bcmgenet_phy_power_set(struct net_device *dev, bool enable) u32 reg = 0; /* EXT_GPHY_CTRL is only valid for GENETv4 and onward */ - if (GENET_IS_V4(priv)) { + if (GENET_IS_V4(priv) || priv->ephy_16nm) { reg = bcmgenet_ext_readl(priv, EXT_GPHY_CTRL); if (enable) { reg &= ~EXT_CK25_DIS; bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL); mdelay(1); - reg &= ~(EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN); + reg &= ~(EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN | + EXT_CFG_IDDQ_GLOBAL_PWR); reg |= EXT_GPHY_RESET; bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL); mdelay(1); @@ -154,7 +155,7 @@ void bcmgenet_phy_power_set(struct net_device *dev, bool enable) reg &= ~EXT_GPHY_RESET; } else { reg |= EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN | - EXT_GPHY_RESET; + EXT_GPHY_RESET | EXT_CFG_IDDQ_GLOBAL_PWR; bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL); mdelay(1); reg |= EXT_CK25_DIS; diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 029dea2873e3..309371abfe23 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -522,21 +522,21 @@ static void macb_validate(struct phylink_config *config, state->interface != PHY_INTERFACE_MODE_SGMII && state->interface != PHY_INTERFACE_MODE_10GBASER && !phy_interface_mode_is_rgmii(state->interface)) { - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); return; } if (!macb_is_gem(bp) && (state->interface == PHY_INTERFACE_MODE_GMII || phy_interface_mode_is_rgmii(state->interface))) { - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); return; } if (state->interface == PHY_INTERFACE_MODE_10GBASER && !(bp->caps & MACB_CAPS_HIGH_SPEED && bp->caps & MACB_CAPS_PCS)) { - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); return; } @@ -570,9 +570,8 @@ static void macb_validate(struct phylink_config *config, phylink_set(mask, 1000baseT_Half); } out: - bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_and(state->advertising, state->advertising, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); } static void macb_usx_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, @@ -898,6 +897,17 @@ static int macb_mdiobus_register(struct macb *bp) { struct device_node *child, *np = bp->pdev->dev.of_node; + /* If we have a child named mdio, probe it instead of looking for PHYs + * directly under the MAC node + */ + child = of_get_child_by_name(np, "mdio"); + if (np) { + int ret = of_mdiobus_register(bp->mii_bus, child); + + of_node_put(child); + return ret; + } + if (of_phy_is_fixed_link(np)) return mdiobus_register(bp->mii_bus); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c index 64f92770691f..0e87c7043b77 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c @@ -942,7 +942,7 @@ static void enetc_pl_mac_validate(struct phylink_config *config, state->interface != PHY_INTERFACE_MODE_2500BASEX && state->interface != PHY_INTERFACE_MODE_USXGMII && !phy_interface_mode_is_rgmii(state->interface)) { - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); return; } @@ -965,10 +965,8 @@ static void enetc_pl_mac_validate(struct phylink_config *config, phylink_set(mask, 2500baseX_Full); } - bitmap_and(supported, supported, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_and(state->advertising, state->advertising, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); } static void enetc_pl_mac_config(struct phylink_config *config, diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h index 51ed8fe71d2d..b719f72281c4 100644 --- a/drivers/net/ethernet/google/gve/gve.h +++ b/drivers/net/ethernet/google/gve/gve.h @@ -142,6 +142,19 @@ struct gve_index_list { s16 tail; }; +/* A single received packet split across multiple buffers may be + * reconstructed using the information in this structure. + */ +struct gve_rx_ctx { + /* head and tail of skb chain for the current packet or NULL if none */ + struct sk_buff *skb_head; + struct sk_buff *skb_tail; + u16 total_expected_size; + u8 expected_frag_cnt; + u8 curr_frag_cnt; + u8 reuse_frags; +}; + /* Contains datapath state used to represent an RX queue. */ struct gve_rx_ring { struct gve_priv *gve; @@ -153,6 +166,7 @@ struct gve_rx_ring { /* threshold for posting new buffs and descs */ u32 db_threshold; + u16 packet_buffer_size; }; /* DQO fields. */ @@ -200,15 +214,16 @@ struct gve_rx_ring { u64 rx_skb_alloc_fail; /* free-running count of skb alloc fails */ u64 rx_buf_alloc_fail; /* free-running count of buffer alloc fails */ u64 rx_desc_err_dropped_pkt; /* free-running count of packets dropped by descriptor error */ + u64 rx_cont_packet_cnt; /* free-running multi-fragment packets received */ + u64 rx_frag_flip_cnt; /* free-running count of rx segments where page_flip was used */ + u64 rx_frag_copy_cnt; /* free-running count of rx segments copied into skb linear portion */ u32 q_num; /* queue index */ u32 ntfy_id; /* notification block index */ struct gve_queue_resources *q_resources; /* head and tail pointer idx */ dma_addr_t q_resources_bus; /* dma address for the queue resources */ struct u64_stats_sync statss; /* sync stats for 32bit archs */ - /* head and tail of skb chain for the current packet or NULL if none */ - struct sk_buff *skb_head; - struct sk_buff *skb_tail; + struct gve_rx_ctx ctx; /* Info for packet currently being processed in this ring. */ }; /* A TX desc ring entry */ diff --git a/drivers/net/ethernet/google/gve/gve_adminq.c b/drivers/net/ethernet/google/gve/gve_adminq.c index af2c1d1535f5..83ae56c310d3 100644 --- a/drivers/net/ethernet/google/gve/gve_adminq.c +++ b/drivers/net/ethernet/google/gve/gve_adminq.c @@ -38,7 +38,8 @@ void gve_parse_device_option(struct gve_priv *priv, struct gve_device_option *option, struct gve_device_option_gqi_rda **dev_op_gqi_rda, struct gve_device_option_gqi_qpl **dev_op_gqi_qpl, - struct gve_device_option_dqo_rda **dev_op_dqo_rda) + struct gve_device_option_dqo_rda **dev_op_dqo_rda, + struct gve_device_option_jumbo_frames **dev_op_jumbo_frames) { u32 req_feat_mask = be32_to_cpu(option->required_features_mask); u16 option_length = be16_to_cpu(option->option_length); @@ -111,6 +112,24 @@ void gve_parse_device_option(struct gve_priv *priv, } *dev_op_dqo_rda = (void *)(option + 1); break; + case GVE_DEV_OPT_ID_JUMBO_FRAMES: + if (option_length < sizeof(**dev_op_jumbo_frames) || + req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_JUMBO_FRAMES) { + dev_warn(&priv->pdev->dev, GVE_DEVICE_OPTION_ERROR_FMT, + "Jumbo Frames", + (int)sizeof(**dev_op_jumbo_frames), + GVE_DEV_OPT_REQ_FEAT_MASK_JUMBO_FRAMES, + option_length, req_feat_mask); + break; + } + + if (option_length > sizeof(**dev_op_jumbo_frames)) { + dev_warn(&priv->pdev->dev, + GVE_DEVICE_OPTION_TOO_BIG_FMT, + "Jumbo Frames"); + } + *dev_op_jumbo_frames = (void *)(option + 1); + break; default: /* If we don't recognize the option just continue * without doing anything. @@ -126,7 +145,8 @@ gve_process_device_options(struct gve_priv *priv, struct gve_device_descriptor *descriptor, struct gve_device_option_gqi_rda **dev_op_gqi_rda, struct gve_device_option_gqi_qpl **dev_op_gqi_qpl, - struct gve_device_option_dqo_rda **dev_op_dqo_rda) + struct gve_device_option_dqo_rda **dev_op_dqo_rda, + struct gve_device_option_jumbo_frames **dev_op_jumbo_frames) { const int num_options = be16_to_cpu(descriptor->num_device_options); struct gve_device_option *dev_opt; @@ -146,7 +166,7 @@ gve_process_device_options(struct gve_priv *priv, gve_parse_device_option(priv, descriptor, dev_opt, dev_op_gqi_rda, dev_op_gqi_qpl, - dev_op_dqo_rda); + dev_op_dqo_rda, dev_op_jumbo_frames); dev_opt = next_opt; } @@ -530,6 +550,7 @@ static int gve_adminq_create_rx_queue(struct gve_priv *priv, u32 queue_index) cpu_to_be64(rx->data.data_bus), cmd.create_rx_queue.index = cpu_to_be32(queue_index); cmd.create_rx_queue.queue_page_list_id = cpu_to_be32(qpl_id); + cmd.create_rx_queue.packet_buffer_size = cpu_to_be16(rx->packet_buffer_size); } else { cmd.create_rx_queue.rx_ring_size = cpu_to_be16(priv->rx_desc_cnt); @@ -660,12 +681,31 @@ gve_set_desc_cnt_dqo(struct gve_priv *priv, return 0; } +static void gve_enable_supported_features(struct gve_priv *priv, + u32 supported_features_mask, + const struct gve_device_option_jumbo_frames + *dev_op_jumbo_frames) +{ + /* Before control reaches this point, the page-size-capped max MTU from + * the gve_device_descriptor field has already been stored in + * priv->dev->max_mtu. We overwrite it with the true max MTU below. + */ + if (dev_op_jumbo_frames && + (supported_features_mask & GVE_SUP_JUMBO_FRAMES_MASK)) { + dev_info(&priv->pdev->dev, + "JUMBO FRAMES device option enabled.\n"); + priv->dev->max_mtu = be16_to_cpu(dev_op_jumbo_frames->max_mtu); + } +} + int gve_adminq_describe_device(struct gve_priv *priv) { + struct gve_device_option_jumbo_frames *dev_op_jumbo_frames = NULL; struct gve_device_option_gqi_rda *dev_op_gqi_rda = NULL; struct gve_device_option_gqi_qpl *dev_op_gqi_qpl = NULL; struct gve_device_option_dqo_rda *dev_op_dqo_rda = NULL; struct gve_device_descriptor *descriptor; + u32 supported_features_mask = 0; union gve_adminq_command cmd; dma_addr_t descriptor_bus; int err = 0; @@ -689,7 +729,8 @@ int gve_adminq_describe_device(struct gve_priv *priv) goto free_device_descriptor; err = gve_process_device_options(priv, descriptor, &dev_op_gqi_rda, - &dev_op_gqi_qpl, &dev_op_dqo_rda); + &dev_op_gqi_qpl, &dev_op_dqo_rda, + &dev_op_jumbo_frames); if (err) goto free_device_descriptor; @@ -704,12 +745,19 @@ int gve_adminq_describe_device(struct gve_priv *priv) priv->queue_format = GVE_DQO_RDA_FORMAT; dev_info(&priv->pdev->dev, "Driver is running with DQO RDA queue format.\n"); + supported_features_mask = + be32_to_cpu(dev_op_dqo_rda->supported_features_mask); } else if (dev_op_gqi_rda) { priv->queue_format = GVE_GQI_RDA_FORMAT; dev_info(&priv->pdev->dev, "Driver is running with GQI RDA queue format.\n"); + supported_features_mask = + be32_to_cpu(dev_op_gqi_rda->supported_features_mask); } else { priv->queue_format = GVE_GQI_QPL_FORMAT; + if (dev_op_gqi_qpl) + supported_features_mask = + be32_to_cpu(dev_op_gqi_qpl->supported_features_mask); dev_info(&priv->pdev->dev, "Driver is running with GQI QPL queue format.\n"); } @@ -746,6 +794,9 @@ int gve_adminq_describe_device(struct gve_priv *priv) } priv->default_num_queues = be16_to_cpu(descriptor->default_num_queues); + gve_enable_supported_features(priv, supported_features_mask, + dev_op_jumbo_frames); + free_device_descriptor: dma_free_coherent(&priv->pdev->dev, PAGE_SIZE, descriptor, descriptor_bus); diff --git a/drivers/net/ethernet/google/gve/gve_adminq.h b/drivers/net/ethernet/google/gve/gve_adminq.h index 3953f6f7a427..83c0b40cd2d9 100644 --- a/drivers/net/ethernet/google/gve/gve_adminq.h +++ b/drivers/net/ethernet/google/gve/gve_adminq.h @@ -108,6 +108,14 @@ struct gve_device_option_dqo_rda { static_assert(sizeof(struct gve_device_option_dqo_rda) == 8); +struct gve_device_option_jumbo_frames { + __be32 supported_features_mask; + __be16 max_mtu; + u8 padding[2]; +}; + +static_assert(sizeof(struct gve_device_option_jumbo_frames) == 8); + /* Terminology: * * RDA - Raw DMA Addressing - Buffers associated with SKBs are directly DMA @@ -121,6 +129,7 @@ enum gve_dev_opt_id { GVE_DEV_OPT_ID_GQI_RDA = 0x2, GVE_DEV_OPT_ID_GQI_QPL = 0x3, GVE_DEV_OPT_ID_DQO_RDA = 0x4, + GVE_DEV_OPT_ID_JUMBO_FRAMES = 0x8, }; enum gve_dev_opt_req_feat_mask { @@ -128,6 +137,11 @@ enum gve_dev_opt_req_feat_mask { GVE_DEV_OPT_REQ_FEAT_MASK_GQI_RDA = 0x0, GVE_DEV_OPT_REQ_FEAT_MASK_GQI_QPL = 0x0, GVE_DEV_OPT_REQ_FEAT_MASK_DQO_RDA = 0x0, + GVE_DEV_OPT_REQ_FEAT_MASK_JUMBO_FRAMES = 0x0, +}; + +enum gve_sup_feature_mask { + GVE_SUP_JUMBO_FRAMES_MASK = 1 << 2, }; #define GVE_DEV_OPT_LEN_GQI_RAW_ADDRESSING 0x0 diff --git a/drivers/net/ethernet/google/gve/gve_desc.h b/drivers/net/ethernet/google/gve/gve_desc.h index 05ae6300e984..4d225a18d8ce 100644 --- a/drivers/net/ethernet/google/gve/gve_desc.h +++ b/drivers/net/ethernet/google/gve/gve_desc.h @@ -90,12 +90,13 @@ union gve_rx_data_slot { /* GVE Recive Packet Descriptor Flags */ #define GVE_RXFLG(x) cpu_to_be16(1 << (3 + (x))) -#define GVE_RXF_FRAG GVE_RXFLG(3) /* IP Fragment */ -#define GVE_RXF_IPV4 GVE_RXFLG(4) /* IPv4 */ -#define GVE_RXF_IPV6 GVE_RXFLG(5) /* IPv6 */ -#define GVE_RXF_TCP GVE_RXFLG(6) /* TCP Packet */ -#define GVE_RXF_UDP GVE_RXFLG(7) /* UDP Packet */ -#define GVE_RXF_ERR GVE_RXFLG(8) /* Packet Error Detected */ +#define GVE_RXF_FRAG GVE_RXFLG(3) /* IP Fragment */ +#define GVE_RXF_IPV4 GVE_RXFLG(4) /* IPv4 */ +#define GVE_RXF_IPV6 GVE_RXFLG(5) /* IPv6 */ +#define GVE_RXF_TCP GVE_RXFLG(6) /* TCP Packet */ +#define GVE_RXF_UDP GVE_RXFLG(7) /* UDP Packet */ +#define GVE_RXF_ERR GVE_RXFLG(8) /* Packet Error Detected */ +#define GVE_RXF_PKT_CONT GVE_RXFLG(10) /* Multi Fragment RX packet */ /* GVE IRQ */ #define GVE_IRQ_ACK BIT(31) diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c index 618a3e1d858e..c8df47a97fa4 100644 --- a/drivers/net/ethernet/google/gve/gve_ethtool.c +++ b/drivers/net/ethernet/google/gve/gve_ethtool.c @@ -43,6 +43,7 @@ static const char gve_gstrings_main_stats[][ETH_GSTRING_LEN] = { static const char gve_gstrings_rx_stats[][ETH_GSTRING_LEN] = { "rx_posted_desc[%u]", "rx_completed_desc[%u]", "rx_bytes[%u]", + "rx_cont_packet_cnt[%u]", "rx_frag_flip_cnt[%u]", "rx_frag_copy_cnt[%u]", "rx_dropped_pkt[%u]", "rx_copybreak_pkt[%u]", "rx_copied_pkt[%u]", "rx_queue_drop_cnt[%u]", "rx_no_buffers_posted[%u]", "rx_drops_packet_over_mru[%u]", "rx_drops_invalid_checksum[%u]", @@ -265,6 +266,9 @@ gve_get_ethtool_stats(struct net_device *netdev, } while (u64_stats_fetch_retry(&priv->rx[ring].statss, start)); data[i++] = tmp_rx_bytes; + data[i++] = rx->rx_cont_packet_cnt; + data[i++] = rx->rx_frag_flip_cnt; + data[i++] = rx->rx_frag_copy_cnt; /* rx dropped packets */ data[i++] = tmp_rx_skb_alloc_fail + tmp_rx_buf_alloc_fail + diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c index 7647cd05b1d2..6b02ef432eda 100644 --- a/drivers/net/ethernet/google/gve/gve_main.c +++ b/drivers/net/ethernet/google/gve/gve_main.c @@ -1371,14 +1371,6 @@ static int gve_init_priv(struct gve_priv *priv, bool skip_describe_device) "Could not get device information: err=%d\n", err); goto err; } - if (gve_is_gqi(priv) && priv->dev->max_mtu > PAGE_SIZE) { - priv->dev->max_mtu = PAGE_SIZE; - err = gve_adminq_set_mtu(priv, priv->dev->mtu); - if (err) { - dev_err(&priv->pdev->dev, "Could not set mtu"); - goto err; - } - } priv->dev->mtu = priv->dev->max_mtu; num_ntfy = pci_msix_vec_count(priv->pdev); if (num_ntfy <= 0) { diff --git a/drivers/net/ethernet/google/gve/gve_rx.c b/drivers/net/ethernet/google/gve/gve_rx.c index 95bc4d8a1811..c8500babbd1d 100644 --- a/drivers/net/ethernet/google/gve/gve_rx.c +++ b/drivers/net/ethernet/google/gve/gve_rx.c @@ -143,6 +143,16 @@ alloc_err: return err; } +static void gve_rx_ctx_clear(struct gve_rx_ctx *ctx) +{ + ctx->curr_frag_cnt = 0; + ctx->total_expected_size = 0; + ctx->expected_frag_cnt = 0; + ctx->skb_head = NULL; + ctx->skb_tail = NULL; + ctx->reuse_frags = false; +} + static int gve_rx_alloc_ring(struct gve_priv *priv, int idx) { struct gve_rx_ring *rx = &priv->rx[idx]; @@ -209,6 +219,12 @@ static int gve_rx_alloc_ring(struct gve_priv *priv, int idx) rx->cnt = 0; rx->db_threshold = priv->rx_desc_cnt / 2; rx->desc.seqno = 1; + + /* Allocating half-page buffers allows page-flipping which is faster + * than copying or allocating new pages. + */ + rx->packet_buffer_size = PAGE_SIZE / 2; + gve_rx_ctx_clear(&rx->ctx); gve_rx_add_to_block(priv, idx); return 0; @@ -275,18 +291,28 @@ static enum pkt_hash_types gve_rss_type(__be16 pkt_flags) return PKT_HASH_TYPE_L2; } +static u16 gve_rx_ctx_padding(struct gve_rx_ctx *ctx) +{ + return (ctx->curr_frag_cnt == 0) ? GVE_RX_PAD : 0; +} + static struct sk_buff *gve_rx_add_frags(struct napi_struct *napi, struct gve_rx_slot_page_info *page_info, - u16 len) + u16 packet_buffer_size, u16 len, + struct gve_rx_ctx *ctx) { - struct sk_buff *skb = napi_get_frags(napi); + u32 offset = page_info->page_offset + gve_rx_ctx_padding(ctx); + struct sk_buff *skb; + + if (!ctx->skb_head) + ctx->skb_head = napi_get_frags(napi); - if (unlikely(!skb)) + if (unlikely(!ctx->skb_head)) return NULL; - skb_add_rx_frag(skb, 0, page_info->page, - page_info->page_offset + - GVE_RX_PAD, len, PAGE_SIZE / 2); + skb = ctx->skb_head; + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page_info->page, + offset, len, packet_buffer_size); return skb; } @@ -300,12 +326,6 @@ static void gve_rx_flip_buff(struct gve_rx_slot_page_info *page_info, __be64 *sl *(slot_addr) ^= offset; } -static bool gve_rx_can_flip_buffers(struct net_device *netdev) -{ - return PAGE_SIZE >= 4096 - ? netdev->mtu + GVE_RX_PAD + ETH_HLEN <= PAGE_SIZE / 2 : false; -} - static int gve_rx_can_recycle_buffer(struct gve_rx_slot_page_info *page_info) { int pagecount = page_count(page_info->page); @@ -325,11 +345,11 @@ static struct sk_buff * gve_rx_raw_addressing(struct device *dev, struct net_device *netdev, struct gve_rx_slot_page_info *page_info, u16 len, struct napi_struct *napi, - union gve_rx_data_slot *data_slot) + union gve_rx_data_slot *data_slot, + u16 packet_buffer_size, struct gve_rx_ctx *ctx) { - struct sk_buff *skb; + struct sk_buff *skb = gve_rx_add_frags(napi, page_info, packet_buffer_size, len, ctx); - skb = gve_rx_add_frags(napi, page_info, len); if (!skb) return NULL; @@ -348,6 +368,7 @@ gve_rx_qpl(struct device *dev, struct net_device *netdev, u16 len, struct napi_struct *napi, union gve_rx_data_slot *data_slot) { + struct gve_rx_ctx *ctx = &rx->ctx; struct sk_buff *skb; /* if raw_addressing mode is not enabled gvnic can only receive into @@ -355,8 +376,8 @@ gve_rx_qpl(struct device *dev, struct net_device *netdev, * choice is to copy the data out of it so that we can return it to the * device. */ - if (page_info->can_flip) { - skb = gve_rx_add_frags(napi, page_info, len); + if (ctx->reuse_frags) { + skb = gve_rx_add_frags(napi, page_info, rx->packet_buffer_size, len, ctx); /* No point in recycling if we didn't get the skb */ if (skb) { /* Make sure that the page isn't freed. */ @@ -364,114 +385,247 @@ gve_rx_qpl(struct device *dev, struct net_device *netdev, gve_rx_flip_buff(page_info, &data_slot->qpl_offset); } } else { - skb = gve_rx_copy(netdev, napi, page_info, len, GVE_RX_PAD); + const u16 padding = gve_rx_ctx_padding(ctx); + + skb = gve_rx_copy(netdev, napi, page_info, len, padding, ctx); if (skb) { u64_stats_update_begin(&rx->statss); - rx->rx_copied_pkt++; + rx->rx_frag_copy_cnt++; u64_stats_update_end(&rx->statss); } } return skb; } -static bool gve_rx(struct gve_rx_ring *rx, struct gve_rx_desc *rx_desc, - netdev_features_t feat, u32 idx) +#define GVE_PKTCONT_BIT_IS_SET(x) (GVE_RXF_PKT_CONT & (x)) +static u16 gve_rx_get_fragment_size(struct gve_rx_ctx *ctx, struct gve_rx_desc *desc) { + return be16_to_cpu(desc->len) - gve_rx_ctx_padding(ctx); +} + +static bool gve_rx_ctx_init(struct gve_rx_ctx *ctx, struct gve_rx_ring *rx) +{ + bool qpl_mode = !rx->data.raw_addressing, packet_size_error = false; + bool buffer_error = false, desc_error = false, seqno_error = false; struct gve_rx_slot_page_info *page_info; struct gve_priv *priv = rx->gve; - struct napi_struct *napi = &priv->ntfy_blocks[rx->ntfy_id].napi; - struct net_device *dev = priv->dev; - union gve_rx_data_slot *data_slot; - struct sk_buff *skb = NULL; - dma_addr_t page_bus; - void *va; - u16 len; + u32 idx = rx->cnt & rx->mask; + bool reuse_frags, can_flip; + struct gve_rx_desc *desc; + u16 packet_size = 0; + u16 n_frags = 0; + int recycle; - /* Prefetch two packet pages ahead, we will need it soon. */ - page_info = &rx->data.page_info[(idx + 2) & rx->mask]; - va = page_info->page_address + GVE_RX_PAD + - page_info->page_offset; + /** In QPL mode, we only flip buffers when all buffers containing the packet + * can be flipped. RDA can_flip decisions will be made later, per frag. + */ + can_flip = qpl_mode; + reuse_frags = can_flip; + do { + u16 frag_size; + + n_frags++; + desc = &rx->desc.desc_ring[idx]; + desc_error = unlikely(desc->flags_seq & GVE_RXF_ERR) || desc_error; + if (GVE_SEQNO(desc->flags_seq) != rx->desc.seqno) { + seqno_error = true; + netdev_warn(priv->dev, + "RX seqno error: want=%d, got=%d, dropping packet and scheduling reset.", + rx->desc.seqno, GVE_SEQNO(desc->flags_seq)); + } + frag_size = be16_to_cpu(desc->len); + packet_size += frag_size; + if (frag_size > rx->packet_buffer_size) { + packet_size_error = true; + netdev_warn(priv->dev, + "RX fragment error: packet_buffer_size=%d, frag_size=%d, droping packet.", + rx->packet_buffer_size, be16_to_cpu(desc->len)); + } + page_info = &rx->data.page_info[idx]; + if (can_flip) { + recycle = gve_rx_can_recycle_buffer(page_info); + reuse_frags = reuse_frags && recycle > 0; + buffer_error = buffer_error || unlikely(recycle < 0); + } + idx = (idx + 1) & rx->mask; + rx->desc.seqno = gve_next_seqno(rx->desc.seqno); + } while (GVE_PKTCONT_BIT_IS_SET(desc->flags_seq)); - prefetch(page_info->page); /* Kernel page struct. */ - prefetch(va); /* Packet header. */ - prefetch(va + 64); /* Next cacheline too. */ + prefetch(rx->desc.desc_ring + idx); - /* drop this packet */ - if (unlikely(rx_desc->flags_seq & GVE_RXF_ERR)) { + ctx->curr_frag_cnt = 0; + ctx->total_expected_size = packet_size - GVE_RX_PAD; + ctx->expected_frag_cnt = n_frags; + ctx->skb_head = NULL; + ctx->reuse_frags = reuse_frags; + + if (ctx->expected_frag_cnt > 1) { u64_stats_update_begin(&rx->statss); - rx->rx_desc_err_dropped_pkt++; + rx->rx_cont_packet_cnt++; + u64_stats_update_end(&rx->statss); + } + if (ctx->total_expected_size > priv->rx_copybreak && !ctx->reuse_frags && qpl_mode) { + u64_stats_update_begin(&rx->statss); + rx->rx_copied_pkt++; u64_stats_update_end(&rx->statss); + } + + if (unlikely(buffer_error || seqno_error || packet_size_error)) { + gve_schedule_reset(priv); return false; } - len = be16_to_cpu(rx_desc->len) - GVE_RX_PAD; - page_info = &rx->data.page_info[idx]; + if (unlikely(desc_error)) { + u64_stats_update_begin(&rx->statss); + rx->rx_desc_err_dropped_pkt++; + u64_stats_update_end(&rx->statss); + return false; + } + return true; +} - data_slot = &rx->data.data_ring[idx]; - page_bus = (rx->data.raw_addressing) ? - be64_to_cpu(data_slot->addr) & GVE_DATA_SLOT_ADDR_PAGE_MASK : - rx->data.qpl->page_buses[idx]; - dma_sync_single_for_cpu(&priv->pdev->dev, page_bus, - PAGE_SIZE, DMA_FROM_DEVICE); +static struct sk_buff *gve_rx_skb(struct gve_priv *priv, struct gve_rx_ring *rx, + struct gve_rx_slot_page_info *page_info, struct napi_struct *napi, + u16 len, union gve_rx_data_slot *data_slot) +{ + struct net_device *netdev = priv->dev; + struct gve_rx_ctx *ctx = &rx->ctx; + struct sk_buff *skb = NULL; - if (len <= priv->rx_copybreak) { + if (len <= priv->rx_copybreak && ctx->expected_frag_cnt == 1) { /* Just copy small packets */ - skb = gve_rx_copy(dev, napi, page_info, len, GVE_RX_PAD); - u64_stats_update_begin(&rx->statss); - rx->rx_copied_pkt++; - rx->rx_copybreak_pkt++; - u64_stats_update_end(&rx->statss); + skb = gve_rx_copy(netdev, napi, page_info, len, GVE_RX_PAD, ctx); + if (skb) { + u64_stats_update_begin(&rx->statss); + rx->rx_copied_pkt++; + rx->rx_frag_copy_cnt++; + rx->rx_copybreak_pkt++; + } u64_stats_update_end(&rx->statss); } else { - u8 can_flip = gve_rx_can_flip_buffers(dev); - int recycle = 0; + if (rx->data.raw_addressing) { + int recycle = gve_rx_can_recycle_buffer(page_info); - if (can_flip) { - recycle = gve_rx_can_recycle_buffer(page_info); - if (recycle < 0) { - if (!rx->data.raw_addressing) - gve_schedule_reset(priv); - return false; + if (unlikely(recycle < 0)) { + gve_schedule_reset(priv); + return NULL; } - } - - page_info->can_flip = can_flip && recycle; - if (rx->data.raw_addressing) { - skb = gve_rx_raw_addressing(&priv->pdev->dev, dev, + page_info->can_flip = recycle; + if (page_info->can_flip) { + u64_stats_update_begin(&rx->statss); + rx->rx_frag_flip_cnt++; + u64_stats_update_end(&rx->statss); + } + skb = gve_rx_raw_addressing(&priv->pdev->dev, netdev, page_info, len, napi, - data_slot); + data_slot, + rx->packet_buffer_size, ctx); } else { - skb = gve_rx_qpl(&priv->pdev->dev, dev, rx, + if (ctx->reuse_frags) { + u64_stats_update_begin(&rx->statss); + rx->rx_frag_flip_cnt++; + u64_stats_update_end(&rx->statss); + } + skb = gve_rx_qpl(&priv->pdev->dev, netdev, rx, page_info, len, napi, data_slot); } } + return skb; +} - if (!skb) { - u64_stats_update_begin(&rx->statss); - rx->rx_skb_alloc_fail++; - u64_stats_update_end(&rx->statss); - return false; +static bool gve_rx(struct gve_rx_ring *rx, netdev_features_t feat, + u64 *packet_size_bytes, u32 *work_done) +{ + struct gve_rx_slot_page_info *page_info; + struct gve_rx_ctx *ctx = &rx->ctx; + union gve_rx_data_slot *data_slot; + struct gve_priv *priv = rx->gve; + struct gve_rx_desc *first_desc; + struct sk_buff *skb = NULL; + struct gve_rx_desc *desc; + struct napi_struct *napi; + dma_addr_t page_bus; + u32 work_cnt = 0; + void *va; + u32 idx; + u16 len; + + idx = rx->cnt & rx->mask; + first_desc = &rx->desc.desc_ring[idx]; + desc = first_desc; + napi = &priv->ntfy_blocks[rx->ntfy_id].napi; + + if (unlikely(!gve_rx_ctx_init(ctx, rx))) + goto skb_alloc_fail; + + while (ctx->curr_frag_cnt < ctx->expected_frag_cnt) { + /* Prefetch two packet buffers ahead, we will need it soon. */ + page_info = &rx->data.page_info[(idx + 2) & rx->mask]; + va = page_info->page_address + page_info->page_offset; + + prefetch(page_info->page); /* Kernel page struct. */ + prefetch(va); /* Packet header. */ + prefetch(va + 64); /* Next cacheline too. */ + + len = gve_rx_get_fragment_size(ctx, desc); + + page_info = &rx->data.page_info[idx]; + data_slot = &rx->data.data_ring[idx]; + page_bus = rx->data.raw_addressing ? + be64_to_cpu(data_slot->addr) - page_info->page_offset : + rx->data.qpl->page_buses[idx]; + dma_sync_single_for_cpu(&priv->pdev->dev, page_bus, PAGE_SIZE, DMA_FROM_DEVICE); + + skb = gve_rx_skb(priv, rx, page_info, napi, len, data_slot); + if (!skb) { + u64_stats_update_begin(&rx->statss); + rx->rx_skb_alloc_fail++; + u64_stats_update_end(&rx->statss); + goto skb_alloc_fail; + } + + ctx->curr_frag_cnt++; + rx->cnt++; + idx = rx->cnt & rx->mask; + work_cnt++; + desc = &rx->desc.desc_ring[idx]; } if (likely(feat & NETIF_F_RXCSUM)) { /* NIC passes up the partial sum */ - if (rx_desc->csum) + if (first_desc->csum) skb->ip_summed = CHECKSUM_COMPLETE; else skb->ip_summed = CHECKSUM_NONE; - skb->csum = csum_unfold(rx_desc->csum); + skb->csum = csum_unfold(first_desc->csum); } /* parse flags & pass relevant info up */ if (likely(feat & NETIF_F_RXHASH) && - gve_needs_rss(rx_desc->flags_seq)) - skb_set_hash(skb, be32_to_cpu(rx_desc->rss_hash), - gve_rss_type(rx_desc->flags_seq)); + gve_needs_rss(first_desc->flags_seq)) + skb_set_hash(skb, be32_to_cpu(first_desc->rss_hash), + gve_rss_type(first_desc->flags_seq)); + *packet_size_bytes = skb->len + (skb->protocol ? ETH_HLEN : 0); + *work_done = work_cnt; if (skb_is_nonlinear(skb)) napi_gro_frags(napi); else napi_gro_receive(napi, skb); + + gve_rx_ctx_clear(ctx); return true; + +skb_alloc_fail: + if (napi->skb) + napi_free_frags(napi); + *packet_size_bytes = 0; + *work_done = ctx->expected_frag_cnt; + while (ctx->curr_frag_cnt < ctx->expected_frag_cnt) { + rx->cnt++; + ctx->curr_frag_cnt++; + } + gve_rx_ctx_clear(ctx); + return false; } bool gve_rx_work_pending(struct gve_rx_ring *rx) @@ -529,7 +683,6 @@ static bool gve_rx_refill_buffers(struct gve_priv *priv, struct gve_rx_ring *rx) union gve_rx_data_slot *data_slot = &rx->data.data_ring[idx]; struct device *dev = &priv->pdev->dev; - gve_rx_free_buffer(dev, page_info, data_slot); page_info->page = NULL; if (gve_rx_alloc_buffer(priv, dev, page_info, @@ -550,16 +703,17 @@ static bool gve_rx_refill_buffers(struct gve_priv *priv, struct gve_rx_ring *rx) static int gve_clean_rx_done(struct gve_rx_ring *rx, int budget, netdev_features_t feat) { + u32 work_done = 0, total_packet_cnt = 0, ok_packet_cnt = 0; struct gve_priv *priv = rx->gve; - u32 work_done = 0, packets = 0; + u32 idx = rx->cnt & rx->mask; struct gve_rx_desc *desc; - u32 cnt = rx->cnt; - u32 idx = cnt & rx->mask; u64 bytes = 0; - desc = rx->desc.desc_ring + idx; + desc = &rx->desc.desc_ring[idx]; while ((GVE_SEQNO(desc->flags_seq) == rx->desc.seqno) && work_done < budget) { + u64 packet_size_bytes = 0; + u32 work_cnt = 0; bool dropped; netif_info(priv, rx_status, priv->dev, @@ -570,37 +724,32 @@ static int gve_clean_rx_done(struct gve_rx_ring *rx, int budget, rx->q_num, GVE_SEQNO(desc->flags_seq), rx->desc.seqno); - /* prefetch two descriptors ahead */ - prefetch(rx->desc.desc_ring + ((cnt + 2) & rx->mask)); - - dropped = !gve_rx(rx, desc, feat, idx); + dropped = !gve_rx(rx, feat, &packet_size_bytes, &work_cnt); if (!dropped) { - bytes += be16_to_cpu(desc->len) - GVE_RX_PAD; - packets++; + bytes += packet_size_bytes; + ok_packet_cnt++; } - cnt++; - idx = cnt & rx->mask; - desc = rx->desc.desc_ring + idx; - rx->desc.seqno = gve_next_seqno(rx->desc.seqno); - work_done++; + total_packet_cnt++; + idx = rx->cnt & rx->mask; + desc = &rx->desc.desc_ring[idx]; + work_done += work_cnt; } - if (!work_done && rx->fill_cnt - cnt > rx->db_threshold) + if (!work_done && rx->fill_cnt - rx->cnt > rx->db_threshold) return 0; if (work_done) { u64_stats_update_begin(&rx->statss); - rx->rpackets += packets; + rx->rpackets += ok_packet_cnt; rx->rbytes += bytes; u64_stats_update_end(&rx->statss); - rx->cnt = cnt; } /* restock ring slots */ if (!rx->data.raw_addressing) { /* In QPL mode buffs are refilled as the desc are processed */ rx->fill_cnt += work_done; - } else if (rx->fill_cnt - cnt <= rx->db_threshold) { + } else if (rx->fill_cnt - rx->cnt <= rx->db_threshold) { /* In raw addressing mode buffs are only refilled if the avail * falls below a threshold. */ @@ -610,14 +759,14 @@ static int gve_clean_rx_done(struct gve_rx_ring *rx, int budget, /* If we were not able to completely refill buffers, we'll want * to schedule this queue for work again to refill buffers. */ - if (rx->fill_cnt - cnt <= rx->db_threshold) { + if (rx->fill_cnt - rx->cnt <= rx->db_threshold) { gve_rx_write_doorbell(priv, rx); return budget; } } gve_rx_write_doorbell(priv, rx); - return work_done; + return total_packet_cnt; } int gve_rx_poll(struct gve_notify_block *block, int budget) diff --git a/drivers/net/ethernet/google/gve/gve_rx_dqo.c b/drivers/net/ethernet/google/gve/gve_rx_dqo.c index 8500621b2cd4..beb8bb079023 100644 --- a/drivers/net/ethernet/google/gve/gve_rx_dqo.c +++ b/drivers/net/ethernet/google/gve/gve_rx_dqo.c @@ -240,8 +240,8 @@ static int gve_rx_alloc_ring_dqo(struct gve_priv *priv, int idx) rx->dqo.bufq.mask = buffer_queue_slots - 1; rx->dqo.complq.num_free_slots = completion_queue_slots; rx->dqo.complq.mask = completion_queue_slots - 1; - rx->skb_head = NULL; - rx->skb_tail = NULL; + rx->ctx.skb_head = NULL; + rx->ctx.skb_tail = NULL; rx->dqo.num_buf_states = min_t(s16, S16_MAX, buffer_queue_slots * 4); rx->dqo.buf_states = kvcalloc(rx->dqo.num_buf_states, @@ -467,12 +467,12 @@ static void gve_rx_skb_hash(struct sk_buff *skb, static void gve_rx_free_skb(struct gve_rx_ring *rx) { - if (!rx->skb_head) + if (!rx->ctx.skb_head) return; - dev_kfree_skb_any(rx->skb_head); - rx->skb_head = NULL; - rx->skb_tail = NULL; + dev_kfree_skb_any(rx->ctx.skb_head); + rx->ctx.skb_head = NULL; + rx->ctx.skb_tail = NULL; } /* Chains multi skbs for single rx packet. @@ -483,7 +483,7 @@ static int gve_rx_append_frags(struct napi_struct *napi, u16 buf_len, struct gve_rx_ring *rx, struct gve_priv *priv) { - int num_frags = skb_shinfo(rx->skb_tail)->nr_frags; + int num_frags = skb_shinfo(rx->ctx.skb_tail)->nr_frags; if (unlikely(num_frags == MAX_SKB_FRAGS)) { struct sk_buff *skb; @@ -492,17 +492,17 @@ static int gve_rx_append_frags(struct napi_struct *napi, if (!skb) return -1; - skb_shinfo(rx->skb_tail)->frag_list = skb; - rx->skb_tail = skb; + skb_shinfo(rx->ctx.skb_tail)->frag_list = skb; + rx->ctx.skb_tail = skb; num_frags = 0; } - if (rx->skb_tail != rx->skb_head) { - rx->skb_head->len += buf_len; - rx->skb_head->data_len += buf_len; - rx->skb_head->truesize += priv->data_buffer_size_dqo; + if (rx->ctx.skb_tail != rx->ctx.skb_head) { + rx->ctx.skb_head->len += buf_len; + rx->ctx.skb_head->data_len += buf_len; + rx->ctx.skb_head->truesize += priv->data_buffer_size_dqo; } - skb_add_rx_frag(rx->skb_tail, num_frags, + skb_add_rx_frag(rx->ctx.skb_tail, num_frags, buf_state->page_info.page, buf_state->page_info.page_offset, buf_len, priv->data_buffer_size_dqo); @@ -556,7 +556,7 @@ static int gve_rx_dqo(struct napi_struct *napi, struct gve_rx_ring *rx, buf_len, DMA_FROM_DEVICE); /* Append to current skb if one exists. */ - if (rx->skb_head) { + if (rx->ctx.skb_head) { if (unlikely(gve_rx_append_frags(napi, buf_state, buf_len, rx, priv)) != 0) { goto error; @@ -567,11 +567,11 @@ static int gve_rx_dqo(struct napi_struct *napi, struct gve_rx_ring *rx, } if (eop && buf_len <= priv->rx_copybreak) { - rx->skb_head = gve_rx_copy(priv->dev, napi, - &buf_state->page_info, buf_len, 0); - if (unlikely(!rx->skb_head)) + rx->ctx.skb_head = gve_rx_copy(priv->dev, napi, + &buf_state->page_info, buf_len, 0, NULL); + if (unlikely(!rx->ctx.skb_head)) goto error; - rx->skb_tail = rx->skb_head; + rx->ctx.skb_tail = rx->ctx.skb_head; u64_stats_update_begin(&rx->statss); rx->rx_copied_pkt++; @@ -583,12 +583,12 @@ static int gve_rx_dqo(struct napi_struct *napi, struct gve_rx_ring *rx, return 0; } - rx->skb_head = napi_get_frags(napi); - if (unlikely(!rx->skb_head)) + rx->ctx.skb_head = napi_get_frags(napi); + if (unlikely(!rx->ctx.skb_head)) goto error; - rx->skb_tail = rx->skb_head; + rx->ctx.skb_tail = rx->ctx.skb_head; - skb_add_rx_frag(rx->skb_head, 0, buf_state->page_info.page, + skb_add_rx_frag(rx->ctx.skb_head, 0, buf_state->page_info.page, buf_state->page_info.page_offset, buf_len, priv->data_buffer_size_dqo); gve_dec_pagecnt_bias(&buf_state->page_info); @@ -635,27 +635,27 @@ static int gve_rx_complete_skb(struct gve_rx_ring *rx, struct napi_struct *napi, rx->gve->ptype_lut_dqo->ptypes[desc->packet_type]; int err; - skb_record_rx_queue(rx->skb_head, rx->q_num); + skb_record_rx_queue(rx->ctx.skb_head, rx->q_num); if (feat & NETIF_F_RXHASH) - gve_rx_skb_hash(rx->skb_head, desc, ptype); + gve_rx_skb_hash(rx->ctx.skb_head, desc, ptype); if (feat & NETIF_F_RXCSUM) - gve_rx_skb_csum(rx->skb_head, desc, ptype); + gve_rx_skb_csum(rx->ctx.skb_head, desc, ptype); /* RSC packets must set gso_size otherwise the TCP stack will complain * that packets are larger than MTU. */ if (desc->rsc) { - err = gve_rx_complete_rsc(rx->skb_head, desc, ptype); + err = gve_rx_complete_rsc(rx->ctx.skb_head, desc, ptype); if (err < 0) return err; } - if (skb_headlen(rx->skb_head) == 0) + if (skb_headlen(rx->ctx.skb_head) == 0) napi_gro_frags(napi); else - napi_gro_receive(napi, rx->skb_head); + napi_gro_receive(napi, rx->ctx.skb_head); return 0; } @@ -717,18 +717,18 @@ int gve_rx_poll_dqo(struct gve_notify_block *block, int budget) /* Free running counter of completed descriptors */ rx->cnt++; - if (!rx->skb_head) + if (!rx->ctx.skb_head) continue; if (!compl_desc->end_of_packet) continue; work_done++; - pkt_bytes = rx->skb_head->len; + pkt_bytes = rx->ctx.skb_head->len; /* The ethernet header (first ETH_HLEN bytes) is snipped off * by eth_type_trans. */ - if (skb_headlen(rx->skb_head)) + if (skb_headlen(rx->ctx.skb_head)) pkt_bytes += ETH_HLEN; /* gve_rx_complete_skb() will consume skb if successful */ @@ -741,8 +741,8 @@ int gve_rx_poll_dqo(struct gve_notify_block *block, int budget) } bytes += pkt_bytes; - rx->skb_head = NULL; - rx->skb_tail = NULL; + rx->ctx.skb_head = NULL; + rx->ctx.skb_tail = NULL; } gve_rx_post_buffers_dqo(rx); diff --git a/drivers/net/ethernet/google/gve/gve_utils.c b/drivers/net/ethernet/google/gve/gve_utils.c index 45ff7a9ab5f9..88ca49cbc1e2 100644 --- a/drivers/net/ethernet/google/gve/gve_utils.c +++ b/drivers/net/ethernet/google/gve/gve_utils.c @@ -50,20 +50,31 @@ void gve_rx_add_to_block(struct gve_priv *priv, int queue_idx) struct sk_buff *gve_rx_copy(struct net_device *dev, struct napi_struct *napi, struct gve_rx_slot_page_info *page_info, u16 len, - u16 pad) + u16 padding, struct gve_rx_ctx *ctx) { - struct sk_buff *skb = napi_alloc_skb(napi, len); - void *va = page_info->page_address + pad + - page_info->page_offset; - - if (unlikely(!skb)) - return NULL; - + void *va = page_info->page_address + padding + page_info->page_offset; + int skb_linear_offset = 0; + bool set_protocol = false; + struct sk_buff *skb; + + if (ctx) { + if (!ctx->skb_head) + ctx->skb_head = napi_alloc_skb(napi, ctx->total_expected_size); + + if (unlikely(!ctx->skb_head)) + return NULL; + skb = ctx->skb_head; + skb_linear_offset = skb->len; + set_protocol = ctx->curr_frag_cnt == ctx->expected_frag_cnt - 1; + } else { + skb = napi_alloc_skb(napi, len); + set_protocol = true; + } __skb_put(skb, len); + skb_copy_to_linear_data_offset(skb, skb_linear_offset, va, len); - skb_copy_to_linear_data(skb, va, len); - - skb->protocol = eth_type_trans(skb, dev); + if (set_protocol) + skb->protocol = eth_type_trans(skb, dev); return skb; } diff --git a/drivers/net/ethernet/google/gve/gve_utils.h b/drivers/net/ethernet/google/gve/gve_utils.h index 79595940b351..6d98e69fd3b8 100644 --- a/drivers/net/ethernet/google/gve/gve_utils.h +++ b/drivers/net/ethernet/google/gve/gve_utils.h @@ -19,7 +19,7 @@ void gve_rx_add_to_block(struct gve_priv *priv, int queue_idx); struct sk_buff *gve_rx_copy(struct net_device *dev, struct napi_struct *napi, struct gve_rx_slot_page_info *page_info, u16 len, - u16 pad); + u16 pad, struct gve_rx_ctx *ctx); /* Decrement pagecnt_bias. Set it back to INT_MAX if it reached zero. */ void gve_dec_pagecnt_bias(struct gve_rx_slot_page_info *page_info); diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 30a3954b78e0..3f7a9a4c59d5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -299,6 +299,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_SERV_INFO, HNAE3_DBG_CMD_UMV_INFO, HNAE3_DBG_CMD_PAGE_POOL_INFO, + HNAE3_DBG_CMD_COAL_INFO, HNAE3_DBG_CMD_UNKNOWN, }; @@ -348,6 +349,7 @@ struct hnae3_dev_specs { u16 max_qset_num; u16 umv_size; u16 mc_mac_size; + u32 mac_stats_num; }; struct hnae3_client_ops { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index b26d43c9c088..1a1bebd453d3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -343,6 +343,13 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "coalesce_info", + .cmd = HNAE3_DBG_CMD_COAL_INFO, + .dentry = HNS3_DBG_DENTRY_COMMON, + .buf_len = HNS3_DBG_READ_LEN_1MB, + .init = hns3_dbg_common_file_init, + }, }; static struct hns3_dbg_cap_info hns3_dbg_cap[] = { @@ -391,6 +398,26 @@ static struct hns3_dbg_cap_info hns3_dbg_cap[] = { } }; +static const struct hns3_dbg_item coal_info_items[] = { + { "VEC_ID", 2 }, + { "ALGO_STATE", 2 }, + { "PROFILE_ID", 2 }, + { "CQE_MODE", 2 }, + { "TUNE_STATE", 2 }, + { "STEPS_LEFT", 2 }, + { "STEPS_RIGHT", 2 }, + { "TIRED", 2 }, + { "SW_GL", 2 }, + { "SW_QL", 2 }, + { "HW_GL", 2 }, + { "HW_QL", 2 }, +}; + +static const char * const dim_cqe_mode_str[] = { "EQE", "CQE" }; +static const char * const dim_state_str[] = { "START", "IN_PROG", "APPLY" }; +static const char * const +dim_tune_stat_str[] = { "ON_TOP", "TIRED", "RIGHT", "LEFT" }; + static void hns3_dbg_fill_content(char *content, u16 len, const struct hns3_dbg_item *items, const char **result, u16 size) @@ -412,6 +439,94 @@ static void hns3_dbg_fill_content(char *content, u16 len, *pos++ = '\0'; } +static void hns3_get_coal_info(struct hns3_enet_tqp_vector *tqp_vector, + char **result, int i, bool is_tx) +{ + unsigned int gl_offset, ql_offset; + struct hns3_enet_coalesce *coal; + unsigned int reg_val; + unsigned int j = 0; + struct dim *dim; + bool ql_enable; + + if (is_tx) { + coal = &tqp_vector->tx_group.coal; + dim = &tqp_vector->tx_group.dim; + gl_offset = HNS3_VECTOR_GL1_OFFSET; + ql_offset = HNS3_VECTOR_TX_QL_OFFSET; + ql_enable = tqp_vector->tx_group.coal.ql_enable; + } else { + coal = &tqp_vector->rx_group.coal; + dim = &tqp_vector->rx_group.dim; + gl_offset = HNS3_VECTOR_GL0_OFFSET; + ql_offset = HNS3_VECTOR_RX_QL_OFFSET; + ql_enable = tqp_vector->rx_group.coal.ql_enable; + } + + sprintf(result[j++], "%d", i); + sprintf(result[j++], "%s", dim_state_str[dim->state]); + sprintf(result[j++], "%u", dim->profile_ix); + sprintf(result[j++], "%s", dim_cqe_mode_str[dim->mode]); + sprintf(result[j++], "%s", + dim_tune_stat_str[dim->tune_state]); + sprintf(result[j++], "%u", dim->steps_left); + sprintf(result[j++], "%u", dim->steps_right); + sprintf(result[j++], "%u", dim->tired); + sprintf(result[j++], "%u", coal->int_gl); + sprintf(result[j++], "%u", coal->int_ql); + reg_val = readl(tqp_vector->mask_addr + gl_offset) & + HNS3_VECTOR_GL_MASK; + sprintf(result[j++], "%u", reg_val); + if (ql_enable) { + reg_val = readl(tqp_vector->mask_addr + ql_offset) & + HNS3_VECTOR_QL_MASK; + sprintf(result[j++], "%u", reg_val); + } else { + sprintf(result[j++], "NA"); + } +} + +static void hns3_dump_coal_info(struct hnae3_handle *h, char *buf, int len, + int *pos, bool is_tx) +{ + char data_str[ARRAY_SIZE(coal_info_items)][HNS3_DBG_DATA_STR_LEN]; + char *result[ARRAY_SIZE(coal_info_items)]; + struct hns3_enet_tqp_vector *tqp_vector; + struct hns3_nic_priv *priv = h->priv; + char content[HNS3_DBG_INFO_LEN]; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(coal_info_items); i++) + result[i] = &data_str[i][0]; + + *pos += scnprintf(buf + *pos, len - *pos, + "%s interrupt coalesce info:\n", + is_tx ? "tx" : "rx"); + hns3_dbg_fill_content(content, sizeof(content), coal_info_items, + NULL, ARRAY_SIZE(coal_info_items)); + *pos += scnprintf(buf + *pos, len - *pos, "%s", content); + + for (i = 0; i < priv->vector_num; i++) { + tqp_vector = &priv->tqp_vector[i]; + hns3_get_coal_info(tqp_vector, result, i, is_tx); + hns3_dbg_fill_content(content, sizeof(content), coal_info_items, + (const char **)result, + ARRAY_SIZE(coal_info_items)); + *pos += scnprintf(buf + *pos, len - *pos, "%s", content); + } +} + +static int hns3_dbg_coal_info(struct hnae3_handle *h, char *buf, int len) +{ + int pos = 0; + + hns3_dump_coal_info(h, buf, len, &pos, true); + pos += scnprintf(buf + pos, len - pos, "\n"); + hns3_dump_coal_info(h, buf, len, &pos, false); + + return 0; +} + static const struct hns3_dbg_item tx_spare_info_items[] = { { "QUEUE_ID", 2 }, { "COPYBREAK", 2 }, @@ -935,6 +1050,8 @@ hns3_dbg_dev_specs(struct hnae3_handle *h, char *buf, int len, int *pos) dev_specs->umv_size); *pos += scnprintf(buf + *pos, len - *pos, "mc mac size: %u\n", dev_specs->mc_mac_size); + *pos += scnprintf(buf + *pos, len - *pos, "MAC statistics number: %u\n", + dev_specs->mac_stats_num); } static int hns3_dbg_dev_info(struct hnae3_handle *h, char *buf, int len) @@ -1056,6 +1173,10 @@ static const struct hns3_dbg_func hns3_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_PAGE_POOL_INFO, .dbg_dump = hns3_dbg_page_pool_info, }, + { + .cmd = HNAE3_DBG_CMD_COAL_INFO, + .dbg_dump = hns3_dbg_coal_info, + }, }; static int hns3_dbg_read_cmd(struct hns3_dbg_data *dbg_data, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index f09a61d9c626..1715c98d906d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -189,12 +189,13 @@ enum hns3_nic_state { #define HNS3_MAX_TSO_SIZE 1048576U #define HNS3_MAX_NON_TSO_SIZE 9728U - +#define HNS3_VECTOR_GL_MASK GENMASK(11, 0) #define HNS3_VECTOR_GL0_OFFSET 0x100 #define HNS3_VECTOR_GL1_OFFSET 0x200 #define HNS3_VECTOR_GL2_OFFSET 0x300 #define HNS3_VECTOR_RL_OFFSET 0x900 #define HNS3_VECTOR_RL_EN_B 6 +#define HNS3_VECTOR_QL_MASK GENMASK(9, 0) #define HNS3_VECTOR_TX_QL_OFFSET 0xe00 #define HNS3_VECTOR_RX_QL_OFFSET 0xf00 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index 9c2eeaa82294..c327df9dbac4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -482,6 +482,7 @@ static int hclge_firmware_compat_config(struct hclge_dev *hdev, bool en) hnae3_set_bit(compat, HCLGE_NCSI_ERROR_REPORT_EN_B, 1); if (hnae3_dev_phy_imp_supported(hdev)) hnae3_set_bit(compat, HCLGE_PHY_IMP_EN_B, 1); + hnae3_set_bit(compat, HCLGE_MAC_STATS_EXT_EN_B, 1); req->compat = cpu_to_le32(compat); } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index bfcfefa9d2b5..c38b57fc6c6a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -1150,6 +1150,7 @@ struct hclge_query_ppu_pf_other_int_dfx_cmd { #define HCLGE_LINK_EVENT_REPORT_EN_B 0 #define HCLGE_NCSI_ERROR_REPORT_EN_B 1 #define HCLGE_PHY_IMP_EN_B 2 +#define HCLGE_MAC_STATS_EXT_EN_B 3 struct hclge_firmware_compat_cmd { __le32 compat; u8 rsv[20]; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c index 93aa7f2bdc13..20e628c2bd44 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c @@ -1243,6 +1243,9 @@ static const struct hclge_hw_module_id hclge_hw_module_id_st[] = { .module_id = MODULE_MASTER, .msg = "MODULE_MASTER" }, { + .module_id = MODULE_HIMAC, + .msg = "MODULE_HIMAC" + }, { .module_id = MODULE_ROCEE_TOP, .msg = "MODULE_ROCEE_TOP" }, { @@ -1316,12 +1319,21 @@ static const struct hclge_hw_type_id hclge_hw_type_id_st[] = { .type_id = GLB_ERROR, .msg = "glb_error" }, { + .type_id = LINK_ERROR, + .msg = "link_error" + }, { + .type_id = PTP_ERROR, + .msg = "ptp_error" + }, { .type_id = ROCEE_NORMAL_ERR, .msg = "rocee_normal_error" }, { .type_id = ROCEE_OVF_ERR, .msg = "rocee_ovf_error" - } + }, { + .type_id = ROCEE_BUS_ERR, + .msg = "rocee_bus_error" + }, }; static void hclge_log_error(struct device *dev, char *reg, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h index d811eeefe2c0..86be6fb32990 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h @@ -138,6 +138,7 @@ enum hclge_mod_name_list { MODULE_RCB_TX = 12, MODULE_TXDMA = 13, MODULE_MASTER = 14, + MODULE_HIMAC = 15, /* add new MODULE NAME for NIC here in order */ MODULE_ROCEE_TOP = 40, MODULE_ROCEE_TIMER = 41, @@ -166,9 +167,12 @@ enum hclge_err_type_list { ETS_ERROR = 10, NCSI_ERROR = 11, GLB_ERROR = 12, + LINK_ERROR = 13, + PTP_ERROR = 14, /* add new ERROR TYPE for NIC here in order */ ROCEE_NORMAL_ERR = 40, ROCEE_OVF_ERR = 41, + ROCEE_BUS_ERR = 42, /* add new ERROR TYPE for ROCEE here in order */ }; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index be6f0a6229aa..f1db6699f81f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -156,174 +156,210 @@ static const char hns3_nic_test_strs[][ETH_GSTRING_LEN] = { }; static const struct hclge_comm_stats_str g_mac_stats_string[] = { - {"mac_tx_mac_pause_num", + {"mac_tx_mac_pause_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_mac_pause_num)}, - {"mac_rx_mac_pause_num", + {"mac_rx_mac_pause_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_mac_pause_num)}, - {"mac_tx_control_pkt_num", + {"mac_tx_pause_xoff_time", HCLGE_MAC_STATS_MAX_NUM_V2, + HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pause_xoff_time)}, + {"mac_rx_pause_xoff_time", HCLGE_MAC_STATS_MAX_NUM_V2, + HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pause_xoff_time)}, + {"mac_tx_control_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_ctrl_pkt_num)}, - {"mac_rx_control_pkt_num", + {"mac_rx_control_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_ctrl_pkt_num)}, - {"mac_tx_pfc_pkt_num", + {"mac_tx_pfc_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pause_pkt_num)}, - {"mac_tx_pfc_pri0_pkt_num", + {"mac_tx_pfc_pri0_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri0_pkt_num)}, - {"mac_tx_pfc_pri1_pkt_num", + {"mac_tx_pfc_pri1_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri1_pkt_num)}, - {"mac_tx_pfc_pri2_pkt_num", + {"mac_tx_pfc_pri2_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri2_pkt_num)}, - {"mac_tx_pfc_pri3_pkt_num", + {"mac_tx_pfc_pri3_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri3_pkt_num)}, - {"mac_tx_pfc_pri4_pkt_num", + {"mac_tx_pfc_pri4_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri4_pkt_num)}, - {"mac_tx_pfc_pri5_pkt_num", + {"mac_tx_pfc_pri5_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri5_pkt_num)}, - {"mac_tx_pfc_pri6_pkt_num", + {"mac_tx_pfc_pri6_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri6_pkt_num)}, - {"mac_tx_pfc_pri7_pkt_num", + {"mac_tx_pfc_pri7_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri7_pkt_num)}, - {"mac_rx_pfc_pkt_num", + {"mac_tx_pfc_pri0_xoff_time", HCLGE_MAC_STATS_MAX_NUM_V2, + HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri0_xoff_time)}, + {"mac_tx_pfc_pri1_xoff_time", HCLGE_MAC_STATS_MAX_NUM_V2, + HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri1_xoff_time)}, + {"mac_tx_pfc_pri2_xoff_time", HCLGE_MAC_STATS_MAX_NUM_V2, + HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri2_xoff_time)}, + {"mac_tx_pfc_pri3_xoff_time", HCLGE_MAC_STATS_MAX_NUM_V2, + HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri3_xoff_time)}, + {"mac_tx_pfc_pri4_xoff_time", HCLGE_MAC_STATS_MAX_NUM_V2, + HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri4_xoff_time)}, + {"mac_tx_pfc_pri5_xoff_time", HCLGE_MAC_STATS_MAX_NUM_V2, + HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri5_xoff_time)}, + {"mac_tx_pfc_pri6_xoff_time", HCLGE_MAC_STATS_MAX_NUM_V2, + HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri6_xoff_time)}, + {"mac_tx_pfc_pri7_xoff_time", HCLGE_MAC_STATS_MAX_NUM_V2, + HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri7_xoff_time)}, + {"mac_rx_pfc_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pause_pkt_num)}, - {"mac_rx_pfc_pri0_pkt_num", + {"mac_rx_pfc_pri0_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri0_pkt_num)}, - {"mac_rx_pfc_pri1_pkt_num", + {"mac_rx_pfc_pri1_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri1_pkt_num)}, - {"mac_rx_pfc_pri2_pkt_num", + {"mac_rx_pfc_pri2_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri2_pkt_num)}, - {"mac_rx_pfc_pri3_pkt_num", + {"mac_rx_pfc_pri3_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri3_pkt_num)}, - {"mac_rx_pfc_pri4_pkt_num", + {"mac_rx_pfc_pri4_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri4_pkt_num)}, - {"mac_rx_pfc_pri5_pkt_num", + {"mac_rx_pfc_pri5_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri5_pkt_num)}, - {"mac_rx_pfc_pri6_pkt_num", + {"mac_rx_pfc_pri6_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri6_pkt_num)}, - {"mac_rx_pfc_pri7_pkt_num", + {"mac_rx_pfc_pri7_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri7_pkt_num)}, - {"mac_tx_total_pkt_num", + {"mac_rx_pfc_pri0_xoff_time", HCLGE_MAC_STATS_MAX_NUM_V2, + HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri0_xoff_time)}, + {"mac_rx_pfc_pri1_xoff_time", HCLGE_MAC_STATS_MAX_NUM_V2, + HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri1_xoff_time)}, + {"mac_rx_pfc_pri2_xoff_time", HCLGE_MAC_STATS_MAX_NUM_V2, + HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri2_xoff_time)}, + {"mac_rx_pfc_pri3_xoff_time", HCLGE_MAC_STATS_MAX_NUM_V2, + HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri3_xoff_time)}, + {"mac_rx_pfc_pri4_xoff_time", HCLGE_MAC_STATS_MAX_NUM_V2, + HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri4_xoff_time)}, + {"mac_rx_pfc_pri5_xoff_time", HCLGE_MAC_STATS_MAX_NUM_V2, + HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri5_xoff_time)}, + {"mac_rx_pfc_pri6_xoff_time", HCLGE_MAC_STATS_MAX_NUM_V2, + HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri6_xoff_time)}, + {"mac_rx_pfc_pri7_xoff_time", HCLGE_MAC_STATS_MAX_NUM_V2, + HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri7_xoff_time)}, + {"mac_tx_total_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_total_pkt_num)}, - {"mac_tx_total_oct_num", + {"mac_tx_total_oct_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_total_oct_num)}, - {"mac_tx_good_pkt_num", + {"mac_tx_good_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_good_pkt_num)}, - {"mac_tx_bad_pkt_num", + {"mac_tx_bad_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_bad_pkt_num)}, - {"mac_tx_good_oct_num", + {"mac_tx_good_oct_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_good_oct_num)}, - {"mac_tx_bad_oct_num", + {"mac_tx_bad_oct_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_bad_oct_num)}, - {"mac_tx_uni_pkt_num", + {"mac_tx_uni_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_uni_pkt_num)}, - {"mac_tx_multi_pkt_num", + {"mac_tx_multi_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_multi_pkt_num)}, - {"mac_tx_broad_pkt_num", + {"mac_tx_broad_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_broad_pkt_num)}, - {"mac_tx_undersize_pkt_num", + {"mac_tx_undersize_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_undersize_pkt_num)}, - {"mac_tx_oversize_pkt_num", + {"mac_tx_oversize_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_oversize_pkt_num)}, - {"mac_tx_64_oct_pkt_num", + {"mac_tx_64_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_64_oct_pkt_num)}, - {"mac_tx_65_127_oct_pkt_num", + {"mac_tx_65_127_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_65_127_oct_pkt_num)}, - {"mac_tx_128_255_oct_pkt_num", + {"mac_tx_128_255_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_128_255_oct_pkt_num)}, - {"mac_tx_256_511_oct_pkt_num", + {"mac_tx_256_511_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_256_511_oct_pkt_num)}, - {"mac_tx_512_1023_oct_pkt_num", + {"mac_tx_512_1023_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_512_1023_oct_pkt_num)}, - {"mac_tx_1024_1518_oct_pkt_num", + {"mac_tx_1024_1518_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_1024_1518_oct_pkt_num)}, - {"mac_tx_1519_2047_oct_pkt_num", + {"mac_tx_1519_2047_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_1519_2047_oct_pkt_num)}, - {"mac_tx_2048_4095_oct_pkt_num", + {"mac_tx_2048_4095_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_2048_4095_oct_pkt_num)}, - {"mac_tx_4096_8191_oct_pkt_num", + {"mac_tx_4096_8191_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_4096_8191_oct_pkt_num)}, - {"mac_tx_8192_9216_oct_pkt_num", + {"mac_tx_8192_9216_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_8192_9216_oct_pkt_num)}, - {"mac_tx_9217_12287_oct_pkt_num", + {"mac_tx_9217_12287_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_9217_12287_oct_pkt_num)}, - {"mac_tx_12288_16383_oct_pkt_num", + {"mac_tx_12288_16383_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_12288_16383_oct_pkt_num)}, - {"mac_tx_1519_max_good_pkt_num", + {"mac_tx_1519_max_good_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_1519_max_good_oct_pkt_num)}, - {"mac_tx_1519_max_bad_pkt_num", + {"mac_tx_1519_max_bad_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_1519_max_bad_oct_pkt_num)}, - {"mac_rx_total_pkt_num", + {"mac_rx_total_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_total_pkt_num)}, - {"mac_rx_total_oct_num", + {"mac_rx_total_oct_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_total_oct_num)}, - {"mac_rx_good_pkt_num", + {"mac_rx_good_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_good_pkt_num)}, - {"mac_rx_bad_pkt_num", + {"mac_rx_bad_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_bad_pkt_num)}, - {"mac_rx_good_oct_num", + {"mac_rx_good_oct_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_good_oct_num)}, - {"mac_rx_bad_oct_num", + {"mac_rx_bad_oct_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_bad_oct_num)}, - {"mac_rx_uni_pkt_num", + {"mac_rx_uni_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_uni_pkt_num)}, - {"mac_rx_multi_pkt_num", + {"mac_rx_multi_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_multi_pkt_num)}, - {"mac_rx_broad_pkt_num", + {"mac_rx_broad_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_broad_pkt_num)}, - {"mac_rx_undersize_pkt_num", + {"mac_rx_undersize_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_undersize_pkt_num)}, - {"mac_rx_oversize_pkt_num", + {"mac_rx_oversize_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_oversize_pkt_num)}, - {"mac_rx_64_oct_pkt_num", + {"mac_rx_64_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_64_oct_pkt_num)}, - {"mac_rx_65_127_oct_pkt_num", + {"mac_rx_65_127_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_65_127_oct_pkt_num)}, - {"mac_rx_128_255_oct_pkt_num", + {"mac_rx_128_255_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_128_255_oct_pkt_num)}, - {"mac_rx_256_511_oct_pkt_num", + {"mac_rx_256_511_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_256_511_oct_pkt_num)}, - {"mac_rx_512_1023_oct_pkt_num", + {"mac_rx_512_1023_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_512_1023_oct_pkt_num)}, - {"mac_rx_1024_1518_oct_pkt_num", + {"mac_rx_1024_1518_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_1024_1518_oct_pkt_num)}, - {"mac_rx_1519_2047_oct_pkt_num", + {"mac_rx_1519_2047_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_1519_2047_oct_pkt_num)}, - {"mac_rx_2048_4095_oct_pkt_num", + {"mac_rx_2048_4095_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_2048_4095_oct_pkt_num)}, - {"mac_rx_4096_8191_oct_pkt_num", + {"mac_rx_4096_8191_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_4096_8191_oct_pkt_num)}, - {"mac_rx_8192_9216_oct_pkt_num", + {"mac_rx_8192_9216_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_8192_9216_oct_pkt_num)}, - {"mac_rx_9217_12287_oct_pkt_num", + {"mac_rx_9217_12287_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_9217_12287_oct_pkt_num)}, - {"mac_rx_12288_16383_oct_pkt_num", + {"mac_rx_12288_16383_oct_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_12288_16383_oct_pkt_num)}, - {"mac_rx_1519_max_good_pkt_num", + {"mac_rx_1519_max_good_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_1519_max_good_oct_pkt_num)}, - {"mac_rx_1519_max_bad_pkt_num", + {"mac_rx_1519_max_bad_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_1519_max_bad_oct_pkt_num)}, - {"mac_tx_fragment_pkt_num", + {"mac_tx_fragment_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_fragment_pkt_num)}, - {"mac_tx_undermin_pkt_num", + {"mac_tx_undermin_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_undermin_pkt_num)}, - {"mac_tx_jabber_pkt_num", + {"mac_tx_jabber_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_jabber_pkt_num)}, - {"mac_tx_err_all_pkt_num", + {"mac_tx_err_all_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_err_all_pkt_num)}, - {"mac_tx_from_app_good_pkt_num", + {"mac_tx_from_app_good_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_from_app_good_pkt_num)}, - {"mac_tx_from_app_bad_pkt_num", + {"mac_tx_from_app_bad_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_tx_from_app_bad_pkt_num)}, - {"mac_rx_fragment_pkt_num", + {"mac_rx_fragment_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_fragment_pkt_num)}, - {"mac_rx_undermin_pkt_num", + {"mac_rx_undermin_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_undermin_pkt_num)}, - {"mac_rx_jabber_pkt_num", + {"mac_rx_jabber_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_jabber_pkt_num)}, - {"mac_rx_fcs_err_pkt_num", + {"mac_rx_fcs_err_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_fcs_err_pkt_num)}, - {"mac_rx_send_app_good_pkt_num", + {"mac_rx_send_app_good_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_send_app_good_pkt_num)}, - {"mac_rx_send_app_bad_pkt_num", + {"mac_rx_send_app_bad_pkt_num", HCLGE_MAC_STATS_MAX_NUM_V1, HCLGE_MAC_STATS_FIELD_OFF(mac_rx_send_app_bad_pkt_num)} }; @@ -451,8 +487,9 @@ static int hclge_mac_update_stats_defective(struct hclge_dev *hdev) u64 *data = (u64 *)(&hdev->mac_stats); struct hclge_desc desc[HCLGE_MAC_CMD_NUM]; __le64 *desc_data; - int i, k, n; + u32 data_size; int ret; + u32 i; hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_STATS_MAC, true); ret = hclge_cmd_send(&hdev->hw, desc, HCLGE_MAC_CMD_NUM); @@ -463,33 +500,37 @@ static int hclge_mac_update_stats_defective(struct hclge_dev *hdev) return ret; } - for (i = 0; i < HCLGE_MAC_CMD_NUM; i++) { - /* for special opcode 0032, only the first desc has the head */ - if (unlikely(i == 0)) { - desc_data = (__le64 *)(&desc[i].data[0]); - n = HCLGE_RD_FIRST_STATS_NUM; - } else { - desc_data = (__le64 *)(&desc[i]); - n = HCLGE_RD_OTHER_STATS_NUM; - } + /* The first desc has a 64-bit header, so data size need to minus 1 */ + data_size = sizeof(desc) / (sizeof(u64)) - 1; - for (k = 0; k < n; k++) { - *data += le64_to_cpu(*desc_data); - data++; - desc_data++; - } + desc_data = (__le64 *)(&desc[0].data[0]); + for (i = 0; i < data_size; i++) { + /* data memory is continuous becase only the first desc has a + * header in this command + */ + *data += le64_to_cpu(*desc_data); + data++; + desc_data++; } return 0; } -static int hclge_mac_update_stats_complete(struct hclge_dev *hdev, u32 desc_num) +static int hclge_mac_update_stats_complete(struct hclge_dev *hdev) { +#define HCLGE_REG_NUM_PER_DESC 4 + + u32 reg_num = hdev->ae_dev->dev_specs.mac_stats_num; u64 *data = (u64 *)(&hdev->mac_stats); struct hclge_desc *desc; __le64 *desc_data; - u16 i, k, n; + u32 data_size; + u32 desc_num; int ret; + u32 i; + + /* The first desc has a 64-bit header, so need to consider it */ + desc_num = reg_num / HCLGE_REG_NUM_PER_DESC + 1; /* This may be called inside atomic sections, * so GFP_ATOMIC is more suitalbe here @@ -505,21 +546,16 @@ static int hclge_mac_update_stats_complete(struct hclge_dev *hdev, u32 desc_num) return ret; } - for (i = 0; i < desc_num; i++) { - /* for special opcode 0034, only the first desc has the head */ - if (i == 0) { - desc_data = (__le64 *)(&desc[i].data[0]); - n = HCLGE_RD_FIRST_STATS_NUM; - } else { - desc_data = (__le64 *)(&desc[i]); - n = HCLGE_RD_OTHER_STATS_NUM; - } + data_size = min_t(u32, sizeof(hdev->mac_stats) / sizeof(u64), reg_num); - for (k = 0; k < n; k++) { - *data += le64_to_cpu(*desc_data); - data++; - desc_data++; - } + desc_data = (__le64 *)(&desc[0].data[0]); + for (i = 0; i < data_size; i++) { + /* data memory is continuous becase only the first desc has a + * header in this command + */ + *data += le64_to_cpu(*desc_data); + data++; + desc_data++; } kfree(desc); @@ -527,42 +563,37 @@ static int hclge_mac_update_stats_complete(struct hclge_dev *hdev, u32 desc_num) return 0; } -static int hclge_mac_query_reg_num(struct hclge_dev *hdev, u32 *desc_num) +static int hclge_mac_query_reg_num(struct hclge_dev *hdev, u32 *reg_num) { struct hclge_desc desc; - __le32 *desc_data; - u32 reg_num; int ret; hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_MAC_REG_NUM, true); ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to query mac statistic reg number, ret = %d\n", + ret); return ret; + } - desc_data = (__le32 *)(&desc.data[0]); - reg_num = le32_to_cpu(*desc_data); - - *desc_num = 1 + ((reg_num - 3) >> 2) + - (u32)(((reg_num - 3) & 0x3) ? 1 : 0); + *reg_num = le32_to_cpu(desc.data[0]); + if (*reg_num == 0) { + dev_err(&hdev->pdev->dev, + "mac statistic reg number is invalid!\n"); + return -ENODATA; + } return 0; } static int hclge_mac_update_stats(struct hclge_dev *hdev) { - u32 desc_num; - int ret; - - ret = hclge_mac_query_reg_num(hdev, &desc_num); /* The firmware supports the new statistics acquisition method */ - if (!ret) - ret = hclge_mac_update_stats_complete(hdev, desc_num); - else if (ret == -EOPNOTSUPP) - ret = hclge_mac_update_stats_defective(hdev); + if (hdev->ae_dev->dev_specs.mac_stats_num) + return hclge_mac_update_stats_complete(hdev); else - dev_err(&hdev->pdev->dev, "query mac reg num fail!\n"); - - return ret; + return hclge_mac_update_stats_defective(hdev); } static int hclge_tqps_update_stats(struct hnae3_handle *handle) @@ -670,20 +701,39 @@ static u8 *hclge_tqps_get_strings(struct hnae3_handle *handle, u8 *data) return buff; } -static u64 *hclge_comm_get_stats(const void *comm_stats, +static int hclge_comm_get_count(struct hclge_dev *hdev, + const struct hclge_comm_stats_str strs[], + u32 size) +{ + int count = 0; + u32 i; + + for (i = 0; i < size; i++) + if (strs[i].stats_num <= hdev->ae_dev->dev_specs.mac_stats_num) + count++; + + return count; +} + +static u64 *hclge_comm_get_stats(struct hclge_dev *hdev, const struct hclge_comm_stats_str strs[], int size, u64 *data) { u64 *buf = data; u32 i; - for (i = 0; i < size; i++) - buf[i] = HCLGE_STATS_READ(comm_stats, strs[i].offset); + for (i = 0; i < size; i++) { + if (strs[i].stats_num > hdev->ae_dev->dev_specs.mac_stats_num) + continue; - return buf + size; + *buf = HCLGE_STATS_READ(&hdev->mac_stats, strs[i].offset); + buf++; + } + + return buf; } -static u8 *hclge_comm_get_strings(u32 stringset, +static u8 *hclge_comm_get_strings(struct hclge_dev *hdev, u32 stringset, const struct hclge_comm_stats_str strs[], int size, u8 *data) { @@ -694,6 +744,9 @@ static u8 *hclge_comm_get_strings(u32 stringset, return buff; for (i = 0; i < size; i++) { + if (strs[i].stats_num > hdev->ae_dev->dev_specs.mac_stats_num) + continue; + snprintf(buff, ETH_GSTRING_LEN, "%s", strs[i].desc); buff = buff + ETH_GSTRING_LEN; } @@ -785,7 +838,8 @@ static int hclge_get_sset_count(struct hnae3_handle *handle, int stringset) handle->flags |= HNAE3_SUPPORT_PHY_LOOPBACK; } } else if (stringset == ETH_SS_STATS) { - count = ARRAY_SIZE(g_mac_stats_string) + + count = hclge_comm_get_count(hdev, g_mac_stats_string, + ARRAY_SIZE(g_mac_stats_string)) + hclge_tqps_get_sset_count(handle, stringset); } @@ -795,12 +849,14 @@ static int hclge_get_sset_count(struct hnae3_handle *handle, int stringset) static void hclge_get_strings(struct hnae3_handle *handle, u32 stringset, u8 *data) { + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; u8 *p = (char *)data; int size; if (stringset == ETH_SS_STATS) { size = ARRAY_SIZE(g_mac_stats_string); - p = hclge_comm_get_strings(stringset, g_mac_stats_string, + p = hclge_comm_get_strings(hdev, stringset, g_mac_stats_string, size, p); p = hclge_tqps_get_strings(handle, p); } else if (stringset == ETH_SS_TEST) { @@ -834,7 +890,7 @@ static void hclge_get_stats(struct hnae3_handle *handle, u64 *data) struct hclge_dev *hdev = vport->back; u64 *p; - p = hclge_comm_get_stats(&hdev->mac_stats, g_mac_stats_string, + p = hclge_comm_get_stats(hdev, g_mac_stats_string, ARRAY_SIZE(g_mac_stats_string), data); p = hclge_tqps_get_stats(handle, p); } @@ -1037,96 +1093,100 @@ static int hclge_check_port_speed(struct hnae3_handle *handle, u32 speed) return -EINVAL; } -static void hclge_convert_setting_sr(struct hclge_mac *mac, u16 speed_ability) +static void hclge_convert_setting_sr(u16 speed_ability, + unsigned long *link_mode) { if (speed_ability & HCLGE_SUPPORT_10G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, - mac->supported); + link_mode); if (speed_ability & HCLGE_SUPPORT_25G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, - mac->supported); + link_mode); if (speed_ability & HCLGE_SUPPORT_40G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, - mac->supported); + link_mode); if (speed_ability & HCLGE_SUPPORT_50G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, - mac->supported); + link_mode); if (speed_ability & HCLGE_SUPPORT_100G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, - mac->supported); + link_mode); if (speed_ability & HCLGE_SUPPORT_200G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT, - mac->supported); + link_mode); } -static void hclge_convert_setting_lr(struct hclge_mac *mac, u16 speed_ability) +static void hclge_convert_setting_lr(u16 speed_ability, + unsigned long *link_mode) { if (speed_ability & HCLGE_SUPPORT_10G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, - mac->supported); + link_mode); if (speed_ability & HCLGE_SUPPORT_25G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, - mac->supported); + link_mode); if (speed_ability & HCLGE_SUPPORT_50G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, - mac->supported); + link_mode); if (speed_ability & HCLGE_SUPPORT_40G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, - mac->supported); + link_mode); if (speed_ability & HCLGE_SUPPORT_100G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT, - mac->supported); + link_mode); if (speed_ability & HCLGE_SUPPORT_200G_BIT) linkmode_set_bit( ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT, - mac->supported); + link_mode); } -static void hclge_convert_setting_cr(struct hclge_mac *mac, u16 speed_ability) +static void hclge_convert_setting_cr(u16 speed_ability, + unsigned long *link_mode) { if (speed_ability & HCLGE_SUPPORT_10G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, - mac->supported); + link_mode); if (speed_ability & HCLGE_SUPPORT_25G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, - mac->supported); + link_mode); if (speed_ability & HCLGE_SUPPORT_40G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, - mac->supported); + link_mode); if (speed_ability & HCLGE_SUPPORT_50G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, - mac->supported); + link_mode); if (speed_ability & HCLGE_SUPPORT_100G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, - mac->supported); + link_mode); if (speed_ability & HCLGE_SUPPORT_200G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT, - mac->supported); + link_mode); } -static void hclge_convert_setting_kr(struct hclge_mac *mac, u16 speed_ability) +static void hclge_convert_setting_kr(u16 speed_ability, + unsigned long *link_mode) { if (speed_ability & HCLGE_SUPPORT_1G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, - mac->supported); + link_mode); if (speed_ability & HCLGE_SUPPORT_10G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, - mac->supported); + link_mode); if (speed_ability & HCLGE_SUPPORT_25G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, - mac->supported); + link_mode); if (speed_ability & HCLGE_SUPPORT_40G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, - mac->supported); + link_mode); if (speed_ability & HCLGE_SUPPORT_50G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT, - mac->supported); + link_mode); if (speed_ability & HCLGE_SUPPORT_100G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, - mac->supported); + link_mode); if (speed_ability & HCLGE_SUPPORT_200G_BIT) linkmode_set_bit(ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT, - mac->supported); + link_mode); } static void hclge_convert_setting_fec(struct hclge_mac *mac) @@ -1170,9 +1230,9 @@ static void hclge_parse_fiber_link_mode(struct hclge_dev *hdev, linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, mac->supported); - hclge_convert_setting_sr(mac, speed_ability); - hclge_convert_setting_lr(mac, speed_ability); - hclge_convert_setting_cr(mac, speed_ability); + hclge_convert_setting_sr(speed_ability, mac->supported); + hclge_convert_setting_lr(speed_ability, mac->supported); + hclge_convert_setting_cr(speed_ability, mac->supported); if (hnae3_dev_fec_supported(hdev)) hclge_convert_setting_fec(mac); @@ -1188,7 +1248,7 @@ static void hclge_parse_backplane_link_mode(struct hclge_dev *hdev, { struct hclge_mac *mac = &hdev->hw.mac; - hclge_convert_setting_kr(mac, speed_ability); + hclge_convert_setting_kr(speed_ability, mac->supported); if (hnae3_dev_fec_supported(hdev)) hclge_convert_setting_fec(mac); @@ -1465,12 +1525,29 @@ static void hclge_check_dev_specs(struct hclge_dev *hdev) dev_specs->umv_size = HCLGE_DEFAULT_UMV_SPACE_PER_PF; } +static int hclge_query_mac_stats_num(struct hclge_dev *hdev) +{ + u32 reg_num = 0; + int ret; + + ret = hclge_mac_query_reg_num(hdev, ®_num); + if (ret && ret != -EOPNOTSUPP) + return ret; + + hdev->ae_dev->dev_specs.mac_stats_num = reg_num; + return 0; +} + static int hclge_query_dev_specs(struct hclge_dev *hdev) { struct hclge_desc desc[HCLGE_QUERY_DEV_SPECS_BD_NUM]; int ret; int i; + ret = hclge_query_mac_stats_num(hdev); + if (ret) + return ret; + /* set default specifications as devices lower than version V3 do not * support querying specifications from firmware. */ @@ -2974,6 +3051,82 @@ static void hclge_update_link_status(struct hclge_dev *hdev) clear_bit(HCLGE_STATE_LINK_UPDATING, &hdev->state); } +static void hclge_update_speed_advertising(struct hclge_mac *mac) +{ + u32 speed_ability; + + if (hclge_get_speed_bit(mac->speed, &speed_ability)) + return; + + switch (mac->module_type) { + case HNAE3_MODULE_TYPE_FIBRE_LR: + hclge_convert_setting_lr(speed_ability, mac->advertising); + break; + case HNAE3_MODULE_TYPE_FIBRE_SR: + case HNAE3_MODULE_TYPE_AOC: + hclge_convert_setting_sr(speed_ability, mac->advertising); + break; + case HNAE3_MODULE_TYPE_CR: + hclge_convert_setting_cr(speed_ability, mac->advertising); + break; + case HNAE3_MODULE_TYPE_KR: + hclge_convert_setting_kr(speed_ability, mac->advertising); + break; + default: + break; + } +} + +static void hclge_update_fec_advertising(struct hclge_mac *mac) +{ + if (mac->fec_mode & BIT(HNAE3_FEC_RS)) + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_RS_BIT, + mac->advertising); + else if (mac->fec_mode & BIT(HNAE3_FEC_BASER)) + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_BASER_BIT, + mac->advertising); + else + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_NONE_BIT, + mac->advertising); +} + +static void hclge_update_pause_advertising(struct hclge_dev *hdev) +{ + struct hclge_mac *mac = &hdev->hw.mac; + bool rx_en, tx_en; + + switch (hdev->fc_mode_last_time) { + case HCLGE_FC_RX_PAUSE: + rx_en = true; + tx_en = false; + break; + case HCLGE_FC_TX_PAUSE: + rx_en = false; + tx_en = true; + break; + case HCLGE_FC_FULL: + rx_en = true; + tx_en = true; + break; + default: + rx_en = false; + tx_en = false; + break; + } + + linkmode_set_pause(mac->advertising, tx_en, rx_en); +} + +static void hclge_update_advertising(struct hclge_dev *hdev) +{ + struct hclge_mac *mac = &hdev->hw.mac; + + linkmode_zero(mac->advertising); + hclge_update_speed_advertising(mac); + hclge_update_fec_advertising(mac); + hclge_update_pause_advertising(hdev); +} + static void hclge_update_port_capability(struct hclge_dev *hdev, struct hclge_mac *mac) { @@ -2996,7 +3149,7 @@ static void hclge_update_port_capability(struct hclge_dev *hdev, } else { linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, mac->supported); - linkmode_zero(mac->advertising); + hclge_update_advertising(hdev); } } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index ca25e2edf3f0..4f8403af84be 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -403,8 +403,13 @@ struct hclge_tm_info { u8 pfc_en; /* PFC enabled or not for user priority */ }; +/* max number of mac statistics on each version */ +#define HCLGE_MAC_STATS_MAX_NUM_V1 84 +#define HCLGE_MAC_STATS_MAX_NUM_V2 105 + struct hclge_comm_stats_str { char desc[ETH_GSTRING_LEN]; + u32 stats_num; unsigned long offset; }; @@ -412,6 +417,7 @@ struct hclge_comm_stats_str { struct hclge_mac_stats { u64 mac_tx_mac_pause_num; u64 mac_rx_mac_pause_num; + u64 rsv0; u64 mac_tx_pfc_pri0_pkt_num; u64 mac_tx_pfc_pri1_pkt_num; u64 mac_tx_pfc_pri2_pkt_num; @@ -448,7 +454,7 @@ struct hclge_mac_stats { u64 mac_tx_1519_2047_oct_pkt_num; u64 mac_tx_2048_4095_oct_pkt_num; u64 mac_tx_4096_8191_oct_pkt_num; - u64 rsv0; + u64 rsv1; u64 mac_tx_8192_9216_oct_pkt_num; u64 mac_tx_9217_12287_oct_pkt_num; u64 mac_tx_12288_16383_oct_pkt_num; @@ -475,7 +481,7 @@ struct hclge_mac_stats { u64 mac_rx_1519_2047_oct_pkt_num; u64 mac_rx_2048_4095_oct_pkt_num; u64 mac_rx_4096_8191_oct_pkt_num; - u64 rsv1; + u64 rsv2; u64 mac_rx_8192_9216_oct_pkt_num; u64 mac_rx_9217_12287_oct_pkt_num; u64 mac_rx_12288_16383_oct_pkt_num; @@ -498,6 +504,28 @@ struct hclge_mac_stats { u64 mac_rx_pfc_pause_pkt_num; u64 mac_tx_ctrl_pkt_num; u64 mac_rx_ctrl_pkt_num; + + /* duration of pfc */ + u64 mac_tx_pfc_pri0_xoff_time; + u64 mac_tx_pfc_pri1_xoff_time; + u64 mac_tx_pfc_pri2_xoff_time; + u64 mac_tx_pfc_pri3_xoff_time; + u64 mac_tx_pfc_pri4_xoff_time; + u64 mac_tx_pfc_pri5_xoff_time; + u64 mac_tx_pfc_pri6_xoff_time; + u64 mac_tx_pfc_pri7_xoff_time; + u64 mac_rx_pfc_pri0_xoff_time; + u64 mac_rx_pfc_pri1_xoff_time; + u64 mac_rx_pfc_pri2_xoff_time; + u64 mac_rx_pfc_pri3_xoff_time; + u64 mac_rx_pfc_pri4_xoff_time; + u64 mac_rx_pfc_pri5_xoff_time; + u64 mac_rx_pfc_pri6_xoff_time; + u64 mac_rx_pfc_pri7_xoff_time; + + /* duration of pause */ + u64 mac_tx_pause_xoff_time; + u64 mac_rx_pause_xoff_time; }; #define HCLGE_STATS_TIMER_INTERVAL 300UL diff --git a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c index b431c300ef1b..a85667078b72 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c @@ -322,12 +322,10 @@ static int hinic_get_link_ksettings(struct net_device *netdev, } } - bitmap_copy(link_ksettings->link_modes.supported, - (unsigned long *)&settings.supported, - __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_copy(link_ksettings->link_modes.advertising, - (unsigned long *)&settings.advertising, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_copy(link_ksettings->link_modes.supported, + (unsigned long *)&settings.supported); + linkmode_copy(link_ksettings->link_modes.advertising, + (unsigned long *)&settings.advertising); return 0; } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index beda8e0ef7d4..8362822316a9 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -467,9 +467,8 @@ static int ixgbe_set_link_ksettings(struct net_device *netdev, * this function does not support duplex forcing, but can * limit the advertising of the adapter to the specified speed */ - if (!bitmap_subset(cmd->link_modes.advertising, - cmd->link_modes.supported, - __ETHTOOL_LINK_MODE_MASK_NBITS)) + if (!linkmode_subset(cmd->link_modes.advertising, + cmd->link_modes.supported)) return -EINVAL; /* only allow one speed at a time if no autoneg */ diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 98f276c617fb..b6c636592dfa 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -3834,14 +3834,14 @@ static void mvneta_validate(struct phylink_config *config, */ if (phy_interface_mode_is_8023z(state->interface)) { if (!phylink_test(state->advertising, Autoneg)) { - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); return; } } else if (state->interface != PHY_INTERFACE_MODE_NA && state->interface != PHY_INTERFACE_MODE_QSGMII && state->interface != PHY_INTERFACE_MODE_SGMII && !phy_interface_mode_is_rgmii(state->interface)) { - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); return; } @@ -3870,10 +3870,8 @@ static void mvneta_validate(struct phylink_config *config, phylink_set(mask, 100baseT_Full); } - bitmap_and(supported, supported, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_and(state->advertising, state->advertising, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); /* We can only operate at 2500BaseX or 1000BaseX. If requested * to advertise both, only report advertising at 2500BaseX. diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index ad3be55cce68..8ddf58f379ac 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -6338,15 +6338,14 @@ static void mvpp2_phylink_validate(struct phylink_config *config, goto empty_set; } - bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_and(state->advertising, state->advertising, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); phylink_helper_basex_speed(state); return; empty_set: - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); } static void mvpp2_xlg_config(struct mvpp2_port *port, unsigned int mode, diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc.h b/drivers/net/ethernet/marvell/octeontx2/af/npc.h index 6e1192f52608..3144d309783c 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/npc.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/npc.h @@ -25,10 +25,7 @@ enum npc_kpu_la_ltype { NPC_LT_LA_8023 = 1, NPC_LT_LA_ETHER, NPC_LT_LA_IH_NIX_ETHER, - NPC_LT_LA_IH_8_ETHER, - NPC_LT_LA_IH_4_ETHER, - NPC_LT_LA_IH_2_ETHER, - NPC_LT_LA_HIGIG2_ETHER, + NPC_LT_LA_HIGIG2_ETHER = 7, NPC_LT_LA_IH_NIX_HIGIG2_ETHER, NPC_LT_LA_CUSTOM_L2_90B_ETHER, NPC_LT_LA_CPT_HDR, @@ -554,7 +551,7 @@ struct npc_kpu_profile_fwdata { #define KPU_SIGN 0x00666f727075706b #define KPU_NAME_LEN 32 /** Maximum number of custom KPU entries supported by the built-in profile. */ -#define KPU_MAX_CST_ENT 2 +#define KPU_MAX_CST_ENT 6 /* KPU Profle Header */ __le64 signature; /* "kpuprof\0" (8 bytes/ASCII characters) */ u8 name[KPU_NAME_LEN]; /* KPU Profile name */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h b/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h index 1a8c5376297c..0fe7ad35e36f 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h @@ -8,7 +8,7 @@ #ifndef NPC_PROFILE_H #define NPC_PROFILE_H -#define NPC_KPU_PROFILE_VER 0x0000000100060000 +#define NPC_KPU_PROFILE_VER 0x0000000100070000 #define NPC_KPU_VER_MAJ(ver) ((u16)(((ver) >> 32) & 0xFFFF)) #define NPC_KPU_VER_MIN(ver) ((u16)(((ver) >> 16) & 0xFFFF)) #define NPC_KPU_VER_PATCH(ver) ((u16)((ver) & 0xFFFF)) @@ -184,7 +184,6 @@ enum npc_kpu_parser_state { NPC_S_KPU2_SBTAG, NPC_S_KPU2_QINQ, NPC_S_KPU2_ETAG, - NPC_S_KPU2_PREHEADER, NPC_S_KPU2_EXDSA, NPC_S_KPU2_NGIO, NPC_S_KPU2_CPT_CTAG, @@ -1010,7 +1009,7 @@ static struct npc_kpu_profile_action ikpu_action_entries[] = { NPC_S_KPU1_CPT_HDR, 40, 0, NPC_LID_LA, NPC_LT_NA, 0, - 7, 7, 0, 0, + 0, 7, 0, 0, }, { @@ -1063,6 +1062,10 @@ static struct npc_kpu_profile_action ikpu_action_entries[] = { static struct npc_kpu_profile_cam kpu1_cam_entries[] = { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, { NPC_S_KPU1_ETHER, 0xff, NPC_ETYPE_IP, @@ -1380,33 +1383,6 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = { }, { NPC_S_KPU1_IH, 0xff, - NPC_IH_W | NPC_IH_UTAG, - NPC_IH_W | NPC_IH_UTAG, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - }, - { - NPC_S_KPU1_IH, 0xff, - NPC_IH_W, - NPC_IH_W | NPC_IH_UTAG, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - }, - { - NPC_S_KPU1_IH, 0xff, - 0x0000, - NPC_IH_W | NPC_IH_UTAG, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - }, - { - NPC_S_KPU1_IH, 0xff, 0x0000, 0x0000, 0x0000, @@ -1905,6 +1881,10 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = { static struct npc_kpu_profile_cam kpu2_cam_entries[] = { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, { NPC_S_KPU2_CTAG, 0xff, NPC_ETYPE_IP, @@ -2626,114 +2606,6 @@ static struct npc_kpu_profile_cam kpu2_cam_entries[] = { 0x0000, }, { - NPC_S_KPU2_PREHEADER, 0xff, - NPC_ETYPE_IP, - 0xffff, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - }, - { - NPC_S_KPU2_PREHEADER, 0xff, - NPC_ETYPE_IP6, - 0xffff, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - }, - { - NPC_S_KPU2_PREHEADER, 0xff, - NPC_ETYPE_ARP, - 0xffff, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - }, - { - NPC_S_KPU2_PREHEADER, 0xff, - NPC_ETYPE_RARP, - 0xffff, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - }, - { - NPC_S_KPU2_PREHEADER, 0xff, - NPC_ETYPE_PTP, - 0xffff, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - }, - { - NPC_S_KPU2_PREHEADER, 0xff, - NPC_ETYPE_FCOE, - 0xffff, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - }, - { - NPC_S_KPU2_PREHEADER, 0xff, - NPC_ETYPE_CTAG, - 0xffff, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - }, - { - NPC_S_KPU2_PREHEADER, 0xff, - NPC_ETYPE_SBTAG, - 0xffff, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - }, - { - NPC_S_KPU2_PREHEADER, 0xff, - NPC_ETYPE_QINQ, - 0xffff, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - }, - { - NPC_S_KPU2_PREHEADER, 0xff, - NPC_ETYPE_MPLSU, - 0xffff, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - }, - { - NPC_S_KPU2_PREHEADER, 0xff, - NPC_ETYPE_MPLSM, - 0xffff, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - }, - { - NPC_S_KPU2_PREHEADER, 0xff, - NPC_ETYPE_NSH, - 0xffff, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - }, - { NPC_S_KPU2_EXDSA, 0xff, NPC_DSA_EDSA, NPC_DSA_EDSA, @@ -2936,6 +2808,10 @@ static struct npc_kpu_profile_cam kpu2_cam_entries[] = { static struct npc_kpu_profile_cam kpu3_cam_entries[] = { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, { NPC_S_KPU3_CTAG, 0xff, NPC_ETYPE_IP, @@ -3913,6 +3789,10 @@ static struct npc_kpu_profile_cam kpu3_cam_entries[] = { static struct npc_kpu_profile_cam kpu4_cam_entries[] = { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, { NPC_S_KPU4_MPLS, 0xff, NPC_MPLS_S, @@ -4224,6 +4104,10 @@ static struct npc_kpu_profile_cam kpu4_cam_entries[] = { static struct npc_kpu_profile_cam kpu5_cam_entries[] = { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, { NPC_S_KPU5_IP, 0xff, 0x0000, @@ -5219,6 +5103,10 @@ static struct npc_kpu_profile_cam kpu5_cam_entries[] = { static struct npc_kpu_profile_cam kpu6_cam_entries[] = { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, { NPC_S_KPU6_IP6_EXT, 0xff, 0x0000, @@ -5890,6 +5778,10 @@ static struct npc_kpu_profile_cam kpu6_cam_entries[] = { static struct npc_kpu_profile_cam kpu7_cam_entries[] = { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, { NPC_S_KPU7_IP6_EXT, 0xff, 0x0000, @@ -6210,6 +6102,10 @@ static struct npc_kpu_profile_cam kpu7_cam_entries[] = { static struct npc_kpu_profile_cam kpu8_cam_entries[] = { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, { NPC_S_KPU8_TCP, 0xff, 0x0000, @@ -6953,6 +6849,10 @@ static struct npc_kpu_profile_cam kpu8_cam_entries[] = { static struct npc_kpu_profile_cam kpu9_cam_entries[] = { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, { NPC_S_KPU9_TU_MPLS_IN_GRE, 0xff, NPC_MPLS_S, @@ -7417,6 +7317,10 @@ static struct npc_kpu_profile_cam kpu9_cam_entries[] = { static struct npc_kpu_profile_cam kpu10_cam_entries[] = { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, { NPC_S_KPU10_TU_MPLS, 0xff, NPC_MPLS_S, @@ -7584,6 +7488,10 @@ static struct npc_kpu_profile_cam kpu10_cam_entries[] = { static struct npc_kpu_profile_cam kpu11_cam_entries[] = { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, { NPC_S_KPU11_TU_ETHER, 0xff, NPC_ETYPE_IP, @@ -7895,6 +7803,10 @@ static struct npc_kpu_profile_cam kpu11_cam_entries[] = { static struct npc_kpu_profile_cam kpu12_cam_entries[] = { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, { NPC_S_KPU12_TU_IP, 0xff, NPC_IPNH_TCP, @@ -8152,6 +8064,10 @@ static struct npc_kpu_profile_cam kpu12_cam_entries[] = { static struct npc_kpu_profile_cam kpu13_cam_entries[] = { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, { NPC_S_KPU13_TU_IP6_EXT, 0xff, 0x0000, @@ -8166,6 +8082,10 @@ static struct npc_kpu_profile_cam kpu13_cam_entries[] = { static struct npc_kpu_profile_cam kpu14_cam_entries[] = { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, { NPC_S_KPU14_TU_IP6_EXT, 0xff, 0x0000, @@ -8180,6 +8100,10 @@ static struct npc_kpu_profile_cam kpu14_cam_entries[] = { static struct npc_kpu_profile_cam kpu15_cam_entries[] = { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, { NPC_S_KPU15_TU_TCP, 0xff, 0x0000, @@ -8383,6 +8307,10 @@ static struct npc_kpu_profile_cam kpu15_cam_entries[] = { static struct npc_kpu_profile_cam kpu16_cam_entries[] = { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, + NPC_KPU_NOP_CAM, { NPC_S_KPU16_TCP_DATA, 0xff, 0x0000, @@ -8442,6 +8370,10 @@ static struct npc_kpu_profile_cam kpu16_cam_entries[] = { static struct npc_kpu_profile_action kpu1_action_entries[] = { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, { NPC_ERRLEV_RE, NPC_EC_NOERR, 8, 0, 6, 3, 0, @@ -8728,30 +8660,6 @@ static struct npc_kpu_profile_action kpu1_action_entries[] = { 0, 0, 0, 0, }, { - NPC_ERRLEV_RE, NPC_EC_NOERR, - 12, 14, 16, 0, 0, - NPC_S_KPU2_PREHEADER, 8, 1, - NPC_LID_LA, NPC_LT_LA_IH_8_ETHER, - 0, - 1, 0xff, 0, 0, - }, - { - NPC_ERRLEV_RE, NPC_EC_NOERR, - 12, 14, 16, 0, 0, - NPC_S_KPU2_PREHEADER, 4, 1, - NPC_LID_LA, NPC_LT_LA_IH_4_ETHER, - 0, - 1, 0xff, 0, 0, - }, - { - NPC_ERRLEV_RE, NPC_EC_NOERR, - 12, 14, 16, 0, 0, - NPC_S_KPU2_PREHEADER, 2, 1, - NPC_LID_LA, NPC_LT_LA_IH_2_ETHER, - 0, - 1, 0xff, 0, 0, - }, - { NPC_ERRLEV_LA, NPC_EC_IH_LENGTH, 0, 0, 0, 0, 1, NPC_S_NA, 0, 1, @@ -9210,6 +9118,10 @@ static struct npc_kpu_profile_action kpu1_action_entries[] = { static struct npc_kpu_profile_action kpu2_action_entries[] = { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, { NPC_ERRLEV_RE, NPC_EC_NOERR, 8, 0, 6, 2, 0, @@ -9853,102 +9765,6 @@ static struct npc_kpu_profile_action kpu2_action_entries[] = { { NPC_ERRLEV_RE, NPC_EC_NOERR, 8, 0, 6, 2, 0, - NPC_S_KPU5_IP, 14, 0, - NPC_LID_LB, NPC_LT_NA, - 0, - 0, 0, 0, 0, - }, - { - NPC_ERRLEV_RE, NPC_EC_NOERR, - 6, 0, 0, 2, 0, - NPC_S_KPU5_IP6, 14, 0, - NPC_LID_LB, NPC_LT_NA, - 0, - 0, 0, 0, 0, - }, - { - NPC_ERRLEV_RE, NPC_EC_NOERR, - 0, 0, 0, 2, 0, - NPC_S_KPU5_ARP, 14, 0, - NPC_LID_LB, NPC_LT_NA, - 0, - 0, 0, 0, 0, - }, - { - NPC_ERRLEV_RE, NPC_EC_NOERR, - 0, 0, 0, 2, 0, - NPC_S_KPU5_RARP, 14, 0, - NPC_LID_LB, NPC_LT_NA, - 0, - 0, 0, 0, 0, - }, - { - NPC_ERRLEV_RE, NPC_EC_NOERR, - 0, 0, 0, 2, 0, - NPC_S_KPU5_PTP, 14, 0, - NPC_LID_LB, NPC_LT_NA, - 0, - 0, 0, 0, 0, - }, - { - NPC_ERRLEV_RE, NPC_EC_NOERR, - 0, 0, 0, 2, 0, - NPC_S_KPU5_FCOE, 14, 0, - NPC_LID_LB, NPC_LT_NA, - 0, - 0, 0, 0, 0, - }, - { - NPC_ERRLEV_RE, NPC_EC_NOERR, - 2, 6, 0, 0, 0, - NPC_S_KPU3_CTAG_C, 14, 0, - NPC_LID_LB, NPC_LT_NA, - 0, - 0, 0, 0, 0, - }, - { - NPC_ERRLEV_RE, NPC_EC_NOERR, - 2, 6, 20, 0, 0, - NPC_S_KPU3_STAG_C, 14, 0, - NPC_LID_LB, NPC_LT_NA, - 0, - 0, 0, 0, 0, - }, - { - NPC_ERRLEV_RE, NPC_EC_NOERR, - 2, 6, 0, 0, 0, - NPC_S_KPU3_QINQ_C, 14, 0, - NPC_LID_LB, NPC_LT_NA, - 0, - 0, 0, 0, 0, - }, - { - NPC_ERRLEV_RE, NPC_EC_NOERR, - 2, 6, 10, 1, 0, - NPC_S_KPU4_MPLS, 14, 0, - NPC_LID_LB, NPC_LT_NA, - 0, - 0, 0, 0, 0, - }, - { - NPC_ERRLEV_RE, NPC_EC_NOERR, - 2, 6, 10, 1, 0, - NPC_S_KPU4_MPLS, 14, 0, - NPC_LID_LB, NPC_LT_NA, - 0, - 0, 0, 0, 0, - }, - { - NPC_ERRLEV_RE, NPC_EC_NOERR, - 2, 0, 0, 1, 0, - NPC_S_KPU4_NSH, 14, 0, - NPC_LID_LB, NPC_LT_NA, - 0, - 0, 0, 0, 0, - }, - { - NPC_ERRLEV_RE, NPC_EC_NOERR, - 8, 0, 6, 2, 0, NPC_S_KPU5_IP, 18, 1, NPC_LID_LB, NPC_LT_LB_EDSA, NPC_F_LB_L_EDSA, @@ -10127,6 +9943,10 @@ static struct npc_kpu_profile_action kpu2_action_entries[] = { static struct npc_kpu_profile_action kpu3_action_entries[] = { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, { NPC_ERRLEV_RE, NPC_EC_NOERR, 8, 0, 6, 1, 0, @@ -10996,6 +10816,10 @@ static struct npc_kpu_profile_action kpu3_action_entries[] = { static struct npc_kpu_profile_action kpu4_action_entries[] = { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, { NPC_ERRLEV_RE, NPC_EC_NOERR, 0, 0, 0, 0, 0, @@ -11273,6 +11097,10 @@ static struct npc_kpu_profile_action kpu4_action_entries[] = { static struct npc_kpu_profile_action kpu5_action_entries[] = { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, { NPC_ERRLEV_LC, NPC_EC_IP_TTL_0, 0, 0, 0, 0, 1, @@ -12158,6 +11986,10 @@ static struct npc_kpu_profile_action kpu5_action_entries[] = { static struct npc_kpu_profile_action kpu6_action_entries[] = { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, { NPC_ERRLEV_RE, NPC_EC_NOERR, 0, 0, 0, 0, 1, @@ -12755,6 +12587,10 @@ static struct npc_kpu_profile_action kpu6_action_entries[] = { static struct npc_kpu_profile_action kpu7_action_entries[] = { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, { NPC_ERRLEV_RE, NPC_EC_NOERR, 0, 0, 0, 0, 1, @@ -13040,6 +12876,10 @@ static struct npc_kpu_profile_action kpu7_action_entries[] = { static struct npc_kpu_profile_action kpu8_action_entries[] = { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, { NPC_ERRLEV_LD, NPC_EC_TCP_FLAGS_FIN_ONLY, 0, 0, 0, 0, 1, @@ -13701,6 +13541,10 @@ static struct npc_kpu_profile_action kpu8_action_entries[] = { static struct npc_kpu_profile_action kpu9_action_entries[] = { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, { NPC_ERRLEV_RE, NPC_EC_NOERR, 0, 0, 0, 0, 0, @@ -14114,6 +13958,10 @@ static struct npc_kpu_profile_action kpu9_action_entries[] = { static struct npc_kpu_profile_action kpu10_action_entries[] = { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, { NPC_ERRLEV_RE, NPC_EC_NOERR, 8, 0, 6, 1, 0, @@ -14263,6 +14111,10 @@ static struct npc_kpu_profile_action kpu10_action_entries[] = { static struct npc_kpu_profile_action kpu11_action_entries[] = { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, { NPC_ERRLEV_RE, NPC_EC_NOERR, 8, 0, 6, 0, 0, @@ -14540,6 +14392,10 @@ static struct npc_kpu_profile_action kpu11_action_entries[] = { static struct npc_kpu_profile_action kpu12_action_entries[] = { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, { NPC_ERRLEV_RE, NPC_EC_NOERR, 2, 12, 0, 2, 0, @@ -14769,6 +14625,10 @@ static struct npc_kpu_profile_action kpu12_action_entries[] = { static struct npc_kpu_profile_action kpu13_action_entries[] = { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, { NPC_ERRLEV_RE, NPC_EC_NOERR, 0, 0, 0, 0, 1, @@ -14782,6 +14642,10 @@ static struct npc_kpu_profile_action kpu13_action_entries[] = { static struct npc_kpu_profile_action kpu14_action_entries[] = { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, { NPC_ERRLEV_RE, NPC_EC_NOERR, 0, 0, 0, 0, 1, @@ -14795,6 +14659,10 @@ static struct npc_kpu_profile_action kpu14_action_entries[] = { static struct npc_kpu_profile_action kpu15_action_entries[] = { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, { NPC_ERRLEV_LG, NPC_EC_TCP_FLAGS_FIN_ONLY, 0, 0, 0, 0, 1, @@ -14976,6 +14844,10 @@ static struct npc_kpu_profile_action kpu15_action_entries[] = { static struct npc_kpu_profile_action kpu16_action_entries[] = { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, + NPC_KPU_NOP_ACTION, { NPC_ERRLEV_RE, NPC_EC_NOERR, 0, 0, 0, 0, 1, diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c index b0f57bda7e27..80d4ce61f442 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c @@ -1175,9 +1175,8 @@ static int otx2_set_link_ksettings(struct net_device *netdev, otx2_get_link_ksettings(netdev, &cur_ks); /* Check requested modes against supported modes by hardware */ - if (!bitmap_subset(cmd->link_modes.advertising, - cur_ks.link_modes.supported, - __ETHTOOL_LINK_MODE_MASK_NBITS)) + if (!linkmode_subset(cmd->link_modes.advertising, + cur_ks.link_modes.supported)) return -EINVAL; mutex_lock(&mbox->lock); diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index 6c02e1740609..1d607bc6b59e 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -977,8 +977,7 @@ static int pxa168_init_phy(struct net_device *dev) cmd.base.phy_address = pep->phy_addr; cmd.base.speed = pep->phy_speed; cmd.base.duplex = pep->phy_duplex; - bitmap_copy(cmd.link_modes.advertising, PHY_BASIC_FEATURES, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_copy(cmd.link_modes.advertising, PHY_BASIC_FEATURES); cmd.base.autoneg = AUTONEG_ENABLE; if (cmd.base.speed != 0) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index 66c8ae29bc7a..066d79e4ecfc 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c @@ -39,6 +39,7 @@ #include <linux/in.h> #include <net/ip.h> #include <linux/bitmap.h> +#include <linux/mii.h> #include "mlx4_en.h" #include "en_port.h" @@ -651,10 +652,8 @@ static unsigned long *ptys2ethtool_link_mode(struct ptys2ethtool_config *cfg, unsigned int i; \ cfg = &ptys2ethtool_map[reg_]; \ cfg->speed = speed_; \ - bitmap_zero(cfg->supported, \ - __ETHTOOL_LINK_MODE_MASK_NBITS); \ - bitmap_zero(cfg->advertised, \ - __ETHTOOL_LINK_MODE_MASK_NBITS); \ + linkmode_zero(cfg->supported); \ + linkmode_zero(cfg->advertised); \ for (i = 0 ; i < ARRAY_SIZE(modes) ; ++i) { \ __set_bit(modes[i], cfg->supported); \ __set_bit(modes[i], cfg->advertised); \ @@ -710,10 +709,8 @@ static void ptys2ethtool_update_link_modes(unsigned long *link_modes, int i; for (i = 0; i < MLX4_LINK_MODES_SZ; i++) { if (eth_proto & MLX4_PROT_MASK(i)) - bitmap_or(link_modes, link_modes, - ptys2ethtool_link_mode(&ptys2ethtool_map[i], - report), - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_or(link_modes, link_modes, + ptys2ethtool_link_mode(&ptys2ethtool_map[i], report)); } } @@ -724,11 +721,9 @@ static u32 ethtool2ptys_link_modes(const unsigned long *link_modes, u32 ptys_modes = 0; for (i = 0; i < MLX4_LINK_MODES_SZ; i++) { - if (bitmap_intersects( - ptys2ethtool_link_mode(&ptys2ethtool_map[i], - report), - link_modes, - __ETHTOOL_LINK_MODE_MASK_NBITS)) + ulong *map_mode = ptys2ethtool_link_mode(&ptys2ethtool_map[i], + report); + if (linkmode_intersects(map_mode, link_modes)) ptys_modes |= 1 << i; } return ptys_modes; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.c index d1d7e4b9f7ad..1046b7ea5c88 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.c @@ -509,13 +509,6 @@ mlx5e_tc_sample_offload(struct mlx5e_tc_psample *tc_psample, if (IS_ERR_OR_NULL(tc_psample)) return ERR_PTR(-EOPNOTSUPP); - /* If slow path flag is set, eg. when the neigh is invalid for encap, - * don't offload sample action. - */ - esw = tc_psample->esw; - if (attr->flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH) - return mlx5_eswitch_add_offloaded_rule(esw, spec, attr); - sample_flow = kzalloc(sizeof(*sample_flow), GFP_KERNEL); if (!sample_flow) return ERR_PTR(-ENOMEM); @@ -527,6 +520,7 @@ mlx5e_tc_sample_offload(struct mlx5e_tc_psample *tc_psample, * Only match the fte id instead of the same match in the * original flow table. */ + esw = tc_psample->esw; if (MLX5_CAP_GEN(esw->dev, reg_c_preserve) || attr->action & MLX5_FLOW_CONTEXT_ACTION_DECAP) { struct mlx5_flow_table *ft; @@ -634,15 +628,6 @@ mlx5e_tc_sample_unoffload(struct mlx5e_tc_psample *tc_psample, if (IS_ERR_OR_NULL(tc_psample)) return; - /* If slow path flag is set, sample action is not offloaded. - * No need to delete sample rule. - */ - esw = tc_psample->esw; - if (attr->flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH) { - mlx5_eswitch_del_offloaded_rule(esw, rule, attr); - return; - } - /* The following delete order can't be changed, otherwise, * will hit fw syndromes. */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 0ff36c83714b..f3dec58026d9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -4432,13 +4432,17 @@ void mlx5e_build_nic_params(struct mlx5e_priv *priv, struct mlx5e_xsk *xsk, u16 static void mlx5e_set_netdev_dev_addr(struct net_device *netdev) { struct mlx5e_priv *priv = netdev_priv(netdev); + u8 addr[ETH_ALEN]; - mlx5_query_mac_address(priv->mdev, netdev->dev_addr); - if (is_zero_ether_addr(netdev->dev_addr) && + mlx5_query_mac_address(priv->mdev, addr); + if (is_zero_ether_addr(addr) && !MLX5_CAP_GEN(priv->mdev, vport_group_manager)) { eth_hw_addr_random(netdev); mlx5_core_info(priv->mdev, "Assigned random MAC address %pM\n", netdev->dev_addr); + return; } + + eth_hw_addr_set(netdev, addr); } static int mlx5e_vxlan_set_port(struct net_device *netdev, unsigned int table, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c index 588622ba38c1..f690f430f40f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c @@ -888,14 +888,20 @@ mlx5_esw_bridge_fdb_entry_cleanup(struct mlx5_esw_bridge_fdb_entry *entry, kvfree(entry); } +static void +mlx5_esw_bridge_fdb_entry_notify_and_cleanup(struct mlx5_esw_bridge_fdb_entry *entry, + struct mlx5_esw_bridge *bridge) +{ + mlx5_esw_bridge_fdb_del_notify(entry); + mlx5_esw_bridge_fdb_entry_cleanup(entry, bridge); +} + static void mlx5_esw_bridge_fdb_flush(struct mlx5_esw_bridge *bridge) { struct mlx5_esw_bridge_fdb_entry *entry, *tmp; - list_for_each_entry_safe(entry, tmp, &bridge->fdb_list, list) { - mlx5_esw_bridge_fdb_del_notify(entry); - mlx5_esw_bridge_fdb_entry_cleanup(entry, bridge); - } + list_for_each_entry_safe(entry, tmp, &bridge->fdb_list, list) + mlx5_esw_bridge_fdb_entry_notify_and_cleanup(entry, bridge); } static struct mlx5_esw_bridge_vlan * @@ -1065,10 +1071,8 @@ static void mlx5_esw_bridge_vlan_flush(struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw = bridge->br_offloads->esw; struct mlx5_esw_bridge_fdb_entry *entry, *tmp; - list_for_each_entry_safe(entry, tmp, &vlan->fdb_list, vlan_list) { - mlx5_esw_bridge_fdb_del_notify(entry); - mlx5_esw_bridge_fdb_entry_cleanup(entry, bridge); - } + list_for_each_entry_safe(entry, tmp, &vlan->fdb_list, vlan_list) + mlx5_esw_bridge_fdb_entry_notify_and_cleanup(entry, bridge); if (vlan->pkt_reformat_pop) mlx5_esw_bridge_vlan_pop_cleanup(vlan, esw); @@ -1128,6 +1132,17 @@ mlx5_esw_bridge_port_vlan_lookup(u16 vid, u16 vport_num, u16 esw_owner_vhca_id, } static struct mlx5_esw_bridge_fdb_entry * +mlx5_esw_bridge_fdb_lookup(struct mlx5_esw_bridge *bridge, + const unsigned char *addr, u16 vid) +{ + struct mlx5_esw_bridge_fdb_key key = {}; + + ether_addr_copy(key.addr, addr); + key.vid = vid; + return rhashtable_lookup_fast(&bridge->fdb_ht, &key, fdb_ht_params); +} + +static struct mlx5_esw_bridge_fdb_entry * mlx5_esw_bridge_fdb_entry_init(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id, const unsigned char *addr, u16 vid, bool added_by_user, bool peer, struct mlx5_eswitch *esw, struct mlx5_esw_bridge *bridge) @@ -1145,6 +1160,10 @@ mlx5_esw_bridge_fdb_entry_init(struct net_device *dev, u16 vport_num, u16 esw_ow return ERR_CAST(vlan); } + entry = mlx5_esw_bridge_fdb_lookup(bridge, addr, vid); + if (entry) + mlx5_esw_bridge_fdb_entry_notify_and_cleanup(entry, bridge); + entry = kvzalloc(sizeof(*entry), GFP_KERNEL); if (!entry) return ERR_PTR(-ENOMEM); @@ -1444,7 +1463,6 @@ void mlx5_esw_bridge_fdb_update_used(struct net_device *dev, u16 vport_num, u16 struct switchdev_notifier_fdb_info *fdb_info) { struct mlx5_esw_bridge_fdb_entry *entry; - struct mlx5_esw_bridge_fdb_key key; struct mlx5_esw_bridge_port *port; struct mlx5_esw_bridge *bridge; @@ -1453,13 +1471,11 @@ void mlx5_esw_bridge_fdb_update_used(struct net_device *dev, u16 vport_num, u16 return; bridge = port->bridge; - ether_addr_copy(key.addr, fdb_info->addr); - key.vid = fdb_info->vid; - entry = rhashtable_lookup_fast(&bridge->fdb_ht, &key, fdb_ht_params); + entry = mlx5_esw_bridge_fdb_lookup(bridge, fdb_info->addr, fdb_info->vid); if (!entry) { esw_debug(br_offloads->esw->dev, "FDB entry with specified key not found (MAC=%pM,vid=%u,vport=%u)\n", - key.addr, key.vid, vport_num); + fdb_info->addr, fdb_info->vid, vport_num); return; } @@ -1501,7 +1517,6 @@ void mlx5_esw_bridge_fdb_remove(struct net_device *dev, u16 vport_num, u16 esw_o { struct mlx5_eswitch *esw = br_offloads->esw; struct mlx5_esw_bridge_fdb_entry *entry; - struct mlx5_esw_bridge_fdb_key key; struct mlx5_esw_bridge_port *port; struct mlx5_esw_bridge *bridge; @@ -1510,18 +1525,15 @@ void mlx5_esw_bridge_fdb_remove(struct net_device *dev, u16 vport_num, u16 esw_o return; bridge = port->bridge; - ether_addr_copy(key.addr, fdb_info->addr); - key.vid = fdb_info->vid; - entry = rhashtable_lookup_fast(&bridge->fdb_ht, &key, fdb_ht_params); + entry = mlx5_esw_bridge_fdb_lookup(bridge, fdb_info->addr, fdb_info->vid); if (!entry) { esw_warn(esw->dev, "FDB entry with specified key not found (MAC=%pM,vid=%u,vport=%u)\n", - key.addr, key.vid, vport_num); + fdb_info->addr, fdb_info->vid, vport_num); return; } - mlx5_esw_bridge_fdb_del_notify(entry); - mlx5_esw_bridge_fdb_entry_cleanup(entry, bridge); + mlx5_esw_bridge_fdb_entry_notify_and_cleanup(entry, bridge); } void mlx5_esw_bridge_update(struct mlx5_esw_bridge_offloads *br_offloads) @@ -1537,13 +1549,11 @@ void mlx5_esw_bridge_update(struct mlx5_esw_bridge_offloads *br_offloads) if (entry->flags & MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER) continue; - if (time_after(lastuse, entry->lastuse)) { + if (time_after(lastuse, entry->lastuse)) mlx5_esw_bridge_fdb_entry_refresh(entry); - } else if (!(entry->flags & MLX5_ESW_BRIDGE_FLAG_PEER) && - time_is_before_jiffies(entry->lastuse + bridge->ageing_time)) { - mlx5_esw_bridge_fdb_del_notify(entry); - mlx5_esw_bridge_fdb_entry_cleanup(entry, bridge); - } + else if (!(entry->flags & MLX5_ESW_BRIDGE_FLAG_PEER) && + time_is_before_jiffies(entry->lastuse + bridge->ageing_time)) + mlx5_esw_bridge_fdb_entry_notify_and_cleanup(entry, bridge); } } } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c index f542a36be62c..60c9df1bc912 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c @@ -40,6 +40,7 @@ #define MLX5_FC_STATS_PERIOD msecs_to_jiffies(1000) /* Max number of counters to query in bulk read is 32K */ #define MLX5_SW_MAX_COUNTERS_BULK BIT(15) +#define MLX5_SF_NUM_COUNTERS_BULK 6 #define MLX5_FC_POOL_MAX_THRESHOLD BIT(18) #define MLX5_FC_POOL_USED_BUFF_RATIO 10 @@ -146,8 +147,12 @@ static void mlx5_fc_stats_remove(struct mlx5_core_dev *dev, static int get_max_bulk_query_len(struct mlx5_core_dev *dev) { - return min_t(int, MLX5_SW_MAX_COUNTERS_BULK, - (1 << MLX5_CAP_GEN(dev, log_max_flow_counter_bulk))); + int num_counters_bulk = mlx5_core_is_sf(dev) ? + MLX5_SF_NUM_COUNTERS_BULK : + MLX5_SW_MAX_COUNTERS_BULK; + + return min_t(int, num_counters_bulk, + (1 << MLX5_CAP_GEN(dev, log_max_flow_counter_bulk))); } static void update_counter_cache(int index, u32 *bulk_raw_data, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index 6a4dd7f78958..64f1abc4dc36 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -36,6 +36,7 @@ #include <linux/vmalloc.h> #include <linux/hardirq.h> #include <linux/mlx5/driver.h> +#include <linux/kern_levels.h> #include "mlx5_core.h" #include "lib/eq.h" #include "lib/mlx5.h" @@ -74,6 +75,11 @@ enum { MLX5_SENSOR_FW_SYND_RFR = 5, }; +enum { + MLX5_SEVERITY_MASK = 0x7, + MLX5_SEVERITY_VALID_MASK = 0x8, +}; + u8 mlx5_get_nic_state(struct mlx5_core_dev *dev) { return (ioread32be(&dev->iseg->cmdq_addr_l_sz) >> 8) & 7; @@ -98,12 +104,19 @@ static bool sensor_pci_not_working(struct mlx5_core_dev *dev) return (ioread32be(&h->fw_ver) == 0xffffffff); } +static int mlx5_health_get_rfr(u8 rfr_severity) +{ + return rfr_severity >> MLX5_RFR_BIT_OFFSET; +} + static bool sensor_fw_synd_rfr(struct mlx5_core_dev *dev) { struct mlx5_core_health *health = &dev->priv.health; struct health_buffer __iomem *h = health->health; - u32 rfr = ioread32be(&h->rfr) >> MLX5_RFR_OFFSET; u8 synd = ioread8(&h->synd); + u8 rfr; + + rfr = mlx5_health_get_rfr(ioread8(&h->rfr_severity)); if (rfr && synd) mlx5_core_dbg(dev, "FW requests reset, synd: %d\n", synd); @@ -366,35 +379,69 @@ static const char *hsynd_str(u8 synd) } } +static const char *mlx5_loglevel_str(int level) +{ + switch (level) { + case LOGLEVEL_EMERG: + return "EMERGENCY"; + case LOGLEVEL_ALERT: + return "ALERT"; + case LOGLEVEL_CRIT: + return "CRITICAL"; + case LOGLEVEL_ERR: + return "ERROR"; + case LOGLEVEL_WARNING: + return "WARNING"; + case LOGLEVEL_NOTICE: + return "NOTICE"; + case LOGLEVEL_INFO: + return "INFO"; + case LOGLEVEL_DEBUG: + return "DEBUG"; + } + return "Unknown log level"; +} + +static int mlx5_health_get_severity(u8 rfr_severity) +{ + return rfr_severity & MLX5_SEVERITY_VALID_MASK ? + rfr_severity & MLX5_SEVERITY_MASK : LOGLEVEL_ERR; +} + static void print_health_info(struct mlx5_core_dev *dev) { struct mlx5_core_health *health = &dev->priv.health; struct health_buffer __iomem *h = health->health; - char fw_str[18]; - u32 fw; + u8 rfr_severity; + int severity; int i; /* If the syndrome is 0, the device is OK and no need to print buffer */ if (!ioread8(&h->synd)) return; + rfr_severity = ioread8(&h->rfr_severity); + severity = mlx5_health_get_severity(rfr_severity); + mlx5_log(dev, severity, "Health issue observed, %s, severity(%d) %s:\n", + hsynd_str(ioread8(&h->synd)), severity, mlx5_loglevel_str(severity)); + for (i = 0; i < ARRAY_SIZE(h->assert_var); i++) - mlx5_core_err(dev, "assert_var[%d] 0x%08x\n", i, - ioread32be(h->assert_var + i)); - - mlx5_core_err(dev, "assert_exit_ptr 0x%08x\n", - ioread32be(&h->assert_exit_ptr)); - mlx5_core_err(dev, "assert_callra 0x%08x\n", - ioread32be(&h->assert_callra)); - sprintf(fw_str, "%d.%d.%d", fw_rev_maj(dev), fw_rev_min(dev), fw_rev_sub(dev)); - mlx5_core_err(dev, "fw_ver %s\n", fw_str); - mlx5_core_err(dev, "hw_id 0x%08x\n", ioread32be(&h->hw_id)); - mlx5_core_err(dev, "irisc_index %d\n", ioread8(&h->irisc_index)); - mlx5_core_err(dev, "synd 0x%x: %s\n", ioread8(&h->synd), - hsynd_str(ioread8(&h->synd))); - mlx5_core_err(dev, "ext_synd 0x%04x\n", ioread16be(&h->ext_synd)); - fw = ioread32be(&h->fw_ver); - mlx5_core_err(dev, "raw fw_ver 0x%08x\n", fw); + mlx5_log(dev, severity, "assert_var[%d] 0x%08x\n", i, + ioread32be(h->assert_var + i)); + + mlx5_log(dev, severity, "assert_exit_ptr 0x%08x\n", ioread32be(&h->assert_exit_ptr)); + mlx5_log(dev, severity, "assert_callra 0x%08x\n", ioread32be(&h->assert_callra)); + mlx5_log(dev, severity, "fw_ver %d.%d.%d", fw_rev_maj(dev), fw_rev_min(dev), + fw_rev_sub(dev)); + mlx5_log(dev, severity, "time %u\n", ioread32be(&h->time)); + mlx5_log(dev, severity, "hw_id 0x%08x\n", ioread32be(&h->hw_id)); + mlx5_log(dev, severity, "rfr %d\n", mlx5_health_get_rfr(rfr_severity)); + mlx5_log(dev, severity, "severity %d (%s)\n", severity, mlx5_loglevel_str(severity)); + mlx5_log(dev, severity, "irisc_index %d\n", ioread8(&h->irisc_index)); + mlx5_log(dev, severity, "synd 0x%x: %s\n", ioread8(&h->synd), + hsynd_str(ioread8(&h->synd))); + mlx5_log(dev, severity, "ext_synd 0x%04x\n", ioread16be(&h->ext_synd)); + mlx5_log(dev, severity, "raw fw_ver 0x%08x\n", ioread32be(&h->fw_ver)); } static int @@ -443,6 +490,7 @@ mlx5_fw_reporter_heath_buffer_data_put(struct mlx5_core_dev *dev, { struct mlx5_core_health *health = &dev->priv.health; struct health_buffer __iomem *h = health->health; + u8 rfr_severity; int err; int i; @@ -475,9 +523,19 @@ mlx5_fw_reporter_heath_buffer_data_put(struct mlx5_core_dev *dev, ioread32be(&h->assert_callra)); if (err) return err; + err = devlink_fmsg_u32_pair_put(fmsg, "time", ioread32be(&h->time)); + if (err) + return err; err = devlink_fmsg_u32_pair_put(fmsg, "hw_id", ioread32be(&h->hw_id)); if (err) return err; + rfr_severity = ioread8(&h->rfr_severity); + err = devlink_fmsg_u8_pair_put(fmsg, "rfr", mlx5_health_get_rfr(rfr_severity)); + if (err) + return err; + err = devlink_fmsg_u8_pair_put(fmsg, "severity", mlx5_health_get_severity(rfr_severity)); + if (err) + return err; err = devlink_fmsg_u8_pair_put(fmsg, "irisc_index", ioread8(&h->irisc_index)); if (err) @@ -694,6 +752,31 @@ void mlx5_trigger_health_work(struct mlx5_core_dev *dev) spin_unlock_irqrestore(&health->wq_lock, flags); } +#define MLX5_MSEC_PER_HOUR (MSEC_PER_SEC * 60 * 60) +static void mlx5_health_log_ts_update(struct work_struct *work) +{ + struct delayed_work *dwork = to_delayed_work(work); + u32 out[MLX5_ST_SZ_DW(mrtc_reg)] = {}; + u32 in[MLX5_ST_SZ_DW(mrtc_reg)] = {}; + struct mlx5_core_health *health; + struct mlx5_core_dev *dev; + struct mlx5_priv *priv; + u64 now_us; + + health = container_of(dwork, struct mlx5_core_health, update_fw_log_ts_work); + priv = container_of(health, struct mlx5_priv, health); + dev = container_of(priv, struct mlx5_core_dev, priv); + + now_us = ktime_to_us(ktime_get_real()); + + MLX5_SET(mrtc_reg, in, time_h, now_us >> 32); + MLX5_SET(mrtc_reg, in, time_l, now_us & 0xFFFFFFFF); + mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out), MLX5_REG_MRTC, 0, 1); + + queue_delayed_work(health->wq, &health->update_fw_log_ts_work, + msecs_to_jiffies(MLX5_MSEC_PER_HOUR)); +} + static void poll_health(struct timer_list *t) { struct mlx5_core_dev *dev = from_timer(dev, t, priv.health.timer); @@ -776,6 +859,7 @@ void mlx5_drain_health_wq(struct mlx5_core_dev *dev) spin_lock_irqsave(&health->wq_lock, flags); set_bit(MLX5_DROP_NEW_HEALTH_WORK, &health->flags); spin_unlock_irqrestore(&health->wq_lock, flags); + cancel_delayed_work_sync(&health->update_fw_log_ts_work); cancel_work_sync(&health->report_work); cancel_work_sync(&health->fatal_report_work); } @@ -791,6 +875,7 @@ void mlx5_health_cleanup(struct mlx5_core_dev *dev) { struct mlx5_core_health *health = &dev->priv.health; + cancel_delayed_work_sync(&health->update_fw_log_ts_work); destroy_workqueue(health->wq); mlx5_fw_reporters_destroy(dev); } @@ -816,6 +901,9 @@ int mlx5_health_init(struct mlx5_core_dev *dev) spin_lock_init(&health->wq_lock); INIT_WORK(&health->fatal_report_work, mlx5_fw_fatal_reporter_err_work); INIT_WORK(&health->report_work, mlx5_fw_reporter_err_work); + INIT_DELAYED_WORK(&health->update_fw_log_ts_work, mlx5_health_log_ts_update); + if (mlx5_core_is_pf(dev)) + queue_delayed_work(health->wq, &health->update_fw_log_ts_work, 0); return 0; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c index ee0eb4a4b819..962d41418ce7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c @@ -33,11 +33,6 @@ #include "en.h" #include "ipoib.h" -static u32 mlx5i_flow_type_mask(u32 flow_type) -{ - return flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS); -} - static void mlx5i_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) { @@ -223,6 +218,11 @@ static int mlx5i_get_link_ksettings(struct net_device *netdev, } #ifdef CONFIG_MLX5_EN_RXNFC +static u32 mlx5i_flow_type_mask(u32 flow_type) +{ + return flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS); +} + static int mlx5i_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) { struct mlx5e_priv *priv = mlx5i_epriv(dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h index 230eab7e3bc9..bb677329ea08 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h @@ -97,6 +97,30 @@ do { \ __func__, __LINE__, current->pid, \ ##__VA_ARGS__) +static inline void mlx5_printk(struct mlx5_core_dev *dev, int level, const char *format, ...) +{ + struct device *device = dev->device; + struct va_format vaf; + va_list args; + + if (WARN_ONCE(level < LOGLEVEL_EMERG || level > LOGLEVEL_DEBUG, + "Level %d is out of range, set to default level\n", level)) + level = LOGLEVEL_DEFAULT; + + va_start(args, format); + vaf.fmt = format; + vaf.va = &args; + + dev_printk_emit(level, device, "%s %s: %pV", dev_driver_string(device), dev_name(device), + &vaf); + va_end(args); +} + +#define mlx5_log(__dev, level, format, ...) \ + mlx5_printk(__dev, level, "%s:%d:(pid %d): " format, \ + __func__, __LINE__, current->pid, \ + ##__VA_ARGS__) + static inline struct device *mlx5_core_dma_dev(struct mlx5_core_dev *dev) { return &dev->pdev->dev; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c index 871c2fbe18d3..f37db7cc32a6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c @@ -9,6 +9,8 @@ #include "sf/sf.h" #include "sf/mlx5_ifc_vhca_event.h" #include "ecpf.h" +#define CREATE_TRACE_POINTS +#include "diag/dev_tracepoint.h" struct mlx5_sf_dev_table { struct xarray devices; @@ -66,13 +68,18 @@ static void mlx5_sf_dev_release(struct device *device) kfree(sf_dev); } -static void mlx5_sf_dev_remove(struct mlx5_sf_dev *sf_dev) +static void mlx5_sf_dev_remove(struct mlx5_core_dev *dev, struct mlx5_sf_dev *sf_dev) { + int id; + + id = sf_dev->adev.id; + trace_mlx5_sf_dev_del(dev, sf_dev, id); + auxiliary_device_delete(&sf_dev->adev); auxiliary_device_uninit(&sf_dev->adev); } -static void mlx5_sf_dev_add(struct mlx5_core_dev *dev, u16 sf_index, u32 sfnum) +static void mlx5_sf_dev_add(struct mlx5_core_dev *dev, u16 sf_index, u16 fn_id, u32 sfnum) { struct mlx5_sf_dev_table *table = dev->priv.sf_dev_table; struct mlx5_sf_dev *sf_dev; @@ -100,6 +107,7 @@ static void mlx5_sf_dev_add(struct mlx5_core_dev *dev, u16 sf_index, u32 sfnum) sf_dev->adev.dev.groups = sf_attr_groups; sf_dev->sfnum = sfnum; sf_dev->parent_mdev = dev; + sf_dev->fn_id = fn_id; if (!table->max_sfs) { mlx5_adev_idx_free(id); @@ -109,6 +117,8 @@ static void mlx5_sf_dev_add(struct mlx5_core_dev *dev, u16 sf_index, u32 sfnum) } sf_dev->bar_base_addr = table->base_address + (sf_index * table->sf_bar_length); + trace_mlx5_sf_dev_add(dev, sf_dev, id); + err = auxiliary_device_init(&sf_dev->adev); if (err) { mlx5_adev_idx_free(id); @@ -128,7 +138,7 @@ static void mlx5_sf_dev_add(struct mlx5_core_dev *dev, u16 sf_index, u32 sfnum) return; xa_err: - mlx5_sf_dev_remove(sf_dev); + mlx5_sf_dev_remove(dev, sf_dev); add_err: mlx5_core_err(dev, "SF DEV: fail device add for index=%d sfnum=%d err=%d\n", sf_index, sfnum, err); @@ -139,7 +149,7 @@ static void mlx5_sf_dev_del(struct mlx5_core_dev *dev, struct mlx5_sf_dev *sf_de struct mlx5_sf_dev_table *table = dev->priv.sf_dev_table; xa_erase(&table->devices, sf_index); - mlx5_sf_dev_remove(sf_dev); + mlx5_sf_dev_remove(dev, sf_dev); } static int @@ -178,7 +188,8 @@ mlx5_sf_dev_state_change_handler(struct notifier_block *nb, unsigned long event_ break; case MLX5_VHCA_STATE_ACTIVE: if (!sf_dev) - mlx5_sf_dev_add(table->dev, sf_index, event->sw_function_id); + mlx5_sf_dev_add(table->dev, sf_index, event->function_id, + event->sw_function_id); break; default: break; @@ -260,7 +271,7 @@ static void mlx5_sf_dev_destroy_all(struct mlx5_sf_dev_table *table) xa_for_each(&table->devices, index, sf_dev) { xa_erase(&table->devices, index); - mlx5_sf_dev_remove(sf_dev); + mlx5_sf_dev_remove(table->dev, sf_dev); } } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.h b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.h index 149fd9e698cf..2a66a427ef15 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.h @@ -16,6 +16,7 @@ struct mlx5_sf_dev { struct mlx5_core_dev *mdev; phys_addr_t bar_base_addr; u32 sfnum; + u16 fn_id; }; void mlx5_sf_dev_table_create(struct mlx5_core_dev *dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/diag/dev_tracepoint.h b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/diag/dev_tracepoint.h new file mode 100644 index 000000000000..7f7c9af5deed --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/diag/dev_tracepoint.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mlx5 + +#if !defined(_MLX5_SF_DEV_TP_) || defined(TRACE_HEADER_MULTI_READ) +#define _MLX5_SF_DEV_TP_ + +#include <linux/tracepoint.h> +#include <linux/mlx5/driver.h> +#include "../../dev/dev.h" + +DECLARE_EVENT_CLASS(mlx5_sf_dev_template, + TP_PROTO(const struct mlx5_core_dev *dev, + const struct mlx5_sf_dev *sfdev, + int aux_id), + TP_ARGS(dev, sfdev, aux_id), + TP_STRUCT__entry(__string(devname, dev_name(dev->device)) + __field(const struct mlx5_sf_dev*, sfdev) + __field(int, aux_id) + __field(u16, hw_fn_id) + __field(u32, sfnum) + ), + TP_fast_assign(__assign_str(devname, dev_name(dev->device)); + __entry->sfdev = sfdev; + __entry->aux_id = aux_id; + __entry->hw_fn_id = sfdev->fn_id; + __entry->sfnum = sfdev->sfnum; + ), + TP_printk("(%s) sfdev=%pK aux_id=%d hw_id=0x%x sfnum=%u\n", + __get_str(devname), __entry->sfdev, + __entry->aux_id, __entry->hw_fn_id, + __entry->sfnum) +); + +DEFINE_EVENT(mlx5_sf_dev_template, mlx5_sf_dev_add, + TP_PROTO(const struct mlx5_core_dev *dev, + const struct mlx5_sf_dev *sfdev, + int aux_id), + TP_ARGS(dev, sfdev, aux_id) + ); + +DEFINE_EVENT(mlx5_sf_dev_template, mlx5_sf_dev_del, + TP_PROTO(const struct mlx5_core_dev *dev, + const struct mlx5_sf_dev *sfdev, + int aux_id), + TP_ARGS(dev, sfdev, aux_id) + ); + +#endif /* _MLX5_SF_DEV_TP_ */ + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH sf/dev/diag +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE dev_tracepoint +#include <trace/define_trace.h> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c index e1bb3acf45e6..3be659cd91f1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c @@ -8,6 +8,8 @@ #include "mlx5_ifc_vhca_event.h" #include "vhca_event.h" #include "ecpf.h" +#define CREATE_TRACE_POINTS +#include "diag/sf_tracepoint.h" struct mlx5_sf { struct devlink_port dl_port; @@ -112,6 +114,7 @@ static void mlx5_sf_free(struct mlx5_sf_table *table, struct mlx5_sf *sf) { mlx5_sf_id_erase(table, sf); mlx5_sf_hw_table_sf_free(table->dev, sf->controller, sf->id); + trace_mlx5_sf_free(table->dev, sf->port_index, sf->controller, sf->hw_fn_id); kfree(sf); } @@ -209,6 +212,7 @@ static int mlx5_sf_activate(struct mlx5_core_dev *dev, struct mlx5_sf *sf, return err; sf->hw_state = MLX5_VHCA_STATE_ACTIVE; + trace_mlx5_sf_activate(dev, sf->port_index, sf->controller, sf->hw_fn_id); return 0; } @@ -224,6 +228,7 @@ static int mlx5_sf_deactivate(struct mlx5_core_dev *dev, struct mlx5_sf *sf) return err; sf->hw_state = MLX5_VHCA_STATE_TEARDOWN_REQUEST; + trace_mlx5_sf_deactivate(dev, sf->port_index, sf->controller, sf->hw_fn_id); return 0; } @@ -293,6 +298,7 @@ static int mlx5_sf_add(struct mlx5_core_dev *dev, struct mlx5_sf_table *table, if (err) goto esw_err; *new_port_index = sf->port_index; + trace_mlx5_sf_add(dev, sf->port_index, sf->controller, sf->hw_fn_id, new_attr->sfnum); return 0; esw_err: @@ -442,6 +448,8 @@ static int mlx5_sf_vhca_event(struct notifier_block *nb, unsigned long opcode, v update = mlx5_sf_state_update_check(sf, event->new_vhca_state); if (update) sf->hw_state = event->new_vhca_state; + trace_mlx5_sf_update_state(table->dev, sf->port_index, sf->controller, + sf->hw_fn_id, sf->hw_state); sf_err: mutex_unlock(&table->sf_state_lock); mlx5_sf_table_put(table); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/diag/sf_tracepoint.h b/drivers/net/ethernet/mellanox/mlx5/core/sf/diag/sf_tracepoint.h new file mode 100644 index 000000000000..8bf1cd90930d --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/diag/sf_tracepoint.h @@ -0,0 +1,173 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mlx5 + +#if !defined(_MLX5_SF_TP_) || defined(TRACE_HEADER_MULTI_READ) +#define _MLX5_SF_TP_ + +#include <linux/tracepoint.h> +#include <linux/mlx5/driver.h> +#include "sf/vhca_event.h" + +TRACE_EVENT(mlx5_sf_add, + TP_PROTO(const struct mlx5_core_dev *dev, + unsigned int port_index, + u32 controller, + u16 hw_fn_id, + u32 sfnum), + TP_ARGS(dev, port_index, controller, hw_fn_id, sfnum), + TP_STRUCT__entry(__string(devname, dev_name(dev->device)) + __field(unsigned int, port_index) + __field(u32, controller) + __field(u16, hw_fn_id) + __field(u32, sfnum) + ), + TP_fast_assign(__assign_str(devname, dev_name(dev->device)); + __entry->port_index = port_index; + __entry->controller = controller; + __entry->hw_fn_id = hw_fn_id; + __entry->sfnum = sfnum; + ), + TP_printk("(%s) port_index=%u controller=%u hw_id=0x%x sfnum=%u\n", + __get_str(devname), __entry->port_index, __entry->controller, + __entry->hw_fn_id, __entry->sfnum) +); + +TRACE_EVENT(mlx5_sf_free, + TP_PROTO(const struct mlx5_core_dev *dev, + unsigned int port_index, + u32 controller, + u16 hw_fn_id), + TP_ARGS(dev, port_index, controller, hw_fn_id), + TP_STRUCT__entry(__string(devname, dev_name(dev->device)) + __field(unsigned int, port_index) + __field(u32, controller) + __field(u16, hw_fn_id) + ), + TP_fast_assign(__assign_str(devname, dev_name(dev->device)); + __entry->port_index = port_index; + __entry->controller = controller; + __entry->hw_fn_id = hw_fn_id; + ), + TP_printk("(%s) port_index=%u controller=%u hw_id=0x%x\n", + __get_str(devname), __entry->port_index, __entry->controller, + __entry->hw_fn_id) +); + +TRACE_EVENT(mlx5_sf_hwc_alloc, + TP_PROTO(const struct mlx5_core_dev *dev, + u32 controller, + u16 hw_fn_id, + u32 sfnum), + TP_ARGS(dev, controller, hw_fn_id, sfnum), + TP_STRUCT__entry(__string(devname, dev_name(dev->device)) + __field(u32, controller) + __field(u16, hw_fn_id) + __field(u32, sfnum) + ), + TP_fast_assign(__assign_str(devname, dev_name(dev->device)); + __entry->controller = controller; + __entry->hw_fn_id = hw_fn_id; + __entry->sfnum = sfnum; + ), + TP_printk("(%s) controller=%u hw_id=0x%x sfnum=%u\n", + __get_str(devname), __entry->controller, __entry->hw_fn_id, + __entry->sfnum) +); + +TRACE_EVENT(mlx5_sf_hwc_free, + TP_PROTO(const struct mlx5_core_dev *dev, + u16 hw_fn_id), + TP_ARGS(dev, hw_fn_id), + TP_STRUCT__entry(__string(devname, dev_name(dev->device)) + __field(u16, hw_fn_id) + ), + TP_fast_assign(__assign_str(devname, dev_name(dev->device)); + __entry->hw_fn_id = hw_fn_id; + ), + TP_printk("(%s) hw_id=0x%x\n", __get_str(devname), __entry->hw_fn_id) +); + +TRACE_EVENT(mlx5_sf_hwc_deferred_free, + TP_PROTO(const struct mlx5_core_dev *dev, + u16 hw_fn_id), + TP_ARGS(dev, hw_fn_id), + TP_STRUCT__entry(__string(devname, dev_name(dev->device)) + __field(u16, hw_fn_id) + ), + TP_fast_assign(__assign_str(devname, dev_name(dev->device)); + __entry->hw_fn_id = hw_fn_id; + ), + TP_printk("(%s) hw_id=0x%x\n", __get_str(devname), __entry->hw_fn_id) +); + +DECLARE_EVENT_CLASS(mlx5_sf_state_template, + TP_PROTO(const struct mlx5_core_dev *dev, + u32 port_index, + u32 controller, + u16 hw_fn_id), + TP_ARGS(dev, port_index, controller, hw_fn_id), + TP_STRUCT__entry(__string(devname, dev_name(dev->device)) + __field(unsigned int, port_index) + __field(u32, controller) + __field(u16, hw_fn_id)), + TP_fast_assign(__assign_str(devname, dev_name(dev->device)); + __entry->port_index = port_index; + __entry->controller = controller; + __entry->hw_fn_id = hw_fn_id; + ), + TP_printk("(%s) port_index=%u controller=%u hw_id=0x%x\n", + __get_str(devname), __entry->port_index, __entry->controller, + __entry->hw_fn_id) +); + +DEFINE_EVENT(mlx5_sf_state_template, mlx5_sf_activate, + TP_PROTO(const struct mlx5_core_dev *dev, + u32 port_index, + u32 controller, + u16 hw_fn_id), + TP_ARGS(dev, port_index, controller, hw_fn_id) + ); + +DEFINE_EVENT(mlx5_sf_state_template, mlx5_sf_deactivate, + TP_PROTO(const struct mlx5_core_dev *dev, + u32 port_index, + u32 controller, + u16 hw_fn_id), + TP_ARGS(dev, port_index, controller, hw_fn_id) + ); + +TRACE_EVENT(mlx5_sf_update_state, + TP_PROTO(const struct mlx5_core_dev *dev, + unsigned int port_index, + u32 controller, + u16 hw_fn_id, + u8 state), + TP_ARGS(dev, port_index, controller, hw_fn_id, state), + TP_STRUCT__entry(__string(devname, dev_name(dev->device)) + __field(unsigned int, port_index) + __field(u32, controller) + __field(u16, hw_fn_id) + __field(u8, state) + ), + TP_fast_assign(__assign_str(devname, dev_name(dev->device)); + __entry->port_index = port_index; + __entry->controller = controller; + __entry->hw_fn_id = hw_fn_id; + __entry->state = state; + ), + TP_printk("(%s) port_index=%u controller=%u hw_id=0x%x state=%u\n", + __get_str(devname), __entry->port_index, __entry->controller, + __entry->hw_fn_id, __entry->state) +); + +#endif /* _MLX5_SF_TP_ */ + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH sf/diag +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE sf_tracepoint +#include <trace/define_trace.h> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/diag/vhca_tracepoint.h b/drivers/net/ethernet/mellanox/mlx5/core/sf/diag/vhca_tracepoint.h new file mode 100644 index 000000000000..fd814a190b8b --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/diag/vhca_tracepoint.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mlx5 + +#if !defined(_MLX5_SF_VHCA_TP_) || defined(TRACE_HEADER_MULTI_READ) +#define _MLX5_SF_VHCA_TP_ + +#include <linux/tracepoint.h> +#include <linux/mlx5/driver.h> +#include "sf/vhca_event.h" + +TRACE_EVENT(mlx5_sf_vhca_event, + TP_PROTO(const struct mlx5_core_dev *dev, + const struct mlx5_vhca_state_event *event), + TP_ARGS(dev, event), + TP_STRUCT__entry(__string(devname, dev_name(dev->device)) + __field(u16, hw_fn_id) + __field(u32, sfnum) + __field(u8, vhca_state) + ), + TP_fast_assign(__assign_str(devname, dev_name(dev->device)); + __entry->hw_fn_id = event->function_id; + __entry->sfnum = event->sw_function_id; + __entry->vhca_state = event->new_vhca_state; + ), + TP_printk("(%s) hw_id=0x%x sfnum=%u vhca_state=%d\n", + __get_str(devname), __entry->hw_fn_id, + __entry->sfnum, __entry->vhca_state) +); + +#endif /* _MLX5_SF_VHCA_TP_ */ + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH sf/diag +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE vhca_tracepoint +#include <trace/define_trace.h> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c index d9c69123c1ab..252d6017387d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c @@ -8,6 +8,7 @@ #include "ecpf.h" #include "mlx5_core.h" #include "eswitch.h" +#include "diag/sf_tracepoint.h" struct mlx5_sf_hw { u32 usr_sfnum; @@ -142,6 +143,7 @@ int mlx5_sf_hw_table_sf_alloc(struct mlx5_core_dev *dev, u32 controller, u32 usr goto vhca_err; } + trace_mlx5_sf_hwc_alloc(dev, controller, hw_fn_id, usr_sfnum); mutex_unlock(&table->table_lock); return sw_id; @@ -172,6 +174,7 @@ static void mlx5_sf_hw_table_hwc_sf_free(struct mlx5_core_dev *dev, mlx5_cmd_dealloc_sf(dev, hwc->start_fn_id + idx); hwc->sfs[idx].allocated = false; hwc->sfs[idx].pending_delete = false; + trace_mlx5_sf_hwc_free(dev, hwc->start_fn_id + idx); } void mlx5_sf_hw_table_sf_deferred_free(struct mlx5_core_dev *dev, u32 controller, u16 id) @@ -195,6 +198,7 @@ void mlx5_sf_hw_table_sf_deferred_free(struct mlx5_core_dev *dev, u32 controller hwc->sfs[id].allocated = false; } else { hwc->sfs[id].pending_delete = true; + trace_mlx5_sf_hwc_deferred_free(dev, hw_fn_id); } err: mutex_unlock(&table->table_lock); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/vhca_event.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/vhca_event.c index 28b14b05086f..d908fba968f0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/vhca_event.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/vhca_event.c @@ -6,6 +6,8 @@ #include "mlx5_core.h" #include "vhca_event.h" #include "ecpf.h" +#define CREATE_TRACE_POINTS +#include "diag/vhca_tracepoint.h" struct mlx5_vhca_state_notifier { struct mlx5_core_dev *dev; @@ -82,6 +84,7 @@ mlx5_vhca_event_notify(struct mlx5_core_dev *dev, struct mlx5_vhca_state_event * vhca_state_context.vhca_state); mlx5_vhca_event_arm(dev, event->function_id); + trace_mlx5_sf_vhca_event(dev, event); blocking_notifier_call_chain(&dev->priv.vhca_state_notifier->n_head, 0, event); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 48b817ba6d4e..8d420eb8ade2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -6526,6 +6526,12 @@ MLXSW_ITEM32(reg, ritr, mtu, 0x34, 0, 16); */ MLXSW_ITEM32(reg, ritr, if_swid, 0x08, 24, 8); +/* reg_ritr_if_mac_profile_id + * MAC msb profile ID. + * Access: RW + */ +MLXSW_ITEM32(reg, ritr, if_mac_profile_id, 0x10, 16, 4); + /* reg_ritr_if_mac * Router interface MAC address. * In Spectrum, all MAC addresses must have the same 38 MSBits. diff --git a/drivers/net/ethernet/mellanox/mlxsw/resources.h b/drivers/net/ethernet/mellanox/mlxsw/resources.h index a1512be77867..c7fc650608eb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/resources.h +++ b/drivers/net/ethernet/mellanox/mlxsw/resources.h @@ -49,6 +49,7 @@ enum mlxsw_res_id { MLXSW_RES_ID_MAX_VRS, MLXSW_RES_ID_MAX_RIFS, MLXSW_RES_ID_MC_ERIF_LIST_ENTRIES, + MLXSW_RES_ID_MAX_RIF_MAC_PROFILES, MLXSW_RES_ID_MAX_LPM_TREES, MLXSW_RES_ID_MAX_NVE_MC_ENTRIES_IPV4, MLXSW_RES_ID_MAX_NVE_MC_ENTRIES_IPV6, @@ -105,6 +106,7 @@ static u16 mlxsw_res_ids[] = { [MLXSW_RES_ID_MAX_VRS] = 0x2C01, [MLXSW_RES_ID_MAX_RIFS] = 0x2C02, [MLXSW_RES_ID_MC_ERIF_LIST_ENTRIES] = 0x2C10, + [MLXSW_RES_ID_MAX_RIF_MAC_PROFILES] = 0x2C14, [MLXSW_RES_ID_MAX_LPM_TREES] = 0x2C30, [MLXSW_RES_ID_MAX_NVE_MC_ENTRIES_IPV4] = 0x2E02, [MLXSW_RES_ID_MAX_NVE_MC_ENTRIES_IPV6] = 0x2E03, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 66c346a86ec5..5925db386b1b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -3282,6 +3282,30 @@ static int mlxsw_sp_resources_span_register(struct mlxsw_core *mlxsw_core) &span_size_params); } +static int +mlxsw_sp_resources_rif_mac_profile_register(struct mlxsw_core *mlxsw_core) +{ + struct devlink *devlink = priv_to_devlink(mlxsw_core); + struct devlink_resource_size_params size_params; + u8 max_rif_mac_profiles; + + if (!MLXSW_CORE_RES_VALID(mlxsw_core, MAX_RIF_MAC_PROFILES)) + return -EIO; + + max_rif_mac_profiles = MLXSW_CORE_RES_GET(mlxsw_core, + MAX_RIF_MAC_PROFILES); + devlink_resource_size_params_init(&size_params, max_rif_mac_profiles, + max_rif_mac_profiles, 1, + DEVLINK_RESOURCE_UNIT_ENTRY); + + return devlink_resource_register(devlink, + "rif_mac_profiles", + max_rif_mac_profiles, + MLXSW_SP_RESOURCE_RIF_MAC_PROFILES, + DEVLINK_RESOURCE_ID_PARENT_TOP, + &size_params); +} + static int mlxsw_sp1_resources_register(struct mlxsw_core *mlxsw_core) { int err; @@ -3300,10 +3324,16 @@ static int mlxsw_sp1_resources_register(struct mlxsw_core *mlxsw_core) err = mlxsw_sp_policer_resources_register(mlxsw_core); if (err) - goto err_resources_counter_register; + goto err_policer_resources_register; + + err = mlxsw_sp_resources_rif_mac_profile_register(mlxsw_core); + if (err) + goto err_resources_rif_mac_profile_register; return 0; +err_resources_rif_mac_profile_register: +err_policer_resources_register: err_resources_counter_register: err_resources_span_register: devlink_resources_unregister(priv_to_devlink(mlxsw_core), NULL); @@ -3328,10 +3358,16 @@ static int mlxsw_sp2_resources_register(struct mlxsw_core *mlxsw_core) err = mlxsw_sp_policer_resources_register(mlxsw_core); if (err) - goto err_resources_counter_register; + goto err_policer_resources_register; + + err = mlxsw_sp_resources_rif_mac_profile_register(mlxsw_core); + if (err) + goto err_resources_rif_mac_profile_register; return 0; +err_resources_rif_mac_profile_register: +err_policer_resources_register: err_resources_counter_register: err_resources_span_register: devlink_resources_unregister(priv_to_devlink(mlxsw_core), NULL); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 3ab57e98cad2..32fdd37657dd 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -67,6 +67,7 @@ enum mlxsw_sp_resource_id { MLXSW_SP_RESOURCE_COUNTERS_RIF, MLXSW_SP_RESOURCE_GLOBAL_POLICERS, MLXSW_SP_RESOURCE_SINGLE_RATE_POLICERS, + MLXSW_SP_RESOURCE_RIF_MAC_PROFILES, }; struct mlxsw_sp_port; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c index ded4cf658680..4b713832fdd5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c @@ -119,7 +119,6 @@ mlxsw_sp_acl_atcam_region_12kb_init(struct mlxsw_sp_acl_atcam_region *aregion) { struct mlxsw_sp *mlxsw_sp = aregion->region->mlxsw_sp; struct mlxsw_sp_acl_atcam_region_12kb *region_12kb; - size_t alloc_size; u64 max_lkey_id; int err; @@ -131,8 +130,7 @@ mlxsw_sp_acl_atcam_region_12kb_init(struct mlxsw_sp_acl_atcam_region *aregion) if (!region_12kb) return -ENOMEM; - alloc_size = BITS_TO_LONGS(max_lkey_id) * sizeof(unsigned long); - region_12kb->used_lkey_id = kzalloc(alloc_size, GFP_KERNEL); + region_12kb->used_lkey_id = bitmap_zalloc(max_lkey_id, GFP_KERNEL); if (!region_12kb->used_lkey_id) { err = -ENOMEM; goto err_used_lkey_id_alloc; @@ -149,7 +147,7 @@ mlxsw_sp_acl_atcam_region_12kb_init(struct mlxsw_sp_acl_atcam_region *aregion) return 0; err_rhashtable_init: - kfree(region_12kb->used_lkey_id); + bitmap_free(region_12kb->used_lkey_id); err_used_lkey_id_alloc: kfree(region_12kb); return err; @@ -161,7 +159,7 @@ mlxsw_sp_acl_atcam_region_12kb_fini(struct mlxsw_sp_acl_atcam_region *aregion) struct mlxsw_sp_acl_atcam_region_12kb *region_12kb = aregion->priv; rhashtable_destroy(®ion_12kb->lkey_ht); - kfree(region_12kb->used_lkey_id); + bitmap_free(region_12kb->used_lkey_id); kfree(region_12kb); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 7cccc41dd69c..31f7f4c3acc3 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -36,7 +36,6 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, u64 max_tcam_regions; u64 max_regions; u64 max_groups; - size_t alloc_size; int err; mutex_init(&tcam->lock); @@ -52,15 +51,13 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, if (max_tcam_regions < max_regions) max_regions = max_tcam_regions; - alloc_size = sizeof(tcam->used_regions[0]) * BITS_TO_LONGS(max_regions); - tcam->used_regions = kzalloc(alloc_size, GFP_KERNEL); + tcam->used_regions = bitmap_zalloc(max_regions, GFP_KERNEL); if (!tcam->used_regions) return -ENOMEM; tcam->max_regions = max_regions; max_groups = MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_GROUPS); - alloc_size = sizeof(tcam->used_groups[0]) * BITS_TO_LONGS(max_groups); - tcam->used_groups = kzalloc(alloc_size, GFP_KERNEL); + tcam->used_groups = bitmap_zalloc(max_groups, GFP_KERNEL); if (!tcam->used_groups) { err = -ENOMEM; goto err_alloc_used_groups; @@ -76,9 +73,9 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, return 0; err_tcam_init: - kfree(tcam->used_groups); + bitmap_free(tcam->used_groups); err_alloc_used_groups: - kfree(tcam->used_regions); + bitmap_free(tcam->used_regions); return err; } @@ -89,8 +86,8 @@ void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp, mutex_destroy(&tcam->lock); ops->fini(mlxsw_sp, tcam->priv); - kfree(tcam->used_groups); - kfree(tcam->used_regions); + bitmap_free(tcam->used_groups); + bitmap_free(tcam->used_regions); } int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.c index b65b93a2b9bc..fc2257753b9b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.c @@ -122,7 +122,6 @@ int mlxsw_sp_counter_pool_init(struct mlxsw_sp *mlxsw_sp) unsigned int sub_pools_count = ARRAY_SIZE(mlxsw_sp_counter_sub_pools); struct devlink *devlink = priv_to_devlink(mlxsw_sp->core); struct mlxsw_sp_counter_pool *pool; - unsigned int map_size; int err; pool = kzalloc(struct_size(pool, sub_pools, sub_pools_count), @@ -143,9 +142,7 @@ int mlxsw_sp_counter_pool_init(struct mlxsw_sp *mlxsw_sp) devlink_resource_occ_get_register(devlink, MLXSW_SP_RESOURCE_COUNTERS, mlxsw_sp_counter_pool_occ_get, pool); - map_size = BITS_TO_LONGS(pool->pool_size) * sizeof(unsigned long); - - pool->usage = kzalloc(map_size, GFP_KERNEL); + pool->usage = bitmap_zalloc(pool->pool_size, GFP_KERNEL); if (!pool->usage) { err = -ENOMEM; goto err_usage_alloc; @@ -158,7 +155,7 @@ int mlxsw_sp_counter_pool_init(struct mlxsw_sp *mlxsw_sp) return 0; err_sub_pools_init: - kfree(pool->usage); + bitmap_free(pool->usage); err_usage_alloc: devlink_resource_occ_get_unregister(devlink, MLXSW_SP_RESOURCE_COUNTERS); @@ -176,7 +173,7 @@ void mlxsw_sp_counter_pool_fini(struct mlxsw_sp *mlxsw_sp) WARN_ON(find_first_bit(pool->usage, pool->pool_size) != pool->pool_size); WARN_ON(atomic_read(&pool->active_entries_count)); - kfree(pool->usage); + bitmap_free(pool->usage); devlink_resource_occ_get_unregister(devlink, MLXSW_SP_RESOURCE_COUNTERS); kfree(pool); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 1e141b5944cd..217e3b351dfe 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -57,6 +57,7 @@ struct mlxsw_sp_rif { unsigned char addr[ETH_ALEN]; int mtu; u16 rif_index; + u8 mac_profile_id; u16 vr_id; const struct mlxsw_sp_rif_ops *ops; struct mlxsw_sp *mlxsw_sp; @@ -106,13 +107,20 @@ struct mlxsw_sp_rif_ops { void (*setup)(struct mlxsw_sp_rif *rif, const struct mlxsw_sp_rif_params *params); - int (*configure)(struct mlxsw_sp_rif *rif); + int (*configure)(struct mlxsw_sp_rif *rif, + struct netlink_ext_ack *extack); void (*deconfigure)(struct mlxsw_sp_rif *rif); struct mlxsw_sp_fid * (*fid_get)(struct mlxsw_sp_rif *rif, struct netlink_ext_ack *extack); void (*fdb_del)(struct mlxsw_sp_rif *rif, const char *mac); }; +struct mlxsw_sp_rif_mac_profile { + unsigned char mac_prefix[ETH_ALEN]; + refcount_t ref_count; + u8 id; +}; + struct mlxsw_sp_router_ops { int (*init)(struct mlxsw_sp *mlxsw_sp); int (*ipips_init)(struct mlxsw_sp *mlxsw_sp); @@ -8186,7 +8194,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, if (ops->setup) ops->setup(rif, params); - err = ops->configure(rif); + err = ops->configure(rif, extack); if (err) goto err_configure; @@ -8305,6 +8313,200 @@ static void mlxsw_sp_rif_subport_put(struct mlxsw_sp_rif *rif) mlxsw_sp_rif_destroy(rif); } +static int mlxsw_sp_rif_mac_profile_index_alloc(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_rif_mac_profile *profile, + struct netlink_ext_ack *extack) +{ + u8 max_rif_mac_profiles = mlxsw_sp->router->max_rif_mac_profile; + struct mlxsw_sp_router *router = mlxsw_sp->router; + int id; + + id = idr_alloc(&router->rif_mac_profiles_idr, profile, 0, + max_rif_mac_profiles, GFP_KERNEL); + + if (id >= 0) { + profile->id = id; + return 0; + } + + if (id == -ENOSPC) + NL_SET_ERR_MSG_MOD(extack, + "Exceeded number of supported router interface MAC profiles"); + + return id; +} + +static struct mlxsw_sp_rif_mac_profile * +mlxsw_sp_rif_mac_profile_index_free(struct mlxsw_sp *mlxsw_sp, u8 mac_profile) +{ + struct mlxsw_sp_rif_mac_profile *profile; + + profile = idr_remove(&mlxsw_sp->router->rif_mac_profiles_idr, + mac_profile); + WARN_ON(!profile); + return profile; +} + +static struct mlxsw_sp_rif_mac_profile * +mlxsw_sp_rif_mac_profile_alloc(const char *mac) +{ + struct mlxsw_sp_rif_mac_profile *profile; + + profile = kzalloc(sizeof(*profile), GFP_KERNEL); + if (!profile) + return NULL; + + ether_addr_copy(profile->mac_prefix, mac); + refcount_set(&profile->ref_count, 1); + return profile; +} + +static struct mlxsw_sp_rif_mac_profile * +mlxsw_sp_rif_mac_profile_find(const struct mlxsw_sp *mlxsw_sp, const char *mac) +{ + struct mlxsw_sp_router *router = mlxsw_sp->router; + struct mlxsw_sp_rif_mac_profile *profile; + int id; + + idr_for_each_entry(&router->rif_mac_profiles_idr, profile, id) { + if (!profile) + continue; + + if (ether_addr_equal_masked(profile->mac_prefix, mac, + mlxsw_sp->mac_mask)) + return profile; + } + + return NULL; +} + +static u64 mlxsw_sp_rif_mac_profiles_occ_get(void *priv) +{ + const struct mlxsw_sp *mlxsw_sp = priv; + + return atomic_read(&mlxsw_sp->router->rif_mac_profiles_count); +} + +static struct mlxsw_sp_rif_mac_profile * +mlxsw_sp_rif_mac_profile_create(struct mlxsw_sp *mlxsw_sp, const char *mac, + struct netlink_ext_ack *extack) +{ + struct mlxsw_sp_rif_mac_profile *profile; + int err; + + profile = mlxsw_sp_rif_mac_profile_alloc(mac); + if (!profile) + return ERR_PTR(-ENOMEM); + + err = mlxsw_sp_rif_mac_profile_index_alloc(mlxsw_sp, profile, extack); + if (err) + goto profile_index_alloc_err; + + atomic_inc(&mlxsw_sp->router->rif_mac_profiles_count); + return profile; + +profile_index_alloc_err: + kfree(profile); + return ERR_PTR(err); +} + +static void mlxsw_sp_rif_mac_profile_destroy(struct mlxsw_sp *mlxsw_sp, + u8 mac_profile) +{ + struct mlxsw_sp_rif_mac_profile *profile; + + atomic_dec(&mlxsw_sp->router->rif_mac_profiles_count); + profile = mlxsw_sp_rif_mac_profile_index_free(mlxsw_sp, mac_profile); + kfree(profile); +} + +static int mlxsw_sp_rif_mac_profile_get(struct mlxsw_sp *mlxsw_sp, + const char *mac, u8 *p_mac_profile, + struct netlink_ext_ack *extack) +{ + struct mlxsw_sp_rif_mac_profile *profile; + + profile = mlxsw_sp_rif_mac_profile_find(mlxsw_sp, mac); + if (profile) { + refcount_inc(&profile->ref_count); + goto out; + } + + profile = mlxsw_sp_rif_mac_profile_create(mlxsw_sp, mac, extack); + if (IS_ERR(profile)) + return PTR_ERR(profile); + +out: + *p_mac_profile = profile->id; + return 0; +} + +static void mlxsw_sp_rif_mac_profile_put(struct mlxsw_sp *mlxsw_sp, + u8 mac_profile) +{ + struct mlxsw_sp_rif_mac_profile *profile; + + profile = idr_find(&mlxsw_sp->router->rif_mac_profiles_idr, + mac_profile); + if (WARN_ON(!profile)) + return; + + if (!refcount_dec_and_test(&profile->ref_count)) + return; + + mlxsw_sp_rif_mac_profile_destroy(mlxsw_sp, mac_profile); +} + +static bool mlxsw_sp_rif_mac_profile_is_shared(const struct mlxsw_sp_rif *rif) +{ + struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; + struct mlxsw_sp_rif_mac_profile *profile; + + profile = idr_find(&mlxsw_sp->router->rif_mac_profiles_idr, + rif->mac_profile_id); + if (WARN_ON(!profile)) + return false; + + return refcount_read(&profile->ref_count) > 1; +} + +static int mlxsw_sp_rif_mac_profile_edit(struct mlxsw_sp_rif *rif, + const char *new_mac) +{ + struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; + struct mlxsw_sp_rif_mac_profile *profile; + + profile = idr_find(&mlxsw_sp->router->rif_mac_profiles_idr, + rif->mac_profile_id); + if (WARN_ON(!profile)) + return -EINVAL; + + ether_addr_copy(profile->mac_prefix, new_mac); + return 0; +} + +static int +mlxsw_sp_rif_mac_profile_replace(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_rif *rif, + const char *new_mac, + struct netlink_ext_ack *extack) +{ + u8 mac_profile; + int err; + + if (!mlxsw_sp_rif_mac_profile_is_shared(rif)) + return mlxsw_sp_rif_mac_profile_edit(rif, new_mac); + + err = mlxsw_sp_rif_mac_profile_get(mlxsw_sp, new_mac, + &mac_profile, extack); + if (err) + return err; + + mlxsw_sp_rif_mac_profile_put(mlxsw_sp, rif->mac_profile_id); + rif->mac_profile_id = mac_profile; + return 0; +} + static int __mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan, struct net_device *l3_dev, @@ -8653,36 +8855,6 @@ static int mlxsw_sp_inetaddr_macvlan_event(struct mlxsw_sp *mlxsw_sp, return 0; } -static int mlxsw_sp_router_port_check_rif_addr(struct mlxsw_sp *mlxsw_sp, - struct net_device *dev, - const unsigned char *dev_addr, - struct netlink_ext_ack *extack) -{ - struct mlxsw_sp_rif *rif; - int i; - - /* A RIF is not created for macvlan netdevs. Their MAC is used to - * populate the FDB - */ - if (netif_is_macvlan(dev) || netif_is_l3_master(dev)) - return 0; - - for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) { - rif = mlxsw_sp->router->rifs[i]; - if (rif && rif->ops && - rif->ops->type == MLXSW_SP_RIF_TYPE_IPIP_LB) - continue; - if (rif && rif->dev && rif->dev != dev && - !ether_addr_equal_masked(rif->dev->dev_addr, dev_addr, - mlxsw_sp->mac_mask)) { - NL_SET_ERR_MSG_MOD(extack, "All router interface MAC addresses must have the same prefix"); - return -EINVAL; - } - } - - return 0; -} - static int __mlxsw_sp_inetaddr_event(struct mlxsw_sp *mlxsw_sp, struct net_device *dev, unsigned long event, @@ -8748,11 +8920,6 @@ int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused, if (!mlxsw_sp_rif_should_config(rif, dev, event)) goto out; - err = mlxsw_sp_router_port_check_rif_addr(mlxsw_sp, dev, dev->dev_addr, - ivi->extack); - if (err) - goto out; - err = __mlxsw_sp_inetaddr_event(mlxsw_sp, dev, event, ivi->extack); out: mutex_unlock(&mlxsw_sp->router->lock); @@ -8836,11 +9003,6 @@ int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused, if (!mlxsw_sp_rif_should_config(rif, dev, event)) goto out; - err = mlxsw_sp_router_port_check_rif_addr(mlxsw_sp, dev, dev->dev_addr, - i6vi->extack); - if (err) - goto out; - err = __mlxsw_sp_inetaddr_event(mlxsw_sp, dev, event, i6vi->extack); out: mutex_unlock(&mlxsw_sp->router->lock); @@ -8848,7 +9010,7 @@ out: } static int mlxsw_sp_rif_edit(struct mlxsw_sp *mlxsw_sp, u16 rif_index, - const char *mac, int mtu) + const char *mac, int mtu, u8 mac_profile) { char ritr_pl[MLXSW_REG_RITR_LEN]; int err; @@ -8860,15 +9022,18 @@ static int mlxsw_sp_rif_edit(struct mlxsw_sp *mlxsw_sp, u16 rif_index, mlxsw_reg_ritr_mtu_set(ritr_pl, mtu); mlxsw_reg_ritr_if_mac_memcpy_to(ritr_pl, mac); + mlxsw_reg_ritr_if_mac_profile_id_set(ritr_pl, mac_profile); mlxsw_reg_ritr_op_set(ritr_pl, MLXSW_REG_RITR_RIF_CREATE); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl); } static int mlxsw_sp_router_port_change_event(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_rif *rif) + struct mlxsw_sp_rif *rif, + struct netlink_ext_ack *extack) { struct net_device *dev = rif->dev; + u8 old_mac_profile; u16 fid_index; int err; @@ -8878,8 +9043,14 @@ mlxsw_sp_router_port_change_event(struct mlxsw_sp *mlxsw_sp, if (err) return err; + old_mac_profile = rif->mac_profile_id; + err = mlxsw_sp_rif_mac_profile_replace(mlxsw_sp, rif, dev->dev_addr, + extack); + if (err) + goto err_rif_mac_profile_replace; + err = mlxsw_sp_rif_edit(mlxsw_sp, rif->rif_index, dev->dev_addr, - dev->mtu); + dev->mtu, rif->mac_profile_id); if (err) goto err_rif_edit; @@ -8909,8 +9080,11 @@ mlxsw_sp_router_port_change_event(struct mlxsw_sp *mlxsw_sp, return 0; err_rif_fdb_op: - mlxsw_sp_rif_edit(mlxsw_sp, rif->rif_index, rif->addr, rif->mtu); + mlxsw_sp_rif_edit(mlxsw_sp, rif->rif_index, rif->addr, rif->mtu, + old_mac_profile); err_rif_edit: + mlxsw_sp_rif_mac_profile_replace(mlxsw_sp, rif, rif->addr, extack); +err_rif_mac_profile_replace: mlxsw_sp_rif_fdb_op(mlxsw_sp, rif->addr, fid_index, true); return err; } @@ -8918,16 +9092,34 @@ err_rif_edit: static int mlxsw_sp_router_port_pre_changeaddr_event(struct mlxsw_sp_rif *rif, struct netdev_notifier_pre_changeaddr_info *info) { + struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; + struct mlxsw_sp_rif_mac_profile *profile; struct netlink_ext_ack *extack; + u8 max_rif_mac_profiles; + u64 occ; extack = netdev_notifier_info_to_extack(&info->info); - return mlxsw_sp_router_port_check_rif_addr(rif->mlxsw_sp, rif->dev, - info->dev_addr, extack); + + profile = mlxsw_sp_rif_mac_profile_find(mlxsw_sp, info->dev_addr); + if (profile) + return 0; + + max_rif_mac_profiles = mlxsw_sp->router->max_rif_mac_profile; + occ = mlxsw_sp_rif_mac_profiles_occ_get(mlxsw_sp); + if (occ < max_rif_mac_profiles) + return 0; + + if (!mlxsw_sp_rif_mac_profile_is_shared(rif)) + return 0; + + NL_SET_ERR_MSG_MOD(extack, "Exceeded number of supported router interface MAC profiles"); + return -ENOBUFS; } int mlxsw_sp_netdevice_router_port_event(struct net_device *dev, unsigned long event, void *ptr) { + struct netlink_ext_ack *extack = netdev_notifier_info_to_extack(ptr); struct mlxsw_sp *mlxsw_sp; struct mlxsw_sp_rif *rif; int err = 0; @@ -8944,7 +9136,7 @@ int mlxsw_sp_netdevice_router_port_event(struct net_device *dev, switch (event) { case NETDEV_CHANGEMTU: case NETDEV_CHANGEADDR: - err = mlxsw_sp_router_port_change_event(mlxsw_sp, rif); + err = mlxsw_sp_router_port_change_event(mlxsw_sp, rif, extack); break; case NETDEV_PRE_CHANGEADDR: err = mlxsw_sp_router_port_pre_changeaddr_event(rif, ptr); @@ -9067,6 +9259,7 @@ static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif *rif, bool enable) mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_SP_IF, rif->rif_index, rif->vr_id, rif->dev->mtu); mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr); + mlxsw_reg_ritr_if_mac_profile_id_set(ritr_pl, rif->mac_profile_id); mlxsw_reg_ritr_sp_if_pack(ritr_pl, rif_subport->lag, rif_subport->lag ? rif_subport->lag_id : rif_subport->system_port, @@ -9075,13 +9268,21 @@ static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif *rif, bool enable) return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl); } -static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif) +static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif, + struct netlink_ext_ack *extack) { + u8 mac_profile; int err; - err = mlxsw_sp_rif_subport_op(rif, true); + err = mlxsw_sp_rif_mac_profile_get(rif->mlxsw_sp, rif->addr, + &mac_profile, extack); if (err) return err; + rif->mac_profile_id = mac_profile; + + err = mlxsw_sp_rif_subport_op(rif, true); + if (err) + goto err_rif_subport_op; err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, mlxsw_sp_fid_index(rif->fid), true); @@ -9093,6 +9294,8 @@ static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif) err_rif_fdb_op: mlxsw_sp_rif_subport_op(rif, false); +err_rif_subport_op: + mlxsw_sp_rif_mac_profile_put(rif->mlxsw_sp, mac_profile); return err; } @@ -9105,6 +9308,7 @@ static void mlxsw_sp_rif_subport_deconfigure(struct mlxsw_sp_rif *rif) mlxsw_sp_fid_index(fid), false); mlxsw_sp_rif_macvlan_flush(rif); mlxsw_sp_rif_subport_op(rif, false); + mlxsw_sp_rif_mac_profile_put(rif->mlxsw_sp, rif->mac_profile_id); } static struct mlxsw_sp_fid * @@ -9133,6 +9337,7 @@ static int mlxsw_sp_rif_vlan_fid_op(struct mlxsw_sp_rif *rif, mlxsw_reg_ritr_pack(ritr_pl, enable, type, rif->rif_index, rif->vr_id, rif->dev->mtu); mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr); + mlxsw_reg_ritr_if_mac_profile_id_set(ritr_pl, rif->mac_profile_id); mlxsw_reg_ritr_fid_set(ritr_pl, type, vid_fid); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl); @@ -9143,16 +9348,24 @@ u8 mlxsw_sp_router_port(const struct mlxsw_sp *mlxsw_sp) return mlxsw_core_max_ports(mlxsw_sp->core) + 1; } -static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif) +static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif, + struct netlink_ext_ack *extack) { struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; u16 fid_index = mlxsw_sp_fid_index(rif->fid); + u8 mac_profile; int err; + err = mlxsw_sp_rif_mac_profile_get(mlxsw_sp, rif->addr, + &mac_profile, extack); + if (err) + return err; + rif->mac_profile_id = mac_profile; + err = mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_FID_IF, fid_index, true); if (err) - return err; + goto err_rif_vlan_fid_op; err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC, mlxsw_sp_router_port(mlxsw_sp), true); @@ -9180,6 +9393,8 @@ err_fid_bc_flood_set: mlxsw_sp_router_port(mlxsw_sp), false); err_fid_mc_flood_set: mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_FID_IF, fid_index, false); +err_rif_vlan_fid_op: + mlxsw_sp_rif_mac_profile_put(mlxsw_sp, mac_profile); return err; } @@ -9198,6 +9413,7 @@ static void mlxsw_sp_rif_fid_deconfigure(struct mlxsw_sp_rif *rif) mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC, mlxsw_sp_router_port(mlxsw_sp), false); mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_FID_IF, fid_index, false); + mlxsw_sp_rif_mac_profile_put(rif->mlxsw_sp, rif->mac_profile_id); } static struct mlxsw_sp_fid * @@ -9302,7 +9518,8 @@ mlxsw_sp_rif_ipip_lb_setup(struct mlxsw_sp_rif *rif, } static int -mlxsw_sp1_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif) +mlxsw_sp1_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif, + struct netlink_ext_ack *extack) { struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif); u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev); @@ -9489,7 +9706,8 @@ out: } static int -mlxsw_sp2_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif) +mlxsw_sp2_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif, + struct netlink_ext_ack *extack) { struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif); u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev); @@ -9544,6 +9762,13 @@ static const struct mlxsw_sp_rif_ops *mlxsw_sp2_rif_ops_arr[] = { static int mlxsw_sp_rifs_init(struct mlxsw_sp *mlxsw_sp) { u64 max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); + struct devlink *devlink = priv_to_devlink(mlxsw_sp->core); + struct mlxsw_core *core = mlxsw_sp->core; + + if (!MLXSW_CORE_RES_VALID(core, MAX_RIF_MAC_PROFILES)) + return -EIO; + mlxsw_sp->router->max_rif_mac_profile = + MLXSW_CORE_RES_GET(core, MAX_RIF_MAC_PROFILES); mlxsw_sp->router->rifs = kcalloc(max_rifs, sizeof(struct mlxsw_sp_rif *), @@ -9551,16 +9776,28 @@ static int mlxsw_sp_rifs_init(struct mlxsw_sp *mlxsw_sp) if (!mlxsw_sp->router->rifs) return -ENOMEM; + idr_init(&mlxsw_sp->router->rif_mac_profiles_idr); + atomic_set(&mlxsw_sp->router->rif_mac_profiles_count, 0); + devlink_resource_occ_get_register(devlink, + MLXSW_SP_RESOURCE_RIF_MAC_PROFILES, + mlxsw_sp_rif_mac_profiles_occ_get, + mlxsw_sp); + return 0; } static void mlxsw_sp_rifs_fini(struct mlxsw_sp *mlxsw_sp) { + struct devlink *devlink = priv_to_devlink(mlxsw_sp->core); int i; for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) WARN_ON_ONCE(mlxsw_sp->router->rifs[i]); + devlink_resource_occ_get_unregister(devlink, + MLXSW_SP_RESOURCE_RIF_MAC_PROFILES); + WARN_ON(!idr_is_empty(&mlxsw_sp->router->rif_mac_profiles_idr)); + idr_destroy(&mlxsw_sp->router->rif_mac_profiles_idr); kfree(mlxsw_sp->router->rifs); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h index 1d0d28f8ff05..99e8371a82a5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h @@ -39,6 +39,9 @@ mlxsw_sp_fib_entry_op_ctx_clear(struct mlxsw_sp_fib_entry_op_ctx *op_ctx) struct mlxsw_sp_router { struct mlxsw_sp *mlxsw_sp; struct mlxsw_sp_rif **rifs; + struct idr rif_mac_profiles_idr; + atomic_t rif_mac_profiles_count; + u8 max_rif_mac_profile; struct mlxsw_sp_vr *vrs; struct rhashtable neigh_ht; struct rhashtable nexthop_group_ht; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 22fede5cb32c..81c7e8a7fcf5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -1635,16 +1635,13 @@ mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp, u16 fid) { struct mlxsw_sp_mid *mid; - size_t alloc_size; mid = kzalloc(sizeof(*mid), GFP_KERNEL); if (!mid) return NULL; - alloc_size = sizeof(unsigned long) * - BITS_TO_LONGS(mlxsw_core_max_ports(mlxsw_sp->core)); - - mid->ports_in_mid = kzalloc(alloc_size, GFP_KERNEL); + mid->ports_in_mid = bitmap_zalloc(mlxsw_core_max_ports(mlxsw_sp->core), + GFP_KERNEL); if (!mid->ports_in_mid) goto err_ports_in_mid_alloc; @@ -1663,7 +1660,7 @@ out: return mid; err_write_mdb_entry: - kfree(mid->ports_in_mid); + bitmap_free(mid->ports_in_mid); err_ports_in_mid_alloc: kfree(mid); return NULL; @@ -1680,7 +1677,7 @@ static int mlxsw_sp_port_remove_from_mid(struct mlxsw_sp_port *mlxsw_sp_port, mlxsw_core_max_ports(mlxsw_sp->core))) { err = mlxsw_sp_mc_remove_mdb_entry(mlxsw_sp, mid); list_del(&mid->list); - kfree(mid->ports_in_mid); + bitmap_free(mid->ports_in_mid); kfree(mid); } return err; diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c b/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c index af70e2795125..fb74752de0ca 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c @@ -92,12 +92,11 @@ static void sparx5_phylink_validate(struct phylink_config *config, } break; default: - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); return; } - bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_and(state->advertising, state->advertising, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); } static void sparx5_phylink_mac_config(struct phylink_config *config, diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c index d65697c239c8..ef95f4017c6d 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_en.c +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c @@ -1667,24 +1667,23 @@ int mana_attach(struct net_device *ndev) if (err) return err; - err = mana_alloc_queues(ndev); - if (err) { - kfree(apc->rxqs); - apc->rxqs = NULL; - return err; + if (apc->port_st_save) { + err = mana_alloc_queues(ndev); + if (err) { + mana_cleanup_port_context(apc); + return err; + } } - netif_device_attach(ndev); - apc->port_is_up = apc->port_st_save; /* Ensure port state updated before txq state */ smp_wmb(); - if (apc->port_is_up) { + if (apc->port_is_up) netif_carrier_on(ndev); - netif_tx_wake_all_queues(ndev); - } + + netif_device_attach(ndev); return 0; } diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c index 7e74339f39ae..c3c81ae3fafd 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c +++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c @@ -211,9 +211,6 @@ static int mana_set_channels(struct net_device *ndev, unsigned int old_count = apc->num_queues; int err, err2; - if (!apc->port_is_up) - return -EOPNOTSUPP; - err = mana_detach(ndev, false); if (err) { netdev_err(ndev, "mana_detach failed: %d\n", err); diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 4e5ae687d2e2..e6c18b598d5c 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -20,11 +20,13 @@ struct ocelot_mact_entry { enum macaccess_entry_type type; }; +/* Caller must hold &ocelot->mact_lock */ static inline u32 ocelot_mact_read_macaccess(struct ocelot *ocelot) { return ocelot_read(ocelot, ANA_TABLES_MACACCESS); } +/* Caller must hold &ocelot->mact_lock */ static inline int ocelot_mact_wait_for_completion(struct ocelot *ocelot) { u32 val; @@ -36,6 +38,7 @@ static inline int ocelot_mact_wait_for_completion(struct ocelot *ocelot) TABLE_UPDATE_SLEEP_US, TABLE_UPDATE_TIMEOUT_US); } +/* Caller must hold &ocelot->mact_lock */ static void ocelot_mact_select(struct ocelot *ocelot, const unsigned char mac[ETH_ALEN], unsigned int vid) @@ -67,6 +70,7 @@ int ocelot_mact_learn(struct ocelot *ocelot, int port, ANA_TABLES_MACACCESS_ENTRYTYPE(type) | ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_LEARN); unsigned int mc_ports; + int err; /* Set MAC_CPU_COPY if the CPU port is used by a multicast entry */ if (type == ENTRYTYPE_MACv4) @@ -79,18 +83,28 @@ int ocelot_mact_learn(struct ocelot *ocelot, int port, if (mc_ports & BIT(ocelot->num_phys_ports)) cmd |= ANA_TABLES_MACACCESS_MAC_CPU_COPY; + mutex_lock(&ocelot->mact_lock); + ocelot_mact_select(ocelot, mac, vid); /* Issue a write command */ ocelot_write(ocelot, cmd, ANA_TABLES_MACACCESS); - return ocelot_mact_wait_for_completion(ocelot); + err = ocelot_mact_wait_for_completion(ocelot); + + mutex_unlock(&ocelot->mact_lock); + + return err; } EXPORT_SYMBOL(ocelot_mact_learn); int ocelot_mact_forget(struct ocelot *ocelot, const unsigned char mac[ETH_ALEN], unsigned int vid) { + int err; + + mutex_lock(&ocelot->mact_lock); + ocelot_mact_select(ocelot, mac, vid); /* Issue a forget command */ @@ -98,7 +112,11 @@ int ocelot_mact_forget(struct ocelot *ocelot, ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_FORGET), ANA_TABLES_MACACCESS); - return ocelot_mact_wait_for_completion(ocelot); + err = ocelot_mact_wait_for_completion(ocelot); + + mutex_unlock(&ocelot->mact_lock); + + return err; } EXPORT_SYMBOL(ocelot_mact_forget); @@ -114,7 +132,9 @@ static void ocelot_mact_init(struct ocelot *ocelot) | ANA_AGENCTRL_LEARN_IGNORE_VLAN, ANA_AGENCTRL); - /* Clear the MAC table */ + /* Clear the MAC table. We are not concurrent with anyone, so + * holding &ocelot->mact_lock is pointless. + */ ocelot_write(ocelot, MACACCESS_CMD_INIT, ANA_TABLES_MACACCESS); } @@ -1170,6 +1190,7 @@ nla_put_failure: } EXPORT_SYMBOL(ocelot_port_fdb_do_dump); +/* Caller must hold &ocelot->mact_lock */ static int ocelot_mact_read(struct ocelot *ocelot, int port, int row, int col, struct ocelot_mact_entry *entry) { @@ -1220,33 +1241,40 @@ static int ocelot_mact_read(struct ocelot *ocelot, int port, int row, int col, int ocelot_fdb_dump(struct ocelot *ocelot, int port, dsa_fdb_dump_cb_t *cb, void *data) { + int err = 0; int i, j; + /* We could take the lock just around ocelot_mact_read, but doing so + * thousands of times in a row seems rather pointless and inefficient. + */ + mutex_lock(&ocelot->mact_lock); + /* Loop through all the mac tables entries. */ for (i = 0; i < ocelot->num_mact_rows; i++) { for (j = 0; j < 4; j++) { struct ocelot_mact_entry entry; bool is_static; - int ret; - ret = ocelot_mact_read(ocelot, port, i, j, &entry); + err = ocelot_mact_read(ocelot, port, i, j, &entry); /* If the entry is invalid (wrong port, invalid...), * skip it. */ - if (ret == -EINVAL) + if (err == -EINVAL) continue; - else if (ret) - return ret; + else if (err) + break; is_static = (entry.type == ENTRYTYPE_LOCKED); - ret = cb(entry.mac, entry.vid, is_static, data); - if (ret) - return ret; + err = cb(entry.mac, entry.vid, is_static, data); + if (err) + break; } } - return 0; + mutex_unlock(&ocelot->mact_lock); + + return err; } EXPORT_SYMBOL(ocelot_fdb_dump); @@ -2231,6 +2259,7 @@ int ocelot_init(struct ocelot *ocelot) mutex_init(&ocelot->stats_lock); mutex_init(&ocelot->ptp_lock); + mutex_init(&ocelot->mact_lock); spin_lock_init(&ocelot->ptp_clock_lock); spin_lock_init(&ocelot->ts_id_lock); snprintf(queue_name, sizeof(queue_name), "%s-stats", diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index e3fc4548f642..eaeba60b1bba 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -1509,7 +1509,7 @@ static void vsc7514_phylink_validate(struct phylink_config *config, if (state->interface != PHY_INTERFACE_MODE_NA && state->interface != ocelot_port->phy_mode) { - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); return; } @@ -1528,9 +1528,8 @@ static void vsc7514_phylink_validate(struct phylink_config *config, phylink_set(mask, 2500baseT_Full); phylink_set(mask, 2500baseX_Full); - bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_and(state->advertising, state->advertising, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); } static void vsc7514_phylink_mac_config(struct phylink_config *config, diff --git a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c index 6b45cae39a20..c54d735b9e2e 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c @@ -214,8 +214,7 @@ static int ionic_get_link_ksettings(struct net_device *netdev, break; } - bitmap_copy(ks->link_modes.advertising, ks->link_modes.supported, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_copy(ks->link_modes.advertising, ks->link_modes.supported); ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER); ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS); diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index 18f3bf7c4dfe..cc4ec2bb36db 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -3992,7 +3992,7 @@ static int qed_hw_get_resc(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) } else if (rc == -EINVAL) { DP_INFO(p_hwfn, "Skip the max values setting of the soft resources since the resource lock is not supported by the MFW\n"); - } else if (!rc && !resc_lock_params.b_granted) { + } else if (!resc_lock_params.b_granted) { DP_NOTICE(p_hwfn, "Failed to acquire the resource lock for the resource allocation commands\n"); return -EBUSY; diff --git a/drivers/net/ethernet/qlogic/qed/qed_ptp.c b/drivers/net/ethernet/qlogic/qed/qed_ptp.c index 2c62d732e5c2..295ce435a1a4 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_ptp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_ptp.c @@ -63,12 +63,12 @@ static int qed_ptp_res_lock(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) DP_INFO(p_hwfn, "PF doesn't have lock ownership\n"); return -EBUSY; - } else if (!rc && !params.b_granted) { + } else if (!params.b_granted) { DP_INFO(p_hwfn, "Failed to acquire ptp resource lock\n"); return -EBUSY; } - return rc; + return 0; } static int qed_ptp_res_unlock(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 0b7606987c1e..9b068b81ae09 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -1525,7 +1525,7 @@ static void axienet_validate(struct phylink_config *config, netdev_warn(ndev, "Cannot use PHY mode %s, supported: %s\n", phy_modes(state->interface), phy_modes(lp->phy_mode)); - bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(supported); return; } } @@ -1558,10 +1558,8 @@ static void axienet_validate(struct phylink_config *config, break; } - bitmap_and(supported, supported, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_and(state->advertising, state->advertising, mask, - __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); } static void axienet_mac_pcs_get_state(struct phylink_config *config, diff --git a/drivers/net/fddi/defza.c b/drivers/net/fddi/defza.c index 3a6b08eb5e1b..f5c25acaa577 100644 --- a/drivers/net/fddi/defza.c +++ b/drivers/net/fddi/defza.c @@ -1380,7 +1380,7 @@ static int fza_probe(struct device *bdev) goto err_out_irq; fza_reads(&init->hw_addr, &hw_addr, sizeof(hw_addr)); - dev_addr_set(dev, &hw_addr); + dev_addr_set(dev, (u8 *)&hw_addr); fza_reads(&init->rom_rev, &rom_rev, sizeof(rom_rev)); fza_reads(&init->fw_rev, &fw_rev, sizeof(fw_rev)); diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 18b6dba9394e..16aa3a478e9e 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -250,7 +250,7 @@ static bool send_sci(const struct macsec_secy *secy) (secy->n_rx_sc > 1 && !tx_sc->end_station && !tx_sc->scb); } -static sci_t make_sci(u8 *addr, __be16 port) +static sci_t make_sci(const u8 *addr, __be16 port) { sci_t sci; diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 6189acb33973..d2f830ec2969 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -698,7 +698,8 @@ hash_del: return 0; } -static int macvlan_sync_address(struct net_device *dev, unsigned char *addr) +static int macvlan_sync_address(struct net_device *dev, + const unsigned char *addr) { struct macvlan_dev *vlan = netdev_priv(dev); struct net_device *lowerdev = vlan->lowerdev; diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c index 7de631f5356f..cd6742e6ba8b 100644 --- a/drivers/net/pcs/pcs-xpcs.c +++ b/drivers/net/pcs/pcs-xpcs.c @@ -646,7 +646,7 @@ void xpcs_validate(struct dw_xpcs *xpcs, unsigned long *supported, if (state->interface == PHY_INTERFACE_MODE_NA) return; - bitmap_zero(xpcs_supported, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(xpcs_supported); compat = xpcs_find_compat(xpcs->id, state->interface); diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index 69da011e82c8..f1cbe1f6ddec 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -33,14 +33,17 @@ #define AT803X_SFC_DISABLE_JABBER BIT(0) #define AT803X_SPECIFIC_STATUS 0x11 -#define AT803X_SS_SPEED_MASK (3 << 14) -#define AT803X_SS_SPEED_1000 (2 << 14) -#define AT803X_SS_SPEED_100 (1 << 14) -#define AT803X_SS_SPEED_10 (0 << 14) +#define AT803X_SS_SPEED_MASK GENMASK(15, 14) +#define AT803X_SS_SPEED_1000 2 +#define AT803X_SS_SPEED_100 1 +#define AT803X_SS_SPEED_10 0 #define AT803X_SS_DUPLEX BIT(13) #define AT803X_SS_SPEED_DUPLEX_RESOLVED BIT(11) #define AT803X_SS_MDIX BIT(6) +#define QCA808X_SS_SPEED_MASK GENMASK(9, 7) +#define QCA808X_SS_SPEED_2500 4 + #define AT803X_INTR_ENABLE 0x12 #define AT803X_INTR_ENABLE_AUTONEG_ERR BIT(15) #define AT803X_INTR_ENABLE_SPEED_CHANGED BIT(14) @@ -70,7 +73,8 @@ #define AT803X_CDT_STATUS_DELTA_TIME_MASK GENMASK(7, 0) #define AT803X_LED_CONTROL 0x18 -#define AT803X_DEVICE_ADDR 0x03 +#define AT803X_PHY_MMD3_WOL_CTRL 0x8012 +#define AT803X_WOL_EN BIT(5) #define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C #define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B #define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A @@ -157,6 +161,8 @@ #define ATH8035_PHY_ID 0x004dd072 #define AT8030_PHY_ID_MASK 0xffffffef +#define QCA8081_PHY_ID 0x004dd101 + #define QCA8327_A_PHY_ID 0x004dd033 #define QCA8327_B_PHY_ID 0x004dd034 #define QCA8337_PHY_ID 0x004dd036 @@ -172,7 +178,84 @@ #define AT803X_KEEP_PLL_ENABLED BIT(0) #define AT803X_DISABLE_SMARTEEE BIT(1) -MODULE_DESCRIPTION("Qualcomm Atheros AR803x PHY driver"); +/* ADC threshold */ +#define QCA808X_PHY_DEBUG_ADC_THRESHOLD 0x2c80 +#define QCA808X_ADC_THRESHOLD_MASK GENMASK(7, 0) +#define QCA808X_ADC_THRESHOLD_80MV 0 +#define QCA808X_ADC_THRESHOLD_100MV 0xf0 +#define QCA808X_ADC_THRESHOLD_200MV 0x0f +#define QCA808X_ADC_THRESHOLD_300MV 0xff + +/* CLD control */ +#define QCA808X_PHY_MMD3_ADDR_CLD_CTRL7 0x8007 +#define QCA808X_8023AZ_AFE_CTRL_MASK GENMASK(8, 4) +#define QCA808X_8023AZ_AFE_EN 0x90 + +/* AZ control */ +#define QCA808X_PHY_MMD3_AZ_TRAINING_CTRL 0x8008 +#define QCA808X_MMD3_AZ_TRAINING_VAL 0x1c32 + +#define QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB 0x8014 +#define QCA808X_MSE_THRESHOLD_20DB_VALUE 0x529 + +#define QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB 0x800E +#define QCA808X_MSE_THRESHOLD_17DB_VALUE 0x341 + +#define QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB 0x801E +#define QCA808X_MSE_THRESHOLD_27DB_VALUE 0x419 + +#define QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB 0x8020 +#define QCA808X_MSE_THRESHOLD_28DB_VALUE 0x341 + +#define QCA808X_PHY_MMD7_TOP_OPTION1 0x901c +#define QCA808X_TOP_OPTION1_DATA 0x0 + +#define QCA808X_PHY_MMD3_DEBUG_1 0xa100 +#define QCA808X_MMD3_DEBUG_1_VALUE 0x9203 +#define QCA808X_PHY_MMD3_DEBUG_2 0xa101 +#define QCA808X_MMD3_DEBUG_2_VALUE 0x48ad +#define QCA808X_PHY_MMD3_DEBUG_3 0xa103 +#define QCA808X_MMD3_DEBUG_3_VALUE 0x1698 +#define QCA808X_PHY_MMD3_DEBUG_4 0xa105 +#define QCA808X_MMD3_DEBUG_4_VALUE 0x8001 +#define QCA808X_PHY_MMD3_DEBUG_5 0xa106 +#define QCA808X_MMD3_DEBUG_5_VALUE 0x1111 +#define QCA808X_PHY_MMD3_DEBUG_6 0xa011 +#define QCA808X_MMD3_DEBUG_6_VALUE 0x5f85 + +/* master/slave seed config */ +#define QCA808X_PHY_DEBUG_LOCAL_SEED 9 +#define QCA808X_MASTER_SLAVE_SEED_ENABLE BIT(1) +#define QCA808X_MASTER_SLAVE_SEED_CFG GENMASK(12, 2) +#define QCA808X_MASTER_SLAVE_SEED_RANGE 0x32 + +/* Hibernation yields lower power consumpiton in contrast with normal operation mode. + * when the copper cable is unplugged, the PHY enters into hibernation mode in about 10s. + */ +#define QCA808X_DBG_AN_TEST 0xb +#define QCA808X_HIBERNATION_EN BIT(15) + +#define QCA808X_CDT_ENABLE_TEST BIT(15) +#define QCA808X_CDT_INTER_CHECK_DIS BIT(13) +#define QCA808X_CDT_LENGTH_UNIT BIT(10) + +#define QCA808X_MMD3_CDT_STATUS 0x8064 +#define QCA808X_MMD3_CDT_DIAG_PAIR_A 0x8065 +#define QCA808X_MMD3_CDT_DIAG_PAIR_B 0x8066 +#define QCA808X_MMD3_CDT_DIAG_PAIR_C 0x8067 +#define QCA808X_MMD3_CDT_DIAG_PAIR_D 0x8068 +#define QCA808X_CDT_DIAG_LENGTH GENMASK(7, 0) + +#define QCA808X_CDT_CODE_PAIR_A GENMASK(15, 12) +#define QCA808X_CDT_CODE_PAIR_B GENMASK(11, 8) +#define QCA808X_CDT_CODE_PAIR_C GENMASK(7, 4) +#define QCA808X_CDT_CODE_PAIR_D GENMASK(3, 0) +#define QCA808X_CDT_STATUS_STAT_FAIL 0 +#define QCA808X_CDT_STATUS_STAT_NORMAL 1 +#define QCA808X_CDT_STATUS_STAT_OPEN 2 +#define QCA808X_CDT_STATUS_STAT_SHORT 3 + +MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver"); MODULE_AUTHOR("Matus Ujhelyi"); MODULE_LICENSE("GPL"); @@ -336,9 +419,9 @@ static int at803x_set_wol(struct phy_device *phydev, { struct net_device *ndev = phydev->attached_dev; const u8 *mac; - int ret; - u32 value; - unsigned int i, offsets[] = { + int ret, irq_enabled; + unsigned int i; + const unsigned int offsets[] = { AT803X_LOC_MAC_ADDR_32_47_OFFSET, AT803X_LOC_MAC_ADDR_16_31_OFFSET, AT803X_LOC_MAC_ADDR_0_15_OFFSET, @@ -354,25 +437,48 @@ static int at803x_set_wol(struct phy_device *phydev, return -EINVAL; for (i = 0; i < 3; i++) - phy_write_mmd(phydev, AT803X_DEVICE_ADDR, offsets[i], + phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i], mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); - value = phy_read(phydev, AT803X_INTR_ENABLE); - value |= AT803X_INTR_ENABLE_WOL; - ret = phy_write(phydev, AT803X_INTR_ENABLE, value); + /* Enable WOL function */ + ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_PHY_MMD3_WOL_CTRL, + 0, AT803X_WOL_EN); + if (ret) + return ret; + /* Enable WOL interrupt */ + ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL); if (ret) return ret; - value = phy_read(phydev, AT803X_INTR_STATUS); } else { - value = phy_read(phydev, AT803X_INTR_ENABLE); - value &= (~AT803X_INTR_ENABLE_WOL); - ret = phy_write(phydev, AT803X_INTR_ENABLE, value); + /* Disable WoL function */ + ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_PHY_MMD3_WOL_CTRL, + AT803X_WOL_EN, 0); + if (ret) + return ret; + /* Disable WOL interrupt */ + ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0); if (ret) return ret; - value = phy_read(phydev, AT803X_INTR_STATUS); } - return ret; + /* Clear WOL status */ + ret = phy_read(phydev, AT803X_INTR_STATUS); + if (ret < 0) + return ret; + + /* Check if there are other interrupts except for WOL triggered when PHY is + * in interrupt mode, only the interrupts enabled by AT803X_INTR_ENABLE can + * be passed up to the interrupt PIN. + */ + irq_enabled = phy_read(phydev, AT803X_INTR_ENABLE); + if (irq_enabled < 0) + return irq_enabled; + + irq_enabled &= ~AT803X_INTR_ENABLE_WOL; + if (ret & irq_enabled && !phy_polling_mode(phydev)) + phy_trigger_machine(phydev); + + return 0; } static void at803x_get_wol(struct phy_device *phydev, @@ -383,8 +489,11 @@ static void at803x_get_wol(struct phy_device *phydev, wol->supported = WAKE_MAGIC; wol->wolopts = 0; - value = phy_read(phydev, AT803X_INTR_ENABLE); - if (value & AT803X_INTR_ENABLE_WOL) + value = phy_read_mmd(phydev, MDIO_MMD_PCS, AT803X_PHY_MMD3_WOL_CTRL); + if (value < 0) + return; + + if (value & AT803X_WOL_EN) wol->wolopts |= WAKE_MAGIC; } @@ -712,6 +821,15 @@ static int at803x_get_features(struct phy_device *phydev) if (err) return err; + if (phydev->drv->phy_id == QCA8081_PHY_ID) { + err = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_NG_EXTABLE); + if (err < 0) + return err; + + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported, + err & MDIO_PMA_NG_EXTABLE_2_5GBT); + } + if (phydev->drv->phy_id != ATH8031_PHY_ID) return 0; @@ -930,27 +1048,9 @@ static void at803x_link_change_notify(struct phy_device *phydev) } } -static int at803x_read_status(struct phy_device *phydev) +static int at803x_read_specific_status(struct phy_device *phydev) { - int ss, err, old_link = phydev->link; - - /* Update the link, but return if there was an error */ - err = genphy_update_link(phydev); - if (err) - return err; - - /* why bother the PHY if nothing can have changed */ - if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link) - return 0; - - phydev->speed = SPEED_UNKNOWN; - phydev->duplex = DUPLEX_UNKNOWN; - phydev->pause = 0; - phydev->asym_pause = 0; - - err = genphy_read_lpa(phydev); - if (err < 0) - return err; + int ss; /* Read the AT8035 PHY-Specific Status register, which indicates the * speed and duplex that the PHY is actually using, irrespective of @@ -961,13 +1061,19 @@ static int at803x_read_status(struct phy_device *phydev) return ss; if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) { - int sfc; + int sfc, speed; sfc = phy_read(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL); if (sfc < 0) return sfc; - switch (ss & AT803X_SS_SPEED_MASK) { + /* qca8081 takes the different bits for speed value from at803x */ + if (phydev->drv->phy_id == QCA8081_PHY_ID) + speed = FIELD_GET(QCA808X_SS_SPEED_MASK, ss); + else + speed = FIELD_GET(AT803X_SS_SPEED_MASK, ss); + + switch (speed) { case AT803X_SS_SPEED_10: phydev->speed = SPEED_10; break; @@ -977,6 +1083,9 @@ static int at803x_read_status(struct phy_device *phydev) case AT803X_SS_SPEED_1000: phydev->speed = SPEED_1000; break; + case QCA808X_SS_SPEED_2500: + phydev->speed = SPEED_2500; + break; } if (ss & AT803X_SS_DUPLEX) phydev->duplex = DUPLEX_FULL; @@ -1001,6 +1110,35 @@ static int at803x_read_status(struct phy_device *phydev) } } + return 0; +} + +static int at803x_read_status(struct phy_device *phydev) +{ + int err, old_link = phydev->link; + + /* Update the link, but return if there was an error */ + err = genphy_update_link(phydev); + if (err) + return err; + + /* why bother the PHY if nothing can have changed */ + if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link) + return 0; + + phydev->speed = SPEED_UNKNOWN; + phydev->duplex = DUPLEX_UNKNOWN; + phydev->pause = 0; + phydev->asym_pause = 0; + + err = genphy_read_lpa(phydev); + if (err < 0) + return err; + + err = at803x_read_specific_status(phydev); + if (err < 0) + return err; + if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) phy_resolve_aneg_pause(phydev); @@ -1048,7 +1186,30 @@ static int at803x_config_aneg(struct phy_device *phydev) return ret; } - return genphy_config_aneg(phydev); + /* Do not restart auto-negotiation by setting ret to 0 defautly, + * when calling __genphy_config_aneg later. + */ + ret = 0; + + if (phydev->drv->phy_id == QCA8081_PHY_ID) { + int phy_ctrl = 0; + + /* The reg MII_BMCR also needs to be configured for force mode, the + * genphy_config_aneg is also needed. + */ + if (phydev->autoneg == AUTONEG_DISABLE) + genphy_c45_pma_setup_forced(phydev); + + if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->advertising)) + phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G; + + ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, + MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl); + if (ret < 0) + return ret; + } + + return __genphy_config_aneg(phydev, ret); } static int at803x_get_downshift(struct phy_device *phydev, u8 *d) @@ -1184,8 +1345,14 @@ static int at803x_cdt_start(struct phy_device *phydev, int pair) { u16 cdt; - cdt = FIELD_PREP(AT803X_CDT_MDI_PAIR_MASK, pair) | - AT803X_CDT_ENABLE_TEST; + /* qca8081 takes the different bit 15 to enable CDT test */ + if (phydev->drv->phy_id == QCA8081_PHY_ID) + cdt = QCA808X_CDT_ENABLE_TEST | + QCA808X_CDT_LENGTH_UNIT | + QCA808X_CDT_INTER_CHECK_DIS; + else + cdt = FIELD_PREP(AT803X_CDT_MDI_PAIR_MASK, pair) | + AT803X_CDT_ENABLE_TEST; return phy_write(phydev, AT803X_CDT, cdt); } @@ -1193,10 +1360,16 @@ static int at803x_cdt_start(struct phy_device *phydev, int pair) static int at803x_cdt_wait_for_completion(struct phy_device *phydev) { int val, ret; + u16 cdt_en; + + if (phydev->drv->phy_id == QCA8081_PHY_ID) + cdt_en = QCA808X_CDT_ENABLE_TEST; + else + cdt_en = AT803X_CDT_ENABLE_TEST; /* One test run takes about 25ms */ ret = phy_read_poll_timeout(phydev, AT803X_CDT, val, - !(val & AT803X_CDT_ENABLE_TEST), + !(val & cdt_en), 30000, 100000, true); return ret < 0 ? ret : 0; @@ -1405,6 +1578,298 @@ static int qca83xx_suspend(struct phy_device *phydev) return 0; } +static int qca808x_phy_fast_retrain_config(struct phy_device *phydev) +{ + int ret; + + /* Enable fast retrain */ + ret = genphy_c45_fast_retrain(phydev, true); + if (ret) + return ret; + + phy_write_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_TOP_OPTION1, + QCA808X_TOP_OPTION1_DATA); + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB, + QCA808X_MSE_THRESHOLD_20DB_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB, + QCA808X_MSE_THRESHOLD_17DB_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB, + QCA808X_MSE_THRESHOLD_27DB_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB, + QCA808X_MSE_THRESHOLD_28DB_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_1, + QCA808X_MMD3_DEBUG_1_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_4, + QCA808X_MMD3_DEBUG_4_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_5, + QCA808X_MMD3_DEBUG_5_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_3, + QCA808X_MMD3_DEBUG_3_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_6, + QCA808X_MMD3_DEBUG_6_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_2, + QCA808X_MMD3_DEBUG_2_VALUE); + + return 0; +} + +static int qca808x_phy_ms_random_seed_set(struct phy_device *phydev) +{ + u16 seed_value = (prandom_u32() % QCA808X_MASTER_SLAVE_SEED_RANGE); + + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, + QCA808X_MASTER_SLAVE_SEED_CFG, + FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value)); +} + +static int qca808x_phy_ms_seed_enable(struct phy_device *phydev, bool enable) +{ + u16 seed_enable = 0; + + if (enable) + seed_enable = QCA808X_MASTER_SLAVE_SEED_ENABLE; + + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, + QCA808X_MASTER_SLAVE_SEED_ENABLE, seed_enable); +} + +static int qca808x_config_init(struct phy_device *phydev) +{ + int ret; + + /* Active adc&vga on 802.3az for the link 1000M and 100M */ + ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_ADDR_CLD_CTRL7, + QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN); + if (ret) + return ret; + + /* Adjust the threshold on 802.3az for the link 1000M */ + ret = phy_write_mmd(phydev, MDIO_MMD_PCS, + QCA808X_PHY_MMD3_AZ_TRAINING_CTRL, QCA808X_MMD3_AZ_TRAINING_VAL); + if (ret) + return ret; + + /* Config the fast retrain for the link 2500M */ + ret = qca808x_phy_fast_retrain_config(phydev); + if (ret) + return ret; + + /* Configure lower ramdom seed to make phy linked as slave mode */ + ret = qca808x_phy_ms_random_seed_set(phydev); + if (ret) + return ret; + + /* Enable seed */ + ret = qca808x_phy_ms_seed_enable(phydev, true); + if (ret) + return ret; + + /* Configure adc threshold as 100mv for the link 10M */ + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, + QCA808X_ADC_THRESHOLD_MASK, QCA808X_ADC_THRESHOLD_100MV); +} + +static int qca808x_read_status(struct phy_device *phydev) +{ + int ret; + + ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT); + if (ret < 0) + return ret; + + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->lp_advertising, + ret & MDIO_AN_10GBT_STAT_LP2_5G); + + ret = genphy_read_status(phydev); + if (ret) + return ret; + + ret = at803x_read_specific_status(phydev); + if (ret < 0) + return ret; + + if (phydev->link && phydev->speed == SPEED_2500) + phydev->interface = PHY_INTERFACE_MODE_2500BASEX; + else + phydev->interface = PHY_INTERFACE_MODE_SMII; + + /* generate seed as a lower random value to make PHY linked as SLAVE easily, + * except for master/slave configuration fault detected. + * the reason for not putting this code into the function link_change_notify is + * the corner case where the link partner is also the qca8081 PHY and the seed + * value is configured as the same value, the link can't be up and no link change + * occurs. + */ + if (!phydev->link) { + if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR) { + qca808x_phy_ms_seed_enable(phydev, false); + } else { + qca808x_phy_ms_random_seed_set(phydev); + qca808x_phy_ms_seed_enable(phydev, true); + } + } + + return 0; +} + +static int qca808x_soft_reset(struct phy_device *phydev) +{ + int ret; + + ret = genphy_soft_reset(phydev); + if (ret < 0) + return ret; + + return qca808x_phy_ms_seed_enable(phydev, true); +} + +static bool qca808x_cdt_fault_length_valid(int cdt_code) +{ + switch (cdt_code) { + case QCA808X_CDT_STATUS_STAT_SHORT: + case QCA808X_CDT_STATUS_STAT_OPEN: + return true; + default: + return false; + } +} + +static int qca808x_cable_test_result_trans(int cdt_code) +{ + switch (cdt_code) { + case QCA808X_CDT_STATUS_STAT_NORMAL: + return ETHTOOL_A_CABLE_RESULT_CODE_OK; + case QCA808X_CDT_STATUS_STAT_SHORT: + return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; + case QCA808X_CDT_STATUS_STAT_OPEN: + return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; + case QCA808X_CDT_STATUS_STAT_FAIL: + default: + return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; + } +} + +static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair) +{ + int val; + u32 cdt_length_reg = 0; + + switch (pair) { + case ETHTOOL_A_CABLE_PAIR_A: + cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_A; + break; + case ETHTOOL_A_CABLE_PAIR_B: + cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_B; + break; + case ETHTOOL_A_CABLE_PAIR_C: + cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_C; + break; + case ETHTOOL_A_CABLE_PAIR_D: + cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_D; + break; + default: + return -EINVAL; + } + + val = phy_read_mmd(phydev, MDIO_MMD_PCS, cdt_length_reg); + if (val < 0) + return val; + + return (FIELD_GET(QCA808X_CDT_DIAG_LENGTH, val) * 824) / 10; +} + +static int qca808x_cable_test_start(struct phy_device *phydev) +{ + int ret; + + /* perform CDT with the following configs: + * 1. disable hibernation. + * 2. force PHY working in MDI mode. + * 3. for PHY working in 1000BaseT. + * 4. configure the threshold. + */ + + ret = at803x_debug_reg_mask(phydev, QCA808X_DBG_AN_TEST, QCA808X_HIBERNATION_EN, 0); + if (ret < 0) + return ret; + + ret = at803x_config_mdix(phydev, ETH_TP_MDI); + if (ret < 0) + return ret; + + /* Force 1000base-T needs to configure PMA/PMD and MII_BMCR */ + phydev->duplex = DUPLEX_FULL; + phydev->speed = SPEED_1000; + ret = genphy_c45_pma_setup_forced(phydev); + if (ret < 0) + return ret; + + ret = genphy_setup_forced(phydev); + if (ret < 0) + return ret; + + /* configure the thresholds for open, short, pair ok test */ + phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8074, 0xc040); + phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8076, 0xc040); + phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8077, 0xa060); + phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8078, 0xc050); + phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807a, 0xc060); + phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807e, 0xb060); + + return 0; +} + +static int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished) +{ + int ret, val; + int pair_a, pair_b, pair_c, pair_d; + + *finished = false; + + ret = at803x_cdt_start(phydev, 0); + if (ret) + return ret; + + ret = at803x_cdt_wait_for_completion(phydev); + if (ret) + return ret; + + val = phy_read_mmd(phydev, MDIO_MMD_PCS, QCA808X_MMD3_CDT_STATUS); + if (val < 0) + return val; + + pair_a = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, val); + pair_b = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, val); + pair_c = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, val); + pair_d = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, val); + + ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, + qca808x_cable_test_result_trans(pair_a)); + ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_B, + qca808x_cable_test_result_trans(pair_b)); + ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_C, + qca808x_cable_test_result_trans(pair_c)); + ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_D, + qca808x_cable_test_result_trans(pair_d)); + + if (qca808x_cdt_fault_length_valid(pair_a)) + ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A, + qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A)); + if (qca808x_cdt_fault_length_valid(pair_b)) + ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B, + qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B)); + if (qca808x_cdt_fault_length_valid(pair_c)) + ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C, + qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C)); + if (qca808x_cdt_fault_length_valid(pair_d)) + ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D, + qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D)); + + *finished = true; + + return 0; +} + static struct phy_driver at803x_driver[] = { { /* Qualcomm Atheros AR8035 */ @@ -1564,6 +2029,26 @@ static struct phy_driver at803x_driver[] = { .get_stats = at803x_get_stats, .suspend = qca83xx_suspend, .resume = qca83xx_resume, +}, { + /* Qualcomm QCA8081 */ + PHY_ID_MATCH_EXACT(QCA8081_PHY_ID), + .name = "Qualcomm QCA8081", + .flags = PHY_POLL_CABLE_TEST, + .config_intr = at803x_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .get_tunable = at803x_get_tunable, + .set_tunable = at803x_set_tunable, + .set_wol = at803x_set_wol, + .get_wol = at803x_get_wol, + .get_features = at803x_get_features, + .config_aneg = at803x_config_aneg, + .suspend = genphy_suspend, + .resume = genphy_resume, + .read_status = qca808x_read_status, + .config_init = qca808x_config_init, + .soft_reset = qca808x_soft_reset, + .cable_test_start = qca808x_cable_test_start, + .cable_test_get_status = qca808x_cable_test_get_status, }, }; module_phy_driver(at803x_driver); @@ -1578,6 +2063,7 @@ static struct mdio_device_id __maybe_unused atheros_tbl[] = { { PHY_ID_MATCH_EXACT(QCA8327_A_PHY_ID) }, { PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID) }, { PHY_ID_MATCH_EXACT(QCA9561_PHY_ID) }, + { PHY_ID_MATCH_EXACT(QCA8081_PHY_ID) }, { } }; diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c index 6ceadd2a0082..75593e7d1118 100644 --- a/drivers/net/phy/bcm7xxx.c +++ b/drivers/net/phy/bcm7xxx.c @@ -936,6 +936,7 @@ static struct phy_driver bcm7xxx_driver[] = { BCM7XXX_40NM_EPHY(PHY_ID_BCM7425, "Broadcom BCM7425"), BCM7XXX_40NM_EPHY(PHY_ID_BCM7429, "Broadcom BCM7429"), BCM7XXX_40NM_EPHY(PHY_ID_BCM7435, "Broadcom BCM7435"), + BCM7XXX_16NM_EPHY(PHY_ID_BCM7712, "Broadcom BCM7712"), }; static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = { @@ -958,6 +959,7 @@ static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = { { PHY_ID_BCM7439, 0xfffffff0, }, { PHY_ID_BCM7435, 0xfffffff0, }, { PHY_ID_BCM7445, 0xfffffff0, }, + { PHY_ID_BCM7712, 0xfffffff0, }, { } }; diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index 914619f3f0e3..8561f2d4443b 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -182,7 +182,7 @@ static int dp83867_set_wol(struct phy_device *phydev, { struct net_device *ndev = phydev->attached_dev; u16 val_rxcfg, val_micr; - u8 *mac; + const u8 *mac; val_rxcfg = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG); val_micr = phy_read(phydev, MII_DP83867_MICR); @@ -193,7 +193,7 @@ static int dp83867_set_wol(struct phy_device *phydev, val_micr |= MII_DP83867_MICR_WOL_INT_EN; if (wol->wolopts & WAKE_MAGIC) { - mac = (u8 *)ndev->dev_addr; + mac = (const u8 *)ndev->dev_addr; if (!is_valid_ether_addr(mac)) return -EINVAL; diff --git a/drivers/net/phy/dp83869.c b/drivers/net/phy/dp83869.c index 755220c6451f..7113925606f7 100644 --- a/drivers/net/phy/dp83869.c +++ b/drivers/net/phy/dp83869.c @@ -246,7 +246,7 @@ static int dp83869_set_wol(struct phy_device *phydev, { struct net_device *ndev = phydev->attached_dev; int val_rxcfg, val_micr; - u8 *mac; + const u8 *mac; int ret; val_rxcfg = phy_read_mmd(phydev, DP83869_DEVADDR, DP83869_RXFCFG); @@ -264,7 +264,7 @@ static int dp83869_set_wol(struct phy_device *phydev, if (wol->wolopts & WAKE_MAGIC || wol->wolopts & WAKE_MAGICSECURE) { - mac = (u8 *)ndev->dev_addr; + mac = (const u8 *)ndev->dev_addr; if (!is_valid_ether_addr(mac)) return -EINVAL; diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index c617dbcad6ea..db709d30bf84 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -611,6 +611,41 @@ int genphy_c45_loopback(struct phy_device *phydev, bool enable) } EXPORT_SYMBOL_GPL(genphy_c45_loopback); +/** + * genphy_c45_fast_retrain - configure fast retrain registers + * @phydev: target phy_device struct + * @enable: enable fast retrain or not + * + * Description: If fast-retrain is enabled, we configure PHY as + * advertising fast retrain capable and THP Bypass Request, then + * enable fast retrain. If it is not enabled, we configure fast + * retrain disabled. + */ +int genphy_c45_fast_retrain(struct phy_device *phydev, bool enable) +{ + int ret; + + if (!enable) + return phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FSRT_CSR, + MDIO_PMA_10GBR_FSRT_ENABLE); + + if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported)) { + ret = phy_set_bits_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, + MDIO_AN_10GBT_CTRL_ADVFSRT2_5G); + if (ret) + return ret; + + ret = phy_set_bits_mmd(phydev, MDIO_MMD_AN, MDIO_AN_CTRL2, + MDIO_AN_THP_BP2_5GT); + if (ret) + return ret; + } + + return phy_set_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FSRT_CSR, + MDIO_PMA_10GBR_FSRT_ENABLE); +} +EXPORT_SYMBOL_GPL(genphy_c45_fast_retrain); + struct phy_driver genphy_c45_driver = { .phy_id = 0xffffffff, .phy_id_mask = 0xffffffff, diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 7e93d81fa5ad..6da245dacca4 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -166,9 +166,45 @@ static const char *phylink_an_mode_str(unsigned int mode) return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown"; } +static int phylink_validate_any(struct phylink *pl, unsigned long *supported, + struct phylink_link_state *state) +{ + __ETHTOOL_DECLARE_LINK_MODE_MASK(all_adv) = { 0, }; + __ETHTOOL_DECLARE_LINK_MODE_MASK(all_s) = { 0, }; + __ETHTOOL_DECLARE_LINK_MODE_MASK(s); + struct phylink_link_state t; + int intf; + + for (intf = 0; intf < PHY_INTERFACE_MODE_MAX; intf++) { + if (test_bit(intf, pl->config->supported_interfaces)) { + linkmode_copy(s, supported); + + t = *state; + t.interface = intf; + pl->mac_ops->validate(pl->config, s, &t); + linkmode_or(all_s, all_s, s); + linkmode_or(all_adv, all_adv, t.advertising); + } + } + + linkmode_copy(supported, all_s); + linkmode_copy(state->advertising, all_adv); + + return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; +} + static int phylink_validate(struct phylink *pl, unsigned long *supported, struct phylink_link_state *state) { + if (!phy_interface_empty(pl->config->supported_interfaces)) { + if (state->interface == PHY_INTERFACE_MODE_NA) + return phylink_validate_any(pl, supported, state); + + if (!test_bit(state->interface, + pl->config->supported_interfaces)) + return -EINVAL; + } + pl->mac_ops->validate(pl->config, supported, state); return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; @@ -2542,12 +2578,10 @@ EXPORT_SYMBOL_GPL(phylink_decode_usxgmii_word); void phylink_mii_c22_pcs_get_state(struct mdio_device *pcs, struct phylink_link_state *state) { - struct mii_bus *bus = pcs->bus; - int addr = pcs->addr; int bmsr, lpa; - bmsr = mdiobus_read(bus, addr, MII_BMSR); - lpa = mdiobus_read(bus, addr, MII_LPA); + bmsr = mdiodev_read(pcs, MII_BMSR); + lpa = mdiodev_read(pcs, MII_LPA); if (bmsr < 0 || lpa < 0) { state->link = false; return; @@ -2603,8 +2637,6 @@ int phylink_mii_c22_pcs_set_advertisement(struct mdio_device *pcs, phy_interface_t interface, const unsigned long *advertising) { - struct mii_bus *bus = pcs->bus; - int addr = pcs->addr; u16 adv; switch (interface) { @@ -2618,12 +2650,10 @@ int phylink_mii_c22_pcs_set_advertisement(struct mdio_device *pcs, advertising)) adv |= ADVERTISE_1000XPSE_ASYM; - return mdiobus_modify_changed(bus, addr, MII_ADVERTISE, - 0xffff, adv); + return mdiodev_modify_changed(pcs, MII_ADVERTISE, 0xffff, adv); case PHY_INTERFACE_MODE_SGMII: - return mdiobus_modify_changed(bus, addr, MII_ADVERTISE, - 0xffff, 0x0001); + return mdiodev_modify_changed(pcs, MII_ADVERTISE, 0xffff, 0x0001); default: /* Nothing to do for other modes */ @@ -2666,8 +2696,7 @@ int phylink_mii_c22_pcs_config(struct mdio_device *pcs, unsigned int mode, else bmcr = 0; - ret = mdiobus_modify(pcs->bus, pcs->addr, MII_BMCR, - BMCR_ANENABLE | BMCR_ISOLATE, bmcr); + ret = mdiodev_modify(pcs, MII_BMCR, BMCR_ANENABLE | BMCR_ISOLATE, bmcr); if (ret < 0) return ret; @@ -2688,14 +2717,12 @@ EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_config); */ void phylink_mii_c22_pcs_an_restart(struct mdio_device *pcs) { - struct mii_bus *bus = pcs->bus; - int val, addr = pcs->addr; + int val = mdiodev_read(pcs, MII_BMCR); - val = mdiobus_read(bus, addr, MII_BMCR); if (val >= 0) { val |= BMCR_ANRESTART; - mdiobus_write(bus, addr, MII_BMCR, val); + mdiodev_write(pcs, MII_BMCR, val); } } EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_an_restart); diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c index 7362f8c3271c..0c6c0d1843bc 100644 --- a/drivers/net/phy/sfp-bus.c +++ b/drivers/net/phy/sfp-bus.c @@ -373,7 +373,7 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id, if (bus->sfp_quirk) bus->sfp_quirk->modes(id, modes); - bitmap_or(support, support, modes, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_or(support, support, modes); phylink_set(support, Autoneg); phylink_set(support, Pause); diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index 24db5768a3c0..e7fe9c0f63a9 100644 --- a/drivers/net/usb/catc.c +++ b/drivers/net/usb/catc.c @@ -770,17 +770,23 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id struct net_device *netdev; struct catc *catc; u8 broadcast[ETH_ALEN]; - int pktsz, ret; + u8 *macbuf; + int pktsz, ret = -ENOMEM; + + macbuf = kmalloc(ETH_ALEN, GFP_KERNEL); + if (!macbuf) + goto error; if (usb_set_interface(usbdev, intf->altsetting->desc.bInterfaceNumber, 1)) { dev_err(dev, "Can't set altsetting 1.\n"); - return -EIO; + ret = -EIO; + goto fail_mem;; } netdev = alloc_etherdev(sizeof(struct catc)); if (!netdev) - return -ENOMEM; + goto fail_mem; catc = netdev_priv(netdev); @@ -870,7 +876,8 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id dev_dbg(dev, "Getting MAC from SEEROM.\n"); - catc_get_mac(catc, netdev->dev_addr); + catc_get_mac(catc, macbuf); + eth_hw_addr_set(netdev, macbuf); dev_dbg(dev, "Setting MAC into registers.\n"); @@ -899,7 +906,8 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id } else { dev_dbg(dev, "Performing reset\n"); catc_reset(catc); - catc_get_mac(catc, netdev->dev_addr); + catc_get_mac(catc, macbuf); + eth_hw_addr_set(netdev, macbuf); dev_dbg(dev, "Setting RX Mode\n"); catc->rxmode[0] = RxEnable | RxPolarity | RxMultiCast; @@ -917,6 +925,7 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id if (ret) goto fail_clear_intfdata; + kfree(macbuf); return 0; fail_clear_intfdata: @@ -927,6 +936,9 @@ fail_free: usb_free_urb(catc->rx_urb); usb_free_urb(catc->irq_urb); free_netdev(netdev); +fail_mem: + kfree(macbuf); +error: return ret; } diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 7a205ddf0060..3e1b7746cce4 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -46,7 +46,7 @@ MODULE_DEVICE_TABLE(pci, vmxnet3_pciid_table); static int enable_mq = 1; static void -vmxnet3_write_mac_addr(struct vmxnet3_adapter *adapter, u8 *mac); +vmxnet3_write_mac_addr(struct vmxnet3_adapter *adapter, const u8 *mac); /* * Enable/Disable the given intr @@ -2806,7 +2806,7 @@ vmxnet3_quiesce_dev(struct vmxnet3_adapter *adapter) static void -vmxnet3_write_mac_addr(struct vmxnet3_adapter *adapter, u8 *mac) +vmxnet3_write_mac_addr(struct vmxnet3_adapter *adapter, const u8 *mac) { u32 tmp; diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 662e26117353..ccf677015d5b 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -35,6 +35,7 @@ #include <net/l3mdev.h> #include <net/fib_rules.h> #include <net/netns/generic.h> +#include <net/netfilter/nf_conntrack.h> #define DRV_NAME "vrf" #define DRV_VERSION "1.1" @@ -424,12 +425,26 @@ static int vrf_local_xmit(struct sk_buff *skb, struct net_device *dev, return NETDEV_TX_OK; } +static void vrf_nf_set_untracked(struct sk_buff *skb) +{ + if (skb_get_nfct(skb) == 0) + nf_ct_set(skb, NULL, IP_CT_UNTRACKED); +} + +static void vrf_nf_reset_ct(struct sk_buff *skb) +{ + if (skb_get_nfct(skb) == IP_CT_UNTRACKED) + nf_reset_ct(skb); +} + #if IS_ENABLED(CONFIG_IPV6) static int vrf_ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb) { int err; + vrf_nf_reset_ct(skb); + err = nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, skb, NULL, skb_dst(skb)->dev, dst_output); @@ -508,6 +523,8 @@ static int vrf_ip_local_out(struct net *net, struct sock *sk, { int err; + vrf_nf_reset_ct(skb); + err = nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, net, sk, skb, NULL, skb_dst(skb)->dev, dst_output); if (likely(err == 1)) @@ -626,8 +643,7 @@ static void vrf_finish_direct(struct sk_buff *skb) skb_pull(skb, ETH_HLEN); } - /* reset skb device */ - nf_reset_ct(skb); + vrf_nf_reset_ct(skb); } #if IS_ENABLED(CONFIG_IPV6) @@ -641,7 +657,7 @@ static int vrf_finish_output6(struct net *net, struct sock *sk, struct neighbour *neigh; int ret; - nf_reset_ct(skb); + vrf_nf_reset_ct(skb); skb->protocol = htons(ETH_P_IPV6); skb->dev = dev; @@ -752,6 +768,8 @@ static struct sk_buff *vrf_ip6_out_direct(struct net_device *vrf_dev, skb->dev = vrf_dev; + vrf_nf_set_untracked(skb); + err = nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, skb, NULL, vrf_dev, vrf_ip6_out_direct_finish); @@ -858,7 +876,7 @@ static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *s struct neighbour *neigh; bool is_v6gw = false; - nf_reset_ct(skb); + vrf_nf_reset_ct(skb); /* Be paranoid, rather than too clever. */ if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops)) { @@ -980,6 +998,8 @@ static struct sk_buff *vrf_ip_out_direct(struct net_device *vrf_dev, skb->dev = vrf_dev; + vrf_nf_set_untracked(skb); + err = nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, net, sk, skb, NULL, vrf_dev, vrf_ip_out_direct_finish); diff --git a/drivers/net/wireless/intel/iwlwifi/Makefile b/drivers/net/wireless/intel/iwlwifi/Makefile index d86918d162aa..0d4656efe908 100644 --- a/drivers/net/wireless/intel/iwlwifi/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/Makefile @@ -15,7 +15,7 @@ iwlwifi-objs += iwl-dbg-tlv.o iwlwifi-objs += iwl-trans.o iwlwifi-objs += queue/tx.o -iwlwifi-objs += fw/img.o fw/notif-wait.o +iwlwifi-objs += fw/img.o fw/notif-wait.o fw/rs.o iwlwifi-objs += fw/dbg.o fw/pnvm.o fw/dump.o iwlwifi-$(CONFIG_IWLMVM) += fw/paging.o fw/smem.o fw/init.o iwlwifi-$(CONFIG_ACPI) += fw/acpi.o diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/1000.c b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c index 44c4fe975390..116defb15afb 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/1000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c @@ -3,11 +3,6 @@ * * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2018 - 2020 Intel Corporation - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #include <linux/module.h> diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/2000.c b/drivers/net/wireless/intel/iwlwifi/cfg/2000.c index df6ac00340b2..ab2038a3fbe2 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/2000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/2000.c @@ -3,11 +3,6 @@ * * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2018 - 2020 Intel Corporation - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #include <linux/module.h> diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index c18b27b0d60e..0f18ff990a9c 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -53,6 +53,9 @@ #define IWL_BZ_A_GF_A_FW_PRE "iwlwifi-bz-a0-gf-a0-" #define IWL_BZ_A_GF4_A_FW_PRE "iwlwifi-bz-a0-gf4-a0-" #define IWL_BZ_A_MR_A_FW_PRE "iwlwifi-bz-a0-mr-a0-" +#define IWL_BZ_A_FM_A_FW_PRE "iwlwifi-bz-a0-fm-a0-" +#define IWL_GL_A_FM_A_FW_PRE "iwlwifi-gl-a0-fm7-a0-" + #define IWL_QU_B_HR_B_MODULE_FIRMWARE(api) \ IWL_QU_B_HR_B_FW_PRE __stringify(api) ".ucode" @@ -106,6 +109,10 @@ IWL_BZ_A_GF4_A_FW_PRE __stringify(api) ".ucode" #define IWL_BZ_A_MR_A_MODULE_FIRMWARE(api) \ IWL_BZ_A_MR_A_FW_PRE __stringify(api) ".ucode" +#define IWL_BZ_A_FM_A_MODULE_FIRMWARE(api) \ + IWL_BZ_A_FM_A_FW_PRE __stringify(api) ".ucode" +#define IWL_GL_A_FM_A_MODULE_FIRMWARE(api) \ + IWL_GL_A_FM_A_FW_PRE __stringify(api) ".ucode" static const struct iwl_base_params iwl_22000_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE_32K, @@ -469,6 +476,14 @@ const char iwl_ax210_killer_1675w_name[] = "Killer(R) Wi-Fi 6E AX1675w 160MHz Wireless Network Adapter (210D2W)"; const char iwl_ax210_killer_1675x_name[] = "Killer(R) Wi-Fi 6E AX1675x 160MHz Wireless Network Adapter (210NGW)"; +const char iwl_ax211_killer_1675s_name[] = + "Killer(R) Wi-Fi 6E AX1675s 160MHz Wireless Network Adapter (211NGW)"; +const char iwl_ax211_killer_1675i_name[] = + "Killer(R) Wi-Fi 6E AX1675i 160MHz Wireless Network Adapter (211NGW)"; +const char iwl_ax411_killer_1690s_name[] = + "Killer(R) Wi-Fi 6E AX1690s 160MHz Wireless Network Adapter (411D2W)"; +const char iwl_ax411_killer_1690i_name[] = + "Killer(R) Wi-Fi 6E AX1690i 160MHz Wireless Network Adapter (411NGW)"; const struct iwl_cfg iwl_qu_b0_hr1_b0 = { .fw_name_pre = IWL_QU_B_HR_B_FW_PRE, @@ -850,6 +865,20 @@ const struct iwl_cfg iwl_cfg_bz_a0_mr_a0 = { .num_rbds = IWL_NUM_RBDS_AX210_HE, }; +const struct iwl_cfg iwl_cfg_bz_a0_fm_a0 = { + .fw_name_pre = IWL_BZ_A_FM_A_FW_PRE, + .uhb_supported = true, + IWL_DEVICE_BZ, + .num_rbds = IWL_NUM_RBDS_AX210_HE, +}; + +const struct iwl_cfg iwl_cfg_gl_a0_fm_a0 = { + .fw_name_pre = IWL_GL_A_FM_A_FW_PRE, + .uhb_supported = true, + IWL_DEVICE_BZ, + .num_rbds = IWL_NUM_RBDS_AX210_HE, +}; + MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_QNJ_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); @@ -876,3 +905,5 @@ MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_BZ_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_BZ_A_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_BZ_A_MR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_BZ_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_GL_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c index 6cdd7d983bda..e2e23d2bc1fe 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c @@ -3,11 +3,6 @@ * * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2018 - 2020 Intel Corporation - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #include <linux/module.h> diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/6000.c b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c index 541a3ec85777..20929e59c2f4 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/6000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c @@ -3,11 +3,6 @@ * * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2018 - 2020 Intel Corporation - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #include <linux/module.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/agn.h b/drivers/net/wireless/intel/iwlwifi/dvm/agn.h index 1276df1c7a55..abb8696ba294 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/agn.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/agn.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2005-2014 Intel Corporation + * Copyright (C) 2005-2014, 2021 Intel Corporation */ #ifndef __iwl_agn_h__ #define __iwl_agn_h__ @@ -398,8 +398,10 @@ do { \ if (!iwl_is_rfkill((m))) \ IWL_ERR(m, fmt, ##args); \ else \ - __iwl_err((m)->dev, true, \ - !iwl_have_debug_level(IWL_DL_RADIO), \ + __iwl_err((m)->dev, \ + iwl_have_debug_level(IWL_DL_RADIO) ? \ + IWL_ERR_MODE_RFKILL : \ + IWL_ERR_MODE_TRACE_ONLY, \ fmt, ##args); \ } while (0) #else @@ -408,7 +410,8 @@ do { \ if (!iwl_is_rfkill((m))) \ IWL_ERR(m, fmt, ##args); \ else \ - __iwl_err((m)->dev, true, true, fmt, ##args); \ + __iwl_err((m)->dev, IWL_ERR_MODE_TRACE_ONLY, \ + fmt, ##args); \ } while (0) #endif /* CONFIG_IWLWIFI_DEBUG */ diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c index 911049201838..b246dbd371b3 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c @@ -3,10 +3,6 @@ * * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright (C) 2018 Intel Corporation - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *****************************************************************************/ #include <linux/slab.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/dev.h b/drivers/net/wireless/intel/iwlwifi/dvm/dev.h index 4bd792c06ff6..bbd574091201 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/dev.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/dev.h @@ -2,11 +2,6 @@ /****************************************************************************** * * Copyright(c) 2003 - 2014, 2020 Intel Corporation. All rights reserved. - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ /* * Please use this file (dev.h) for driver implementation definitions. diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/devices.c b/drivers/net/wireless/intel/iwlwifi/dvm/devices.c index c3e25885d194..39e40901fa46 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/devices.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/devices.c @@ -3,11 +3,6 @@ * * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright (C) 2019 Intel Corporation - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #include <linux/units.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/led.c b/drivers/net/wireless/intel/iwlwifi/dvm/led.c index e8a4d604b910..71f67a019cf6 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/led.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/led.c @@ -3,11 +3,6 @@ * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright (C) 2019 Intel Corporation - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/led.h b/drivers/net/wireless/intel/iwlwifi/dvm/led.h index 6fe20180dc87..5038fc378a1f 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/led.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/led.h @@ -2,11 +2,6 @@ /****************************************************************************** * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #ifndef __iwl_leds_h__ diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/lib.c b/drivers/net/wireless/intel/iwlwifi/dvm/lib.c index 3b937a7dd403..40d790b36d85 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/lib.c @@ -2,11 +2,6 @@ /****************************************************************************** * * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #include <linux/etherdevice.h> #include <linux/kernel.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c index 75e7665773c5..754876cd27ce 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c @@ -6,11 +6,6 @@ * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #include <linux/kernel.h> #include <linux/module.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c index 69d1aae96bbb..fbd57a2b2bd5 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c @@ -6,11 +6,6 @@ * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -52,7 +47,6 @@ #define DRV_DESCRIPTION "Intel(R) Wireless WiFi Link AGN driver for Linux" MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_AUTHOR); MODULE_LICENSE("GPL"); /* Please keep this array *SORTED* by hex value. diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/power.c b/drivers/net/wireless/intel/iwlwifi/dvm/power.c index 93ef023905c9..6d16a7105656 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/power.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/power.c @@ -6,10 +6,6 @@ * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *****************************************************************************/ diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/power.h b/drivers/net/wireless/intel/iwlwifi/dvm/power.h index 3f8db1fc4b59..f38201ce1e99 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/power.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/power.h @@ -5,10 +5,6 @@ * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *****************************************************************************/ #ifndef __iwl_power_setting_h__ #define __iwl_power_setting_h__ diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c index 548540dd0c0f..b7c8b209bfea 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c @@ -3,11 +3,6 @@ * * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright (C) 2019 - 2020 Intel Corporation - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #include <linux/kernel.h> #include <linux/skbuff.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rs.h b/drivers/net/wireless/intel/iwlwifi/dvm/rs.h index 68a840d739e8..0b47f1993c5d 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rs.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rs.h @@ -2,11 +2,6 @@ /****************************************************************************** * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #ifndef __iwl_agn_rs_h__ diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c index 3cd7b423c588..db0c41bbeb0e 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c @@ -7,11 +7,6 @@ * * Portions of this file are derived from the ipw3945 project, as well * as portionhelp of the ieee80211 subsystem header files. - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #include <linux/etherdevice.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c b/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c index 12a3d464ae64..70338bc7bb54 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c @@ -3,11 +3,6 @@ * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2015 Intel Deutschland GmbH - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #include <linux/etherdevice.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/scan.c b/drivers/net/wireless/intel/iwlwifi/dvm/scan.c index c4ecf6ed2186..2d38227dfdd2 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/scan.c @@ -3,10 +3,6 @@ * * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2018 Intel Corporation - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *****************************************************************************/ #include <linux/slab.h> #include <linux/types.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/sta.c b/drivers/net/wireless/intel/iwlwifi/dvm/sta.c index ddc14059b07d..8f7a0f36c276 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/sta.c @@ -5,11 +5,6 @@ * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #include <linux/etherdevice.h> #include <net/mac80211.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tt.c b/drivers/net/wireless/intel/iwlwifi/dvm/tt.c index 2684a924ba57..43e8d04d5a8b 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/tt.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/tt.c @@ -6,10 +6,6 @@ * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *****************************************************************************/ diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tt.h b/drivers/net/wireless/intel/iwlwifi/dvm/tt.h index 3b0ff458a158..7ace052fc78a 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/tt.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/tt.h @@ -5,10 +5,6 @@ * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *****************************************************************************/ #ifndef __iwl_tt_setting_h__ #define __iwl_tt_setting_h__ diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c index 847b8e07f81c..60a7b61d59aa 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c @@ -3,11 +3,6 @@ * * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright (C) 2019 Intel Corporation - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #include <linux/kernel.h> diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c b/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c index 24194c791218..4b27a53d0bb4 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c @@ -3,11 +3,6 @@ * * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2015 Intel Deutschland GmbH - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #include <linux/kernel.h> diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h index 16ed0995b51e..0822c6b15c43 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h @@ -116,7 +116,8 @@ enum iwl_dsm_funcs_rev_0 { DSM_FUNC_DISABLE_SRD = 1, DSM_FUNC_ENABLE_INDONESIA_5G2 = 2, DSM_FUNC_11AX_ENABLEMENT = 6, - DSM_FUNC_ENABLE_UNII4_CHAN = 7 + DSM_FUNC_ENABLE_UNII4_CHAN = 7, + DSM_FUNC_ACTIVATE_CHANNEL = 8 }; enum iwl_dsm_values_srd { diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h index 3ec82cae3981..e199d1813a61 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h @@ -624,7 +624,7 @@ struct iwl_wowlan_status_v6 { } __packed; /* WOWLAN_STATUSES_API_S_VER_6 */ /** - * struct iwl_wowlan_status - WoWLAN status + * struct iwl_wowlan_status_v7 - WoWLAN status * @gtk: GTK data * @igtk: IGTK data * @replay_ctr: GTK rekey replay counter diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h index d8b5870d6e9a..3988f5fea33a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h @@ -7,6 +7,7 @@ #include <linux/bitops.h> +#define IWL_FW_INI_HW_SMEM_REGION_ID 15 #define IWL_FW_INI_MAX_REGION_ID 64 #define IWL_FW_INI_MAX_NAME 32 #define IWL_FW_INI_MAX_CFG_NAME 64 @@ -243,6 +244,62 @@ struct iwl_fw_ini_hcmd_tlv { } __packed; /* FW_TLV_DEBUG_HCMD_API_S_VER_1 */ /** +* struct iwl_fw_ini_conf_tlv - preset configuration TLV +* +* @address: the base address +* @value: value to set at address + +*/ +struct iwl_fw_ini_addr_val { + __le32 address; + __le32 value; +} __packed; /* FW_TLV_DEBUG_ADDR_VALUE_VER_1 */ + +/** + * struct iwl_fw_ini_conf_tlv - configuration TLV to set register/memory. + * + * @hdr: debug header + * @time_point: time point to apply config. One of &enum iwl_fw_ini_time_point + * @set_type: write access type preset token for time point. + * one of &enum iwl_fw_ini_config_set_type + * @addr_offset: the offset to add to any item in address[0] field + * @addr_val: address value pair + */ +struct iwl_fw_ini_conf_set_tlv { + struct iwl_fw_ini_header hdr; + __le32 time_point; + __le32 set_type; + __le32 addr_offset; + struct iwl_fw_ini_addr_val addr_val[0]; +} __packed; /* FW_TLV_DEBUG_CONFIG_SET_API_S_VER_1 */ + +/** + * enum iwl_fw_ini_config_set_type + * + * @IWL_FW_INI_CONFIG_SET_TYPE_INVALID: invalid config set + * @IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_MAC: for PERIPHERY MAC configuration + * @IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_PHY: for PERIPHERY PHY configuration + * @IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_AUX: for PERIPHERY AUX configuration + * @IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_MEMORY: for DEVICE MEMORY configuration + * @IWL_FW_INI_CONFIG_SET_TYPE_CSR: for CSR configuration + * @IWL_FW_INI_CONFIG_SET_TYPE_DBGC_DRAM_ADDR: for DBGC_DRAM_ADDR configuration + * @IWL_FW_INI_CONFIG_SET_TYPE_PERIPH_SCRATCH_HWM: for PERIPH SCRATCH HWM configuration + * @IWL_FW_INI_ALLOCATION_NUM: max number of configuration supported +*/ + +enum iwl_fw_ini_config_set_type { + IWL_FW_INI_CONFIG_SET_TYPE_INVALID = 0, + IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_MAC, + IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_PHY, + IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_AUX, + IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_MEMORY, + IWL_FW_INI_CONFIG_SET_TYPE_CSR, + IWL_FW_INI_CONFIG_SET_TYPE_DBGC_DRAM_ADDR, + IWL_FW_INI_CONFIG_SET_TYPE_PERIPH_SCRATCH_HWM, + IWL_FW_INI_CONFIG_SET_TYPE_MAX_NUM, +} __packed; + +/** * enum iwl_fw_ini_allocation_id * * @IWL_FW_INI_ALLOCATION_INVALID: invalid diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h b/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h index 8adccd5da095..0abed12df2cb 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h @@ -361,6 +361,24 @@ struct iwl_buf_alloc_cmd { struct iwl_buf_alloc_frag frags[BUF_ALLOC_MAX_NUM_FRAGS]; } __packed; /* BUFFER_ALLOCATION_CMD_API_S_VER_2 */ +#define DRAM_INFO_FIRST_MAGIC_WORD 0x76543210 +#define DRAM_INFO_SECOND_MAGIC_WORD 0x89ABCDEF + +/** + * struct iwL_dram_info - DRAM fragments allocation struct + * + * Driver will fill in the first 1K(+) of the pointed DRAM fragment + * + * @first_word: magic word value + * @second_word: magic word value + * @framfrags: DRAM fragmentaion detail +*/ +struct iwl_dram_info { + __le32 first_word; + __le32 second_word; + struct iwl_buf_alloc_cmd dram_frags[IWL_FW_INI_ALLOCATION_NUM - 1]; +} __packed; /* INIT_DRAM_FRAGS_ALLOCATIONS_S_VER_1 */ + /** * struct iwl_dbg_host_event_cfg_cmd * @enabled_severities: enabled severities diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h index 6bbb8b8c91cd..12af94e166ed 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h @@ -206,7 +206,7 @@ enum iwl_tof_responder_cfg_flags { IWL_TOF_RESPONDER_FLAGS_SPECIFIC_CALIB_MODE = BIT(8), IWL_TOF_RESPONDER_FLAGS_FAST_ALGO_SUPPORT = BIT(9), IWL_TOF_RESPONDER_FLAGS_RETRY_ON_ALGO_FAIL = BIT(10), - IWL_TOF_RESPONDER_FLAGS_FTM_TX_ANT = RATE_MCS_ANT_ABC_MSK, + IWL_TOF_RESPONDER_FLAGS_FTM_TX_ANT = RATE_MCS_ANT_AB_MSK, IWL_TOF_RESPONDER_FLAGS_NDP_SUPPORT = BIT(24), IWL_TOF_RESPONDER_FLAGS_LMR_FEEDBACK = BIT(25), IWL_TOF_RESPONDER_FLAGS_SESSION_ID = BIT(27), @@ -629,6 +629,7 @@ enum iwl_location_bw { IWL_LOCATION_BW_20MHZ, IWL_LOCATION_BW_40MHZ, IWL_LOCATION_BW_80MHZ, + IWL_LOCATION_BW_160MHZ, }; #define TK_11AZ_LEN 32 @@ -1500,7 +1501,9 @@ struct iwl_tof_range_rsp_ap_entry_ntfy_v6 { u8 reserved[3]; u8 rx_pn[IEEE80211_CCMP_PN_LEN]; u8 tx_pn[IEEE80211_CCMP_PN_LEN]; -} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_6 */ +} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_6, + LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_7 */ + /** * enum iwl_tof_response_status - tof response status @@ -1581,7 +1584,8 @@ struct iwl_tof_range_rsp_ntfy_v8 { u8 last_report; u8 reserved; struct iwl_tof_range_rsp_ap_entry_ntfy_v6 ap[IWL_MVM_TOF_MAX_APS]; -} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_8 */ +} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_8, + LOCATION_RANGE_RSP_NTFY_API_S_VER_9 */ #define IWL_MVM_TOF_MCSI_BUF_SIZE (245) /** diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h index 7be7715b431d..11f0bd283e49 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h @@ -138,6 +138,8 @@ struct iwl_mac_data_ibss { * @FLEXIBLE_TWT_SUPPORTED: AP supports flexible TWT schedule * @PROTECTED_TWT_SUPPORTED: AP supports protected TWT frames (with 11w) * @BROADCAST_TWT_SUPPORTED: AP and STA support broadcast TWT + * @COEX_HIGH_PRIORITY_ENABLE: high priority mode for BT coex, to be used + * during 802.1X negotiation (and allowed during 4-way-HS) */ enum iwl_mac_data_policy { TWT_SUPPORTED = BIT(0), @@ -145,6 +147,7 @@ enum iwl_mac_data_policy { FLEXIBLE_TWT_SUPPORTED = BIT(2), PROTECTED_TWT_SUPPORTED = BIT(3), BROADCAST_TWT_SUPPORTED = BIT(4), + COEX_HIGH_PRIORITY_ENABLE = BIT(5), }; /** diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h index cf48c6fa8f65..3551a3f1c1aa 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h @@ -472,6 +472,29 @@ struct iwl_lari_config_change_cmd_v4 { } __packed; /* LARI_CHANGE_CONF_CMD_S_VER_4 */ /** + * struct iwl_lari_config_change_cmd_v5 - change LARI configuration + * @config_bitmap: Bitmap of the config commands. Each bit will trigger a + * different predefined FW config operation. + * @oem_uhb_allow_bitmap: Bitmap of UHB enabled MCC sets. + * @oem_11ax_allow_bitmap: Bitmap of 11ax allowed MCCs. There are two bits + * per country, one to indicate whether to override and the other to + * indicate the value to use. + * @oem_unii4_allow_bitmap: Bitmap of unii4 allowed MCCs.There are two bits + * per country, one to indicate whether to override and the other to + * indicate allow/disallow unii4 channels. + * @chan_state_active_bitmap: Bitmap for overriding channel state to active. + * Each bit represents a country or region to activate, according to the BIOS + * definitions. + */ +struct iwl_lari_config_change_cmd_v5 { + __le32 config_bitmap; + __le32 oem_uhb_allow_bitmap; + __le32 oem_11ax_allow_bitmap; + __le32 oem_unii4_allow_bitmap; + __le32 chan_state_active_bitmap; +} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_5 */ + +/** * struct iwl_pnvm_init_complete_ntfy - PNVM initialization complete * @status: PNVM image loading status */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h index fc2fa49e9825..a09081d7ed45 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h @@ -184,6 +184,14 @@ struct iwl_tlc_update_notif { __le32 amsdu_enabled; } __packed; /* TLC_MNG_UPDATE_NTFY_API_S_VER_2 */ + +#define IWL_MAX_MCS_DISPLAY_SIZE 12 + +struct iwl_rate_mcs_info { + char mbps[IWL_MAX_MCS_DISPLAY_SIZE]; + char mcs[IWL_MAX_MCS_DISPLAY_SIZE]; +}; + /* * These serve as indexes into * struct iwl_rate_info fw_rate_idx_to_plcp[IWL_RATE_COUNT]; @@ -226,6 +234,8 @@ enum { IWL_LAST_HE_RATE = IWL_RATE_MCS_11_INDEX, IWL_RATE_COUNT_LEGACY = IWL_LAST_NON_HT_RATE + 1, IWL_RATE_COUNT = IWL_LAST_HE_RATE + 1, + IWL_RATE_INVM_INDEX = IWL_RATE_COUNT, + IWL_RATE_INVALID = IWL_RATE_COUNT, }; #define IWL_RATE_BIT_MSK(r) BIT(IWL_RATE_##r##M_INDEX) @@ -248,7 +258,7 @@ enum { }; /* - * rate_n_flags bit fields + * rate_n_flags bit fields version 1 * * The 32-bit value has different layouts in the low 8 bites depending on the * format. There are three formats, HT, VHT and legacy (11abg, with subformats @@ -266,15 +276,15 @@ enum { /* Bit 8: (1) HT format, (0) legacy or VHT format */ #define RATE_MCS_HT_POS 8 -#define RATE_MCS_HT_MSK (1 << RATE_MCS_HT_POS) +#define RATE_MCS_HT_MSK_V1 BIT(RATE_MCS_HT_POS) /* Bit 9: (1) CCK, (0) OFDM. HT (bit 8) must be "0" for this bit to be valid */ -#define RATE_MCS_CCK_POS 9 -#define RATE_MCS_CCK_MSK (1 << RATE_MCS_CCK_POS) +#define RATE_MCS_CCK_POS_V1 9 +#define RATE_MCS_CCK_MSK_V1 BIT(RATE_MCS_CCK_POS_V1) /* Bit 26: (1) VHT format, (0) legacy format in bits 8:0 */ -#define RATE_MCS_VHT_POS 26 -#define RATE_MCS_VHT_MSK (1 << RATE_MCS_VHT_POS) +#define RATE_MCS_VHT_POS_V1 26 +#define RATE_MCS_VHT_MSK_V1 BIT(RATE_MCS_VHT_POS_V1) /* @@ -300,15 +310,16 @@ enum { * streams and 16-23 have three streams. We could also support MCS 32 * which is the duplicate 20 MHz MCS (bit 5 set, all others zero.) */ -#define RATE_HT_MCS_RATE_CODE_MSK 0x7 -#define RATE_HT_MCS_NSS_POS 3 -#define RATE_HT_MCS_NSS_MSK (3 << RATE_HT_MCS_NSS_POS) +#define RATE_HT_MCS_RATE_CODE_MSK_V1 0x7 +#define RATE_HT_MCS_NSS_POS_V1 3 +#define RATE_HT_MCS_NSS_MSK_V1 (3 << RATE_HT_MCS_NSS_POS_V1) +#define RATE_HT_MCS_MIMO2_MSK BIT(RATE_HT_MCS_NSS_POS_V1) /* Bit 10: (1) Use Green Field preamble */ #define RATE_HT_MCS_GF_POS 10 #define RATE_HT_MCS_GF_MSK (1 << RATE_HT_MCS_GF_POS) -#define RATE_HT_MCS_INDEX_MSK 0x3f +#define RATE_HT_MCS_INDEX_MSK_V1 0x3f /* * Very High-throughput (VHT) rate format for bits 7:0 @@ -324,6 +335,7 @@ enum { #define RATE_VHT_MCS_RATE_CODE_MSK 0xf #define RATE_VHT_MCS_NSS_POS 4 #define RATE_VHT_MCS_NSS_MSK (3 << RATE_VHT_MCS_NSS_POS) +#define RATE_VHT_MCS_MIMO2_MSK BIT(RATE_VHT_MCS_NSS_POS) /* * Legacy OFDM rate format for bits 7:0 @@ -347,37 +359,30 @@ enum { * 110) 11 Mbps * (bit 7 is 0) */ -#define RATE_LEGACY_RATE_MSK 0xff +#define RATE_LEGACY_RATE_MSK_V1 0xff /* Bit 10 - OFDM HE */ -#define RATE_MCS_HE_POS 10 -#define RATE_MCS_HE_MSK BIT(RATE_MCS_HE_POS) +#define RATE_MCS_HE_POS_V1 10 +#define RATE_MCS_HE_MSK_V1 BIT(RATE_MCS_HE_POS_V1) /* * Bit 11-12: (0) 20MHz, (1) 40MHz, (2) 80MHz, (3) 160MHz * 0 and 1 are valid for HT and VHT, 2 and 3 only for VHT */ #define RATE_MCS_CHAN_WIDTH_POS 11 -#define RATE_MCS_CHAN_WIDTH_MSK (3 << RATE_MCS_CHAN_WIDTH_POS) -#define RATE_MCS_CHAN_WIDTH_20 (0 << RATE_MCS_CHAN_WIDTH_POS) -#define RATE_MCS_CHAN_WIDTH_40 (1 << RATE_MCS_CHAN_WIDTH_POS) -#define RATE_MCS_CHAN_WIDTH_80 (2 << RATE_MCS_CHAN_WIDTH_POS) -#define RATE_MCS_CHAN_WIDTH_160 (3 << RATE_MCS_CHAN_WIDTH_POS) +#define RATE_MCS_CHAN_WIDTH_MSK_V1 (3 << RATE_MCS_CHAN_WIDTH_POS) /* Bit 13: (1) Short guard interval (0.4 usec), (0) normal GI (0.8 usec) */ -#define RATE_MCS_SGI_POS 13 -#define RATE_MCS_SGI_MSK (1 << RATE_MCS_SGI_POS) +#define RATE_MCS_SGI_POS_V1 13 +#define RATE_MCS_SGI_MSK_V1 BIT(RATE_MCS_SGI_POS_V1) /* Bit 14-16: Antenna selection (1) Ant A, (2) Ant B, (4) Ant C */ #define RATE_MCS_ANT_POS 14 #define RATE_MCS_ANT_A_MSK (1 << RATE_MCS_ANT_POS) #define RATE_MCS_ANT_B_MSK (2 << RATE_MCS_ANT_POS) -#define RATE_MCS_ANT_C_MSK (4 << RATE_MCS_ANT_POS) #define RATE_MCS_ANT_AB_MSK (RATE_MCS_ANT_A_MSK | \ RATE_MCS_ANT_B_MSK) -#define RATE_MCS_ANT_ABC_MSK (RATE_MCS_ANT_AB_MSK | \ - RATE_MCS_ANT_C_MSK) -#define RATE_MCS_ANT_MSK RATE_MCS_ANT_ABC_MSK +#define RATE_MCS_ANT_MSK RATE_MCS_ANT_AB_MSK /* Bit 17: (0) SS, (1) SS*2 */ #define RATE_MCS_STBC_POS 17 @@ -411,27 +416,27 @@ enum { * 3 (does not occur) */ #define RATE_MCS_HE_GI_LTF_POS 20 -#define RATE_MCS_HE_GI_LTF_MSK (3 << RATE_MCS_HE_GI_LTF_POS) +#define RATE_MCS_HE_GI_LTF_MSK_V1 (3 << RATE_MCS_HE_GI_LTF_POS) /* Bit 22-23: HE type. (0) SU, (1) SU_EXT, (2) MU, (3) trigger based */ -#define RATE_MCS_HE_TYPE_POS 22 -#define RATE_MCS_HE_TYPE_SU (0 << RATE_MCS_HE_TYPE_POS) -#define RATE_MCS_HE_TYPE_EXT_SU (1 << RATE_MCS_HE_TYPE_POS) -#define RATE_MCS_HE_TYPE_MU (2 << RATE_MCS_HE_TYPE_POS) -#define RATE_MCS_HE_TYPE_TRIG (3 << RATE_MCS_HE_TYPE_POS) -#define RATE_MCS_HE_TYPE_MSK (3 << RATE_MCS_HE_TYPE_POS) +#define RATE_MCS_HE_TYPE_POS_V1 22 +#define RATE_MCS_HE_TYPE_SU_V1 (0 << RATE_MCS_HE_TYPE_POS_V1) +#define RATE_MCS_HE_TYPE_EXT_SU_V1 BIT(RATE_MCS_HE_TYPE_POS_V1) +#define RATE_MCS_HE_TYPE_MU_V1 (2 << RATE_MCS_HE_TYPE_POS_V1) +#define RATE_MCS_HE_TYPE_TRIG_V1 (3 << RATE_MCS_HE_TYPE_POS_V1) +#define RATE_MCS_HE_TYPE_MSK_V1 (3 << RATE_MCS_HE_TYPE_POS_V1) /* Bit 24-25: (0) 20MHz (no dup), (1) 2x20MHz, (2) 4x20MHz, 3 8x20MHz */ -#define RATE_MCS_DUP_POS 24 -#define RATE_MCS_DUP_MSK (3 << RATE_MCS_DUP_POS) +#define RATE_MCS_DUP_POS_V1 24 +#define RATE_MCS_DUP_MSK_V1 (3 << RATE_MCS_DUP_POS_V1) /* Bit 27: (1) LDPC enabled, (0) LDPC disabled */ -#define RATE_MCS_LDPC_POS 27 -#define RATE_MCS_LDPC_MSK (1 << RATE_MCS_LDPC_POS) +#define RATE_MCS_LDPC_POS_V1 27 +#define RATE_MCS_LDPC_MSK_V1 BIT(RATE_MCS_LDPC_POS_V1) /* Bit 28: (1) 106-tone RX (8 MHz RU), (0) normal bandwidth */ -#define RATE_MCS_HE_106T_POS 28 -#define RATE_MCS_HE_106T_MSK (1 << RATE_MCS_HE_106T_POS) +#define RATE_MCS_HE_106T_POS_V1 28 +#define RATE_MCS_HE_106T_MSK_V1 BIT(RATE_MCS_HE_106T_POS_V1) /* Bit 30-31: (1) RTS, (2) CTS */ #define RATE_MCS_RTS_REQUIRED_POS (30) @@ -440,6 +445,152 @@ enum { #define RATE_MCS_CTS_REQUIRED_POS (31) #define RATE_MCS_CTS_REQUIRED_MSK (0x1 << RATE_MCS_CTS_REQUIRED_POS) +/* rate_n_flags bit field version 2 + * + * The 32-bit value has different layouts in the low 8 bits depending on the + * format. There are three formats, HT, VHT and legacy (11abg, with subformats + * for CCK and OFDM). + * + */ + +/* Bits 10-8: rate format + * (0) Legacy CCK (1) Legacy OFDM (2) High-throughput (HT) + * (3) Very High-throughput (VHT) (4) High-efficiency (HE) + * (5) Extremely High-throughput (EHT) + */ +#define RATE_MCS_MOD_TYPE_POS 8 +#define RATE_MCS_MOD_TYPE_MSK (0x7 << RATE_MCS_MOD_TYPE_POS) +#define RATE_MCS_CCK_MSK (0 << RATE_MCS_MOD_TYPE_POS) +#define RATE_MCS_LEGACY_OFDM_MSK (1 << RATE_MCS_MOD_TYPE_POS) +#define RATE_MCS_HT_MSK (2 << RATE_MCS_MOD_TYPE_POS) +#define RATE_MCS_VHT_MSK (3 << RATE_MCS_MOD_TYPE_POS) +#define RATE_MCS_HE_MSK (4 << RATE_MCS_MOD_TYPE_POS) +#define RATE_MCS_EHT_MSK (5 << RATE_MCS_MOD_TYPE_POS) + +/* + * Legacy CCK rate format for bits 0:3: + * + * (0) 0xa - 1 Mbps + * (1) 0x14 - 2 Mbps + * (2) 0x37 - 5.5 Mbps + * (3) 0x6e - 11 nbps + * + * Legacy OFDM rate format for bis 3:0: + * + * (0) 6 Mbps + * (1) 9 Mbps + * (2) 12 Mbps + * (3) 18 Mbps + * (4) 24 Mbps + * (5) 36 Mbps + * (6) 48 Mbps + * (7) 54 Mbps + * + */ +#define RATE_LEGACY_RATE_MSK 0x7 + +/* + * HT, VHT, HE, EHT rate format for bits 3:0 + * 3-0: MCS + * + */ +#define RATE_HT_MCS_CODE_MSK 0x7 +#define RATE_MCS_NSS_POS 4 +#define RATE_MCS_NSS_MSK (1 << RATE_MCS_NSS_POS) +#define RATE_MCS_CODE_MSK 0xf +#define RATE_HT_MCS_INDEX(r) ((((r) & RATE_MCS_NSS_MSK) >> 1) | \ + ((r) & RATE_HT_MCS_CODE_MSK)) + +/* Bits 7-5: reserved */ + +/* + * Bits 13-11: (0) 20MHz, (1) 40MHz, (2) 80MHz, (3) 160MHz, (4) 320MHz + */ +#define RATE_MCS_CHAN_WIDTH_MSK (0x7 << RATE_MCS_CHAN_WIDTH_POS) +#define RATE_MCS_CHAN_WIDTH_20 (0 << RATE_MCS_CHAN_WIDTH_POS) +#define RATE_MCS_CHAN_WIDTH_40 (1 << RATE_MCS_CHAN_WIDTH_POS) +#define RATE_MCS_CHAN_WIDTH_80 (2 << RATE_MCS_CHAN_WIDTH_POS) +#define RATE_MCS_CHAN_WIDTH_160 (3 << RATE_MCS_CHAN_WIDTH_POS) +#define RATE_MCS_CHAN_WIDTH_320 (4 << RATE_MCS_CHAN_WIDTH_POS) + +/* Bit 15-14: Antenna selection: + * Bit 14: Ant A active + * Bit 15: Ant B active + * + * All relevant definitions are same as in v1 + */ + +/* Bit 16 (1) LDPC enables, (0) LDPC disabled */ +#define RATE_MCS_LDPC_POS 16 +#define RATE_MCS_LDPC_MSK (1 << RATE_MCS_LDPC_POS) + +/* Bit 17: (0) SS, (1) SS*2 (same as v1) */ + +/* Bit 18: OFDM-HE dual carrier mode (same as v1) */ + +/* Bit 19: (0) Beamforming is off, (1) Beamforming is on (same as v1) */ + +/* + * Bit 22-20: HE LTF type and guard interval + * CCK: + * 0 long preamble + * 1 short preamble + * HT/VHT: + * 0 0.8us + * 1 0.4us + * HE (ext) SU: + * 0 1xLTF+0.8us + * 1 2xLTF+0.8us + * 2 2xLTF+1.6us + * 3 4xLTF+3.2us + * 4 4xLTF+0.8us + * HE MU: + * 0 4xLTF+0.8us + * 1 2xLTF+0.8us + * 2 2xLTF+1.6us + * 3 4xLTF+3.2us + * HE TRIG: + * 0 1xLTF+1.6us + * 1 2xLTF+1.6us + * 2 4xLTF+3.2us + * */ +#define RATE_MCS_HE_GI_LTF_MSK (0x7 << RATE_MCS_HE_GI_LTF_POS) +#define RATE_MCS_SGI_POS RATE_MCS_HE_GI_LTF_POS +#define RATE_MCS_SGI_MSK (1 << RATE_MCS_SGI_POS) +#define RATE_MCS_HE_SU_4_LTF 3 +#define RATE_MCS_HE_SU_4_LTF_08_GI 4 + +/* Bit 24-23: HE type. (0) SU, (1) SU_EXT, (2) MU, (3) trigger based */ +#define RATE_MCS_HE_TYPE_POS 23 +#define RATE_MCS_HE_TYPE_SU (0 << RATE_MCS_HE_TYPE_POS) +#define RATE_MCS_HE_TYPE_EXT_SU (1 << RATE_MCS_HE_TYPE_POS) +#define RATE_MCS_HE_TYPE_MU (2 << RATE_MCS_HE_TYPE_POS) +#define RATE_MCS_HE_TYPE_TRIG (3 << RATE_MCS_HE_TYPE_POS) +#define RATE_MCS_HE_TYPE_MSK (3 << RATE_MCS_HE_TYPE_POS) + +/* Bit 25: duplicate channel enabled + * + * if this bit is set, duplicate is according to BW (bits 11-13): + * + * CCK: 2x 20MHz + * OFDM Legacy: N x 20Mhz, (N = BW \ 2 , either 2, 4, 8, 16) + * EHT: 2 x BW/2, (80 - 2x40, 160 - 2x80, 320 - 2x160) + * */ +#define RATE_MCS_DUP_POS 25 +#define RATE_MCS_DUP_MSK (1 << RATE_MCS_DUP_POS) + +/* Bit 26: (1) 106-tone RX (8 MHz RU), (0) normal bandwidth */ +#define RATE_MCS_HE_106T_POS 26 +#define RATE_MCS_HE_106T_MSK (1 << RATE_MCS_HE_106T_POS) + +/* Bit 27: EHT extra LTF: + * instead of 1 LTF for SISO use 2 LTFs, + * instead of 2 LTFs for NSTS=2 use 4 LTFs*/ +#define RATE_MCS_EHT_EXTRA_LTF_POS 27 +#define RATE_MCS_EHT_EXTRA_LTF_MSK (1 << RATE_MCS_EHT_EXTRA_LTF_POS) + +/* Bit 31-28: reserved */ + /* Link Quality definitions */ /* # entries in rate scale table to support Tx retries */ @@ -557,4 +708,13 @@ struct iwl_lq_cmd { __le32 ss_params; }; /* LINK_QUALITY_CMD_API_S_VER_1 */ +u8 iwl_fw_rate_idx_to_plcp(int idx); +u32 iwl_new_rate_from_v1(u32 rate_v1); +u32 iwl_legacy_rate_to_fw_idx(u32 rate_n_flags); +const struct iwl_rate_mcs_info *iwl_rate_mcs(int idx); +const char *iwl_rs_pretty_ant(u8 ant); +const char *iwl_rs_pretty_bw(int bw); +int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate); +bool iwl_he_is_sgi(u32 rate_n_flags); + #endif /* __iwl_fw_api_rs_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h index 3f13b572915a..1989b270862b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2018-2020 Intel Corporation + * Copyright (C) 2012-2014, 2018-2021 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2015-2017 Intel Deutschland GmbH */ @@ -13,7 +13,6 @@ #define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1 #define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff #define IWL_RX_INFO_ENERGY_ANT_B_MSK 0x0000ff00 -#define IWL_RX_INFO_ENERGY_ANT_C_MSK 0x00ff0000 #define IWL_RX_INFO_ENERGY_ANT_A_POS 0 #define IWL_RX_INFO_ENERGY_ANT_B_POS 8 #define IWL_RX_INFO_ENERGY_ANT_C_POS 16 @@ -126,14 +125,12 @@ enum iwl_rx_phy_flags { * @RX_MPDU_RES_STATUS_OVERRUN_OK: there was no RXE overflow * @RX_MPDU_RES_STATUS_SRC_STA_FOUND: station was found * @RX_MPDU_RES_STATUS_KEY_VALID: key was valid - * @RX_MPDU_RES_STATUS_KEY_PARAM_OK: key parameters were usable * @RX_MPDU_RES_STATUS_ICV_OK: ICV is fine, if not, the packet is destroyed * @RX_MPDU_RES_STATUS_MIC_OK: used for CCM alg only. TKIP MIC is checked * in the driver. * @RX_MPDU_RES_STATUS_TTAK_OK: TTAK is fine * @RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR: valid for alg = CCM_CMAC or - * alg = CCM only. Checks replay attack for 11w frames. Relevant only if - * %RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME is set. + * alg = CCM only. Checks replay attack for 11w frames. * @RX_MPDU_RES_STATUS_SEC_NO_ENC: this frame is not encrypted * @RX_MPDU_RES_STATUS_SEC_WEP_ENC: this frame is encrypted using WEP * @RX_MPDU_RES_STATUS_SEC_CCM_ENC: this frame is encrypted using CCM @@ -145,9 +142,6 @@ enum iwl_rx_phy_flags { * @RX_MPDU_RES_STATUS_SEC_ENC_ERR: this frame couldn't be decrypted * @RX_MPDU_RES_STATUS_SEC_ENC_MSK: bitmask of the encryption algorithm * @RX_MPDU_RES_STATUS_DEC_DONE: this frame has been successfully decrypted - * @RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP: extended IV (set with TKIP) - * @RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT: key ID comparison done - * @RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME: this frame is an 11w management frame * @RX_MPDU_RES_STATUS_CSUM_DONE: checksum was done by the hw * @RX_MPDU_RES_STATUS_CSUM_OK: checksum found no errors * @RX_MPDU_RES_STATUS_STA_ID_MSK: station ID mask @@ -158,7 +152,6 @@ enum iwl_mvm_rx_status { RX_MPDU_RES_STATUS_OVERRUN_OK = BIT(1), RX_MPDU_RES_STATUS_SRC_STA_FOUND = BIT(2), RX_MPDU_RES_STATUS_KEY_VALID = BIT(3), - RX_MPDU_RES_STATUS_KEY_PARAM_OK = BIT(4), RX_MPDU_RES_STATUS_ICV_OK = BIT(5), RX_MPDU_RES_STATUS_MIC_OK = BIT(6), RX_MPDU_RES_STATUS_TTAK_OK = BIT(7), @@ -172,9 +165,6 @@ enum iwl_mvm_rx_status { RX_MPDU_RES_STATUS_SEC_ENC_ERR = (7 << 8), RX_MPDU_RES_STATUS_SEC_ENC_MSK = (7 << 8), RX_MPDU_RES_STATUS_DEC_DONE = BIT(11), - RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP = BIT(13), - RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT = BIT(14), - RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME = BIT(15), RX_MPDU_RES_STATUS_CSUM_DONE = BIT(16), RX_MPDU_RES_STATUS_CSUM_OK = BIT(17), RX_MDPU_RES_STATUS_STA_ID_SHIFT = 24, @@ -236,7 +226,6 @@ enum iwl_rx_mpdu_status { IWL_RX_MPDU_STATUS_OVERRUN_OK = BIT(1), IWL_RX_MPDU_STATUS_SRC_STA_FOUND = BIT(2), IWL_RX_MPDU_STATUS_KEY_VALID = BIT(3), - IWL_RX_MPDU_STATUS_KEY_PARAM_OK = BIT(4), IWL_RX_MPDU_STATUS_ICV_OK = BIT(5), IWL_RX_MPDU_STATUS_MIC_OK = BIT(6), IWL_RX_MPDU_RES_STATUS_TTAK_OK = BIT(7), @@ -251,12 +240,8 @@ enum iwl_rx_mpdu_status { IWL_RX_MPDU_STATUS_SEC_EXT_ENC = 0x4 << 8, IWL_RX_MPDU_STATUS_SEC_GCM = 0x5 << 8, IWL_RX_MPDU_STATUS_DECRYPTED = BIT(11), - IWL_RX_MPDU_STATUS_WEP_MATCH = BIT(12), - IWL_RX_MPDU_STATUS_EXT_IV_MATCH = BIT(13), - IWL_RX_MPDU_STATUS_KEY_ID_MATCH = BIT(14), IWL_RX_MPDU_STATUS_ROBUST_MNG_FRAME = BIT(15), - IWL_RX_MPDU_STATUS_KEY = 0x3f0000, IWL_RX_MPDU_STATUS_DUPLICATE = BIT(22), IWL_RX_MPDU_STATUS_STA_ID = 0x1f000000, @@ -460,7 +445,7 @@ struct iwl_rx_mpdu_desc_v1 { __le32 phy_data1; }; }; -} __packed; +} __packed; /* RX_MPDU_RES_START_API_S_VER_4 */ /** * struct iwl_rx_mpdu_desc_v3 - RX MPDU descriptor @@ -560,7 +545,8 @@ struct iwl_rx_mpdu_desc_v3 { * @reserved: reserved */ __le32 reserved[2]; -} __packed; /* RX_MPDU_RES_START_API_S_VER_3 */ +} __packed; /* RX_MPDU_RES_START_API_S_VER_3, + RX_MPDU_RES_START_API_S_VER_5 */ /** * struct iwl_rx_mpdu_desc - RX MPDU descriptor @@ -625,7 +611,9 @@ struct iwl_rx_mpdu_desc { struct iwl_rx_mpdu_desc_v1 v1; struct iwl_rx_mpdu_desc_v3 v3; }; -} __packed; /* RX_MPDU_RES_START_API_S_VER_3 */ +} __packed; /* RX_MPDU_RES_START_API_S_VER_3, + RX_MPDU_RES_START_API_S_VER_4, + RX_MPDU_RES_START_API_S_VER_5 */ #define IWL_RX_DESC_SIZE_V1 offsetofend(struct iwl_rx_mpdu_desc, v1) @@ -679,7 +667,8 @@ struct iwl_rx_no_data { __le32 rate; __le32 phy_info[2]; __le32 rx_vec[2]; -} __packed; /* RX_NO_DATA_NTFY_API_S_VER_1 */ +} __packed; /* RX_NO_DATA_NTFY_API_S_VER_1, + TX_NO_DATA_NTFY_API_S_VER_2 */ struct iwl_frame_release { u8 baid; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h index 24e4a82a55da..9b3bce83efb6 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2018-2020 Intel Corporation + * Copyright (C) 2012-2014, 2018-2021 Intel Corporation * Copyright (C) 2016-2017 Intel Deutschland GmbH */ #ifndef __iwl_fw_api_tx_h__ @@ -81,6 +81,10 @@ enum iwl_tx_cmd_flags { IWL_TX_FLAGS_CMD_RATE = BIT(0), IWL_TX_FLAGS_ENCRYPT_DIS = BIT(1), IWL_TX_FLAGS_HIGH_PRI = BIT(2), + /* Use these flags only from + * TX_FLAGS_BITS_API_S_VER_4 and above */ + IWL_TX_FLAGS_RTS = BIT(3), + IWL_TX_FLAGS_CTS = BIT(4), }; /* TX_FLAGS_BITS_API_S_VER_3 */ /** @@ -267,7 +271,8 @@ struct iwl_tx_cmd_gen2 { struct iwl_dram_sec_info dram_info; __le32 rate_n_flags; struct ieee80211_hdr hdr[]; -} __packed; /* TX_CMD_API_S_VER_7 */ +} __packed; /* TX_CMD_API_S_VER_7, + TX_CMD_API_S_VER_9 */ /** * struct iwl_tx_cmd_gen3 - TX command struct to FW for AX210+ devices @@ -290,7 +295,8 @@ struct iwl_tx_cmd_gen3 { __le32 rate_n_flags; __le64 ttl; struct ieee80211_hdr hdr[]; -} __packed; /* TX_CMD_API_S_VER_8 */ +} __packed; /* TX_CMD_API_S_VER_8, + TX_CMD_API_S_VER_10 */ /* * TX response related data @@ -591,7 +597,8 @@ struct iwl_mvm_tx_resp { __le16 tx_queue; __le16 reserved2; struct agg_tx_status status; -} __packed; /* TX_RSP_API_S_VER_6 */ +} __packed; /* TX_RSP_API_S_VER_6, + TX_RSP_API_S_VER_7 */ /** * struct iwl_mvm_ba_notif - notifies about reception of BA @@ -715,7 +722,8 @@ struct iwl_mvm_compressed_ba_notif { __le16 ra_tid_cnt; struct iwl_mvm_compressed_ba_ratid ra_tid[0]; struct iwl_mvm_compressed_ba_tfd tfd[]; -} __packed; /* COMPRESSED_BA_RES_API_S_VER_4 */ +} __packed; /* COMPRESSED_BA_RES_API_S_VER_4, + COMPRESSED_BA_RES_API_S_VER_5 */ /** * struct iwl_mac_beacon_cmd_v6 - beacon template command @@ -755,12 +763,20 @@ struct iwl_mac_beacon_cmd_v7 { struct ieee80211_hdr frame[]; } __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_7 */ +/* Bit flags for BEACON_TEMPLATE_CMD_API until version 10 */ +enum iwl_mac_beacon_flags_v1 { + IWL_MAC_BEACON_CCK_V1 = BIT(8), + IWL_MAC_BEACON_ANT_A_V1 = BIT(9), + IWL_MAC_BEACON_ANT_B_V1 = BIT(10), + IWL_MAC_BEACON_FILS_V1 = BIT(12), +}; + +/* Bit flags for BEACON_TEMPLATE_CMD_API version 11 and above */ enum iwl_mac_beacon_flags { - IWL_MAC_BEACON_CCK = BIT(8), - IWL_MAC_BEACON_ANT_A = BIT(9), - IWL_MAC_BEACON_ANT_B = BIT(10), - IWL_MAC_BEACON_ANT_C = BIT(11), - IWL_MAC_BEACON_FILS = BIT(12), + IWL_MAC_BEACON_CCK = BIT(5), + IWL_MAC_BEACON_ANT_A = BIT(6), + IWL_MAC_BEACON_ANT_B = BIT(7), + IWL_MAC_BEACON_FILS = BIT(8), }; /** @@ -788,7 +804,9 @@ struct iwl_mac_beacon_cmd { __le32 ecsa_offset; __le32 csa_offset; struct ieee80211_hdr frame[]; -} __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_10 */ +} __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_10, + BEACON_TEMPLATE_CMD_API_S_VER_11, + BEACON_TEMPLATE_CMD_API_S_VER_12 */ struct iwl_beacon_notif { struct iwl_mvm_tx_resp beacon_notify_hdr; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 6dcafd0a3d4b..a39013c401c9 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -159,11 +159,15 @@ static void iwl_fwrt_dump_txf(struct iwl_fw_runtime *fwrt, iwl_trans_read_prph(fwrt->trans, TXF_READ_MODIFY_DATA + offset); /* Read FIFO */ - fifo_len /= sizeof(u32); /* Size in DWORDS */ - for (i = 0; i < fifo_len; i++) + for (i = 0; i < fifo_len / sizeof(u32); i++) fifo_data[i] = iwl_trans_read_prph(fwrt->trans, TXF_READ_MODIFY_DATA + offset); + + if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf) + fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx, + fifo_data, fifo_len); + *dump_data = iwl_fw_error_next_data(*dump_data); } @@ -659,6 +663,10 @@ static void iwl_fw_dump_mem(struct iwl_fw_runtime *fwrt, iwl_trans_read_mem_bytes(fwrt->trans, ofs, dump_mem->data, len); *dump_data = iwl_fw_error_next_data(*dump_data); + if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem) + fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx, ofs, + dump_mem->data, len); + IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n", dump_mem->type); } @@ -752,6 +760,12 @@ static void iwl_dump_paging(struct iwl_fw_runtime *fwrt, PAGING_BLOCK_SIZE, DMA_BIDIRECTIONAL); (*data) = iwl_fw_error_next_data(*data); + + if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem) + fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx, + fwrt->fw_paging_db[i].fw_offs, + paging->data, + PAGING_BLOCK_SIZE); } } @@ -980,6 +994,11 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt, dump_data->data + data_size, data_size); + if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem) + fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx, addr, + dump_data->data + data_size, + data_size); + dump_data = iwl_fw_error_next_data(dump_data); } @@ -1146,6 +1165,13 @@ static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt, iwl_trans_read_mem_bytes(fwrt->trans, addr, range->data, le32_to_cpu(reg->dev_addr.size)); + if ((le32_to_cpu(reg->id) & IWL_FW_INI_REGION_V2_MASK) == + IWL_FW_INI_HW_SMEM_REGION_ID && + fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf) + fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx, + range->data, + le32_to_cpu(reg->dev_addr.size)); + return sizeof(*range) + le32_to_cpu(range->range_data_size); } @@ -1338,6 +1364,10 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt, for (i = 0; i < iter->fifo_size; i += sizeof(*data)) *data++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); + if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf) + fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx, + reg_dump, iter->fifo_size); + out: iwl_trans_release_nic_access(fwrt->trans); @@ -2077,7 +2107,7 @@ static u32 iwl_dump_ini_info(struct iwl_fw_runtime *fwrt, */ hw_type = CSR_HW_REV_TYPE(fwrt->trans->hw_rev); if (hw_type == IWL_AX210_HW_TYPE) { - u32 prph_val = iwl_read_prph(fwrt->trans, WFPM_OTP_CFG1_ADDR); + u32 prph_val = iwl_read_prph(fwrt->trans, WFPM_OTP_CFG1_ADDR_GEN2); u32 is_jacket = !!(prph_val & WFPM_OTP_CFG1_IS_JACKET_BIT); u32 is_cdb = !!(prph_val & WFPM_OTP_CFG1_IS_CDB_BIT); u32 masked_bits = is_jacket | (is_cdb << 1); @@ -2360,7 +2390,9 @@ static void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt, if (dump_data->monitor_only) dump_mask &= BIT(IWL_FW_ERROR_DUMP_FW_MONITOR); - fw_error_dump.trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask); + fw_error_dump.trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask, + fwrt->sanitize_ops, + fwrt->sanitize_ctx); file_len = le32_to_cpu(dump_file->file_len); fw_error_dump.fwrt_len = file_len; @@ -2788,6 +2820,12 @@ void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt) iwl_trans_read_mem_bytes(fwrt->trans, cfg->d3_debug_data_base_addr, fwrt->dump.d3_debug_data, cfg->d3_debug_data_length); + + if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem) + fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx, + cfg->d3_debug_data_base_addr, + fwrt->dump.d3_debug_data, + cfg->d3_debug_data_length); } IWL_EXPORT_SYMBOL(iwl_fw_dbg_read_d3_debug_data); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dump.c b/drivers/net/wireless/intel/iwlwifi/fw/dump.c index a1842205e86a..016b3a4c5f51 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dump.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dump.c @@ -214,7 +214,7 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu /* reset the device */ iwl_trans_sw_reset(trans); - err = iwl_finish_nic_init(trans, trans->trans_cfg); + err = iwl_finish_nic_init(trans); if (err) return; } @@ -328,6 +328,13 @@ static void iwl_fwrt_dump_tcm_error_log(struct iwl_fw_runtime *fwrt) for (i = 0; i < ARRAY_SIZE(table.sw_status); i++) IWL_ERR(fwrt, "0x%08X | tcm SW status[%d]\n", table.sw_status[i], i); + + if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { + u32 scratch = iwl_read32(trans, CSR_FUNC_SCRATCH); + + IWL_ERR(fwrt, "Function Scratch status:\n"); + IWL_ERR(fwrt, "0x%08X | Func Scratch\n", scratch); + } } static void iwl_fwrt_dump_iml_error_log(struct iwl_fw_runtime *fwrt) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index 521ca2bb0e92..9036b32ec765 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h @@ -342,10 +342,6 @@ struct iwl_fw_ini_dump_cfg_name { #define IWL_AX210_HW_TYPE 0x42 /* How many bits to roll when adding to the HW type of AX210 HW */ #define IWL_AX210_HW_TYPE_ADDITION_SHIFT 12 -/* This prph is used to tell apart HW_TYPE == 0x42 NICs */ -#define WFPM_OTP_CFG1_ADDR 0xd03098 -#define WFPM_OTP_CFG1_IS_JACKET_BIT BIT(4) -#define WFPM_OTP_CFG1_IS_CDB_BIT BIT(5) /* struct iwl_fw_ini_dump_info - ini dump information * @version: dump version diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index 6c8e9f3a6af2..565918054ed1 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -100,6 +100,9 @@ enum iwl_ucode_tlv_type { IWL_UCODE_TLV_PNVM_SKU = 64, IWL_UCODE_TLV_TCM_DEBUG_ADDRS = 65, + IWL_UCODE_TLV_SEC_TABLE_ADDR = 66, + IWL_UCODE_TLV_D3_KEK_KCK_ADDR = 67, + IWL_UCODE_TLV_FW_NUM_STATIONS = IWL_UCODE_TLV_CONST_BASE + 0, IWL_UCODE_TLV_TYPE_DEBUG_INFO = IWL_UCODE_TLV_DEBUG_BASE + 0, @@ -107,6 +110,7 @@ enum iwl_ucode_tlv_type { IWL_UCODE_TLV_TYPE_HCMD = IWL_UCODE_TLV_DEBUG_BASE + 2, IWL_UCODE_TLV_TYPE_REGIONS = IWL_UCODE_TLV_DEBUG_BASE + 3, IWL_UCODE_TLV_TYPE_TRIGGERS = IWL_UCODE_TLV_DEBUG_BASE + 4, + IWL_UCODE_TLV_TYPE_CONF_SET = IWL_UCODE_TLV_DEBUG_BASE + 5, IWL_UCODE_TLV_DEBUG_MAX = IWL_UCODE_TLV_TYPE_TRIGGERS, /* TLVs 0x1000-0x2000 are for internal driver usage */ @@ -416,6 +420,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_PASSIVE_6GHZ_SCAN = (__force iwl_ucode_tlv_capa_t)58, IWL_UCODE_TLV_CAPA_HIDDEN_6GHZ_SCAN = (__force iwl_ucode_tlv_capa_t)59, IWL_UCODE_TLV_CAPA_BROADCAST_TWT = (__force iwl_ucode_tlv_capa_t)60, + IWL_UCODE_TLV_CAPA_COEX_HIGH_PRIO = (__force iwl_ucode_tlv_capa_t)61, /* set 2 */ IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64, @@ -450,6 +455,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_BIGTK_SUPPORT = (__force iwl_ucode_tlv_capa_t)100, IWL_UCODE_TLV_CAPA_RFIM_SUPPORT = (__force iwl_ucode_tlv_capa_t)102, + IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT = (__force iwl_ucode_tlv_capa_t)104, #ifdef __CHECKER__ /* sparse says it cannot increment the previous enum member */ @@ -956,6 +962,10 @@ struct iwl_fw_tcm_error_addr { __le32 addr; }; /* FW_TLV_TCM_ERROR_INFO_ADDRS_S */ +struct iwl_fw_dump_exclude { + __le32 addr, size; +}; + static inline size_t _iwl_tlv_array_len(const struct iwl_ucode_tlv *tlv, size_t fixed_size, size_t var_size) { diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.c b/drivers/net/wireless/intel/iwlwifi/fw/img.c index c2a4e60518bc..24a966673691 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/img.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/img.c @@ -1,59 +1,7 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* * Copyright(c) 2019 - 2020 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * The full GNU General Public License is included in this distribution - * in the file called COPYING. - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2019 - 2020 Intel Corporation - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ + */ #include "img.h" diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.h b/drivers/net/wireless/intel/iwlwifi/fw/img.h index 153a3529e77a..993bda17fa30 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/img.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/img.h @@ -124,11 +124,13 @@ struct fw_img { * @fw_paging_phys: page phy pointer * @fw_paging_block: pointer to the allocated block * @fw_paging_size: page size + * @fw_offs: offset in the device */ struct iwl_fw_paging { dma_addr_t fw_paging_phys; struct page *fw_paging_block; u32 fw_paging_size; + u32 fw_offs; }; /** @@ -174,6 +176,10 @@ struct iwl_fw_dbg { u32 dump_mask; }; +struct iwl_dump_exclude { + u32 addr, size; +}; + /** * struct iwl_fw - variables associated with the firmware * @@ -194,6 +200,10 @@ struct iwl_fw_dbg { * @cipher_scheme: optional external cipher scheme. * @human_readable: human readable version * we get the ALIVE from the uCode + * @phy_integration_ver: PHY integration version string + * @phy_integration_ver_len: length of @phy_integration_ver + * @dump_excl: image dump exclusion areas for RT image + * @dump_excl_wowlan: image dump exclusion areas for WoWLAN image */ struct iwl_fw { u32 ucode_ver; @@ -225,6 +235,8 @@ struct iwl_fw { u8 *phy_integration_ver; u32 phy_integration_ver_len; + + struct iwl_dump_exclude dump_excl[2], dump_excl_wowlan[2]; }; static inline const char *get_fw_dbg_mode_string(int mode) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/init.c b/drivers/net/wireless/intel/iwlwifi/fw/init.c index 2ecec00db9da..566957ac4539 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/init.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/init.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2019-2020 Intel Corporation + * Copyright (C) 2019-2021 Intel Corporation */ #include "iwl-drv.h" #include "runtime.h" @@ -16,6 +16,8 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans, const struct iwl_fw *fw, const struct iwl_fw_runtime_ops *ops, void *ops_ctx, + const struct iwl_dump_sanitize_ops *sanitize_ops, + void *sanitize_ctx, struct dentry *dbgfs_dir) { int i; @@ -26,6 +28,8 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans, fwrt->dev = trans->dev; fwrt->dump.conf = FW_DBG_INVALID; fwrt->ops = ops; + fwrt->sanitize_ops = sanitize_ops; + fwrt->sanitize_ctx = sanitize_ctx; fwrt->ops_ctx = ops_ctx; for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++) { fwrt->dump.wks[i].idx = i; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/paging.c b/drivers/net/wireless/intel/iwlwifi/fw/paging.c index 4a8fe9641a32..58ca3849d1f3 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/paging.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/paging.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2019 Intel Corporation + * Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -152,6 +152,7 @@ static int iwl_fill_paging_mem(struct iwl_fw_runtime *fwrt, memcpy(page_address(fwrt->fw_paging_db[0].fw_paging_block), image->sec[sec_idx].data, image->sec[sec_idx].len); + fwrt->fw_paging_db[0].fw_offs = image->sec[sec_idx].offset; dma_sync_single_for_device(fwrt->trans->dev, fwrt->fw_paging_db[0].fw_paging_phys, fwrt->fw_paging_db[0].fw_paging_size, @@ -197,6 +198,7 @@ static int iwl_fill_paging_mem(struct iwl_fw_runtime *fwrt, memcpy(page_address(block->fw_paging_block), image->sec[sec_idx].data + offset, len); + block->fw_offs = image->sec[sec_idx].offset + offset; dma_sync_single_for_device(fwrt->trans->dev, block->fw_paging_phys, block->fw_paging_size, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c index 069fcbc46d2b..7d4aa398729a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c @@ -162,7 +162,7 @@ done: goto out; } - IWL_INFO(trans, "loaded PNVM version 0x%0x\n", sha1); + IWL_INFO(trans, "loaded PNVM version %08x\n", sha1); ret = iwl_trans_set_pnvm(trans, pnvm_data, size); out: diff --git a/drivers/net/wireless/intel/iwlwifi/fw/rs.c b/drivers/net/wireless/intel/iwlwifi/fw/rs.c new file mode 100644 index 000000000000..a21c3befd93b --- /dev/null +++ b/drivers/net/wireless/intel/iwlwifi/fw/rs.c @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* + * Copyright (C) 2021 Intel Corporation + */ + +#include <net/mac80211.h> +#include "fw/api/rs.h" +#include "iwl-drv.h" +#include "iwl-config.h" + +#define IWL_DECLARE_RATE_INFO(r) \ + [IWL_RATE_##r##M_INDEX] = IWL_RATE_##r##M_PLCP + +/* + * Translate from fw_rate_index (IWL_RATE_XXM_INDEX) to PLCP + * */ +static const u8 fw_rate_idx_to_plcp[IWL_RATE_COUNT] = { + IWL_DECLARE_RATE_INFO(1), + IWL_DECLARE_RATE_INFO(2), + IWL_DECLARE_RATE_INFO(5), + IWL_DECLARE_RATE_INFO(11), + IWL_DECLARE_RATE_INFO(6), + IWL_DECLARE_RATE_INFO(9), + IWL_DECLARE_RATE_INFO(12), + IWL_DECLARE_RATE_INFO(18), + IWL_DECLARE_RATE_INFO(24), + IWL_DECLARE_RATE_INFO(36), + IWL_DECLARE_RATE_INFO(48), + IWL_DECLARE_RATE_INFO(54), +}; + +/* mbps, mcs */ +static const struct iwl_rate_mcs_info rate_mcs[IWL_RATE_COUNT] = { + { "1", "BPSK DSSS"}, + { "2", "QPSK DSSS"}, + {"5.5", "BPSK CCK"}, + { "11", "QPSK CCK"}, + { "6", "BPSK 1/2"}, + { "9", "BPSK 1/2"}, + { "12", "QPSK 1/2"}, + { "18", "QPSK 3/4"}, + { "24", "16QAM 1/2"}, + { "36", "16QAM 3/4"}, + { "48", "64QAM 2/3"}, + { "54", "64QAM 3/4"}, + { "60", "64QAM 5/6"}, +}; + +static const char * const ant_name[] = { + [ANT_NONE] = "None", + [ANT_A] = "A", + [ANT_B] = "B", + [ANT_AB] = "AB", +}; + +static const char * const pretty_bw[] = { + "20Mhz", + "40Mhz", + "80Mhz", + "160 Mhz", + "320Mhz", +}; + +u8 iwl_fw_rate_idx_to_plcp(int idx) +{ + return fw_rate_idx_to_plcp[idx]; +} +IWL_EXPORT_SYMBOL(iwl_fw_rate_idx_to_plcp); + +const struct iwl_rate_mcs_info *iwl_rate_mcs(int idx) +{ + return &rate_mcs[idx]; +} +IWL_EXPORT_SYMBOL(iwl_rate_mcs); + +const char *iwl_rs_pretty_ant(u8 ant) +{ + if (ant >= ARRAY_SIZE(ant_name)) + return "UNKNOWN"; + + return ant_name[ant]; +} +IWL_EXPORT_SYMBOL(iwl_rs_pretty_ant); + +const char *iwl_rs_pretty_bw(int bw) +{ + if (bw >= ARRAY_SIZE(pretty_bw)) + return "unknown bw"; + + return pretty_bw[bw]; +} +IWL_EXPORT_SYMBOL(iwl_rs_pretty_bw); + +u32 iwl_new_rate_from_v1(u32 rate_v1) +{ + u32 rate_v2 = 0; + u32 dup = 0; + + if (rate_v1 == 0) + return rate_v1; + /* convert rate */ + if (rate_v1 & RATE_MCS_HT_MSK_V1) { + u32 nss = 0; + + rate_v2 |= RATE_MCS_HT_MSK; + rate_v2 |= + rate_v1 & RATE_HT_MCS_RATE_CODE_MSK_V1; + nss = (rate_v1 & RATE_HT_MCS_MIMO2_MSK) >> + RATE_HT_MCS_NSS_POS_V1; + rate_v2 |= nss << RATE_MCS_NSS_POS; + } else if (rate_v1 & RATE_MCS_VHT_MSK_V1 || + rate_v1 & RATE_MCS_HE_MSK_V1) { + rate_v2 |= rate_v1 & RATE_VHT_MCS_RATE_CODE_MSK; + + rate_v2 |= rate_v1 & RATE_VHT_MCS_MIMO2_MSK; + + if (rate_v1 & RATE_MCS_HE_MSK_V1) { + u32 he_type_bits = rate_v1 & RATE_MCS_HE_TYPE_MSK_V1; + u32 he_type = he_type_bits >> RATE_MCS_HE_TYPE_POS_V1; + u32 he_106t = (rate_v1 & RATE_MCS_HE_106T_MSK_V1) >> + RATE_MCS_HE_106T_POS_V1; + u32 he_gi_ltf = (rate_v1 & RATE_MCS_HE_GI_LTF_MSK_V1) >> + RATE_MCS_HE_GI_LTF_POS; + + if ((he_type_bits == RATE_MCS_HE_TYPE_SU || + he_type_bits == RATE_MCS_HE_TYPE_EXT_SU) && + he_gi_ltf == RATE_MCS_HE_SU_4_LTF) + /* the new rate have an additional bit to + * represent the value 4 rather then using SGI + * bit for this purpose - as it was done in the old + * rate */ + he_gi_ltf += (rate_v1 & RATE_MCS_SGI_MSK_V1) >> + RATE_MCS_SGI_POS_V1; + + rate_v2 |= he_gi_ltf << RATE_MCS_HE_GI_LTF_POS; + rate_v2 |= he_type << RATE_MCS_HE_TYPE_POS; + rate_v2 |= he_106t << RATE_MCS_HE_106T_POS; + rate_v2 |= rate_v1 & RATE_HE_DUAL_CARRIER_MODE_MSK; + rate_v2 |= RATE_MCS_HE_MSK; + } else { + rate_v2 |= RATE_MCS_VHT_MSK; + } + /* if legacy format */ + } else { + u32 legacy_rate = iwl_legacy_rate_to_fw_idx(rate_v1); + + WARN_ON(legacy_rate < 0); + rate_v2 |= legacy_rate; + if (!(rate_v1 & RATE_MCS_CCK_MSK_V1)) + rate_v2 |= RATE_MCS_LEGACY_OFDM_MSK; + } + + /* convert flags */ + if (rate_v1 & RATE_MCS_LDPC_MSK_V1) + rate_v2 |= RATE_MCS_LDPC_MSK; + rate_v2 |= (rate_v1 & RATE_MCS_CHAN_WIDTH_MSK_V1) | + (rate_v1 & RATE_MCS_ANT_AB_MSK) | + (rate_v1 & RATE_MCS_STBC_MSK) | + (rate_v1 & RATE_MCS_BF_MSK); + + dup = (rate_v1 & RATE_MCS_DUP_MSK_V1) >> RATE_MCS_DUP_POS_V1; + if (dup) { + rate_v2 |= RATE_MCS_DUP_MSK; + rate_v2 |= dup << RATE_MCS_CHAN_WIDTH_POS; + } + + if ((!(rate_v1 & RATE_MCS_HE_MSK_V1)) && + (rate_v1 & RATE_MCS_SGI_MSK_V1)) + rate_v2 |= RATE_MCS_SGI_MSK; + + return rate_v2; +} +IWL_EXPORT_SYMBOL(iwl_new_rate_from_v1); + +u32 iwl_legacy_rate_to_fw_idx(u32 rate_n_flags) +{ + int rate = rate_n_flags & RATE_LEGACY_RATE_MSK_V1; + int idx; + bool ofdm = !(rate_n_flags & RATE_MCS_CCK_MSK_V1); + int offset = ofdm ? IWL_FIRST_OFDM_RATE : 0; + int last = ofdm ? IWL_RATE_COUNT_LEGACY : IWL_FIRST_OFDM_RATE; + + for (idx = offset; idx < last; idx++) + if (iwl_fw_rate_idx_to_plcp(idx) == rate) + return idx - offset; + return -1; +} + +int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate) +{ + char *type; + u8 mcs = 0, nss = 0; + u8 ant = (rate & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS; + u32 bw = (rate & RATE_MCS_CHAN_WIDTH_MSK) >> + RATE_MCS_CHAN_WIDTH_POS; + u32 format = rate & RATE_MCS_MOD_TYPE_MSK; + bool sgi; + + if (format == RATE_MCS_CCK_MSK || + format == RATE_MCS_LEGACY_OFDM_MSK) { + int legacy_rate = rate & RATE_LEGACY_RATE_MSK; + int index = format == RATE_MCS_CCK_MSK ? + legacy_rate : + legacy_rate + IWL_FIRST_OFDM_RATE; + + return scnprintf(buf, bufsz, "Legacy | ANT: %s Rate: %s Mbps", + iwl_rs_pretty_ant(ant), + index == IWL_RATE_INVALID ? "BAD" : + iwl_rate_mcs(index)->mbps); + } + + if (format == RATE_MCS_VHT_MSK) + type = "VHT"; + else if (format == RATE_MCS_HT_MSK) + type = "HT"; + else if (format == RATE_MCS_HE_MSK) + type = "HE"; + else + type = "Unknown"; /* shouldn't happen */ + + mcs = format == RATE_MCS_HT_MSK ? + RATE_HT_MCS_INDEX(rate) : + rate & RATE_MCS_CODE_MSK; + nss = ((rate & RATE_MCS_NSS_MSK) + >> RATE_MCS_NSS_POS) + 1; + sgi = format == RATE_MCS_HE_MSK ? + iwl_he_is_sgi(rate) : + rate & RATE_MCS_SGI_MSK; + + return scnprintf(buf, bufsz, + "0x%x: %s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s", + rate, type, iwl_rs_pretty_ant(ant), iwl_rs_pretty_bw(bw), mcs, nss, + (sgi) ? "SGI " : "NGI ", + (rate & RATE_MCS_STBC_MSK) ? "STBC " : "", + (rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "", + (rate & RATE_HE_DUAL_CARRIER_MODE_MSK) ? "DCM " : "", + (rate & RATE_MCS_BF_MSK) ? "BF " : ""); +} +IWL_EXPORT_SYMBOL(rs_pretty_print_rate); + +bool iwl_he_is_sgi(u32 rate_n_flags) +{ + u32 type = rate_n_flags & RATE_MCS_HE_TYPE_MSK; + u32 ltf_gi = rate_n_flags & RATE_MCS_HE_GI_LTF_MSK; + + if (type == RATE_MCS_HE_TYPE_SU || + type == RATE_MCS_HE_TYPE_EXT_SU) + return ltf_gi == RATE_MCS_HE_SU_4_LTF_08_GI; + return false; +} +IWL_EXPORT_SYMBOL(iwl_he_is_sgi); + diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index 35af85a5430b..a569ce3c5e96 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -105,6 +105,9 @@ struct iwl_fw_runtime { const struct iwl_fw_runtime_ops *ops; void *ops_ctx; + const struct iwl_dump_sanitize_ops *sanitize_ops; + void *sanitize_ctx; + /* Paging */ struct iwl_fw_paging fw_paging_db[NUM_OF_FW_PAGING_BLOCKS]; u16 num_of_paging_blk; @@ -161,6 +164,8 @@ struct iwl_fw_runtime { void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans, const struct iwl_fw *fw, const struct iwl_fw_runtime_ops *ops, void *ops_ctx, + const struct iwl_dump_sanitize_ops *sanitize_ops, + void *sanitize_ctx, struct dentry *dbgfs_dir); static inline void iwl_fw_runtime_free(struct iwl_fw_runtime *fwrt) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 7eb534df5331..665167a223f6 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -95,7 +95,6 @@ enum iwl_nvm_type { #define ANT_AC (ANT_A | ANT_C) #define ANT_BC (ANT_B | ANT_C) #define ANT_ABC (ANT_A | ANT_B | ANT_C) -#define MAX_ANT_NUM 3 static inline u8 num_of_ant(u8 mask) @@ -420,6 +419,7 @@ struct iwl_cfg { #define IWL_CFG_MAC_TYPE_SOF 0x43 #define IWL_CFG_MAC_TYPE_MA 0x44 #define IWL_CFG_MAC_TYPE_BZ 0x46 +#define IWL_CFG_MAC_TYPE_GL 0x47 #define IWL_CFG_RF_TYPE_TH 0x105 #define IWL_CFG_RF_TYPE_TH1 0x108 @@ -511,6 +511,10 @@ extern const char iwl_ax210_killer_1675w_name[]; extern const char iwl_ax210_killer_1675x_name[]; extern const char iwl9560_killer_1550i_160_name[]; extern const char iwl9560_killer_1550s_160_name[]; +extern const char iwl_ax211_killer_1675s_name[]; +extern const char iwl_ax211_killer_1675i_name[]; +extern const char iwl_ax411_killer_1690s_name[]; +extern const char iwl_ax411_killer_1690i_name[]; extern const char iwl_ax211_name[]; extern const char iwl_ax221_name[]; extern const char iwl_ax231_name[]; @@ -628,6 +632,8 @@ extern const struct iwl_cfg iwl_cfg_bz_a0_hr_b0; extern const struct iwl_cfg iwl_cfg_bz_a0_gf_a0; extern const struct iwl_cfg iwl_cfg_bz_a0_gf4_a0; extern const struct iwl_cfg iwl_cfg_bz_a0_mr_a0; +extern const struct iwl_cfg iwl_cfg_bz_a0_fm_a0; +extern const struct iwl_cfg iwl_cfg_gl_a0_fm_a0; #endif /* CONFIG_IWLMVM */ #endif /* __IWL_CONFIG_H__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h index e1fec23ac07f..5adf485db38e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h @@ -109,12 +109,12 @@ struct iwl_prph_scratch_pnvm_cfg { * struct iwl_prph_scratch_hwm_cfg - hwm config * @hwm_base_addr: hwm start address * @hwm_size: hwm size in DWs - * @reserved: reserved + * @debug_token_config: debug preset */ struct iwl_prph_scratch_hwm_cfg { __le64 hwm_base_addr; __le32 hwm_size; - __le32 reserved; + __le32 debug_token_config; } __packed; /* PERIPH_SCRATCH_HWM_CFG_S */ /* diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h index cf796403c45c..2c4d70fb32fa 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h @@ -34,6 +34,7 @@ #define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */ #define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/ #define CSR_GP_CNTRL (CSR_BASE+0x024) +#define CSR_FUNC_SCRATCH (CSR_BASE+0x02c) /* Scratch register - used for FW dbg */ /* 2nd byte of CSR_INT_COALESCING, not accessible via iwl_write32()! */ #define CSR_INT_PERIODIC_REG (CSR_BASE+0x005) @@ -135,6 +136,12 @@ #define CSR_DBG_HPET_MEM_REG (CSR_BASE+0x240) #define CSR_DBG_LINK_PWR_MGMT_REG (CSR_BASE+0x250) +/* + * Scratch register initial configuration - this is set on init, and read + * during a error FW error. + */ +#define CSR_FUNC_SCRATCH_INIT_VALUE (0x01010101) + /* Bits for CSR_HW_IF_CONFIG_REG */ #define CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH (0x00000003) #define CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP (0x0000000C) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index 125479b5c0d6..f487cc8b9fe0 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -16,6 +16,7 @@ * @IWL_DBG_TLV_TYPE_HCMD: host command TLV * @IWL_DBG_TLV_TYPE_REGION: region TLV * @IWL_DBG_TLV_TYPE_TRIGGER: trigger TLV + * @IWL_DBG_TLV_TYPE_CONF_SET: conf set TLV * @IWL_DBG_TLV_TYPE_NUM: number of debug TLVs */ enum iwl_dbg_tlv_type { @@ -25,6 +26,7 @@ enum iwl_dbg_tlv_type { IWL_DBG_TLV_TYPE_HCMD, IWL_DBG_TLV_TYPE_REGION, IWL_DBG_TLV_TYPE_TRIGGER, + IWL_DBG_TLV_TYPE_CONF_SET, IWL_DBG_TLV_TYPE_NUM, }; @@ -59,6 +61,7 @@ dbg_ver_table[IWL_DBG_TLV_TYPE_NUM] = { [IWL_DBG_TLV_TYPE_HCMD] = {.min_ver = 1, .max_ver = 1,}, [IWL_DBG_TLV_TYPE_REGION] = {.min_ver = 1, .max_ver = 2,}, [IWL_DBG_TLV_TYPE_TRIGGER] = {.min_ver = 1, .max_ver = 1,}, + [IWL_DBG_TLV_TYPE_CONF_SET] = {.min_ver = 1, .max_ver = 1,}, }; static int iwl_dbg_tlv_add(const struct iwl_ucode_tlv *tlv, @@ -260,6 +263,37 @@ static int iwl_dbg_tlv_alloc_trigger(struct iwl_trans *trans, return ret; } +static int iwl_dbg_tlv_config_set(struct iwl_trans *trans, + const struct iwl_ucode_tlv *tlv) +{ + struct iwl_fw_ini_conf_set_tlv *conf_set = (void *)tlv->data; + u32 tp = le32_to_cpu(conf_set->time_point); + u32 type = le32_to_cpu(conf_set->set_type); + + if (tp <= IWL_FW_INI_TIME_POINT_INVALID || + tp >= IWL_FW_INI_TIME_POINT_NUM) { + IWL_DEBUG_FW(trans, + "WRT: Invalid time point %u for config set TLV\n", tp); + return -EINVAL; + } + + if (type <= IWL_FW_INI_CONFIG_SET_TYPE_INVALID || + type >= IWL_FW_INI_CONFIG_SET_TYPE_MAX_NUM) { + IWL_DEBUG_FW(trans, + "WRT: Invalid config set type %u for config set TLV\n", type); + return -EINVAL; + } + + if (type != IWL_FW_INI_CONFIG_SET_TYPE_PERIPH_SCRATCH_HWM || + trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) { + IWL_DEBUG_FW(trans, + "WRT: Config set type %u is not supported\n", type); + return -EINVAL; + } + + return iwl_dbg_tlv_add(tlv, &trans->dbg.time_point[tp].config_list); +} + static int (*dbg_tlv_alloc[])(struct iwl_trans *trans, const struct iwl_ucode_tlv *tlv) = { [IWL_DBG_TLV_TYPE_DEBUG_INFO] = iwl_dbg_tlv_alloc_debug_info, @@ -267,6 +301,7 @@ static int (*dbg_tlv_alloc[])(struct iwl_trans *trans, [IWL_DBG_TLV_TYPE_HCMD] = iwl_dbg_tlv_alloc_hcmd, [IWL_DBG_TLV_TYPE_REGION] = iwl_dbg_tlv_alloc_region, [IWL_DBG_TLV_TYPE_TRIGGER] = iwl_dbg_tlv_alloc_trigger, + [IWL_DBG_TLV_TYPE_CONF_SET] = iwl_dbg_tlv_config_set, }; void iwl_dbg_tlv_alloc(struct iwl_trans *trans, const struct iwl_ucode_tlv *tlv, @@ -399,6 +434,13 @@ void iwl_dbg_tlv_free(struct iwl_trans *trans) list_del(&tlv_node->list); kfree(tlv_node); } + + list_for_each_entry_safe(tlv_node, tlv_node_tmp, + &tp->config_list, list) { + list_del(&tlv_node->list); + kfree(tlv_node); + } + } for (i = 0; i < ARRAY_SIZE(trans->dbg.fw_mon_ini); i++) @@ -466,6 +508,7 @@ void iwl_dbg_tlv_init(struct iwl_trans *trans) INIT_LIST_HEAD(&tp->trig_list); INIT_LIST_HEAD(&tp->hcmd_list); INIT_LIST_HEAD(&tp->active_trig_list); + INIT_LIST_HEAD(&tp->config_list); } } @@ -649,6 +692,10 @@ static void iwl_dbg_tlv_apply_buffers(struct iwl_fw_runtime *fwrt) { int ret, i; + if (fw_has_capa(&fwrt->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT)) + return; + for (i = 0; i < IWL_FW_INI_ALLOCATION_NUM; i++) { ret = iwl_dbg_tlv_apply_buffer(fwrt, i); if (ret) @@ -658,6 +705,87 @@ static void iwl_dbg_tlv_apply_buffers(struct iwl_fw_runtime *fwrt) } } +static int iwl_dbg_tlv_update_dram(struct iwl_fw_runtime *fwrt, + enum iwl_fw_ini_allocation_id alloc_id, + struct iwl_dram_info *dram_info) +{ + struct iwl_fw_mon *fw_mon; + u32 remain_frags, num_frags; + int j, fw_mon_idx = 0; + struct iwl_buf_alloc_cmd *data; + + if (le32_to_cpu(fwrt->trans->dbg.fw_mon_cfg[alloc_id].buf_location) != + IWL_FW_INI_LOCATION_DRAM_PATH) { + IWL_DEBUG_FW(fwrt, "DRAM_PATH is not supported alloc_id %u\n", alloc_id); + return -1; + } + + fw_mon = &fwrt->trans->dbg.fw_mon_ini[alloc_id]; + + /* the first fragment of DBGC1 is given to the FW via register + * or context info + */ + if (alloc_id == IWL_FW_INI_ALLOCATION_ID_DBGC1) + fw_mon_idx++; + + remain_frags = fw_mon->num_frags - fw_mon_idx; + if (!remain_frags) + return -1; + + num_frags = min_t(u32, remain_frags, BUF_ALLOC_MAX_NUM_FRAGS); + data = &dram_info->dram_frags[alloc_id - 1]; + data->alloc_id = cpu_to_le32(alloc_id); + data->num_frags = cpu_to_le32(num_frags); + data->buf_location = cpu_to_le32(IWL_FW_INI_LOCATION_DRAM_PATH); + + IWL_DEBUG_FW(fwrt, "WRT: DRAM buffer details alloc_id=%u, num_frags=%u\n", + cpu_to_le32(alloc_id), cpu_to_le32(num_frags)); + + for (j = 0; j < num_frags; j++) { + struct iwl_buf_alloc_frag *frag = &data->frags[j]; + struct iwl_dram_data *fw_mon_frag = &fw_mon->frags[fw_mon_idx++]; + + frag->addr = cpu_to_le64(fw_mon_frag->physical); + frag->size = cpu_to_le32(fw_mon_frag->size); + IWL_DEBUG_FW(fwrt, "WRT: DRAM fragment details\n"); + IWL_DEBUG_FW(fwrt, "frag=%u, addr=0x%016llx, size=0x%x)\n", + j, cpu_to_le64(fw_mon_frag->physical), + cpu_to_le32(fw_mon_frag->size)); + } + return 0; +} + +static void iwl_dbg_tlv_update_drams(struct iwl_fw_runtime *fwrt) +{ + int ret, i, dram_alloc = 0; + struct iwl_dram_info dram_info; + struct iwl_dram_data *frags = + &fwrt->trans->dbg.fw_mon_ini[IWL_FW_INI_ALLOCATION_ID_DBGC1].frags[0]; + + if (!fw_has_capa(&fwrt->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT)) + return; + + dram_info.first_word = cpu_to_le32(DRAM_INFO_FIRST_MAGIC_WORD); + dram_info.second_word = cpu_to_le32(DRAM_INFO_SECOND_MAGIC_WORD); + + for (i = IWL_FW_INI_ALLOCATION_ID_DBGC1; + i <= IWL_FW_INI_ALLOCATION_ID_DBGC3; i++) { + ret = iwl_dbg_tlv_update_dram(fwrt, i, &dram_info); + if (!ret) + dram_alloc++; + else + IWL_WARN(fwrt, + "WRT: Failed to set DRAM buffer for alloc id %d, ret=%d\n", + i, ret); + } + if (dram_alloc) { + memcpy(frags->block, &dram_info, sizeof(dram_info)); + IWL_DEBUG_FW(fwrt, "block data after %016x\n", + *((int *)fwrt->trans->dbg.fw_mon_ini[1].frags[0].block)); + } +} + static void iwl_dbg_tlv_send_hcmds(struct iwl_fw_runtime *fwrt, struct list_head *hcmd_list) { @@ -677,6 +805,31 @@ static void iwl_dbg_tlv_send_hcmds(struct iwl_fw_runtime *fwrt, } } +static void iwl_dbg_tlv_apply_config(struct iwl_fw_runtime *fwrt, + struct list_head *config_list) +{ + struct iwl_dbg_tlv_node *node; + + list_for_each_entry(node, config_list, list) { + struct iwl_fw_ini_conf_set_tlv *config_list = (void *)node->tlv.data; + u32 type = le32_to_cpu(config_list->set_type); + + switch (type) { + case IWL_FW_INI_CONFIG_SET_TYPE_PERIPH_SCRATCH_HWM: { + u32 debug_token_config = + le32_to_cpu(config_list->addr_val[0].value); + + IWL_DEBUG_FW(fwrt, "WRT: Setting HWM debug token config: %u\n", + debug_token_config); + fwrt->trans->dbg.ucode_preset = debug_token_config; + break; + } + default: + break; + } + } +} + static void iwl_dbg_tlv_periodic_trig_handler(struct timer_list *t) { struct iwl_dbg_tlv_timer_node *timer_node = @@ -996,8 +1149,10 @@ static void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt) &fwrt->trans->dbg.fw_mon_cfg[i]; u32 dest = le32_to_cpu(fw_mon_cfg->buf_location); - if (dest == IWL_FW_INI_LOCATION_INVALID) + if (dest == IWL_FW_INI_LOCATION_INVALID) { + failed_alloc |= BIT(i); continue; + } if (*ini_dest == IWL_FW_INI_LOCATION_INVALID) *ini_dest = dest; @@ -1024,8 +1179,10 @@ static void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt) &fwrt->trans->dbg.active_regions[i]; u32 reg_type; - if (!*active_reg) + if (!*active_reg) { + fwrt->trans->dbg.unsupported_region_msk |= BIT(i); continue; + } reg = (void *)(*active_reg)->data; reg_type = le32_to_cpu(reg->type); @@ -1051,7 +1208,7 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt, union iwl_dbg_tlv_tp_data *tp_data, bool sync) { - struct list_head *hcmd_list, *trig_list; + struct list_head *hcmd_list, *trig_list, *conf_list; if (!iwl_trans_dbg_ini_valid(fwrt->trans) || tp_id == IWL_FW_INI_TIME_POINT_INVALID || @@ -1060,10 +1217,13 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt, hcmd_list = &fwrt->trans->dbg.time_point[tp_id].hcmd_list; trig_list = &fwrt->trans->dbg.time_point[tp_id].active_trig_list; + conf_list = &fwrt->trans->dbg.time_point[tp_id].config_list; switch (tp_id) { case IWL_FW_INI_TIME_POINT_EARLY: iwl_dbg_tlv_init_cfg(fwrt); + iwl_dbg_tlv_apply_config(fwrt, conf_list); + iwl_dbg_tlv_update_drams(fwrt); iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL); break; case IWL_FW_INI_TIME_POINT_AFTER_ALIVE: diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h index c12b1fd3f479..79287708bd6e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h @@ -33,11 +33,13 @@ union iwl_dbg_tlv_tp_data { * @trig_list: list of triggers * @active_trig_list: list of active triggers * @hcmd_list: list of host commands + * @config_list: list of configuration */ struct iwl_dbg_tlv_time_point_data { struct list_head trig_list; struct list_head active_trig_list; struct list_head hcmd_list; + struct list_head config_list; }; struct iwl_trans; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-debug.c b/drivers/net/wireless/intel/iwlwifi/iwl-debug.c index f6ca2fc37c40..ae4c2a3d63d5 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-debug.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-debug.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2005-2011 Intel Corporation + * Copyright (C) 2005-2011, 2021 Intel Corporation */ #include <linux/device.h> #include <linux/interrupt.h> @@ -31,21 +31,31 @@ IWL_EXPORT_SYMBOL(__iwl_info); __iwl_fn(crit) IWL_EXPORT_SYMBOL(__iwl_crit); -void __iwl_err(struct device *dev, bool rfkill_prefix, bool trace_only, - const char *fmt, ...) +void __iwl_err(struct device *dev, enum iwl_err_mode mode, const char *fmt, ...) { struct va_format vaf = { .fmt = fmt, }; - va_list args; + va_list args, args2; va_start(args, fmt); - vaf.va = &args; - if (!trace_only) { - if (rfkill_prefix) + switch (mode) { + case IWL_ERR_MODE_RATELIMIT: + if (net_ratelimit()) + break; + fallthrough; + case IWL_ERR_MODE_REGULAR: + case IWL_ERR_MODE_RFKILL: + va_copy(args2, args); + vaf.va = &args2; + if (mode == IWL_ERR_MODE_RFKILL) dev_err(dev, "(RFKILL) %pV", &vaf); else dev_err(dev, "%pV", &vaf); + va_end(args2); + break; + default: + break; } trace_iwlwifi_err(&vaf); va_end(args); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-debug.h b/drivers/net/wireless/intel/iwlwifi/iwl-debug.h index 528eba441926..1b9f16a31b54 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-debug.h @@ -2,14 +2,9 @@ /****************************************************************************** * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2018 - 2020 Intel Corporation + * Copyright(c) 2018 - 2021 Intel Corporation * * Portions of this file are derived from the ipw3945 project. - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #ifndef __iwl_debug_h__ @@ -27,9 +22,16 @@ static inline bool iwl_have_debug_level(u32 level) #endif } +enum iwl_err_mode { + IWL_ERR_MODE_REGULAR, + IWL_ERR_MODE_RFKILL, + IWL_ERR_MODE_TRACE_ONLY, + IWL_ERR_MODE_RATELIMIT, +}; + struct device; -void __iwl_err(struct device *dev, bool rfkill_prefix, bool only_trace, - const char *fmt, ...) __printf(4, 5); +void __iwl_err(struct device *dev, enum iwl_err_mode mode, const char *fmt, ...) + __printf(3, 4); void __iwl_warn(struct device *dev, const char *fmt, ...) __printf(2, 3); void __iwl_info(struct device *dev, const char *fmt, ...) __printf(2, 3); void __iwl_crit(struct device *dev, const char *fmt, ...) __printf(2, 3); @@ -38,13 +40,17 @@ void __iwl_crit(struct device *dev, const char *fmt, ...) __printf(2, 3); #define CHECK_FOR_NEWLINE(f) BUILD_BUG_ON(f[sizeof(f) - 2] != '\n') /* No matter what is m (priv, bus, trans), this will work */ -#define IWL_ERR_DEV(d, f, a...) \ +#define __IWL_ERR_DEV(d, mode, f, a...) \ do { \ CHECK_FOR_NEWLINE(f); \ - __iwl_err((d), false, false, f, ## a); \ + __iwl_err((d), mode, f, ## a); \ } while (0) +#define IWL_ERR_DEV(d, f, a...) \ + __IWL_ERR_DEV(d, IWL_ERR_MODE_REGULAR, f, ## a) #define IWL_ERR(m, f, a...) \ IWL_ERR_DEV((m)->dev, f, ## a) +#define IWL_ERR_LIMIT(m, f, a...) \ + __IWL_ERR_DEV((m)->dev, IWL_ERR_MODE_RATELIMIT, f, ## a) #define IWL_WARN(m, f, a...) \ do { \ CHECK_FOR_NEWLINE(f); \ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h index 1bc6ecc32140..347fd95c4e3a 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h @@ -4,11 +4,6 @@ * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2015 Intel Deutschland GmbH * Copyright(c) 2018 - 2019 Intel Corporation - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #if !defined(__IWLWIFI_DEVICE_TRACE_DATA) || defined(TRACE_HEADER_MULTI_READ) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h index a57019241a78..0af9d8362c5b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h @@ -3,11 +3,6 @@ * * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2016-2017 Intel Deutschland GmbH - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #if !defined(__IWLWIFI_DEVICE_TRACE_IO) || defined(TRACE_HEADER_MULTI_READ) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h index 72ca882daed5..46ed723f138a 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h @@ -5,11 +5,6 @@ * Copyright(c) 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2018 Intel Corporation - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #if !defined(__IWLWIFI_DEVICE_TRACE_IWLWIFI) || defined(TRACE_HEADER_MULTI_READ) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h index d0467da5af03..7dd70011fd1e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h @@ -2,11 +2,6 @@ /****************************************************************************** * * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved. - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #if !defined(__IWLWIFI_DEVICE_TRACE_MSG) || defined(TRACE_HEADER_MULTI_READ) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-ucode.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-ucode.h index 2228faefffbc..3ec0205ac9f9 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-ucode.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-ucode.h @@ -2,11 +2,6 @@ /****************************************************************************** * * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved. - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #if !defined(__IWLWIFI_DEVICE_TRACE_UCODE) || defined(TRACE_HEADER_MULTI_READ) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.c index b5037db0c381..999b7c652289 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.c @@ -3,11 +3,6 @@ * * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved. * Copyright (C) 2018 Intel Corporation - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #include <linux/module.h> diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h index fc8bc212ee84..1455b578358b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h @@ -4,11 +4,6 @@ * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved. * Copyright(C) 2016 Intel Deutschland GmbH * Copyright(c) 2018 Intel Corporation - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #ifndef __IWLWIFI_DEVICE_TRACE diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 77124b8b235e..36196e07b1a0 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -31,7 +31,6 @@ #define DRV_DESCRIPTION "Intel(R) Wireless WiFi driver for Linux" MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_AUTHOR); MODULE_LICENSE("GPL"); #ifdef CONFIG_IWLWIFI_DEBUGFS @@ -550,6 +549,43 @@ static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv, return 0; } +static void iwl_drv_set_dump_exclude(struct iwl_drv *drv, + enum iwl_ucode_tlv_type tlv_type, + const void *tlv_data, u32 tlv_len) +{ + const struct iwl_fw_dump_exclude *fw = tlv_data; + struct iwl_dump_exclude *excl; + + if (tlv_len < sizeof(*fw)) + return; + + if (tlv_type == IWL_UCODE_TLV_SEC_TABLE_ADDR) { + excl = &drv->fw.dump_excl[0]; + + /* second time we find this, it's for WoWLAN */ + if (excl->addr) + excl = &drv->fw.dump_excl_wowlan[0]; + } else if (fw_has_capa(&drv->fw.ucode_capa, + IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG)) { + /* IWL_UCODE_TLV_D3_KEK_KCK_ADDR is regular image */ + excl = &drv->fw.dump_excl[0]; + } else { + /* IWL_UCODE_TLV_D3_KEK_KCK_ADDR is WoWLAN image */ + excl = &drv->fw.dump_excl_wowlan[0]; + } + + if (excl->addr) + excl++; + + if (excl->addr) { + IWL_DEBUG_FW_INFO(drv, "found too many excludes in fw file\n"); + return; + } + + excl->addr = le32_to_cpu(fw->addr) & ~FW_ADDR_CACHE_CONTROL; + excl->size = le32_to_cpu(fw->size); +} + static int iwl_parse_tlv_firmware(struct iwl_drv *drv, const struct firmware *ucode_raw, struct iwl_firmware_pieces *pieces, @@ -1133,6 +1169,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, case IWL_UCODE_TLV_TYPE_HCMD: case IWL_UCODE_TLV_TYPE_REGIONS: case IWL_UCODE_TLV_TYPE_TRIGGERS: + case IWL_UCODE_TLV_TYPE_CONF_SET: if (iwlwifi_mod_params.enable_ini) iwl_dbg_tlv_alloc(drv->trans, tlv, false); break; @@ -1166,6 +1203,11 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, return -ENOMEM; drv->fw.phy_integration_ver_len = tlv_len; break; + case IWL_UCODE_TLV_SEC_TABLE_ADDR: + case IWL_UCODE_TLV_D3_KEK_KCK_ADDR: + iwl_drv_set_dump_exclude(drv, tlv_type, + tlv_data, tlv_len); + break; default: IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type); break; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h index b6442df0c643..2e2d60a58692 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2005-2014, 2020 Intel Corporation + * Copyright (C) 2005-2014, 2020-2021 Intel Corporation * Copyright (C) 2013-2014 Intel Mobile Communications GmbH */ #ifndef __iwl_drv_h__ @@ -9,7 +9,6 @@ /* for all modules */ #define DRV_NAME "iwlwifi" -#define DRV_AUTHOR "Intel Corporation <[email protected]>" /* radio config bits (actual values from NVM definition) */ #define NVM_RF_CFG_DASH_MSK(x) (x & 0x3) /* bits 0-1 */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c index dbab2f10d750..b9e86bf972e5 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2005-2014, 2018-2019 Intel Corporation + * Copyright (C) 2005-2014, 2018-2019, 2021 Intel Corporation */ #include <linux/types.h> #include <linux/slab.h> @@ -139,7 +139,7 @@ static int iwl_init_otp_access(struct iwl_trans *trans) { int ret; - ret = iwl_finish_nic_init(trans, trans->trans_cfg); + ret = iwl_finish_nic_init(trans); if (ret) return ret; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index 2517c4ae07ab..6e96ee5bc261 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c @@ -398,9 +398,9 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf) return 0; } -int iwl_finish_nic_init(struct iwl_trans *trans, - const struct iwl_cfg_trans_params *cfg_trans) +int iwl_finish_nic_init(struct iwl_trans *trans) { + const struct iwl_cfg_trans_params *cfg_trans = trans->trans_cfg; u32 poll_ready; int err; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-io.h index 3c21c0e081f8..37b3bd62897e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2018-2020 Intel Corporation + * Copyright (C) 2018-2021 Intel Corporation */ #ifndef __iwl_io_h__ #define __iwl_io_h__ @@ -52,8 +52,7 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); void iwl_force_nmi(struct iwl_trans *trans); -int iwl_finish_nic_init(struct iwl_trans *trans, - const struct iwl_cfg_trans_params *cfg_trans); +int iwl_finish_nic_init(struct iwl_trans *trans); /* Error handling */ int iwl_dump_fh(struct iwl_trans *trans, char **buf); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 475f951d4b1e..f470f9aea50f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -534,6 +534,17 @@ static void iwl_init_vht_hw_capab(struct iwl_trans *trans, cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE); } +static const u8 iwl_vendor_caps[] = { + 0xdd, /* vendor element */ + 0x06, /* length */ + 0x00, 0x17, 0x35, /* Intel OUI */ + 0x08, /* type (Intel Capabilities) */ + /* followed by 16 bits of capabilities */ +#define IWL_VENDOR_CAP_IMPROVED_BF_FDBK_HE BIT(0) + IWL_VENDOR_CAP_IMPROVED_BF_FDBK_HE, + 0x00 +}; + static const struct ieee80211_sband_iftype_data iwl_he_capa[] = { { .types_mask = BIT(NL80211_IFTYPE_STATION), @@ -781,6 +792,12 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans, if (fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_BROADCAST_TWT)) iftype_data->he_cap.he_cap_elem.mac_cap_info[2] |= IEEE80211_HE_MAC_CAP2_BCAST_TWT; + + if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 && + !is_ap) { + iftype_data->vendor_elems.data = iwl_vendor_caps; + iftype_data->vendor_elems.len = ARRAY_SIZE(iwl_vendor_caps); + } } static void iwl_init_he_hw_capab(struct iwl_trans *trans, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h index d0a7d58336a9..a84ab02cf9d7 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h @@ -347,6 +347,12 @@ #define RADIO_REG_SYS_MANUAL_DFT_0 0xAD4078 #define RFIC_REG_RD 0xAD0470 #define WFPM_CTRL_REG 0xA03030 +#define WFPM_CTRL_REG_GEN2 0xd03030 +#define WFPM_OTP_CFG1_ADDR 0x00a03098 +#define WFPM_OTP_CFG1_ADDR_GEN2 0x00d03098 +#define WFPM_OTP_CFG1_IS_JACKET_BIT BIT(4) +#define WFPM_OTP_CFG1_IS_CDB_BIT BIT(5) + #define WFPM_GP2 0xA030B4 /* DBGI SRAM Register details */ @@ -399,10 +405,40 @@ enum { LMPM_PAGE_PASS_NOTIF_POS = BIT(20), }; +/* + * CRF ID register + * + * type: bits 0-11 + * reserved: bits 12-18 + * slave_exist: bit 19 + * dash: bits 20-23 + * step: bits 24-26 + * flavor: bits 27-31 + */ +#define REG_CRF_ID_TYPE(val) (((val) & 0x00000FFF) >> 0) +#define REG_CRF_ID_SLAVE(val) (((val) & 0x00080000) >> 19) +#define REG_CRF_ID_DASH(val) (((val) & 0x00F00000) >> 20) +#define REG_CRF_ID_STEP(val) (((val) & 0x07000000) >> 24) +#define REG_CRF_ID_FLAVOR(val) (((val) & 0xF8000000) >> 27) + #define UREG_CHICK (0xA05C00) #define UREG_CHICK_MSI_ENABLE BIT(24) #define UREG_CHICK_MSIX_ENABLE BIT(25) +#define SD_REG_VER 0xa29600 +#define SD_REG_VER_GEN2 0x00a2b800 + +#define REG_CRF_ID_TYPE_JF_1 0x201 +#define REG_CRF_ID_TYPE_JF_2 0x202 +#define REG_CRF_ID_TYPE_HR_CDB 0x503 +#define REG_CRF_ID_TYPE_HR_NONE_CDB 0x504 +#define REG_CRF_ID_TYPE_HR_NONE_CDB_1X1 0x501 +#define REG_CRF_ID_TYPE_HR_NONE_CDB_CCP 0x532 +#define REG_CRF_ID_TYPE_GF 0x410 +#define REG_CRF_ID_TYPE_GF_TC 0xF08 +#define REG_CRF_ID_TYPE_MR 0x810 +#define REG_CRF_ID_TYPE_FM 0x910 + #define HPM_DEBUG 0xA03440 #define PERSISTENCE_BIT BIT(12) #define PREG_WFPM_ACCESS BIT(12) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 8f0ff540f439..4ebb1871bd1f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -363,6 +363,20 @@ struct iwl_hcmd_arr { { .arr = x, .size = ARRAY_SIZE(x) } /** + * struct iwl_dump_sanitize_ops - dump sanitization operations + * @frob_txf: Scrub the TX FIFO data + * @frob_hcmd: Scrub a host command, the %hcmd pointer is to the header + * but that might be short or long (&struct iwl_cmd_header or + * &struct iwl_cmd_header_wide) + * @frob_mem: Scrub memory data + */ +struct iwl_dump_sanitize_ops { + void (*frob_txf)(void *ctx, void *buf, size_t buflen); + void (*frob_hcmd)(void *ctx, void *hcmd, size_t buflen); + void (*frob_mem)(void *ctx, u32 mem_addr, void *mem, size_t buflen); +}; + +/** * struct iwl_trans_config - transport configuration * * @op_mode: pointer to the upper layer. @@ -586,7 +600,9 @@ struct iwl_trans_ops { u32 value); struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans, - u32 dump_mask); + u32 dump_mask, + const struct iwl_dump_sanitize_ops *sanitize_ops, + void *sanitize_ctx); void (*debugfs_cleanup)(struct iwl_trans *trans); void (*sync_nmi)(struct iwl_trans *trans); int (*set_pnvm)(struct iwl_trans *trans, const void *data, u32 len); @@ -723,8 +739,8 @@ struct iwl_self_init_dram { * @debug_info_tlv_list: list of debug info TLVs * @time_point: array of debug time points * @periodic_trig_list: periodic triggers list - * @domains_bitmap: bitmap of active domains other than - * &IWL_FW_INI_DOMAIN_ALWAYS_ON + * @domains_bitmap: bitmap of active domains other than &IWL_FW_INI_DOMAIN_ALWAYS_ON + * @ucode_preset: preset based on ucode */ struct iwl_trans_debug { u8 n_dest_reg; @@ -758,6 +774,7 @@ struct iwl_trans_debug { struct list_head periodic_trig_list; u32 domains_bitmap; + u32 ucode_preset; }; struct iwl_dma_ptr { @@ -1086,11 +1103,14 @@ static inline int iwl_trans_d3_resume(struct iwl_trans *trans, } static inline struct iwl_trans_dump_data * -iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask) +iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask, + const struct iwl_dump_sanitize_ops *sanitize_ops, + void *sanitize_ctx) { if (!trans->ops->dump_data) return NULL; - return trans->ops->dump_data(trans, dump_mask); + return trans->ops->dump_data(trans, dump_mask, + sanitize_ops, sanitize_ctx); } static inline struct iwl_device_tx_cmd * diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 5dc39fbb74d6..ff66001d507e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -395,10 +395,9 @@ static ssize_t iwl_dbgfs_rs_data_read(struct file *file, char __user *user_buf, "A-MPDU size limit %d\n", lq_sta->pers.dbg_agg_frame_count_lim); desc += scnprintf(buff + desc, bufsz - desc, - "valid_tx_ant %s%s%s\n", + "valid_tx_ant %s%s\n", (iwl_mvm_get_valid_tx_ant(mvm) & ANT_A) ? "ANT_A," : "", - (iwl_mvm_get_valid_tx_ant(mvm) & ANT_B) ? "ANT_B," : "", - (iwl_mvm_get_valid_tx_ant(mvm) & ANT_C) ? "ANT_C" : ""); + (iwl_mvm_get_valid_tx_ant(mvm) & ANT_B) ? "ANT_B," : ""); desc += scnprintf(buff + desc, bufsz - desc, "last tx rate=0x%X ", lq_sta->last_rate_n_flags); @@ -986,8 +985,8 @@ static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm, continue; pos += scnprintf(pos, endpos - pos, "Rate[%d]: ", (int)(ARRAY_SIZE(stats->last_rates) - i)); - pos += rs_pretty_print_rate(pos, endpos - pos, - stats->last_rates[idx]); + pos += rs_pretty_print_rate_v1(pos, endpos - pos, + stats->last_rates[idx]); if (pos < endpos - 1) *pos++ = '\n'; } @@ -1060,8 +1059,6 @@ iwl_dbgfs_scan_ant_rxchain_read(struct file *file, pos += scnprintf(buf + pos, bufsz - pos, "A"); if (mvm->scan_rx_ant & ANT_B) pos += scnprintf(buf + pos, bufsz - pos, "B"); - if (mvm->scan_rx_ant & ANT_C) - pos += scnprintf(buf + pos, bufsz - pos, "C"); pos += scnprintf(buf + pos, bufsz - pos, " (%hhx)\n", mvm->scan_rx_ant); return simple_read_from_buffer(user_buf, count, ppos, buf, pos); @@ -1196,7 +1193,6 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len) struct ieee80211_tx_info *info; struct iwl_mac_beacon_cmd beacon_cmd = {}; u8 rate; - u16 flags; int i; len /= 2; @@ -1243,12 +1239,9 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len) mvmvif = iwl_mvm_vif_from_mac80211(vif); info = IEEE80211_SKB_CB(beacon); rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif); - flags = iwl_mvm_mac80211_idx_to_hwrate(rate); - if (rate == IWL_FIRST_CCK_RATE) - flags |= IWL_MAC_BEACON_CCK; - - beacon_cmd.flags = cpu_to_le16(flags); + beacon_cmd.flags = + cpu_to_le16(iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw, rate)); beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len); beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c index 03e5bf5cb909..949fb790f8fb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c @@ -324,6 +324,7 @@ iwl_mvm_ftm_target_chandef_v2(struct iwl_mvm *mvm, u8 *ctrl_ch_position) { u32 freq = peer->chandef.chan->center_freq; + u8 cmd_ver; *channel = ieee80211_frequency_to_channel(freq); @@ -344,6 +345,17 @@ iwl_mvm_ftm_target_chandef_v2(struct iwl_mvm *mvm, *format_bw = IWL_LOCATION_FRAME_FORMAT_VHT; *format_bw |= IWL_LOCATION_BW_80MHZ << LOCATION_BW_POS; break; + case NL80211_CHAN_WIDTH_160: + cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, LOCATION_GROUP, + TOF_RANGE_REQ_CMD, + IWL_FW_CMD_VER_UNKNOWN); + + if (cmd_ver >= 13) { + *format_bw = IWL_LOCATION_FRAME_FORMAT_HE; + *format_bw |= IWL_LOCATION_BW_160MHZ << LOCATION_BW_POS; + break; + } + fallthrough; default: IWL_ERR(mvm, "Unsupported BW in FTM request (%d)\n", peer->chandef.width); @@ -1142,6 +1154,7 @@ static u8 iwl_mvm_ftm_get_range_resp_ver(struct iwl_mvm *mvm) static bool iwl_mvm_ftm_resp_size_validation(u8 ver, unsigned int pkt_len) { switch (ver) { + case 9: case 8: return pkt_len == sizeof(struct iwl_tof_range_rsp_ntfy_v8); case 7: @@ -1205,7 +1218,7 @@ void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) int peer_idx; if (new_api) { - if (notif_ver == 8) { + if (notif_ver >= 8) { fw_ap = &fw_resp_v8->ap[i]; iwl_mvm_ftm_pasn_update_pn(mvm, fw_ap); } else if (notif_ver == 7) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c index eba5433c2626..bda6da7d988e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c @@ -46,8 +46,8 @@ static int iwl_mvm_ftm_responder_set_bw_v1(struct cfg80211_chan_def *chandef, } static int iwl_mvm_ftm_responder_set_bw_v2(struct cfg80211_chan_def *chandef, - u8 *format_bw, - u8 *ctrl_ch_position) + u8 *format_bw, u8 *ctrl_ch_position, + u8 cmd_ver) { switch (chandef->width) { case NL80211_CHAN_WIDTH_20_NOHT: @@ -68,6 +68,14 @@ static int iwl_mvm_ftm_responder_set_bw_v2(struct cfg80211_chan_def *chandef, *format_bw |= IWL_LOCATION_BW_80MHZ << LOCATION_BW_POS; *ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef); break; + case NL80211_CHAN_WIDTH_160: + if (cmd_ver >= 9) { + *format_bw = IWL_LOCATION_FRAME_FORMAT_HE; + *format_bw |= IWL_LOCATION_BW_160MHZ << LOCATION_BW_POS; + *ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef); + break; + } + fallthrough; default: return -ENOTSUPP; } @@ -140,7 +148,8 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm, if (cmd_ver >= 7) err = iwl_mvm_ftm_responder_set_bw_v2(chandef, &cmd.format_bw, - &cmd.ctrl_ch_position); + &cmd.ctrl_ch_position, + cmd_ver); else err = iwl_mvm_ftm_responder_set_bw_v1(chandef, &cmd.format_bw, &cmd.ctrl_ch_position); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 74404c96063b..410a8d20d56e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -295,6 +295,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, if (ret) { struct iwl_trans *trans = mvm->trans; + /* SecBoot info */ if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) { IWL_ERR(mvm, @@ -302,6 +303,17 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, iwl_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS), iwl_read_umac_prph(trans, UMAG_SB_CPU_2_STATUS)); + } else if (trans->trans_cfg->device_family >= + IWL_DEVICE_FAMILY_8000) { + IWL_ERR(mvm, + "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n", + iwl_read_prph(trans, SB_CPU_1_STATUS), + iwl_read_prph(trans, SB_CPU_2_STATUS)); + } + + /* LMAC/UMAC PC info */ + if (trans->trans_cfg->device_family >= + IWL_DEVICE_FAMILY_9000) { IWL_ERR(mvm, "UMAC PC: 0x%x\n", iwl_read_umac_prph(trans, UREG_UMAC_CURRENT_PC)); @@ -312,12 +324,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, IWL_ERR(mvm, "LMAC2 PC: 0x%x\n", iwl_read_umac_prph(trans, UREG_LMAC2_CURRENT_PC)); - } else if (trans->trans_cfg->device_family >= - IWL_DEVICE_FAMILY_8000) { - IWL_ERR(mvm, - "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n", - iwl_read_prph(trans, SB_CPU_1_STATUS), - iwl_read_prph(trans, SB_CPU_2_STATUS)); } if (ret == -ETIMEDOUT) @@ -1133,7 +1139,7 @@ static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm) { int ret; u32 value; - struct iwl_lari_config_change_cmd_v4 cmd = {}; + struct iwl_lari_config_change_cmd_v5 cmd = {}; cmd.config_bitmap = iwl_acpi_get_lari_config_bitmap(&mvm->fwrt); @@ -1149,14 +1155,23 @@ static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm) if (!ret) cmd.oem_unii4_allow_bitmap = cpu_to_le32(value); + ret = iwl_acpi_get_dsm_u32((&mvm->fwrt)->dev, 0, + DSM_FUNC_ACTIVATE_CHANNEL, + &iwl_guid, &value); + if (!ret) + cmd.chan_state_active_bitmap = cpu_to_le32(value); + if (cmd.config_bitmap || cmd.oem_11ax_allow_bitmap || - cmd.oem_unii4_allow_bitmap) { + cmd.oem_unii4_allow_bitmap || + cmd.chan_state_active_bitmap) { size_t cmd_size; u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, REGULATORY_AND_NVM_GROUP, LARI_CONFIG_CHANGE, 1); - if (cmd_ver == 4) + if (cmd_ver == 5) + cmd_size = sizeof(struct iwl_lari_config_change_cmd_v5); + else if (cmd_ver == 4) cmd_size = sizeof(struct iwl_lari_config_change_cmd_v4); else if (cmd_ver == 3) cmd_size = sizeof(struct iwl_lari_config_change_cmd_v3); @@ -1170,8 +1185,9 @@ static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm) le32_to_cpu(cmd.config_bitmap), le32_to_cpu(cmd.oem_11ax_allow_bitmap)); IWL_DEBUG_RADIO(mvm, - "sending LARI_CONFIG_CHANGE, oem_unii4_allow_bitmap=0x%x, cmd_ver=%d\n", + "sending LARI_CONFIG_CHANGE, oem_unii4_allow_bitmap=0x%x, chan_state_active_bitmap=0x%x, cmd_ver=%d\n", le32_to_cpu(cmd.oem_unii4_allow_bitmap), + le32_to_cpu(cmd.chan_state_active_bitmap), cmd_ver); ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(REGULATORY_AND_NVM_GROUP, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index fd352b2624a6..cfb69e49a687 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -604,6 +604,12 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, ctxt_sta->is_assoc = cpu_to_le32(1); + if (!mvmvif->authorized && + fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_COEX_HIGH_PRIO)) + ctxt_sta->data_policy |= + cpu_to_le32(COEX_HIGH_PRIORITY_ENABLE); + /* * allow multicast data frames only as long as the station is * authorized, i.e., GTK keys are already installed (if needed) @@ -812,6 +818,21 @@ u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info, return rate; } +u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, u8 rate_idx) +{ + u16 flags = iwl_mvm_mac80211_idx_to_hwrate(fw, rate_idx); + bool is_new_rate = iwl_fw_lookup_cmd_ver(fw, + LONG_GROUP, + BEACON_TEMPLATE_CMD, + 0) > 10; + + if (rate_idx <= IWL_FIRST_CCK_RATE) + flags |= is_new_rate ? IWL_MAC_BEACON_CCK + : IWL_MAC_BEACON_CCK_V1; + + return flags; +} + static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct sk_buff *beacon, @@ -844,9 +865,10 @@ static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm, rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif); - tx->rate_n_flags |= cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(rate)); + tx->rate_n_flags |= + cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(mvm->fw, rate)); if (rate == IWL_FIRST_CCK_RATE) - tx->rate_n_flags |= cpu_to_le32(RATE_MCS_CCK_MSK); + tx->rate_n_flags |= cpu_to_le32(RATE_MCS_CCK_MSK_V1); } @@ -929,11 +951,7 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm, u16 flags; struct ieee80211_chanctx_conf *ctx; int channel; - - flags = iwl_mvm_mac80211_idx_to_hwrate(rate); - - if (rate == IWL_FIRST_CCK_RATE) - flags |= IWL_MAC_BEACON_CCK; + flags = iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw, rate); /* Enable FILS on PSC channels only */ rcu_read_lock(); @@ -942,7 +960,11 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm, WARN_ON(channel == 0); if (cfg80211_channel_is_psc(ctx->def.chan) && !IWL_MVM_DISABLE_AP_FILS) { - flags |= IWL_MAC_BEACON_FILS; + flags |= iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP, + BEACON_TEMPLATE_CMD, + 0) > 10 ? + IWL_MAC_BEACON_FILS : + IWL_MAC_BEACON_FILS_V1; beacon_cmd.short_ssid = cpu_to_le32(~crc32_le(~0, vif->bss_conf.ssid, vif->bss_conf.ssid_len)); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 3a4585222d6d..2645dd8fef83 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -145,7 +145,8 @@ static const struct cfg80211_pmsr_capabilities iwl_mvm_pmsr_capa = { .bandwidths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | BIT(NL80211_CHAN_WIDTH_20) | BIT(NL80211_CHAN_WIDTH_40) | - BIT(NL80211_CHAN_WIDTH_80), + BIT(NL80211_CHAN_WIDTH_80) | + BIT(NL80211_CHAN_WIDTH_160), .preambles = BIT(NL80211_PREAMBLE_LEGACY) | BIT(NL80211_PREAMBLE_HT) | BIT(NL80211_PREAMBLE_VHT) | @@ -2022,7 +2023,8 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm, } sband = mvm->hw->wiphy->bands[chanctx_conf->def.chan->band]; - own_he_cap = ieee80211_get_he_iftype_cap(sband, vif->type); + own_he_cap = ieee80211_get_he_iftype_cap(sband, + ieee80211_vif_type_p2p(vif)); sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_ctxt_cmd.sta_id]); if (IS_ERR_OR_NULL(sta)) { @@ -3192,32 +3194,43 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, if (iwl_mvm_phy_ctx_count(mvm) > 1) iwl_mvm_teardown_tdls_peers(mvm); - if (sta->tdls) + if (sta->tdls) { iwl_mvm_tdls_check_trigger(mvm, vif, sta->addr, NL80211_TDLS_ENABLE_LINK); + } else { + /* enable beacon filtering */ + WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0)); - /* enable beacon filtering */ - WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0)); + mvmvif->authorized = 1; - /* - * Now that the station is authorized, i.e., keys were already - * installed, need to indicate to the FW that - * multicast data frames can be forwarded to the driver - */ - iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); + /* + * Now that the station is authorized, i.e., keys were already + * installed, need to indicate to the FW that + * multicast data frames can be forwarded to the driver + */ + iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); + } iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band, true); } else if (old_state == IEEE80211_STA_AUTHORIZED && new_state == IEEE80211_STA_ASSOC) { - /* Multicast data frames are no longer allowed */ - iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); + if (!sta->tdls) { + /* Multicast data frames are no longer allowed */ + iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); - /* disable beacon filtering */ - ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0); - WARN_ON(ret && - !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, - &mvm->status)); + /* + * Set this after the above iwl_mvm_mac_ctxt_changed() + * to avoid sending high prio again for a little time. + */ + mvmvif->authorized = 0; + + /* disable beacon filtering */ + ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0); + WARN_ON(ret && + !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, + &mvm->status)); + } ret = 0; } else if (old_state == IEEE80211_STA_ASSOC && new_state == IEEE80211_STA_AUTH) { @@ -3342,6 +3355,21 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw, mutex_unlock(&mvm->mutex); } +static void iwl_mvm_mac_mgd_complete_tx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_prep_tx_info *info) +{ + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + + /* for successful cases (auth/assoc), don't cancel session protection */ + if (info->success) + return; + + mutex_lock(&mvm->mutex); + iwl_mvm_stop_session_protection(mvm, vif); + mutex_unlock(&mvm->mutex); +} + static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_sched_scan_request *req, @@ -4704,6 +4732,9 @@ static void iwl_mvm_channel_switch_rx_beacon(struct ieee80211_hw *hw, if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_CS_MODIFY)) return; + IWL_DEBUG_MAC80211(mvm, "Modify CSA on mac %d count = %d (old %d) mode = %d\n", + mvmvif->id, chsw->count, mvmvif->csa_count, chsw->block_tx); + if (chsw->count >= mvmvif->csa_count && chsw->block_tx) { if (mvmvif->csa_misbehave) { /* Second time, give up on this AP*/ @@ -4720,8 +4751,6 @@ static void iwl_mvm_channel_switch_rx_beacon(struct ieee80211_hw *hw, if (mvmvif->csa_failed) goto out_unlock; - IWL_DEBUG_MAC80211(mvm, "Modify CSA on mac %d count = %d mode = %d\n", - mvmvif->id, chsw->count, chsw->block_tx); WARN_ON(iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(MAC_CONF_GROUP, CHANNEL_SWITCH_TIME_EVENT_CMD), @@ -4873,6 +4902,8 @@ static int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx, static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo) { + u32 format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK; + switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) { case RATE_MCS_CHAN_WIDTH_20: rinfo->bw = RATE_INFO_BW_20; @@ -4888,30 +4919,65 @@ static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo) break; } - if (rate_n_flags & RATE_MCS_HT_MSK) { - rinfo->flags |= RATE_INFO_FLAGS_MCS; - rinfo->mcs = u32_get_bits(rate_n_flags, RATE_HT_MCS_INDEX_MSK); - rinfo->nss = u32_get_bits(rate_n_flags, - RATE_HT_MCS_NSS_MSK) + 1; - if (rate_n_flags & RATE_MCS_SGI_MSK) - rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; - } else if (rate_n_flags & RATE_MCS_VHT_MSK) { - rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS; - rinfo->mcs = u32_get_bits(rate_n_flags, - RATE_VHT_MCS_RATE_CODE_MSK); - rinfo->nss = u32_get_bits(rate_n_flags, - RATE_VHT_MCS_NSS_MSK) + 1; - if (rate_n_flags & RATE_MCS_SGI_MSK) - rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; - } else if (rate_n_flags & RATE_MCS_HE_MSK) { + if (format == RATE_MCS_CCK_MSK || + format == RATE_MCS_LEGACY_OFDM_MSK) { + int rate = u32_get_bits(rate_n_flags, RATE_LEGACY_RATE_MSK); + + /* add the offset needed to get to the legacy ofdm indices */ + if (format == RATE_MCS_LEGACY_OFDM_MSK) + rate += IWL_FIRST_OFDM_RATE; + + switch (rate) { + case IWL_RATE_1M_INDEX: + rinfo->legacy = 10; + break; + case IWL_RATE_2M_INDEX: + rinfo->legacy = 20; + break; + case IWL_RATE_5M_INDEX: + rinfo->legacy = 55; + break; + case IWL_RATE_11M_INDEX: + rinfo->legacy = 110; + break; + case IWL_RATE_6M_INDEX: + rinfo->legacy = 60; + break; + case IWL_RATE_9M_INDEX: + rinfo->legacy = 90; + break; + case IWL_RATE_12M_INDEX: + rinfo->legacy = 120; + break; + case IWL_RATE_18M_INDEX: + rinfo->legacy = 180; + break; + case IWL_RATE_24M_INDEX: + rinfo->legacy = 240; + break; + case IWL_RATE_36M_INDEX: + rinfo->legacy = 360; + break; + case IWL_RATE_48M_INDEX: + rinfo->legacy = 480; + break; + case IWL_RATE_54M_INDEX: + rinfo->legacy = 540; + } + return; + } + + rinfo->nss = u32_get_bits(rate_n_flags, + RATE_MCS_NSS_MSK) + 1; + rinfo->mcs = format == RATE_MCS_HT_MSK ? + RATE_HT_MCS_INDEX(rate_n_flags) : + u32_get_bits(rate_n_flags, RATE_MCS_CODE_MSK); + + if (format == RATE_MCS_HE_MSK) { u32 gi_ltf = u32_get_bits(rate_n_flags, RATE_MCS_HE_GI_LTF_MSK); rinfo->flags |= RATE_INFO_FLAGS_HE_MCS; - rinfo->mcs = u32_get_bits(rate_n_flags, - RATE_VHT_MCS_RATE_CODE_MSK); - rinfo->nss = u32_get_bits(rate_n_flags, - RATE_VHT_MCS_NSS_MSK) + 1; if (rate_n_flags & RATE_MCS_HE_106T_MSK) { rinfo->bw = RATE_INFO_BW_HE_RU; @@ -4925,10 +4991,10 @@ static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo) rinfo->he_gi = NL80211_RATE_INFO_HE_GI_0_8; else if (gi_ltf == 2) rinfo->he_gi = NL80211_RATE_INFO_HE_GI_1_6; - else if (rate_n_flags & RATE_MCS_SGI_MSK) - rinfo->he_gi = NL80211_RATE_INFO_HE_GI_0_8; - else + else if (gi_ltf == 3) rinfo->he_gi = NL80211_RATE_INFO_HE_GI_3_2; + else + rinfo->he_gi = NL80211_RATE_INFO_HE_GI_0_8; break; case RATE_MCS_HE_TYPE_MU: if (gi_ltf == 0 || gi_ltf == 1) @@ -4948,46 +5014,19 @@ static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo) if (rate_n_flags & RATE_HE_DUAL_CARRIER_MODE_MSK) rinfo->he_dcm = 1; - } else { - switch (u32_get_bits(rate_n_flags, RATE_LEGACY_RATE_MSK)) { - case IWL_RATE_1M_PLCP: - rinfo->legacy = 10; - break; - case IWL_RATE_2M_PLCP: - rinfo->legacy = 20; - break; - case IWL_RATE_5M_PLCP: - rinfo->legacy = 55; - break; - case IWL_RATE_11M_PLCP: - rinfo->legacy = 110; - break; - case IWL_RATE_6M_PLCP: - rinfo->legacy = 60; - break; - case IWL_RATE_9M_PLCP: - rinfo->legacy = 90; - break; - case IWL_RATE_12M_PLCP: - rinfo->legacy = 120; - break; - case IWL_RATE_18M_PLCP: - rinfo->legacy = 180; - break; - case IWL_RATE_24M_PLCP: - rinfo->legacy = 240; - break; - case IWL_RATE_36M_PLCP: - rinfo->legacy = 360; - break; - case IWL_RATE_48M_PLCP: - rinfo->legacy = 480; - break; - case IWL_RATE_54M_PLCP: - rinfo->legacy = 540; - break; - } + return; + } + + if (rate_n_flags & RATE_MCS_SGI_MSK) + rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; + + if (format == RATE_MCS_HT_MSK) { + rinfo->flags |= RATE_INFO_FLAGS_MCS; + + } else if (format == RATE_MCS_VHT_MSK) { + rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS; } + } static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw, @@ -5332,6 +5371,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = { .sta_rc_update = iwl_mvm_sta_rc_update, .conf_tx = iwl_mvm_mac_conf_tx, .mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx, + .mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx, .mgd_protect_tdls_discover = iwl_mvm_mac_mgd_protect_tdls_discover, .flush = iwl_mvm_mac_flush, .sched_scan_start = iwl_mvm_mac_sched_scan_start, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index f877d86b038e..4277536e31c3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -297,6 +297,7 @@ struct iwl_probe_resp_data { * see enum &iwl_mvm_low_latency_cause for causes. * @low_latency_actual: boolean, indicates low latency is set, * as a result from low_latency bit flags and takes force into account. + * @authorized: indicates the AP station was set to authorized * @ps_disabled: indicates that this interface requires PS to be disabled * @queue_params: QoS params for this MAC * @bcast_sta: station used for broadcast packets. Used by the following @@ -330,6 +331,7 @@ struct iwl_mvm_vif { bool monitor_active; u8 low_latency: 6; u8 low_latency_actual: 1; + u8 authorized:1; bool ps_disabled; struct iwl_mvm_vif_bf_data bf_data; @@ -1443,12 +1445,17 @@ int __iwl_mvm_mac_start(struct iwl_mvm *mvm); int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm); /* Utils */ +int iwl_mvm_legacy_hw_idx_to_mac80211_idx(u32 rate_n_flags, + enum nl80211_band band); int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags, enum nl80211_band band); void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags, enum nl80211_band band, struct ieee80211_tx_rate *r); -u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx); +void iwl_mvm_hwrate_to_tx_rate_v1(u32 rate_n_flags, + enum nl80211_band band, + struct ieee80211_tx_rate *r); +u8 iwl_mvm_mac80211_idx_to_hwrate(const struct iwl_fw *fw, int rate_idx); u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac); static inline void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) @@ -1629,6 +1636,8 @@ int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm, void *data, int len); u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info, struct ieee80211_vif *vif); +u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, + u8 rate_idx); void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm, __le32 *tim_index, __le32 *tim_size, u8 *beacon, u32 frame_size); @@ -1732,7 +1741,7 @@ iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif) /* rate scaling */ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq); void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg); -int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate); +int rs_pretty_print_rate_v1(char *buf, int bufsz, const u32 rate); void rs_update_last_rssi(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, struct ieee80211_rx_status *rx_status); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 77ea2d0a3091..e331e18b9ab1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -29,7 +29,6 @@ #define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux" MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_AUTHOR); MODULE_LICENSE("GPL"); static const struct iwl_op_mode_ops iwl_mvm_ops; @@ -726,6 +725,183 @@ static int iwl_mvm_start_post_nvm(struct iwl_mvm *mvm) return 0; } +struct iwl_mvm_frob_txf_data { + u8 *buf; + size_t buflen; +}; + +static void iwl_mvm_frob_txf_key_iter(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key, + void *data) +{ + struct iwl_mvm_frob_txf_data *txf = data; + u8 keylen, match, matchend; + u8 *keydata; + size_t i; + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_CCMP: + keydata = key->key; + keylen = key->keylen; + break; + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + case WLAN_CIPHER_SUITE_TKIP: + /* + * WEP has short keys which might show up in the payload, + * and then you can deduce the key, so in this case just + * remove all FIFO data. + * For TKIP, we don't know the phase 2 keys here, so same. + */ + memset(txf->buf, 0xBB, txf->buflen); + return; + default: + return; + } + + /* scan for key material and clear it out */ + match = 0; + for (i = 0; i < txf->buflen; i++) { + if (txf->buf[i] != keydata[match]) { + match = 0; + continue; + } + match++; + if (match == keylen) { + memset(txf->buf + i - keylen, 0xAA, keylen); + match = 0; + } + } + + /* we're dealing with a FIFO, so check wrapped around data */ + matchend = match; + for (i = 0; match && i < keylen - match; i++) { + if (txf->buf[i] != keydata[match]) + break; + match++; + if (match == keylen) { + memset(txf->buf, 0xAA, i + 1); + memset(txf->buf + txf->buflen - matchend, 0xAA, + matchend); + break; + } + } +} + +static void iwl_mvm_frob_txf(void *ctx, void *buf, size_t buflen) +{ + struct iwl_mvm_frob_txf_data txf = { + .buf = buf, + .buflen = buflen, + }; + struct iwl_mvm *mvm = ctx; + + /* embedded key material exists only on old API */ + if (iwl_mvm_has_new_tx_api(mvm)) + return; + + rcu_read_lock(); + ieee80211_iter_keys_rcu(mvm->hw, NULL, iwl_mvm_frob_txf_key_iter, &txf); + rcu_read_unlock(); +} + +static void iwl_mvm_frob_hcmd(void *ctx, void *hcmd, size_t len) +{ + /* we only use wide headers for commands */ + struct iwl_cmd_header_wide *hdr = hcmd; + unsigned int frob_start = sizeof(*hdr), frob_end = 0; + + if (len < sizeof(hdr)) + return; + + /* all the commands we care about are in LONG_GROUP */ + if (hdr->group_id != LONG_GROUP) + return; + + switch (hdr->cmd) { + case WEP_KEY: + case WOWLAN_TKIP_PARAM: + case WOWLAN_KEK_KCK_MATERIAL: + case ADD_STA_KEY: + /* + * blank out everything here, easier than dealing + * with the various versions of the command + */ + frob_end = INT_MAX; + break; + case MGMT_MCAST_KEY: + frob_start = offsetof(struct iwl_mvm_mgmt_mcast_key_cmd, igtk); + BUILD_BUG_ON(offsetof(struct iwl_mvm_mgmt_mcast_key_cmd, igtk) != + offsetof(struct iwl_mvm_mgmt_mcast_key_cmd_v1, igtk)); + + frob_end = offsetofend(struct iwl_mvm_mgmt_mcast_key_cmd, igtk); + BUILD_BUG_ON(offsetof(struct iwl_mvm_mgmt_mcast_key_cmd, igtk) < + offsetof(struct iwl_mvm_mgmt_mcast_key_cmd_v1, igtk)); + break; + } + + if (frob_start >= frob_end) + return; + + if (frob_end > len) + frob_end = len; + + memset((u8 *)hcmd + frob_start, 0xAA, frob_end - frob_start); +} + +static void iwl_mvm_frob_mem(void *ctx, u32 mem_addr, void *mem, size_t buflen) +{ + const struct iwl_dump_exclude *excl; + struct iwl_mvm *mvm = ctx; + int i; + + switch (mvm->fwrt.cur_fw_img) { + case IWL_UCODE_INIT: + default: + /* not relevant */ + return; + case IWL_UCODE_REGULAR: + case IWL_UCODE_REGULAR_USNIFFER: + excl = mvm->fw->dump_excl; + break; + case IWL_UCODE_WOWLAN: + excl = mvm->fw->dump_excl_wowlan; + break; + } + + BUILD_BUG_ON(sizeof(mvm->fw->dump_excl) != + sizeof(mvm->fw->dump_excl_wowlan)); + + for (i = 0; i < ARRAY_SIZE(mvm->fw->dump_excl); i++) { + u32 start, end; + + if (!excl[i].addr || !excl[i].size) + continue; + + start = excl[i].addr; + end = start + excl[i].size; + + if (end <= mem_addr || start >= mem_addr + buflen) + continue; + + if (start < mem_addr) + start = mem_addr; + + if (end > mem_addr + buflen) + end = mem_addr + buflen; + + memset((u8 *)mem + start - mem_addr, 0xAA, end - start); + } +} + +static const struct iwl_dump_sanitize_ops iwl_mvm_sanitize_ops = { + .frob_txf = iwl_mvm_frob_txf, + .frob_hcmd = iwl_mvm_frob_hcmd, + .frob_mem = iwl_mvm_frob_mem, +}; + static struct iwl_op_mode * iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, const struct iwl_fw *fw, struct dentry *dbgfs_dir) @@ -775,7 +951,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, mvm->hw = hw; iwl_fw_runtime_init(&mvm->fwrt, trans, fw, &iwl_mvm_fwrt_ops, mvm, - dbgfs_dir); + &iwl_mvm_sanitize_ops, mvm, dbgfs_dir); iwl_mvm_get_acpi_tables(mvm); @@ -868,8 +1044,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, mvm->cmd_ver.range_resp = iwl_fw_lookup_notif_ver(mvm->fw, LOCATION_GROUP, TOF_RANGE_RESPONSE_NOTIF, 5); - /* we only support up to version 8 */ - if (WARN_ON_ONCE(mvm->cmd_ver.range_resp > 8)) + /* we only support up to version 9 */ + if (WARN_ON_ONCE(mvm->cmd_ver.range_resp > 9)) goto out_free; /* diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c index f2b090be3898..b2ea2fca5376 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2019 Intel Corporation + * Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation * Copyright (C) 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2015-2017 Intel Deutschland GmbH */ @@ -128,6 +128,19 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm, enum ieee80211_ac_numbers ac; bool tid_found = false; + if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) || + cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) { + cmd->rx_data_timeout_uapsd = + cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT); + cmd->tx_data_timeout_uapsd = + cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); + } else { + cmd->rx_data_timeout_uapsd = + cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT); + cmd->tx_data_timeout_uapsd = + cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT); + } + #ifdef CONFIG_IWLWIFI_DEBUGFS /* set advanced pm flag with no uapsd ACs to enable ps-poll */ if (mvmvif->dbgfs_pm.use_ps_poll) { @@ -182,19 +195,6 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm, cmd->uapsd_max_sp = mvm->hw->uapsd_max_sp_len; - if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) || - cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) { - cmd->rx_data_timeout_uapsd = - cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT); - cmd->tx_data_timeout_uapsd = - cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); - } else { - cmd->rx_data_timeout_uapsd = - cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT); - cmd->tx_data_timeout_uapsd = - cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT); - } - if (cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) { cmd->heavy_tx_thld_packets = IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c index 2d58cb969918..958702403a45 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c @@ -32,10 +32,6 @@ static u8 rs_fw_set_active_chains(u8 chains) fw_chains |= IWL_TLC_MNG_CHAIN_A_MSK; if (chains & ANT_B) fw_chains |= IWL_TLC_MNG_CHAIN_B_MSK; - if (chains & ANT_C) - WARN(false, - "tlc offload doesn't support antenna C. chains: 0x%x\n", - chains); return fw_chains; } @@ -314,7 +310,19 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm, if (flags & IWL_TLC_NOTIF_FLAG_RATE) { char pretty_rate[100]; + + if (iwl_fw_lookup_notif_ver(mvm->fw, DATA_PATH_GROUP, + TLC_MNG_UPDATE_NOTIF, 0) < 3) { + rs_pretty_print_rate_v1(pretty_rate, sizeof(pretty_rate), + le32_to_cpu(notif->rate)); + IWL_DEBUG_RATE(mvm, + "Got rate in old format. Rate: %s. Converting.\n", + pretty_rate); + lq_sta->last_rate_n_flags = + iwl_new_rate_from_v1(le32_to_cpu(notif->rate)); + } else { lq_sta->last_rate_n_flags = le32_to_cpu(notif->rate); + } rs_pretty_print_rate(pretty_rate, sizeof(pretty_rate), lq_sta->last_rate_n_flags); IWL_DEBUG_RATE(mvm, "new rate: %s\n", pretty_rate); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index b97708cb869d..f4d02f9fe16d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -4,11 +4,6 @@ * Copyright(c) 2005 - 2014, 2018 - 2021 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #include <linux/kernel.h> #include <linux/skbuff.h> @@ -335,15 +330,15 @@ static const struct rs_tx_column rs_tx_columns[] = { static inline u8 rs_extract_rate(u32 rate_n_flags) { /* also works for HT because bits 7:6 are zero there */ - return (u8)(rate_n_flags & RATE_LEGACY_RATE_MSK); + return (u8)(rate_n_flags & RATE_LEGACY_RATE_MSK_V1); } static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) { int idx = 0; - if (rate_n_flags & RATE_MCS_HT_MSK) { - idx = rate_n_flags & RATE_HT_MCS_RATE_CODE_MSK; + if (rate_n_flags & RATE_MCS_HT_MSK_V1) { + idx = rate_n_flags & RATE_HT_MCS_RATE_CODE_MSK_V1; idx += IWL_RATE_MCS_0_INDEX; /* skip 9M not supported in HT*/ @@ -351,8 +346,8 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) idx += 1; if ((idx >= IWL_FIRST_HT_RATE) && (idx <= IWL_LAST_HT_RATE)) return idx; - } else if (rate_n_flags & RATE_MCS_VHT_MSK || - rate_n_flags & RATE_MCS_HE_MSK) { + } else if (rate_n_flags & RATE_MCS_VHT_MSK_V1 || + rate_n_flags & RATE_MCS_HE_MSK_V1) { idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK; idx += IWL_RATE_MCS_0_INDEX; @@ -361,8 +356,8 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) idx++; if ((idx >= IWL_FIRST_VHT_RATE) && (idx <= IWL_LAST_VHT_RATE)) return idx; - if ((rate_n_flags & RATE_MCS_HE_MSK) && - (idx <= IWL_LAST_HE_RATE)) + if ((rate_n_flags & RATE_MCS_HE_MSK_V1) && + idx <= IWL_LAST_HE_RATE) return idx; } else { /* legacy rate format, search for match in table */ @@ -459,44 +454,8 @@ static const u16 expected_tpt_mimo2_160MHz[4][IWL_RATE_COUNT] = { {0, 0, 0, 0, 971, 0, 1925, 2861, 3779, 5574, 7304, 8147, 8976, 10592, 11640}, }; -/* mbps, mcs */ -static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { - { "1", "BPSK DSSS"}, - { "2", "QPSK DSSS"}, - {"5.5", "BPSK CCK"}, - { "11", "QPSK CCK"}, - { "6", "BPSK 1/2"}, - { "9", "BPSK 1/2"}, - { "12", "QPSK 1/2"}, - { "18", "QPSK 3/4"}, - { "24", "16QAM 1/2"}, - { "36", "16QAM 3/4"}, - { "48", "64QAM 2/3"}, - { "54", "64QAM 3/4"}, - { "60", "64QAM 5/6"}, -}; - #define MCS_INDEX_PER_STREAM (8) -static const char *rs_pretty_ant(u8 ant) -{ - static const char * const ant_name[] = { - [ANT_NONE] = "None", - [ANT_A] = "A", - [ANT_B] = "B", - [ANT_AB] = "AB", - [ANT_C] = "C", - [ANT_AC] = "AC", - [ANT_BC] = "BC", - [ANT_ABC] = "ABC", - }; - - if (ant > ANT_ABC) - return "UNKNOWN"; - - return ant_name[ant]; -} - static const char *rs_pretty_lq_type(enum iwl_table_type type) { static const char * const lq_types[] = { @@ -558,7 +517,7 @@ static char *rs_pretty_rate(const struct rs_rate *rate) rate_str = "BAD_RATE"; sprintf(buf, "(%s|%s|%s)", rs_pretty_lq_type(rate->type), - rs_pretty_ant(rate->ant), rate_str); + iwl_rs_pretty_ant(rate->ant), rate_str); return buf; } @@ -654,8 +613,7 @@ static void rs_tl_turn_on_agg(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, static inline int get_num_of_ant_from_rate(u32 rate_n_flags) { return !!(rate_n_flags & RATE_MCS_ANT_A_MSK) + - !!(rate_n_flags & RATE_MCS_ANT_B_MSK) + - !!(rate_n_flags & RATE_MCS_ANT_C_MSK); + !!(rate_n_flags & RATE_MCS_ANT_B_MSK); } /* @@ -820,12 +778,12 @@ static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm, int index = rate->index; ucode_rate |= ((rate->ant << RATE_MCS_ANT_POS) & - RATE_MCS_ANT_ABC_MSK); + RATE_MCS_ANT_AB_MSK); if (is_legacy(rate)) { ucode_rate |= iwl_rates[index].plcp; if (index >= IWL_FIRST_CCK_RATE && index <= IWL_LAST_CCK_RATE) - ucode_rate |= RATE_MCS_CCK_MSK; + ucode_rate |= RATE_MCS_CCK_MSK_V1; return ucode_rate; } @@ -840,7 +798,7 @@ static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm, IWL_ERR(mvm, "Invalid HT rate index %d\n", index); index = IWL_LAST_HT_RATE; } - ucode_rate |= RATE_MCS_HT_MSK; + ucode_rate |= RATE_MCS_HT_MSK_V1; if (is_ht_siso(rate)) ucode_rate |= iwl_rates[index].plcp_ht_siso; @@ -853,7 +811,7 @@ static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm, IWL_ERR(mvm, "Invalid VHT rate index %d\n", index); index = IWL_LAST_VHT_RATE; } - ucode_rate |= RATE_MCS_VHT_MSK; + ucode_rate |= RATE_MCS_VHT_MSK_V1; if (is_vht_siso(rate)) ucode_rate |= iwl_rates[index].plcp_vht_siso; else if (is_vht_mimo2(rate)) @@ -873,9 +831,9 @@ static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm, ucode_rate |= rate->bw; if (rate->sgi) - ucode_rate |= RATE_MCS_SGI_MSK; + ucode_rate |= RATE_MCS_SGI_MSK_V1; if (rate->ldpc) - ucode_rate |= RATE_MCS_LDPC_MSK; + ucode_rate |= RATE_MCS_LDPC_MSK_V1; return ucode_rate; } @@ -885,7 +843,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate, enum nl80211_band band, struct rs_rate *rate) { - u32 ant_msk = ucode_rate & RATE_MCS_ANT_ABC_MSK; + u32 ant_msk = ucode_rate & RATE_MCS_ANT_AB_MSK; u8 num_of_ant = get_num_of_ant_from_rate(ucode_rate); u8 nss; @@ -898,9 +856,9 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate, rate->ant = (ant_msk >> RATE_MCS_ANT_POS); /* Legacy */ - if (!(ucode_rate & RATE_MCS_HT_MSK) && - !(ucode_rate & RATE_MCS_VHT_MSK) && - !(ucode_rate & RATE_MCS_HE_MSK)) { + if (!(ucode_rate & RATE_MCS_HT_MSK_V1) && + !(ucode_rate & RATE_MCS_VHT_MSK_V1) && + !(ucode_rate & RATE_MCS_HE_MSK_V1)) { if (num_of_ant == 1) { if (band == NL80211_BAND_5GHZ) rate->type = LQ_LEGACY_A; @@ -912,20 +870,20 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate, } /* HT, VHT or HE */ - if (ucode_rate & RATE_MCS_SGI_MSK) + if (ucode_rate & RATE_MCS_SGI_MSK_V1) rate->sgi = true; - if (ucode_rate & RATE_MCS_LDPC_MSK) + if (ucode_rate & RATE_MCS_LDPC_MSK_V1) rate->ldpc = true; if (ucode_rate & RATE_MCS_STBC_MSK) rate->stbc = true; if (ucode_rate & RATE_MCS_BF_MSK) rate->bfer = true; - rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK; + rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK_V1; - if (ucode_rate & RATE_MCS_HT_MSK) { - nss = ((ucode_rate & RATE_HT_MCS_NSS_MSK) >> - RATE_HT_MCS_NSS_POS) + 1; + if (ucode_rate & RATE_MCS_HT_MSK_V1) { + nss = ((ucode_rate & RATE_HT_MCS_NSS_MSK_V1) >> + RATE_HT_MCS_NSS_POS_V1) + 1; if (nss == 1) { rate->type = LQ_HT_SISO; @@ -938,7 +896,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate, } else { WARN_ON_ONCE(1); } - } else if (ucode_rate & RATE_MCS_VHT_MSK) { + } else if (ucode_rate & RATE_MCS_VHT_MSK_V1) { nss = ((ucode_rate & RATE_VHT_MCS_NSS_MSK) >> RATE_VHT_MCS_NSS_POS) + 1; @@ -953,7 +911,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate, } else { WARN_ON_ONCE(1); } - } else if (ucode_rate & RATE_MCS_HE_MSK) { + } else if (ucode_rate & RATE_MCS_HE_MSK_V1) { nss = ((ucode_rate & RATE_VHT_MCS_NSS_MSK) >> RATE_VHT_MCS_NSS_POS) + 1; @@ -981,9 +939,6 @@ static int rs_toggle_antenna(u32 valid_ant, struct rs_rate *rate) { u8 new_ant_type; - if (!rate->ant || WARN_ON_ONCE(rate->ant & ANT_C)) - return 0; - if (!rs_is_valid_ant(valid_ant, rate->ant)) return 0; @@ -2552,7 +2507,7 @@ static void rs_get_initial_rate(struct iwl_mvm *mvm, } IWL_DEBUG_RATE(mvm, "Best ANT: %s Best RSSI: %d\n", - rs_pretty_ant(best_ant), best_rssi); + iwl_rs_pretty_ant(best_ant), best_rssi); if (best_ant != ANT_A && best_ant != ANT_B) rate->ant = first_antenna(valid_tx_ant); @@ -2652,7 +2607,6 @@ void rs_update_last_rssi(struct iwl_mvm *mvm, lq_sta->pers.chains = rx_status->chains; lq_sta->pers.chain_signal[0] = rx_status->chain_signal[0]; lq_sta->pers.chain_signal[1] = rx_status->chain_signal[1]; - lq_sta->pers.chain_signal[2] = rx_status->chain_signal[2]; lq_sta->pers.last_rssi = S8_MIN; for (i = 0; i < ARRAY_SIZE(lq_sta->pers.chain_signal); i++) { @@ -2738,8 +2692,8 @@ static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta, return; lq_sta = mvm_sta; - iwl_mvm_hwrate_to_tx_rate(lq_sta->last_rate_n_flags, - info->band, &info->control.rates[0]); + iwl_mvm_hwrate_to_tx_rate_v1(lq_sta->last_rate_n_flags, + info->band, &info->control.rates[0]); info->control.rates[0].count = 1; /* Report the optimal rate based on rssi and STA caps if we haven't @@ -2749,8 +2703,8 @@ static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta, optimal_rate = rs_get_optimal_rate(mvm, lq_sta); last_ucode_rate = ucode_rate_from_rs_rate(mvm, optimal_rate); - iwl_mvm_hwrate_to_tx_rate(last_ucode_rate, info->band, - &txrc->reported_rate); + iwl_mvm_hwrate_to_tx_rate_v1(last_ucode_rate, info->band, + &txrc->reported_rate); } } @@ -2909,7 +2863,7 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg) mvm->drv_rx_stats.success_frames++; - switch (rate & RATE_MCS_CHAN_WIDTH_MSK) { + switch (rate & RATE_MCS_CHAN_WIDTH_MSK_V1) { case RATE_MCS_CHAN_WIDTH_20: mvm->drv_rx_stats.bw_20_frames++; break; @@ -2926,10 +2880,10 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg) WARN_ONCE(1, "bad BW. rate 0x%x", rate); } - if (rate & RATE_MCS_HT_MSK) { + if (rate & RATE_MCS_HT_MSK_V1) { mvm->drv_rx_stats.ht_frames++; - nss = ((rate & RATE_HT_MCS_NSS_MSK) >> RATE_HT_MCS_NSS_POS) + 1; - } else if (rate & RATE_MCS_VHT_MSK) { + nss = ((rate & RATE_HT_MCS_NSS_MSK_V1) >> RATE_HT_MCS_NSS_POS_V1) + 1; + } else if (rate & RATE_MCS_VHT_MSK_V1) { mvm->drv_rx_stats.vht_frames++; nss = ((rate & RATE_VHT_MCS_NSS_MSK) >> RATE_VHT_MCS_NSS_POS) + 1; @@ -2942,7 +2896,7 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg) else if (nss == 2) mvm->drv_rx_stats.mimo2_frames++; - if (rate & RATE_MCS_SGI_MSK) + if (rate & RATE_MCS_SGI_MSK_V1) mvm->drv_rx_stats.sgi_frames++; else mvm->drv_rx_stats.ngi_frames++; @@ -3323,7 +3277,7 @@ static void rs_build_rates_table_from_fixed(struct iwl_mvm *mvm, int i; int num_rates = ARRAY_SIZE(lq_cmd->rs_table); __le32 ucode_rate_le32 = cpu_to_le32(ucode_rate); - u8 ant = (ucode_rate & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS; + u8 ant = (ucode_rate & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS; for (i = 0; i < num_rates; i++) lq_cmd->rs_table[i] = ucode_rate_le32; @@ -3688,35 +3642,37 @@ static void rs_free_sta(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta) IWL_DEBUG_RATE(mvm, "leave\n"); } -int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate) +int rs_pretty_print_rate_v1(char *buf, int bufsz, const u32 rate) { - char *type, *bw; + char *type; u8 mcs = 0, nss = 0; - u8 ant = (rate & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS; + u8 ant = (rate & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS; + u32 bw = (rate & RATE_MCS_CHAN_WIDTH_MSK_V1) >> + RATE_MCS_CHAN_WIDTH_POS; - if (!(rate & RATE_MCS_HT_MSK) && - !(rate & RATE_MCS_VHT_MSK) && - !(rate & RATE_MCS_HE_MSK)) { + if (!(rate & RATE_MCS_HT_MSK_V1) && + !(rate & RATE_MCS_VHT_MSK_V1) && + !(rate & RATE_MCS_HE_MSK_V1)) { int index = iwl_hwrate_to_plcp_idx(rate); return scnprintf(buf, bufsz, "Legacy | ANT: %s Rate: %s Mbps", - rs_pretty_ant(ant), + iwl_rs_pretty_ant(ant), index == IWL_RATE_INVALID ? "BAD" : - iwl_rate_mcs[index].mbps); + iwl_rate_mcs(index)->mbps); } - if (rate & RATE_MCS_VHT_MSK) { + if (rate & RATE_MCS_VHT_MSK_V1) { type = "VHT"; mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK; nss = ((rate & RATE_VHT_MCS_NSS_MSK) >> RATE_VHT_MCS_NSS_POS) + 1; - } else if (rate & RATE_MCS_HT_MSK) { + } else if (rate & RATE_MCS_HT_MSK_V1) { type = "HT"; - mcs = rate & RATE_HT_MCS_INDEX_MSK; - nss = ((rate & RATE_HT_MCS_NSS_MSK) - >> RATE_HT_MCS_NSS_POS) + 1; - } else if (rate & RATE_MCS_HE_MSK) { + mcs = rate & RATE_HT_MCS_INDEX_MSK_V1; + nss = ((rate & RATE_HT_MCS_NSS_MSK_V1) + >> RATE_HT_MCS_NSS_POS_V1) + 1; + } else if (rate & RATE_MCS_HE_MSK_V1) { type = "HE"; mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK; nss = ((rate & RATE_VHT_MCS_NSS_MSK) @@ -3725,29 +3681,12 @@ int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate) type = "Unknown"; /* shouldn't happen */ } - switch (rate & RATE_MCS_CHAN_WIDTH_MSK) { - case RATE_MCS_CHAN_WIDTH_20: - bw = "20Mhz"; - break; - case RATE_MCS_CHAN_WIDTH_40: - bw = "40Mhz"; - break; - case RATE_MCS_CHAN_WIDTH_80: - bw = "80Mhz"; - break; - case RATE_MCS_CHAN_WIDTH_160: - bw = "160Mhz"; - break; - default: - bw = "BAD BW"; - } - return scnprintf(buf, bufsz, "0x%x: %s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s", - rate, type, rs_pretty_ant(ant), bw, mcs, nss, - (rate & RATE_MCS_SGI_MSK) ? "SGI " : "NGI ", + rate, type, iwl_rs_pretty_ant(ant), iwl_rs_pretty_bw(bw), mcs, nss, + (rate & RATE_MCS_SGI_MSK_V1) ? "SGI " : "NGI ", (rate & RATE_MCS_STBC_MSK) ? "STBC " : "", - (rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "", + (rate & RATE_MCS_LDPC_MSK_V1) ? "LDPC " : "", (rate & RATE_HE_DUAL_CARRIER_MODE_MSK) ? "DCM " : "", (rate & RATE_MCS_BF_MSK) ? "BF " : ""); } @@ -3830,10 +3769,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, lq_sta->active_legacy_rate); desc += scnprintf(buff + desc, bufsz - desc, "fixed rate 0x%X\n", lq_sta->pers.dbg_fixed_rate); - desc += scnprintf(buff + desc, bufsz - desc, "valid_tx_ant %s%s%s\n", + desc += scnprintf(buff + desc, bufsz - desc, "valid_tx_ant %s%s\n", (iwl_mvm_get_valid_tx_ant(mvm) & ANT_A) ? "ANT_A," : "", - (iwl_mvm_get_valid_tx_ant(mvm) & ANT_B) ? "ANT_B," : "", - (iwl_mvm_get_valid_tx_ant(mvm) & ANT_C) ? "ANT_C" : ""); + (iwl_mvm_get_valid_tx_ant(mvm) & ANT_B) ? "ANT_B," : ""); desc += scnprintf(buff + desc, bufsz - desc, "lq type %s\n", (is_legacy(rate)) ? "legacy" : is_vht(rate) ? "VHT" : "HT"); @@ -3891,7 +3829,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, desc += scnprintf(buff + desc, bufsz - desc, " rate[%d] 0x%X ", i, r); - desc += rs_pretty_print_rate(buff + desc, bufsz - desc, r); + desc += rs_pretty_print_rate_v1(buff + desc, bufsz - desc, r); if (desc < bufsz - 1) buff[desc++] = '\n'; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h index 32104c9f8f5e..b7bc8c1b2dda 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h @@ -5,11 +5,6 @@ * Copyright(c) 2015 Intel Mobile Communications GmbH * Copyright(c) 2017 Intel Deutschland GmbH * Copyright(c) 2018 - 2019 Intel Corporation - * - * Contact Information: - * Intel Linux Wireless <[email protected]> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * *****************************************************************************/ #ifndef __rs_h__ @@ -36,11 +31,6 @@ struct iwl_rs_rate_info { #define IWL_RATE_60M_PLCP 3 -enum { - IWL_RATE_INVM_INDEX = IWL_RATE_COUNT, - IWL_RATE_INVALID = IWL_RATE_COUNT, -}; - #define LINK_QUAL_MAX_RETRY_NUM 16 enum { @@ -211,13 +201,6 @@ struct rs_rate { #define is_ht80(rate) ((rate)->bw == RATE_MCS_CHAN_WIDTH_80) #define is_ht160(rate) ((rate)->bw == RATE_MCS_CHAN_WIDTH_160) -#define IWL_MAX_MCS_DISPLAY_SIZE 12 - -struct iwl_rate_mcs_info { - char mbps[IWL_MAX_MCS_DISPLAY_SIZE]; - char mcs[IWL_MAX_MCS_DISPLAY_SIZE]; -}; - /** * struct iwl_lq_sta_rs_fw - rate and related statistics for RS in FW * @last_rate_n_flags: last rate reported by FW diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c index 8ef5399ad9be..d22f40a5354d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2020 Intel Corporation + * Copyright (C) 2012-2014, 2018-2021 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -103,7 +103,7 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm, struct iwl_rx_phy_info *phy_info, struct ieee80211_rx_status *rx_status) { - int energy_a, energy_b, energy_c, max_energy; + int energy_a, energy_b, max_energy; u32 val; val = @@ -114,14 +114,10 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm, energy_b = (val & IWL_RX_INFO_ENERGY_ANT_B_MSK) >> IWL_RX_INFO_ENERGY_ANT_B_POS; energy_b = energy_b ? -energy_b : S8_MIN; - energy_c = (val & IWL_RX_INFO_ENERGY_ANT_C_MSK) >> - IWL_RX_INFO_ENERGY_ANT_C_POS; - energy_c = energy_c ? -energy_c : S8_MIN; max_energy = max(energy_a, energy_b); - max_energy = max(max_energy, energy_c); - IWL_DEBUG_STATS(mvm, "energy In A %d B %d C %d , and max %d\n", - energy_a, energy_b, energy_c, max_energy); + IWL_DEBUG_STATS(mvm, "energy In A %d B %d , and max %d\n", + energy_a, energy_b, max_energy); rx_status->signal = max_energy; rx_status->chains = (le16_to_cpu(phy_info->phy_flags) & @@ -129,7 +125,6 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm, >> RX_RES_PHY_FLAGS_ANTENNA_POS; rx_status->chain_signal[0] = energy_a; rx_status->chain_signal[1] = energy_b; - rx_status->chain_signal[2] = energy_c; } /* @@ -235,7 +230,7 @@ static void iwl_mvm_rx_handle_tcm(struct iwl_mvm *mvm, mdata->rx.airtime += le16_to_cpu(phy_info->frame_time); } - if (!(rate_n_flags & (RATE_MCS_HT_MSK | RATE_MCS_VHT_MSK))) + if (!(rate_n_flags & (RATE_MCS_HT_MSK_V1 | RATE_MCS_VHT_MSK_V1))) return; mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif); @@ -249,10 +244,10 @@ static void iwl_mvm_rx_handle_tcm(struct iwl_mvm *mvm, mvmsta->sta_id != mvmvif->ap_sta_id) return; - if (rate_n_flags & RATE_MCS_HT_MSK) { - thr = thresh_tpt[rate_n_flags & RATE_HT_MCS_RATE_CODE_MSK]; - thr *= 1 + ((rate_n_flags & RATE_HT_MCS_NSS_MSK) >> - RATE_HT_MCS_NSS_POS); + if (rate_n_flags & RATE_MCS_HT_MSK_V1) { + thr = thresh_tpt[rate_n_flags & RATE_HT_MCS_RATE_CODE_MSK_V1]; + thr *= 1 + ((rate_n_flags & RATE_HT_MCS_NSS_MSK_V1) >> + RATE_HT_MCS_NSS_POS_V1); } else { if (WARN_ON((rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK) >= ARRAY_SIZE(thresh_tpt))) @@ -262,7 +257,7 @@ static void iwl_mvm_rx_handle_tcm(struct iwl_mvm *mvm, RATE_VHT_MCS_NSS_POS); } - thr <<= ((rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) >> + thr <<= ((rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK_V1) >> RATE_MCS_CHAN_WIDTH_POS); mdata->uapsd_nonagg_detect.rx_bytes += len; @@ -455,7 +450,7 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi, } /* Set up the HT phy flags */ - switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) { + switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK_V1) { case RATE_MCS_CHAN_WIDTH_20: break; case RATE_MCS_CHAN_WIDTH_40: @@ -468,20 +463,20 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi, rx_status->bw = RATE_INFO_BW_160; break; } - if (!(rate_n_flags & RATE_MCS_CCK_MSK) && - rate_n_flags & RATE_MCS_SGI_MSK) + if (!(rate_n_flags & RATE_MCS_CCK_MSK_V1) && + rate_n_flags & RATE_MCS_SGI_MSK_V1) rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI; if (rate_n_flags & RATE_HT_MCS_GF_MSK) rx_status->enc_flags |= RX_ENC_FLAG_HT_GF; - if (rate_n_flags & RATE_MCS_LDPC_MSK) + if (rate_n_flags & RATE_MCS_LDPC_MSK_V1) rx_status->enc_flags |= RX_ENC_FLAG_LDPC; - if (rate_n_flags & RATE_MCS_HT_MSK) { + if (rate_n_flags & RATE_MCS_HT_MSK_V1) { u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >> RATE_MCS_STBC_POS; rx_status->encoding = RX_ENC_HT; - rx_status->rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK; + rx_status->rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK_V1; rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT; - } else if (rate_n_flags & RATE_MCS_VHT_MSK) { + } else if (rate_n_flags & RATE_MCS_VHT_MSK_V1) { u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >> RATE_MCS_STBC_POS; rx_status->nss = diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index c12f303cf652..e0601f802628 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -240,8 +240,7 @@ static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm, static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm, struct napi_struct *napi, struct sk_buff *skb, int queue, - struct ieee80211_sta *sta, - bool csi) + struct ieee80211_sta *sta) { if (iwl_mvm_check_pn(mvm, skb, queue, sta)) kfree_skb(skb); @@ -269,7 +268,6 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm, (rate_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS; rx_status->chain_signal[0] = energy_a; rx_status->chain_signal[1] = energy_b; - rx_status->chain_signal[2] = S8_MIN; } static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta, @@ -620,7 +618,7 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm, while ((skb = __skb_dequeue(skb_list))) { iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, reorder_buf->queue, - sta, false); + sta); reorder_buf->num_stored--; } } @@ -1198,7 +1196,7 @@ static void iwl_mvm_decode_he_mu_ext(struct iwl_mvm *mvm, } if (FIELD_GET(IWL_RX_PHY_DATA4_HE_MU_EXT_CH2_CRC_OK, phy_data4) && - (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) != RATE_MCS_CHAN_WIDTH_20) { + (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK_V1) != RATE_MCS_CHAN_WIDTH_20) { he_mu->flags1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_RU_KNOWN | IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_CTR_26T_RU_KNOWN); @@ -1235,7 +1233,7 @@ iwl_mvm_decode_he_phy_ru_alloc(struct iwl_mvm_rx_phy_data *phy_data, * the TSF/timers are not be transmitted in HE-MU. */ u8 ru = le32_get_bits(phy_data->d1, IWL_RX_PHY_DATA1_HE_RU_ALLOC_MASK); - u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK; + u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK_V1; u8 offs = 0; rx_status->bw = RATE_INFO_BW_HE_RU; @@ -1290,13 +1288,13 @@ iwl_mvm_decode_he_phy_ru_alloc(struct iwl_mvm_rx_phy_data *phy_data, if (he_mu) he_mu->flags2 |= - le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK, + le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK_V1, rate_n_flags), IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW); - else if (he_type == RATE_MCS_HE_TYPE_TRIG) + else if (he_type == RATE_MCS_HE_TYPE_TRIG_V1) he->data6 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_KNOWN) | - le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK, + le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK_V1, rate_n_flags), IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW); } @@ -1508,9 +1506,9 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb, stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >> RATE_MCS_STBC_POS; rx_status->nss = - ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >> - RATE_VHT_MCS_NSS_POS) + 1; - rx_status->rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK; + ((rate_n_flags & RATE_MCS_NSS_MSK) >> + RATE_MCS_NSS_POS) + 1; + rx_status->rate_idx = rate_n_flags & RATE_MCS_CODE_MSK; rx_status->encoding = RX_ENC_HE; rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT; if (rate_n_flags & RATE_MCS_BF_MSK) @@ -1562,14 +1560,15 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb, } break; case 3: - if ((he_type == RATE_MCS_HE_TYPE_SU || - he_type == RATE_MCS_HE_TYPE_EXT_SU) && - rate_n_flags & RATE_MCS_SGI_MSK) - rx_status->he_gi = NL80211_RATE_INFO_HE_GI_0_8; - else - rx_status->he_gi = NL80211_RATE_INFO_HE_GI_3_2; + rx_status->he_gi = NL80211_RATE_INFO_HE_GI_3_2; ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X; break; + case 4: + rx_status->he_gi = NL80211_RATE_INFO_HE_GI_0_8; + ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X; + break; + default: + ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN; } he->data5 |= le16_encode_bits(ltf, @@ -1653,7 +1652,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, struct iwl_mvm_rx_phy_data phy_data = { .info_type = IWL_RX_PHY_INFO_TYPE_NONE, }; - bool csi = false; + u32 format; + bool is_sgi; if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))) return; @@ -1691,6 +1691,13 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, phy_data.d2 = desc->v1.phy_data2; phy_data.d3 = desc->v1.phy_data3; } + if (iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP, + REPLY_RX_MPDU_CMD, 0) < 4) { + rate_n_flags = iwl_new_rate_from_v1(rate_n_flags); + IWL_DEBUG_DROP(mvm, "Got old format rate, converting. New rate: 0x%x\n", + rate_n_flags); + } + format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK; len = le16_to_cpu(desc->mpdu_len); @@ -1744,7 +1751,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, break; } - if (rate_n_flags & RATE_MCS_HE_MSK) + if (format == RATE_MCS_HE_MSK) iwl_mvm_rx_he(mvm, skb, &phy_data, rate_n_flags, phy_info, queue); @@ -1761,7 +1768,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; } /* set the preamble flag if appropriate */ - if (rate_n_flags & RATE_MCS_CCK_MSK && + if (format == RATE_MCS_CCK_MSK && phy_info & IWL_RX_MPDU_PHY_SHORT_PREAMBLE) rx_status->enc_flags |= RX_ENC_FLAG_SHORTPRE; @@ -1937,33 +1944,34 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, } } - if (!(rate_n_flags & RATE_MCS_CCK_MSK) && - rate_n_flags & RATE_MCS_SGI_MSK) + is_sgi = format == RATE_MCS_HE_MSK ? + iwl_he_is_sgi(rate_n_flags) : + rate_n_flags & RATE_MCS_SGI_MSK; + + if (!(format == RATE_MCS_CCK_MSK) && is_sgi) rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI; - if (rate_n_flags & RATE_HT_MCS_GF_MSK) - rx_status->enc_flags |= RX_ENC_FLAG_HT_GF; if (rate_n_flags & RATE_MCS_LDPC_MSK) rx_status->enc_flags |= RX_ENC_FLAG_LDPC; - if (rate_n_flags & RATE_MCS_HT_MSK) { + if (format == RATE_MCS_HT_MSK) { u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >> - RATE_MCS_STBC_POS; + RATE_MCS_STBC_POS; rx_status->encoding = RX_ENC_HT; - rx_status->rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK; + rx_status->rate_idx = RATE_HT_MCS_INDEX(rate_n_flags); rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT; - } else if (rate_n_flags & RATE_MCS_VHT_MSK) { + } else if (format == RATE_MCS_VHT_MSK) { u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >> - RATE_MCS_STBC_POS; - rx_status->nss = - ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >> - RATE_VHT_MCS_NSS_POS) + 1; - rx_status->rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK; + RATE_MCS_STBC_POS; + rx_status->nss = + ((rate_n_flags & RATE_MCS_NSS_MSK) >> + RATE_MCS_NSS_POS) + 1; + rx_status->rate_idx = rate_n_flags & RATE_MCS_CODE_MSK; rx_status->encoding = RX_ENC_VHT; rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT; if (rate_n_flags & RATE_MCS_BF_MSK) rx_status->enc_flags |= RX_ENC_FLAG_BF; - } else if (!(rate_n_flags & RATE_MCS_HE_MSK)) { - int rate = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags, - rx_status->band); + } else if (!(format == RATE_MCS_HE_MSK)) { + int rate = iwl_mvm_legacy_hw_idx_to_mac80211_idx(rate_n_flags, + rx_status->band); if (WARN(rate < 0 || rate > 0xFF, "Invalid rate flags 0x%x, band %d,\n", @@ -1994,7 +2002,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, if (!iwl_mvm_reorder(mvm, napi, queue, sta, skb, desc)) iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, - sta, csi); + sta); out: rcu_read_unlock(); } @@ -2013,12 +2021,24 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi, struct ieee80211_sta *sta = NULL; struct sk_buff *skb; u8 channel, energy_a, energy_b; + u32 format; struct iwl_mvm_rx_phy_data phy_data = { .info_type = le32_get_bits(desc->phy_info[1], IWL_RX_PHY_DATA1_INFO_TYPE_MASK), .d0 = desc->phy_info[0], .d1 = desc->phy_info[1], }; + bool is_sgi; + + if (iwl_fw_lookup_notif_ver(mvm->fw, DATA_PATH_GROUP, + RX_NO_DATA_NOTIF, 0) < 2) { + IWL_DEBUG_DROP(mvm, "Got an old rate format. Old rate: 0x%x\n", + rate_n_flags); + rate_n_flags = iwl_new_rate_from_v1(rate_n_flags); + IWL_DEBUG_DROP(mvm, " Rate after conversion to the new format: 0x%x\n", + rate_n_flags); + } + format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK; if (unlikely(iwl_rx_packet_payload_len(pkt) < sizeof(*desc))) return; @@ -2075,7 +2095,7 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi, break; } - if (rate_n_flags & RATE_MCS_HE_MSK) + if (format == RATE_MCS_HE_MSK) iwl_mvm_rx_he(mvm, skb, &phy_data, rate_n_flags, phy_info, queue); @@ -2091,23 +2111,24 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi, rcu_read_lock(); - if (!(rate_n_flags & RATE_MCS_CCK_MSK) && - rate_n_flags & RATE_MCS_SGI_MSK) + is_sgi = format == RATE_MCS_HE_MSK ? + iwl_he_is_sgi(rate_n_flags) : + rate_n_flags & RATE_MCS_SGI_MSK; + + if (!(format == RATE_MCS_CCK_MSK) && is_sgi) rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI; - if (rate_n_flags & RATE_HT_MCS_GF_MSK) - rx_status->enc_flags |= RX_ENC_FLAG_HT_GF; if (rate_n_flags & RATE_MCS_LDPC_MSK) rx_status->enc_flags |= RX_ENC_FLAG_LDPC; - if (rate_n_flags & RATE_MCS_HT_MSK) { + if (format == RATE_MCS_HT_MSK) { u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >> RATE_MCS_STBC_POS; rx_status->encoding = RX_ENC_HT; - rx_status->rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK; + rx_status->rate_idx = RATE_HT_MCS_INDEX(rate_n_flags); rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT; - } else if (rate_n_flags & RATE_MCS_VHT_MSK) { + } else if (format == RATE_MCS_VHT_MSK) { u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >> RATE_MCS_STBC_POS; - rx_status->rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK; + rx_status->rate_idx = rate_n_flags & RATE_MCS_CODE_MSK; rx_status->encoding = RX_ENC_VHT; rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT; if (rate_n_flags & RATE_MCS_BF_MSK) @@ -2120,12 +2141,12 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi, rx_status->nss = le32_get_bits(desc->rx_vec[0], RX_NO_DATA_RX_VEC0_VHT_NSTS_MSK) + 1; - } else if (rate_n_flags & RATE_MCS_HE_MSK) { + } else if (format == RATE_MCS_HE_MSK) { rx_status->nss = le32_get_bits(desc->rx_vec[0], RX_NO_DATA_RX_VEC0_HE_NSTS_MSK) + 1; } else { - int rate = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags, + int rate = iwl_mvm_legacy_hw_idx_to_mac80211_idx(rate_n_flags, rx_status->band); if (WARN(rate < 0 || rate > 0xFF, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index d78e436fa8b5..ce8bdbc70b7e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -163,7 +163,7 @@ iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum nl80211_band band, tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS; if (band == NL80211_BAND_2GHZ && !no_cck) - return cpu_to_le32(IWL_RATE_1M_PLCP | RATE_MCS_CCK_MSK | + return cpu_to_le32(IWL_RATE_1M_PLCP | RATE_MCS_CCK_MSK_V1 | tx_ant); else return cpu_to_le32(IWL_RATE_6M_PLCP | tx_ant); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 0a13c2bda2ee..bdd4ee432548 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -268,6 +268,7 @@ static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm, int rate_idx = -1; u8 rate_plcp; u32 rate_flags = 0; + bool is_cck; struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); /* info->control is only relevant for non HW rate control */ @@ -299,11 +300,18 @@ static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm, BUILD_BUG_ON(IWL_FIRST_CCK_RATE != 0); /* Get PLCP rate for tx_cmd->rate_n_flags */ - rate_plcp = iwl_mvm_mac80211_idx_to_hwrate(rate_idx); + rate_plcp = iwl_mvm_mac80211_idx_to_hwrate(mvm->fw, rate_idx); + is_cck = (rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE); - /* Set CCK flag as needed */ - if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) - rate_flags |= RATE_MCS_CCK_MSK; + /* Set CCK or OFDM flag */ + if (iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP, TX_CMD, 0) > 8) { + if (!is_cck) + rate_flags |= RATE_MCS_LEGACY_OFDM_MSK; + else + rate_flags |= RATE_MCS_CCK_MSK; + } else if (is_cck) { + rate_flags |= RATE_MCS_CCK_MSK_V1; + } return (u32)rate_plcp | rate_flags; } @@ -1284,31 +1292,72 @@ const char *iwl_mvm_get_tx_fail_reason(u32 status) } #endif /* CONFIG_IWLWIFI_DEBUG */ -void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags, - enum nl80211_band band, - struct ieee80211_tx_rate *r) +static int iwl_mvm_get_hwrate_chan_width(u32 chan_width) { - if (rate_n_flags & RATE_HT_MCS_GF_MSK) - r->flags |= IEEE80211_TX_RC_GREEN_FIELD; - switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) { + switch (chan_width) { case RATE_MCS_CHAN_WIDTH_20: - break; + return 0; case RATE_MCS_CHAN_WIDTH_40: - r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; - break; + return IEEE80211_TX_RC_40_MHZ_WIDTH; case RATE_MCS_CHAN_WIDTH_80: - r->flags |= IEEE80211_TX_RC_80_MHZ_WIDTH; - break; + return IEEE80211_TX_RC_80_MHZ_WIDTH; case RATE_MCS_CHAN_WIDTH_160: - r->flags |= IEEE80211_TX_RC_160_MHZ_WIDTH; - break; + return IEEE80211_TX_RC_160_MHZ_WIDTH; + default: + return 0; } +} + +void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags, + enum nl80211_band band, + struct ieee80211_tx_rate *r) +{ + u32 format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK; + u32 rate = format == RATE_MCS_HT_MSK ? + RATE_HT_MCS_INDEX(rate_n_flags) : + rate_n_flags & RATE_MCS_CODE_MSK; + + r->flags |= + iwl_mvm_get_hwrate_chan_width(rate_n_flags & + RATE_MCS_CHAN_WIDTH_MSK); + if (rate_n_flags & RATE_MCS_SGI_MSK) r->flags |= IEEE80211_TX_RC_SHORT_GI; - if (rate_n_flags & RATE_MCS_HT_MSK) { + if (format == RATE_MCS_HT_MSK) { r->flags |= IEEE80211_TX_RC_MCS; - r->idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK; - } else if (rate_n_flags & RATE_MCS_VHT_MSK) { + r->idx = rate; + } else if (format == RATE_MCS_VHT_MSK) { + ieee80211_rate_set_vht(r, rate, + ((rate_n_flags & RATE_MCS_NSS_MSK) >> + RATE_MCS_NSS_POS) + 1); + r->flags |= IEEE80211_TX_RC_VHT_MCS; + } else if (format == RATE_MCS_HE_MSK) { + /* mac80211 cannot do this without ieee80211_tx_status_ext() + * but it only matters for radiotap */ + r->idx = 0; + } else { + r->idx = iwl_mvm_legacy_hw_idx_to_mac80211_idx(rate_n_flags, + band); + } +} + +void iwl_mvm_hwrate_to_tx_rate_v1(u32 rate_n_flags, + enum nl80211_band band, + struct ieee80211_tx_rate *r) +{ + if (rate_n_flags & RATE_HT_MCS_GF_MSK) + r->flags |= IEEE80211_TX_RC_GREEN_FIELD; + + r->flags |= + iwl_mvm_get_hwrate_chan_width(rate_n_flags & + RATE_MCS_CHAN_WIDTH_MSK_V1); + + if (rate_n_flags & RATE_MCS_SGI_MSK_V1) + r->flags |= IEEE80211_TX_RC_SHORT_GI; + if (rate_n_flags & RATE_MCS_HT_MSK_V1) { + r->flags |= IEEE80211_TX_RC_MCS; + r->idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK_V1; + } else if (rate_n_flags & RATE_MCS_VHT_MSK_V1) { ieee80211_rate_set_vht( r, rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK, ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >> @@ -1323,14 +1372,20 @@ void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags, /* * translate ucode response to mac80211 tx status control values */ -static void iwl_mvm_hwrate_to_tx_status(u32 rate_n_flags, +static void iwl_mvm_hwrate_to_tx_status(const struct iwl_fw *fw, + u32 rate_n_flags, struct ieee80211_tx_info *info) { struct ieee80211_tx_rate *r = &info->status.rates[0]; + if (iwl_fw_lookup_notif_ver(fw, LONG_GROUP, + TX_CMD, 0) > 6) + rate_n_flags = iwl_new_rate_from_v1(rate_n_flags); + info->status.antenna = - ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); - iwl_mvm_hwrate_to_tx_rate(rate_n_flags, info->band, r); + ((rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS); + iwl_mvm_hwrate_to_tx_rate(rate_n_flags, + info->band, r); } static void iwl_mvm_tx_status_check_trigger(struct iwl_mvm *mvm, @@ -1450,7 +1505,9 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, /* the FW should have stopped the queue and not * return this status */ - WARN_ON(1); + IWL_ERR_LIMIT(mvm, + "FW reported TX filtered, status=0x%x, FC=0x%x\n", + status, le16_to_cpu(hdr->frame_control)); info->flags |= IEEE80211_TX_STAT_TX_FILTERED; break; default: @@ -1472,8 +1529,14 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, iwl_mvm_tx_status_check_trigger(mvm, status, hdr->frame_control); info->status.rates[0].count = tx_resp->failure_frame + 1; - iwl_mvm_hwrate_to_tx_status(le32_to_cpu(tx_resp->initial_rate), + + iwl_mvm_hwrate_to_tx_status(mvm->fw, + le32_to_cpu(tx_resp->initial_rate), info); + + /* Don't assign the converted initial_rate, because driver + * TLC uses this and doesn't support the new FW rate + */ info->status.status_driver_data[1] = (void *)(uintptr_t)le32_to_cpu(tx_resp->initial_rate); @@ -1835,7 +1898,7 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid, info->flags |= IEEE80211_TX_STAT_AMPDU; memcpy(&info->status, &tx_info->status, sizeof(tx_info->status)); - iwl_mvm_hwrate_to_tx_status(rate, info); + iwl_mvm_hwrate_to_tx_status(mvm->fw, rate, info); } } @@ -1856,7 +1919,7 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid, goto out; tx_info->band = chanctx_conf->def.chan->band; - iwl_mvm_hwrate_to_tx_status(rate, tx_info); + iwl_mvm_hwrate_to_tx_status(mvm->fw, rate, tx_info); if (!iwl_mvm_has_tlc_offload(mvm)) { IWL_DEBUG_TX_REPLY(mvm, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index 4a3d2971a98b..caf1dcf48888 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -135,31 +135,25 @@ int iwl_mvm_send_cmd_pdu_status(struct iwl_mvm *mvm, u32 id, u16 len, return iwl_mvm_send_cmd_status(mvm, &cmd, status); } -#define IWL_DECLARE_RATE_INFO(r) \ - [IWL_RATE_##r##M_INDEX] = IWL_RATE_##r##M_PLCP +int iwl_mvm_legacy_hw_idx_to_mac80211_idx(u32 rate_n_flags, + enum nl80211_band band) +{ + int format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK; + int rate = rate_n_flags & RATE_LEGACY_RATE_MSK; + bool is_LB = band == NL80211_BAND_2GHZ; -/* - * Translate from fw_rate_index (IWL_RATE_XXM_INDEX) to PLCP - */ -static const u8 fw_rate_idx_to_plcp[IWL_RATE_COUNT] = { - IWL_DECLARE_RATE_INFO(1), - IWL_DECLARE_RATE_INFO(2), - IWL_DECLARE_RATE_INFO(5), - IWL_DECLARE_RATE_INFO(11), - IWL_DECLARE_RATE_INFO(6), - IWL_DECLARE_RATE_INFO(9), - IWL_DECLARE_RATE_INFO(12), - IWL_DECLARE_RATE_INFO(18), - IWL_DECLARE_RATE_INFO(24), - IWL_DECLARE_RATE_INFO(36), - IWL_DECLARE_RATE_INFO(48), - IWL_DECLARE_RATE_INFO(54), -}; + if (format == RATE_MCS_LEGACY_OFDM_MSK) + return is_LB ? rate + IWL_FIRST_OFDM_RATE : + rate; + + /* CCK is not allowed in HB */ + return is_LB ? rate : -1; +} int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags, enum nl80211_band band) { - int rate = rate_n_flags & RATE_LEGACY_RATE_MSK; + int rate = rate_n_flags & RATE_LEGACY_RATE_MSK_V1; int idx; int band_offset = 0; @@ -167,16 +161,24 @@ int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags, if (band != NL80211_BAND_2GHZ) band_offset = IWL_FIRST_OFDM_RATE; for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++) - if (fw_rate_idx_to_plcp[idx] == rate) + if (iwl_fw_rate_idx_to_plcp(idx) == rate) return idx - band_offset; return -1; } -u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx) +u8 iwl_mvm_mac80211_idx_to_hwrate(const struct iwl_fw *fw, int rate_idx) { - /* Get PLCP rate for tx_cmd->rate_n_flags */ - return fw_rate_idx_to_plcp[rate_idx]; + if (iwl_fw_lookup_cmd_ver(fw, LONG_GROUP, + TX_CMD, 0) > 8) + /* In the new rate legacy rates are indexed: + * 0 - 3 for CCK and 0 - 7 for OFDM. + */ + return (rate_idx >= IWL_FIRST_OFDM_RATE ? + rate_idx - IWL_FIRST_OFDM_RATE : + rate_idx); + + return iwl_fw_rate_idx_to_plcp(rate_idx); } u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac) @@ -217,6 +219,7 @@ u8 first_antenna(u8 mask) return BIT(ffs(mask) - 1); } +#define MAX_ANT_NUM 2 /* * Toggles between TX antennas to send the probe request on. * Receives the bitmask of valid TX antennas and the *index* used @@ -405,6 +408,9 @@ bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm, lockdep_assert_held(&mvm->mutex); + if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) + return false; + if (num_of_ant(iwl_mvm_get_valid_rx_ant(mvm)) == 1) return false; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index 239a722cd79d..85a6da70ca78 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -57,6 +57,10 @@ iwl_pcie_ctxt_info_dbg_enable(struct iwl_trans *trans, dbg_flags |= IWL_PRPH_SCRATCH_EDBG_DEST_DRAM; dbg_cfg->hwm_base_addr = cpu_to_le64(frag->physical); dbg_cfg->hwm_size = cpu_to_le32(frag->size); + dbg_cfg->debug_token_config = cpu_to_le32(trans->dbg.ucode_preset); + IWL_DEBUG_FW(trans, + "WRT: Applying DRAM destination (debug_token_config=%u)\n", + dbg_cfg->debug_token_config); IWL_DEBUG_FW(trans, "WRT: Applying DRAM destination (alloc_id=%u, num_frags=%u)\n", alloc_id, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 3b974388d834..37a1ef868e6f 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -499,6 +499,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { /* Ma devices */ {IWL_PCI_DEVICE(0x2729, PCI_ANY_ID, iwl_ma_trans_cfg)}, {IWL_PCI_DEVICE(0x7E40, PCI_ANY_ID, iwl_ma_trans_cfg)}, + {IWL_PCI_DEVICE(0x7F70, PCI_ANY_ID, iwl_ma_trans_cfg)}, /* Bz devices */ {IWL_PCI_DEVICE(0x2727, PCI_ANY_ID, iwl_bz_trans_cfg)}, @@ -532,10 +533,20 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { IWL_DEV_INFO(0x31DC, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name), IWL_DEV_INFO(0xA370, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_name), IWL_DEV_INFO(0xA370, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name), + IWL_DEV_INFO(0x54F0, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_160_name), + IWL_DEV_INFO(0x54F0, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name), IWL_DEV_INFO(0x51F0, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_160_name), IWL_DEV_INFO(0x51F0, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_160_name), + IWL_DEV_INFO(0x51F0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name), + IWL_DEV_INFO(0x51F0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), + IWL_DEV_INFO(0x54F0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name), + IWL_DEV_INFO(0x54F0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), + IWL_DEV_INFO(0x7A70, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name), + IWL_DEV_INFO(0x7A70, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), IWL_DEV_INFO(0x271C, 0x0214, iwl9260_2ac_cfg, iwl9260_1_name), + IWL_DEV_INFO(0x7E40, 0x1691, iwl_cfg_ma_a0_gf4_a0, iwl_ax411_killer_1690s_name), + IWL_DEV_INFO(0x7E40, 0x1692, iwl_cfg_ma_a0_gf4_a0, iwl_ax411_killer_1690i_name), /* AX200 */ IWL_DEV_INFO(0x2723, 0x1653, iwl_ax200_cfg_cc, iwl_ax200_killer_1650w_name), @@ -639,6 +650,12 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { IWL_DEV_INFO(0x7AF0, 0x0510, iwlax211_2ax_cfg_so_gf_a0, NULL), IWL_DEV_INFO(0x7AF0, 0x0A10, iwlax211_2ax_cfg_so_gf_a0, NULL), + /* So with JF */ + IWL_DEV_INFO(0x7A70, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_160_name), + IWL_DEV_INFO(0x7A70, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_160_name), + IWL_DEV_INFO(0x7AF0, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_160_name), + IWL_DEV_INFO(0x7AF0, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_160_name), + /* SnJ with HR */ IWL_DEV_INFO(0x2725, 0x00B0, iwlax411_2ax_cfg_sosnj_gf4_a0, NULL), IWL_DEV_INFO(0x2726, 0x0090, iwlax211_cfg_snj_gf_a0, NULL), @@ -648,6 +665,12 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { IWL_DEV_INFO(0x2726, 0x0510, iwlax211_cfg_snj_gf_a0, NULL), IWL_DEV_INFO(0x2726, 0x1651, iwl_cfg_snj_hr_b0, iwl_ax201_killer_1650s_name), IWL_DEV_INFO(0x2726, 0x1652, iwl_cfg_snj_hr_b0, iwl_ax201_killer_1650i_name), + IWL_DEV_INFO(0x2726, 0x1671, iwlax211_cfg_snj_gf_a0, iwl_ax211_killer_1675s_name), + IWL_DEV_INFO(0x2726, 0x1672, iwlax211_cfg_snj_gf_a0, iwl_ax211_killer_1675i_name), + IWL_DEV_INFO(0x2726, 0x1691, iwlax411_2ax_cfg_sosnj_gf4_a0, iwl_ax411_killer_1690s_name), + IWL_DEV_INFO(0x2726, 0x1692, iwlax411_2ax_cfg_sosnj_gf4_a0, iwl_ax411_killer_1690i_name), + IWL_DEV_INFO(0x7F70, 0x1691, iwlax411_2ax_cfg_sosnj_gf4_a0, iwl_ax411_killer_1690s_name), + IWL_DEV_INFO(0x7F70, 0x1692, iwlax411_2ax_cfg_sosnj_gf4_a0, iwl_ax411_killer_1690i_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY, @@ -1112,6 +1135,17 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwl_cfg_bz_a0_mr_a0, iwl_bz_name), + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY, + IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, + IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, + iwl_cfg_bz_a0_fm_a0, iwl_bz_name), + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_GL, IWL_CFG_ANY, + IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, + IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, + iwl_cfg_gl_a0_fm_a0, iwl_bz_name), + /* SoF with JF2 */ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, @@ -1191,6 +1225,95 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { #endif /* CONFIG_IWLMVM */ }; +/* + * In case that there is no OTP on the NIC, get the rf id and cdb info + * from the prph registers. + */ +static int get_crf_id(struct iwl_trans *iwl_trans) +{ + int ret = 0; + u32 wfpm_ctrl_addr; + u32 wfpm_otp_cfg_addr; + u32 sd_reg_ver_addr; + u32 cdb = 0; + u32 val; + + if (iwl_trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { + wfpm_ctrl_addr = WFPM_CTRL_REG_GEN2; + wfpm_otp_cfg_addr = WFPM_OTP_CFG1_ADDR_GEN2; + sd_reg_ver_addr = SD_REG_VER_GEN2; + /* Qu/Pu families have other addresses */ + } else { + wfpm_ctrl_addr = WFPM_CTRL_REG; + wfpm_otp_cfg_addr = WFPM_OTP_CFG1_ADDR; + sd_reg_ver_addr = SD_REG_VER; + } + + if (!iwl_trans_grab_nic_access(iwl_trans)) { + IWL_ERR(iwl_trans, "Failed to grab nic access before reading crf id\n"); + ret = -EIO; + goto out; + } + + /* Enable access to peripheral registers */ + val = iwl_read_umac_prph_no_grab(iwl_trans, wfpm_ctrl_addr); + val |= ENABLE_WFPM; + iwl_write_umac_prph_no_grab(iwl_trans, wfpm_ctrl_addr, val); + + /* Read crf info */ + val = iwl_read_prph_no_grab(iwl_trans, sd_reg_ver_addr); + + /* Read cdb info (also contains the jacket info if needed in the future */ + cdb = iwl_read_umac_prph_no_grab(iwl_trans, wfpm_otp_cfg_addr); + + /* Map between crf id to rf id */ + switch (REG_CRF_ID_TYPE(val)) { + case REG_CRF_ID_TYPE_JF_1: + iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_JF1 << 12); + break; + case REG_CRF_ID_TYPE_JF_2: + iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_JF2 << 12); + break; + case REG_CRF_ID_TYPE_HR_NONE_CDB: + iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_HR1 << 12); + break; + case REG_CRF_ID_TYPE_HR_CDB: + iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_HR2 << 12); + break; + case REG_CRF_ID_TYPE_GF: + iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_GF << 12); + break; + case REG_CRF_ID_TYPE_MR: + iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_MR << 12); + break; + case REG_CRF_ID_TYPE_FM: + iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_FM << 12); + break; + default: + ret = -EIO; + IWL_ERR(iwl_trans, + "Can find a correct rfid for crf id 0x%x\n", + REG_CRF_ID_TYPE(val)); + goto out_release; + + } + + /* Set CDB capabilities */ + if (cdb & BIT(4)) { + iwl_trans->hw_rf_id += BIT(28); + IWL_INFO(iwl_trans, "Adding cdb to rf id\n"); + } + + IWL_INFO(iwl_trans, "Detected RF 0x%x from crf id 0x%x\n", + iwl_trans->hw_rf_id, REG_CRF_ID_TYPE(val)); + +out_release: + iwl_trans_release_nic_access(iwl_trans); + +out: + return ret; +} + /* PCI registers */ #define PCI_CFG_RETRY_TIMEOUT 0x041 @@ -1222,8 +1345,36 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) trans_pcie = IWL_TRANS_GET_PCIE_TRANS(iwl_trans); + /* + * Let's try to grab NIC access early here. Sometimes, NICs may + * fail to initialize, and if that happens it's better if we see + * issues early on (and can reprobe, per the logic inside), than + * first trying to load the firmware etc. and potentially only + * detecting any problems when the first interface is brought up. + */ + ret = iwl_finish_nic_init(iwl_trans); + if (ret) + goto out_free_trans; + if (iwl_trans_grab_nic_access(iwl_trans)) { + /* all good */ + iwl_trans_release_nic_access(iwl_trans); + } else { + ret = -EIO; + goto out_free_trans; + } + iwl_trans->hw_rf_id = iwl_read32(iwl_trans, CSR_HW_RF_ID); + /* + * The RF_ID is set to zero in blank OTP so read version to + * extract the RF_ID. + * This is relevant only for family 9000 and up. + */ + if (iwl_trans->trans_cfg->rf_id && + iwl_trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_9000 && + !CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id) && get_crf_id(iwl_trans)) + goto out_free_trans; + for (i = 0; i < ARRAY_SIZE(iwl_dev_info_table); i++) { const struct iwl_dev_info *dev_info = &iwl_dev_info_table[i]; if ((dev_info->device == (u16)IWL_CFG_ANY || diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c index bf0c32a74ca4..645cb4dd4e5a 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c @@ -47,7 +47,7 @@ int iwl_pcie_gen2_apm_init(struct iwl_trans *trans) iwl_pcie_apm_config(trans); - ret = iwl_finish_nic_init(trans, trans->trans_cfg); + ret = iwl_finish_nic_init(trans); if (ret) return ret; @@ -131,21 +131,9 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans) if (trans_pcie->is_down) return; - if (trans->state >= IWL_TRANS_FW_STARTED) { - if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { - iwl_set_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_REQ); - iwl_poll_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS, - CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS, - 5000); - msleep(100); - iwl_set_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_SW_RESET); - } else if (trans_pcie->fw_reset_handshake) { + if (trans->state >= IWL_TRANS_FW_STARTED) + if (trans_pcie->fw_reset_handshake) iwl_trans_pcie_fw_reset_handshake(trans); - } - } trans_pcie->is_down = true; @@ -175,18 +163,6 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans) else iwl_pcie_ctxt_info_free(trans); - /* Make sure (redundant) we've released our request to stay awake */ - if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) - iwl_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ); - else - iwl_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - - if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { - iwl_set_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_SW_RESET); - } /* Stop the device, and put it in low power state */ iwl_pcie_gen2_apm_stop(trans, false); @@ -466,13 +442,15 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans, iwl_pcie_set_ltr(trans); - if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) + if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { + iwl_write32(trans, CSR_FUNC_SCRATCH, CSR_FUNC_SCRATCH_INIT_VALUE); iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_ROM_START); - else if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) + } else if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { iwl_write_umac_prph(trans, UREG_CPU_INIT_RUN, 1); - else + } else { iwl_write_prph(trans, UREG_CPU_INIT_RUN, 1); + } /* re-check RF-Kill state since we may have missed the interrupt */ hw_rfkill = iwl_pcie_check_hw_rf_kill(trans); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index f252680f18e8..262795368bfe 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -129,7 +129,12 @@ out: static void iwl_trans_pcie_sw_reset(struct iwl_trans *trans) { /* Reset entire device - do controller reset (results in SHRD_HW_RST) */ - iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); + if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) + iwl_set_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_SW_RESET); + else + iwl_set_bit(trans, CSR_RESET, + CSR_RESET_REG_FLAG_SW_RESET); usleep_range(5000, 6000); } @@ -306,7 +311,7 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans) if (trans->trans_cfg->base_params->pll_cfg) iwl_set_bit(trans, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); - ret = iwl_finish_nic_init(trans, trans->trans_cfg); + ret = iwl_finish_nic_init(trans); if (ret) return ret; @@ -378,7 +383,7 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans) iwl_trans_pcie_sw_reset(trans); - ret = iwl_finish_nic_init(trans, trans->trans_cfg); + ret = iwl_finish_nic_init(trans); if (WARN_ON(ret)) { /* Release XTAL ON request */ __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, @@ -458,6 +463,7 @@ void iwl_pcie_apm_stop_master(struct iwl_trans *trans) CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS, CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS, 100); + msleep(100); } else { iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); @@ -1208,8 +1214,12 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans) } /* Make sure (redundant) we've released our request to stay awake */ - iwl_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) + iwl_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ); + else + iwl_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* Stop the device, and put it in low power state */ iwl_pcie_apm_stop(trans, false); @@ -1501,7 +1511,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - ret = iwl_finish_nic_init(trans, trans->trans_cfg); + ret = iwl_finish_nic_init(trans); if (ret) return ret; @@ -1734,7 +1744,7 @@ static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans) { int ret; - ret = iwl_finish_nic_init(trans, trans->trans_cfg); + ret = iwl_finish_nic_init(trans); if (ret < 0) return ret; @@ -2140,9 +2150,12 @@ static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans) if (trans_pcie->cmd_hold_nic_awake) goto out; - - __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) + __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ); + else + __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* * Above we read the CSR_GP_CNTRL register, which will flush * any previous writes, but we need the write that clears the @@ -3203,9 +3216,11 @@ static int iwl_trans_get_fw_monitor_len(struct iwl_trans *trans, u32 *len) return 0; } -static struct iwl_trans_dump_data -*iwl_trans_pcie_dump_data(struct iwl_trans *trans, - u32 dump_mask) +static struct iwl_trans_dump_data * +iwl_trans_pcie_dump_data(struct iwl_trans *trans, + u32 dump_mask, + const struct iwl_dump_sanitize_ops *sanitize_ops, + void *sanitize_ctx) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_fw_error_dump_data *data; @@ -3305,6 +3320,10 @@ static struct iwl_trans_dump_data txcmd->caplen = cpu_to_le32(caplen); memcpy(txcmd->data, cmdq->entries[idx].cmd, caplen); + if (sanitize_ops && sanitize_ops->frob_hcmd) + sanitize_ops->frob_hcmd(sanitize_ctx, + txcmd->data, + caplen); txcmd = (void *)((u8 *)txcmd->data + caplen); } diff --git a/drivers/net/wireless/marvell/libertas/if_usb.c b/drivers/net/wireless/marvell/libertas/if_usb.c index 20436a289d5c..5d6dc1dd050d 100644 --- a/drivers/net/wireless/marvell/libertas/if_usb.c +++ b/drivers/net/wireless/marvell/libertas/if_usb.c @@ -292,6 +292,7 @@ err_add_card: if_usb_reset_device(cardp); dealloc: if_usb_free(cardp); + kfree(cardp); error: return r; @@ -316,6 +317,7 @@ static void if_usb_disconnect(struct usb_interface *intf) /* Unlink and free urb */ if_usb_free(cardp); + kfree(cardp); usb_set_intfdata(intf, NULL); usb_put_dev(interface_to_usbdev(intf)); diff --git a/drivers/net/wireless/marvell/libertas/mesh.c b/drivers/net/wireless/marvell/libertas/mesh.c index 6cbba84989b8..a58c1e141f2c 100644 --- a/drivers/net/wireless/marvell/libertas/mesh.c +++ b/drivers/net/wireless/marvell/libertas/mesh.c @@ -169,7 +169,7 @@ static ssize_t anycast_mask_show(struct device *dev, if (ret) return ret; - return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0])); + return sysfs_emit(buf, "0x%X\n", le32_to_cpu(mesh_access.data[0])); } /** @@ -222,7 +222,7 @@ static ssize_t prb_rsp_limit_show(struct device *dev, return ret; retry_limit = le32_to_cpu(mesh_access.data[1]); - return snprintf(buf, 10, "%d\n", retry_limit); + return sysfs_emit(buf, "%d\n", retry_limit); } /** @@ -270,7 +270,7 @@ static ssize_t lbs_mesh_show(struct device *dev, struct device_attribute *attr, char *buf) { struct lbs_private *priv = to_net_dev(dev)->ml_priv; - return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev); + return sysfs_emit(buf, "0x%X\n", !!priv->mesh_dev); } /** @@ -369,7 +369,7 @@ static ssize_t bootflag_show(struct device *dev, if (ret) return ret; - return snprintf(buf, 12, "%d\n", le32_to_cpu(defs.bootflag)); + return sysfs_emit(buf, "%d\n", le32_to_cpu(defs.bootflag)); } /** @@ -419,7 +419,7 @@ static ssize_t boottime_show(struct device *dev, if (ret) return ret; - return snprintf(buf, 12, "%d\n", defs.boottime); + return sysfs_emit(buf, "%d\n", defs.boottime); } /** @@ -479,7 +479,7 @@ static ssize_t channel_show(struct device *dev, if (ret) return ret; - return snprintf(buf, 12, "%d\n", le16_to_cpu(defs.channel)); + return sysfs_emit(buf, "%d\n", le16_to_cpu(defs.channel)); } /** @@ -605,7 +605,7 @@ static ssize_t protocol_id_show(struct device *dev, if (ret) return ret; - return snprintf(buf, 5, "%d\n", defs.meshie.val.active_protocol_id); + return sysfs_emit(buf, "%d\n", defs.meshie.val.active_protocol_id); } /** @@ -667,7 +667,7 @@ static ssize_t metric_id_show(struct device *dev, if (ret) return ret; - return snprintf(buf, 5, "%d\n", defs.meshie.val.active_metric_id); + return sysfs_emit(buf, "%d\n", defs.meshie.val.active_metric_id); } /** @@ -729,7 +729,7 @@ static ssize_t capability_show(struct device *dev, if (ret) return ret; - return snprintf(buf, 5, "%d\n", defs.meshie.val.mesh_capability); + return sysfs_emit(buf, "%d\n", defs.meshie.val.mesh_capability); } /** diff --git a/drivers/net/wireless/marvell/libertas_tf/if_usb.c b/drivers/net/wireless/marvell/libertas_tf/if_usb.c index fe0a69e804d8..75b5319d033f 100644 --- a/drivers/net/wireless/marvell/libertas_tf/if_usb.c +++ b/drivers/net/wireless/marvell/libertas_tf/if_usb.c @@ -230,6 +230,7 @@ static int if_usb_probe(struct usb_interface *intf, dealloc: if_usb_free(cardp); + kfree(cardp); error: lbtf_deb_leave(LBTF_DEB_MAIN); return -ENOMEM; @@ -254,6 +255,7 @@ static void if_usb_disconnect(struct usb_interface *intf) /* Unlink and free urb */ if_usb_free(cardp); + kfree(cardp); usb_set_intfdata(intf, NULL); usb_put_dev(interface_to_usbdev(intf)); diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 06fb6e5b1b37..d02ec5a735cb 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -1412,7 +1412,7 @@ static void rtw89_core_ba_work(struct work_struct *work) list_for_each_entry_safe(rtwtxq, tmp, &rtwdev->ba_list, list) { struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq); struct ieee80211_sta *sta = txq->sta; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL; u8 tid = txq->tid; if (!sta) { @@ -1462,7 +1462,7 @@ static void rtw89_core_txq_check_agg(struct rtw89_dev *rtwdev, struct ieee80211_hw *hw = rtwdev->hw; struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq); struct ieee80211_sta *sta = txq->sta; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL; if (unlikely(skb_get_queue_mapping(skb) == IEEE80211_AC_VO)) return; @@ -1534,7 +1534,7 @@ static bool rtw89_core_txq_agg_wait(struct rtw89_dev *rtwdev, { struct rtw89_txq *rtwtxq = (struct rtw89_txq *)txq->drv_priv; struct ieee80211_sta *sta = txq->sta; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL; if (!sta || rtwsta->max_agg_wait <= 0) return false; diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index 69384c43c046..afcd07ab1de7 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -560,7 +560,7 @@ static int hfc_pub_cfg_chk(struct rtw89_dev *rtwdev) const struct rtw89_hfc_pub_cfg *pub_cfg = ¶m->pub_cfg; if (pub_cfg->grp0 + pub_cfg->grp1 != pub_cfg->pub_max) - return 0; + return -EFAULT; return 0; } diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h index 34333c441aea..20e6767ea5c4 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.h +++ b/drivers/net/wireless/realtek/rtw89/pci.h @@ -276,11 +276,6 @@ #define B_AX_CH10_BUSY BIT(0) /* Configure */ -#define R_AX_PCIE_INIT_CFG1 0x1000 -#define B_AX_PCIE_RXRST_KEEP_REG BIT(23) -#define B_AX_PCIE_TXRST_KEEP_REG BIT(22) -#define B_AX_DIS_RXDMA_PRE BIT(2) - #define R_AX_PCIE_INIT_CFG2 0x1004 #define B_AX_WD_ITVL_IDLE GENMASK(27, 24) #define B_AX_WD_ITVL_ACT GENMASK(19, 16) diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c index b1b87f0aadbb..5c6ffca3a324 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c @@ -757,7 +757,7 @@ static void rtw8852a_ctrl_ch(struct rtw89_dev *rtwdev, u8 central_ch, else rtw89_phy_write32_idx(rtwdev, R_P1_MODE, B_P1_MODE_SEL, - 1, phy_idx); + 0, phy_idx); /* SCO compensate FC setting */ sco_comp = rtw8852a_sco_mapping(central_ch); rtw89_phy_write32_idx(rtwdev, R_FC0_BW, B_FC0_BW_INV, diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index f26fc150ecd0..354a7e1c3315 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c @@ -488,12 +488,9 @@ static int wl1271_probe(struct spi_device *spi) spi->bits_per_word = 32; glue->reg = devm_regulator_get(&spi->dev, "vwlan"); - if (PTR_ERR(glue->reg) == -EPROBE_DEFER) - return -EPROBE_DEFER; - if (IS_ERR(glue->reg)) { - dev_err(glue->dev, "can't get regulator\n"); - return PTR_ERR(glue->reg); - } + if (IS_ERR(glue->reg)) + return dev_err_probe(glue->dev, PTR_ERR(glue->reg), + "can't get regulator\n"); ret = wlcore_probe_of(spi, glue, pdev_data); if (ret) { diff --git a/drivers/phy/broadcom/phy-bcm-ns-usb3.c b/drivers/phy/broadcom/phy-bcm-ns-usb3.c index b1adaecc26f8..bbfad209c890 100644 --- a/drivers/phy/broadcom/phy-bcm-ns-usb3.c +++ b/drivers/phy/broadcom/phy-bcm-ns-usb3.c @@ -183,7 +183,7 @@ static int bcm_ns_usb3_mdio_phy_write(struct bcm_ns_usb3 *usb3, u16 reg, { struct mdio_device *mdiodev = usb3->mdiodev; - return mdiobus_write(mdiodev->bus, mdiodev->addr, reg, value); + return mdiodev_write(mdiodev, reg, value); } static int bcm_ns_usb3_mdio_probe(struct mdio_device *mdiodev) diff --git a/drivers/phy/broadcom/phy-bcm-ns2-pcie.c b/drivers/phy/broadcom/phy-bcm-ns2-pcie.c index 4c7d11d2b378..9e7434a0d3e0 100644 --- a/drivers/phy/broadcom/phy-bcm-ns2-pcie.c +++ b/drivers/phy/broadcom/phy-bcm-ns2-pcie.c @@ -29,14 +29,12 @@ static int ns2_pci_phy_init(struct phy *p) int rc; /* select the AFE 100MHz block page */ - rc = mdiobus_write(mdiodev->bus, mdiodev->addr, - BLK_ADDR_REG_OFFSET, PLL_AFE1_100MHZ_BLK); + rc = mdiodev_write(mdiodev, BLK_ADDR_REG_OFFSET, PLL_AFE1_100MHZ_BLK); if (rc) goto err; /* set the 100 MHz reference clock amplitude to 2.05 v */ - rc = mdiobus_write(mdiodev->bus, mdiodev->addr, - PLL_CLK_AMP_OFFSET, PLL_CLK_AMP_2P05V); + rc = mdiodev_write(mdiodev, PLL_CLK_AMP_OFFSET, PLL_CLK_AMP_2P05V); if (rc) goto err; diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index 20efafe47897..efbb5e5eca05 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c @@ -24,19 +24,6 @@ #define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer)) static struct kmem_cache *qdio_q_cache; -static struct kmem_cache *qdio_aob_cache; - -struct qaob *qdio_allocate_aob(void) -{ - return kmem_cache_zalloc(qdio_aob_cache, GFP_ATOMIC); -} -EXPORT_SYMBOL_GPL(qdio_allocate_aob); - -void qdio_release_aob(struct qaob *aob) -{ - kmem_cache_free(qdio_aob_cache, aob); -} -EXPORT_SYMBOL_GPL(qdio_release_aob); /** * qdio_free_buffers() - free qdio buffers @@ -447,39 +434,22 @@ void qdio_print_subchannel_info(struct qdio_irq *irq_ptr) int __init qdio_setup_init(void) { - int rc; - qdio_q_cache = kmem_cache_create("qdio_q", sizeof(struct qdio_q), 256, 0, NULL); if (!qdio_q_cache) return -ENOMEM; - qdio_aob_cache = kmem_cache_create("qdio_aob", - sizeof(struct qaob), - sizeof(struct qaob), - 0, - NULL); - if (!qdio_aob_cache) { - rc = -ENOMEM; - goto free_qdio_q_cache; - } - /* Check for OSA/FCP thin interrupts (bit 67). */ DBF_EVENT("thinint:%1d", (css_general_characteristics.aif_osa) ? 1 : 0); /* Check for QEBSM support in general (bit 58). */ DBF_EVENT("cssQEBSM:%1d", css_general_characteristics.qebsm); - rc = 0; -out: - return rc; -free_qdio_q_cache: - kmem_cache_destroy(qdio_q_cache); - goto out; + + return 0; } void qdio_setup_exit(void) { - kmem_cache_destroy(qdio_aob_cache); kmem_cache_destroy(qdio_q_cache); } diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index a5aa0bdc61d6..20dca4c0384a 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -545,7 +545,6 @@ static inline bool qeth_out_queue_is_empty(struct qeth_qdio_out_q *queue) struct qeth_qdio_info { atomic_t state; /* input */ - int no_in_queues; struct qeth_qdio_q *in_q; struct qeth_qdio_q *c_q; struct qeth_qdio_buffer_pool in_buf_pool; @@ -771,8 +770,6 @@ struct qeth_discipline { void (*remove) (struct ccwgroup_device *); int (*set_online)(struct qeth_card *card, bool carrier_ok); void (*set_offline)(struct qeth_card *card); - int (*do_ioctl)(struct net_device *dev, struct ifreq *rq, - void __user *data, int cmd); int (*control_event_handler)(struct qeth_card *card, struct qeth_ipa_cmd *cmd); }; @@ -1087,6 +1084,7 @@ int qeth_setadpparms_set_access_ctrl(struct qeth_card *card, int qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); int qeth_siocdevprivate(struct net_device *dev, struct ifreq *rq, void __user *data, int cmd); +__printf(3, 4) void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...); int qeth_configure_cq(struct qeth_card *, enum qeth_cq); int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action); diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 15999a816054..26c55f67289f 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -59,6 +59,7 @@ EXPORT_SYMBOL_GPL(qeth_dbf); static struct kmem_cache *qeth_core_header_cache; static struct kmem_cache *qeth_qdio_outbuf_cache; +static struct kmem_cache *qeth_qaob_cache; static struct device *qeth_core_root_dev; static struct dentry *qeth_debugfs_root; @@ -354,8 +355,8 @@ static int qeth_cq_init(struct qeth_card *card) qdio_reset_buffers(card->qdio.c_q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q); card->qdio.c_q->next_buf_to_init = 127; - rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, - card->qdio.no_in_queues - 1, 0, 127, NULL); + rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 1, 0, 127, + NULL); if (rc) { QETH_CARD_TEXT_(card, 2, "1err%d", rc); goto out; @@ -375,21 +376,16 @@ static int qeth_alloc_cq(struct qeth_card *card) dev_err(&card->gdev->dev, "Failed to create completion queue\n"); return -ENOMEM; } - - card->qdio.no_in_queues = 2; } else { QETH_CARD_TEXT(card, 2, "nocq"); card->qdio.c_q = NULL; - card->qdio.no_in_queues = 1; } - QETH_CARD_TEXT_(card, 2, "iqc%d", card->qdio.no_in_queues); return 0; } static void qeth_free_cq(struct qeth_card *card) { if (card->qdio.c_q) { - --card->qdio.no_in_queues; qeth_free_qdio_queue(card->qdio.c_q); card->qdio.c_q = NULL; } @@ -1338,7 +1334,7 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, static void qeth_free_out_buf(struct qeth_qdio_out_buffer *buf) { if (buf->aob) - qdio_release_aob(buf->aob); + kmem_cache_free(qeth_qaob_cache, buf->aob); kmem_cache_free(qeth_qdio_outbuf_cache, buf); } @@ -1458,7 +1454,6 @@ static void qeth_init_qdio_info(struct qeth_card *card) card->qdio.default_out_queue = QETH_DEFAULT_QUEUE; /* inbound */ - card->qdio.no_in_queues = 1; card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT; if (IS_IQD(card)) card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_HSDEFAULT; @@ -1930,9 +1925,9 @@ static struct qeth_cmd_buffer *qeth_mpc_alloc_cmd(struct qeth_card *card, * @card: qeth_card structure pointer * @iob: qeth_cmd_buffer pointer * @reply_cb: callback function pointer - * @cb_card: pointer to the qeth_card structure - * @cb_reply: pointer to the qeth_reply structure - * @cb_cmd: pointer to the original iob for non-IPA + * cb_card: pointer to the qeth_card structure + * cb_reply: pointer to the qeth_reply structure + * cb_cmd: pointer to the original iob for non-IPA * commands, or to the qeth_ipa_cmd structure * for the IPA commands. * @reply_param: private pointer passed to the callback @@ -2629,7 +2624,7 @@ static void qeth_free_qdio_queues(struct qeth_card *card) qeth_free_cq(card); for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) { if (card->qdio.in_q->bufs[j].rx_skb) - dev_kfree_skb_any(card->qdio.in_q->bufs[j].rx_skb); + consume_skb(card->qdio.in_q->bufs[j].rx_skb); } qeth_free_qdio_queue(card->qdio.in_q); card->qdio.in_q = NULL; @@ -3039,7 +3034,7 @@ static int qeth_send_ipa_cmd_cb(struct qeth_card *card, return (cmd->hdr.return_code) ? -EIO : 0; } -/** +/* * qeth_send_ipa_cmd() - send an IPA command * * See qeth_send_control_data() for explanation of the arguments. @@ -3554,7 +3549,8 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, !qeth_iqd_is_mcast_queue(card, queue) && count == 1) { if (!buf->aob) - buf->aob = qdio_allocate_aob(); + buf->aob = kmem_cache_zalloc(qeth_qaob_cache, + GFP_ATOMIC); if (buf->aob) { struct qeth_qaob_priv1 *priv; @@ -3780,7 +3776,7 @@ static void qeth_qdio_output_handler(struct ccw_device *ccwdev, qeth_schedule_recovery(card); } -/** +/* * Note: Function assumes that we have 4 outbound queues. */ int qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb) @@ -3877,12 +3873,14 @@ static unsigned int qeth_count_elements(struct sk_buff *skb, /** * qeth_add_hw_header() - add a HW header to an skb. + * @queue: TX queue that the skb will be placed on. * @skb: skb that the HW header should be added to. * @hdr: double pointer to a qeth_hdr. When returning with >= 0, * it contains a valid pointer to a qeth_hdr. * @hdr_len: length of the HW header. * @proto_len: length of protocol headers that need to be in same page as the * HW header. + * @elements: returns the required number of buffer elements for this skb. * * Returns the pushed length. If the header can't be pushed on * (eg. because it would cross a page boundary), it is allocated from @@ -5139,6 +5137,7 @@ static int qeth_qdio_establish(struct qeth_card *card) struct qdio_buffer **in_sbal_ptrs[QETH_MAX_IN_QUEUES]; struct qeth_qib_parms *qib_parms = NULL; struct qdio_initialize init_data; + unsigned int no_input_qs = 1; unsigned int i; int rc = 0; @@ -5153,8 +5152,10 @@ static int qeth_qdio_establish(struct qeth_card *card) } in_sbal_ptrs[0] = card->qdio.in_q->qdio_bufs; - if (card->options.cq == QETH_CQ_ENABLED) + if (card->options.cq == QETH_CQ_ENABLED) { in_sbal_ptrs[1] = card->qdio.c_q->qdio_bufs; + no_input_qs++; + } for (i = 0; i < card->qdio.no_out_queues; i++) out_sbal_ptrs[i] = card->qdio.out_qs[i]->qdio_bufs; @@ -5164,7 +5165,7 @@ static int qeth_qdio_establish(struct qeth_card *card) QDIO_QETH_QFMT; init_data.qib_param_field_format = 0; init_data.qib_param_field = (void *)qib_parms; - init_data.no_input_qs = card->qdio.no_in_queues; + init_data.no_input_qs = no_input_qs; init_data.no_output_qs = card->qdio.no_out_queues; init_data.input_handler = qeth_qdio_input_handler; init_data.output_handler = qeth_qdio_output_handler; @@ -5604,7 +5605,7 @@ static void qeth_receive_skb(struct qeth_card *card, struct sk_buff *skb, if (uses_frags) napi_free_frags(napi); else - dev_kfree_skb_any(skb); + kfree_skb(skb); return; } @@ -5795,7 +5796,7 @@ walk_packet: if (uses_frags) napi_free_frags(napi); else - dev_kfree_skb_any(skb); + kfree_skb(skb); QETH_CARD_STAT_INC(card, rx_length_errors); } @@ -6600,10 +6601,7 @@ int qeth_siocdevprivate(struct net_device *dev, struct ifreq *rq, void __user *d rc = qeth_query_oat_command(card, data); break; default: - if (card->discipline->do_ioctl) - rc = card->discipline->do_ioctl(dev, rq, data, cmd); - else - rc = -EOPNOTSUPP; + rc = -EOPNOTSUPP; } if (rc) QETH_CARD_TEXT_(card, 2, "ioce%x", rc); @@ -7177,6 +7175,16 @@ static int __init qeth_core_init(void) rc = -ENOMEM; goto cqslab_err; } + + qeth_qaob_cache = kmem_cache_create("qeth_qaob", + sizeof(struct qaob), + sizeof(struct qaob), + 0, NULL); + if (!qeth_qaob_cache) { + rc = -ENOMEM; + goto qaob_err; + } + rc = ccw_driver_register(&qeth_ccw_driver); if (rc) goto ccw_err; @@ -7189,6 +7197,8 @@ static int __init qeth_core_init(void) ccwgroup_err: ccw_driver_unregister(&qeth_ccw_driver); ccw_err: + kmem_cache_destroy(qeth_qaob_cache); +qaob_err: kmem_cache_destroy(qeth_qdio_outbuf_cache); cqslab_err: kmem_cache_destroy(qeth_core_header_cache); @@ -7207,6 +7217,7 @@ static void __exit qeth_core_exit(void) qeth_clear_dbf_list(); ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver); ccw_driver_unregister(&qeth_ccw_driver); + kmem_cache_destroy(qeth_qaob_cache); kmem_cache_destroy(qeth_qdio_outbuf_cache); kmem_cache_destroy(qeth_core_header_cache); root_device_unregister(qeth_core_root_dev); diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 5b6187f2d9d6..0347fc184786 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -121,11 +121,11 @@ static int qeth_l2_write_mac(struct qeth_card *card, u8 *mac) QETH_CARD_TEXT(card, 2, "L2Wmac"); rc = qeth_l2_send_setdelmac(card, mac, cmd); if (rc == -EADDRINUSE) - QETH_DBF_MESSAGE(2, "MAC already registered on device %x\n", - CARD_DEVID(card)); + QETH_DBF_MESSAGE(2, "MAC address %012llx is already registered on device %x\n", + ether_addr_to_u64(mac), CARD_DEVID(card)); else if (rc) - QETH_DBF_MESSAGE(2, "Failed to register MAC on device %x: %d\n", - CARD_DEVID(card), rc); + QETH_DBF_MESSAGE(2, "Failed to register MAC address %012llx on device %x: %d\n", + ether_addr_to_u64(mac), CARD_DEVID(card), rc); return rc; } @@ -138,8 +138,8 @@ static int qeth_l2_remove_mac(struct qeth_card *card, u8 *mac) QETH_CARD_TEXT(card, 2, "L2Rmac"); rc = qeth_l2_send_setdelmac(card, mac, cmd); if (rc) - QETH_DBF_MESSAGE(2, "Failed to delete MAC on device %u: %d\n", - CARD_DEVID(card), rc); + QETH_DBF_MESSAGE(2, "Failed to delete MAC address %012llx on device %x: %d\n", + ether_addr_to_u64(mac), CARD_DEVID(card), rc); return rc; } @@ -661,13 +661,13 @@ static void qeth_l2_dev2br_fdb_notify(struct qeth_card *card, u8 code, card->dev, &info.info, NULL); QETH_CARD_TEXT(card, 4, "andelmac"); QETH_CARD_TEXT_(card, 4, - "mc%012lx", ether_addr_to_u64(ntfy_mac)); + "mc%012llx", ether_addr_to_u64(ntfy_mac)); } else { call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_BRIDGE, card->dev, &info.info, NULL); QETH_CARD_TEXT(card, 4, "anaddmac"); QETH_CARD_TEXT_(card, 4, - "mc%012lx", ether_addr_to_u64(ntfy_mac)); + "mc%012llx", ether_addr_to_u64(ntfy_mac)); } } @@ -765,8 +765,8 @@ static void qeth_l2_br2dev_worker(struct work_struct *work) int err = 0; kfree(br2dev_event_work); - QETH_CARD_TEXT_(card, 4, "b2dw%04x", event); - QETH_CARD_TEXT_(card, 4, "ma%012lx", ether_addr_to_u64(addr)); + QETH_CARD_TEXT_(card, 4, "b2dw%04lx", event); + QETH_CARD_TEXT_(card, 4, "ma%012llx", ether_addr_to_u64(addr)); rcu_read_lock(); /* Verify preconditions are still valid: */ @@ -795,7 +795,7 @@ static void qeth_l2_br2dev_worker(struct work_struct *work) if (err) { QETH_CARD_TEXT(card, 2, "b2derris"); QETH_CARD_TEXT_(card, 2, - "err%02x%03d", event, + "err%02lx%03d", event, lowerdev->ifindex); } } @@ -813,7 +813,7 @@ static void qeth_l2_br2dev_worker(struct work_struct *work) break; } if (err) - QETH_CARD_TEXT_(card, 2, "b2derr%02x", event); + QETH_CARD_TEXT_(card, 2, "b2derr%02lx", event); } unlock: @@ -878,7 +878,7 @@ static int qeth_l2_switchdev_event(struct notifier_block *unused, while (lowerdev) { if (qeth_l2_must_learn(lowerdev, dstdev)) { card = lowerdev->ml_priv; - QETH_CARD_TEXT_(card, 4, "b2dqw%03x", event); + QETH_CARD_TEXT_(card, 4, "b2dqw%03lx", event); rc = qeth_l2_br2dev_queue_work(brdev, lowerdev, dstdev, event, fdb_info->addr); @@ -2430,7 +2430,6 @@ const struct qeth_discipline qeth_l2_discipline = { .remove = qeth_l2_remove_device, .set_online = qeth_l2_set_online, .set_offline = qeth_l2_set_offline, - .do_ioctl = NULL, .control_event_handler = qeth_l2_control_event, }; EXPORT_SYMBOL_GPL(qeth_l2_discipline); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index e6e921310211..48a886f7af62 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -492,7 +492,7 @@ int qeth_l3_setrouting_v6(struct qeth_card *card) * IP address takeover related functions */ -/** +/* * qeth_l3_update_ipato() - Update 'takeover' property, for all NORMAL IPs. * * Caller must hold ip_lock. @@ -1511,7 +1511,8 @@ static int qeth_l3_arp_flush_cache(struct qeth_card *card) return rc; } -static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, void __user *data, int cmd) +static int qeth_l3_ndo_siocdevprivate(struct net_device *dev, struct ifreq *rq, + void __user *data, int cmd) { struct qeth_card *card = dev->ml_priv; struct qeth_arp_cache_entry arp_entry; @@ -1552,7 +1553,7 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, void __use rc = qeth_l3_arp_flush_cache(card); break; default: - rc = -EOPNOTSUPP; + rc = qeth_siocdevprivate(dev, rq, data, cmd); } return rc; } @@ -1841,7 +1842,7 @@ static const struct net_device_ops qeth_l3_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_set_rx_mode = qeth_l3_set_rx_mode, .ndo_eth_ioctl = qeth_do_ioctl, - .ndo_siocdevprivate = qeth_siocdevprivate, + .ndo_siocdevprivate = qeth_l3_ndo_siocdevprivate, .ndo_fix_features = qeth_fix_features, .ndo_set_features = qeth_set_features, .ndo_tx_timeout = qeth_tx_timeout, @@ -1857,7 +1858,7 @@ static const struct net_device_ops qeth_l3_osa_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_set_rx_mode = qeth_l3_set_rx_mode, .ndo_eth_ioctl = qeth_do_ioctl, - .ndo_siocdevprivate = qeth_siocdevprivate, + .ndo_siocdevprivate = qeth_l3_ndo_siocdevprivate, .ndo_fix_features = qeth_fix_features, .ndo_set_features = qeth_set_features, .ndo_tx_timeout = qeth_tx_timeout, @@ -2071,7 +2072,6 @@ const struct qeth_discipline qeth_l3_discipline = { .remove = qeth_l3_remove_device, .set_online = qeth_l3_set_online, .set_offline = qeth_l3_set_offline, - .do_ioctl = qeth_l3_do_ioctl, .control_event_handler = qeth_l3_control_event, }; EXPORT_SYMBOL_GPL(qeth_l3_discipline); diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h index 27d9b6683f0e..747fad264033 100644 --- a/include/linux/brcmphy.h +++ b/include/linux/brcmphy.h @@ -50,6 +50,7 @@ #define PHY_ID_BCM7439 0x600d8480 #define PHY_ID_BCM7439_2 0xae025080 #define PHY_ID_BCM7445 0x600d8510 +#define PHY_ID_BCM7712 0x35905330 #define PHY_ID_BCM_CYGNUS 0xae025200 #define PHY_ID_BCM_OMEGA 0xae025100 diff --git a/include/linux/can/bittiming.h b/include/linux/can/bittiming.h index 9de6e9053e34..20b50baf3a02 100644 --- a/include/linux/can/bittiming.h +++ b/include/linux/can/bittiming.h @@ -19,6 +19,9 @@ /* Megahertz */ #define CAN_MHZ 1000000UL +#define CAN_CTRLMODE_TDC_MASK \ + (CAN_CTRLMODE_TDC_AUTO | CAN_CTRLMODE_TDC_MANUAL) + /* * struct can_tdc - CAN FD Transmission Delay Compensation parameters * @@ -28,34 +31,54 @@ * * To solve this issue, ISO 11898-1 introduces in section 11.3.3 * "Transmitter delay compensation" a SSP (Secondary Sample Point) - * equal to the distance, in time quanta, from the start of the bit - * time on the TX pin to the actual measurement on the RX pin. + * equal to the distance from the start of the bit time on the TX pin + * to the actual measurement on the RX pin. * * This structure contains the parameters to calculate that SSP. * - * @tdcv: Transmitter Delay Compensation Value. Distance, in time - * quanta, from when the bit is sent on the TX pin to when it is - * received on the RX pin of the transmitter. Possible options: + * -+----------- one bit ----------+-- TX pin + * |<--- Sample Point --->| * - * 0: automatic mode. The controller dynamically measures @tdcv - * for each transmitted CAN FD frame. + * --+----------- one bit ----------+-- RX pin + * |<-------- TDCV -------->| + * |<------- TDCO ------->| + * |<----------- Secondary Sample Point ---------->| * - * Other values: manual mode. Use the fixed provided value. + * To increase precision, contrary to the other bittiming parameters + * which are measured in time quanta, the TDC parameters are measured + * in clock periods (also referred as "minimum time quantum" in ISO + * 11898-1). * - * @tdco: Transmitter Delay Compensation Offset. Offset value, in time - * quanta, defining the distance between the start of the bit - * reception on the RX pin of the transceiver and the SSP - * position such that SSP = @tdcv + @tdco. + * @tdcv: Transmitter Delay Compensation Value. The time needed for + * the signal to propagate, i.e. the distance, in clock periods, + * from the start of the bit on the TX pin to when it is received + * on the RX pin. @tdcv depends on the controller modes: + * + * CAN_CTRLMODE_TDC_AUTO is set: The transceiver dynamically + * measures @tdcv for each transmitted CAN FD frame and the + * value provided here should be ignored. + * + * CAN_CTRLMODE_TDC_MANUAL is set: use the fixed provided @tdcv + * value. * - * If @tdco is zero, then TDC is disabled and both @tdcv and - * @tdcf should be ignored. + * N.B. CAN_CTRLMODE_TDC_AUTO and CAN_CTRLMODE_TDC_MANUAL are + * mutually exclusive. Only one can be set at a time. If both + * CAN_TDC_CTRLMODE_AUTO and CAN_TDC_CTRLMODE_MANUAL are unset, + * TDC is disabled and all the values of this structure should be + * ignored. + * + * @tdco: Transmitter Delay Compensation Offset. Offset value, in + * clock periods, defining the distance between the start of the + * bit reception on the RX pin of the transceiver and the SSP + * position such that SSP = @tdcv + @tdco. * * @tdcf: Transmitter Delay Compensation Filter window. Defines the - * minimum value for the SSP position in time quanta. If SSP is - * less than @tdcf, then no delay compensations occur and the - * normal sampling point is used instead. The feature is enabled - * if and only if @tdcv is set to zero (automatic mode) and @tdcf - * is configured to a value greater than @tdco. + * minimum value for the SSP position in clock periods. If the + * SSP position is less than @tdcf, then no delay compensations + * occur and the normal sampling point is used instead. The + * feature is enabled if and only if @tdcv is set to zero + * (automatic mode) and @tdcf is configured to a value greater + * than @tdco. */ struct can_tdc { u32 tdcv; @@ -67,19 +90,32 @@ struct can_tdc { * struct can_tdc_const - CAN hardware-dependent constant for * Transmission Delay Compensation * - * @tdcv_max: Transmitter Delay Compensation Value maximum value. - * Should be set to zero if the controller does not support - * manual mode for tdcv. + * @tdcv_min: Transmitter Delay Compensation Value minimum value. If + * the controller does not support manual mode for tdcv + * (c.f. flag CAN_CTRLMODE_TDC_MANUAL) then this value is + * ignored. + * @tdcv_max: Transmitter Delay Compensation Value maximum value. If + * the controller does not support manual mode for tdcv + * (c.f. flag CAN_CTRLMODE_TDC_MANUAL) then this value is + * ignored. + * + * @tdco_min: Transmitter Delay Compensation Offset minimum value. * @tdco_max: Transmitter Delay Compensation Offset maximum value. * Should not be zero. If the controller does not support TDC, * then the pointer to this structure should be NULL. + * + * @tdcf_min: Transmitter Delay Compensation Filter window minimum + * value. If @tdcf_max is zero, this value is ignored. * @tdcf_max: Transmitter Delay Compensation Filter window maximum * value. Should be set to zero if the controller does not * support this feature. */ struct can_tdc_const { + u32 tdcv_min; u32 tdcv_max; + u32 tdco_min; u32 tdco_max; + u32 tdcf_min; u32 tdcf_max; }; @@ -87,7 +123,9 @@ struct can_tdc_const { int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, const struct can_bittiming_const *btc); -void can_calc_tdco(struct net_device *dev); +void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const, + const struct can_bittiming *dbt, + u32 *ctrlmode, u32 ctrlmode_supported); #else /* !CONFIG_CAN_CALC_BITTIMING */ static inline int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, @@ -97,7 +135,10 @@ can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, return -EINVAL; } -static inline void can_calc_tdco(struct net_device *dev) +static inline void +can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const, + const struct can_bittiming *dbt, + u32 *ctrlmode, u32 ctrlmode_supported) { } #endif /* CONFIG_CAN_CALC_BITTIMING */ diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h index 2413253e54c7..45f19d9db5ca 100644 --- a/include/linux/can/dev.h +++ b/include/linux/can/dev.h @@ -82,6 +82,7 @@ struct can_priv { enum can_state *state); int (*do_get_berr_counter)(const struct net_device *dev, struct can_berr_counter *bec); + int (*do_get_auto_tdcv)(const struct net_device *dev, u32 *tdcv); unsigned int echo_skb_max; struct sk_buff **echo_skb; @@ -96,6 +97,39 @@ struct can_priv { #endif }; +static inline bool can_tdc_is_enabled(const struct can_priv *priv) +{ + return !!(priv->ctrlmode & CAN_CTRLMODE_TDC_MASK); +} + +/* + * can_get_relative_tdco() - TDCO relative to the sample point + * + * struct can_tdc::tdco represents the absolute offset from TDCV. Some + * controllers use instead an offset relative to the Sample Point (SP) + * such that: + * + * SSP = TDCV + absolute TDCO + * = TDCV + SP + relative TDCO + * + * -+----------- one bit ----------+-- TX pin + * |<--- Sample Point --->| + * + * --+----------- one bit ----------+-- RX pin + * |<-------- TDCV -------->| + * |<------------------------>| absolute TDCO + * |<--- Sample Point --->| + * | |<->| relative TDCO + * |<------------- Secondary Sample Point ------------>| + */ +static inline s32 can_get_relative_tdco(const struct can_priv *priv) +{ + const struct can_bittiming *dbt = &priv->data_bittiming; + s32 sample_point_in_tc = (CAN_SYNC_SEG + dbt->prop_seg + + dbt->phase_seg1) * dbt->brp; + + return (s32)priv->tdc.tdco - sample_point_in_tc; +} /* helper to define static CAN controller features at device creation time */ static inline void can_set_static_ctrlmode(struct net_device *dev, diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index ef4a69865737..c383630d3f06 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -282,7 +282,6 @@ struct ipv6_pinfo { __be32 rcv_flowinfo; __u32 dst_cookie; - __u32 rx_dst_cookie; struct ipv6_mc_socklist __rcu *ipv6_mc_list; struct ipv6_ac_socklist *ipv6_ac_list; diff --git a/include/linux/mdio.h b/include/linux/mdio.h index f622888a4ba8..9f3587a61e14 100644 --- a/include/linux/mdio.h +++ b/include/linux/mdio.h @@ -352,6 +352,30 @@ int mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask, int mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum, u16 mask, u16 set); +static inline int mdiodev_read(struct mdio_device *mdiodev, u32 regnum) +{ + return mdiobus_read(mdiodev->bus, mdiodev->addr, regnum); +} + +static inline int mdiodev_write(struct mdio_device *mdiodev, u32 regnum, + u16 val) +{ + return mdiobus_write(mdiodev->bus, mdiodev->addr, regnum, val); +} + +static inline int mdiodev_modify(struct mdio_device *mdiodev, u32 regnum, + u16 mask, u16 set) +{ + return mdiobus_modify(mdiodev->bus, mdiodev->addr, regnum, mask, set); +} + +static inline int mdiodev_modify_changed(struct mdio_device *mdiodev, + u32 regnum, u16 mask, u16 set) +{ + return mdiobus_modify_changed(mdiodev->bus, mdiodev->addr, regnum, + mask, set); +} + static inline u32 mdiobus_c45_addr(int devad, u16 regnum) { return MII_ADDR_C45 | devad << MII_DEVADDR_C45_SHIFT | regnum; diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h index 347167c18802..f8a0bbb42c3b 100644 --- a/include/linux/mlx5/device.h +++ b/include/linux/mlx5/device.h @@ -541,19 +541,21 @@ struct mlx5_cmd_layout { u8 status_own; }; -enum mlx5_fatal_assert_bit_offsets { - MLX5_RFR_OFFSET = 31, +enum mlx5_rfr_severity_bit_offsets { + MLX5_RFR_BIT_OFFSET = 0x7, }; struct health_buffer { - __be32 assert_var[5]; - __be32 rsvd0[3]; + __be32 assert_var[6]; + __be32 rsvd0[2]; __be32 assert_exit_ptr; __be32 assert_callra; - __be32 rsvd1[2]; + __be32 rsvd1[1]; + __be32 time; __be32 fw_ver; __be32 hw_id; - __be32 rfr; + u8 rfr_severity; + u8 rsvd2[3]; u8 irisc_index; u8 synd; __be16 ext_synd; diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 3f4c0f2314a5..f617dfbcd9fd 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -134,6 +134,7 @@ enum { MLX5_REG_MCIA = 0x9014, MLX5_REG_MFRL = 0x9028, MLX5_REG_MLCR = 0x902b, + MLX5_REG_MRTC = 0x902d, MLX5_REG_MTRC_CAP = 0x9040, MLX5_REG_MTRC_CONF = 0x9041, MLX5_REG_MTRC_STDB = 0x9042, @@ -440,6 +441,7 @@ struct mlx5_core_health { struct work_struct report_work; struct devlink_health_reporter *fw_reporter; struct devlink_health_reporter *fw_fatal_reporter; + struct delayed_work update_fw_log_ts_work; }; struct mlx5_qp_table { diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 09e43019d877..746381eccccf 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -4149,13 +4149,19 @@ struct mlx5_ifc_health_buffer_bits { u8 assert_callra[0x20]; - u8 reserved_at_140[0x40]; + u8 reserved_at_140[0x20]; + + u8 time[0x20]; u8 fw_version[0x20]; u8 hw_id[0x20]; - u8 reserved_at_1c0[0x20]; + u8 rfr[0x1]; + u8 reserved_at_1c1[0x3]; + u8 valid[0x1]; + u8 severity[0x3]; + u8 reserved_at_1c8[0x18]; u8 irisc_index[0x8]; u8 synd[0x8]; @@ -10352,6 +10358,17 @@ struct mlx5_ifc_pddr_reg_bits { union mlx5_ifc_pddr_reg_page_data_auto_bits page_data; }; +struct mlx5_ifc_mrtc_reg_bits { + u8 time_synced[0x1]; + u8 reserved_at_1[0x1f]; + + u8 reserved_at_20[0x20]; + + u8 time_h[0x20]; + + u8 time_l[0x20]; +}; + union mlx5_ifc_ports_control_registers_document_bits { struct mlx5_ifc_bufferx_reg_bits bufferx_reg; struct mlx5_ifc_eth_2819_cntrs_grp_data_layout_bits eth_2819_cntrs_grp_data_layout; @@ -10413,6 +10430,7 @@ union mlx5_ifc_ports_control_registers_document_bits { struct mlx5_ifc_mirc_reg_bits mirc_reg; struct mlx5_ifc_mfrl_reg_bits mfrl_reg; struct mlx5_ifc_mtutc_reg_bits mtutc_reg; + struct mlx5_ifc_mrtc_reg_bits mrtc_reg; u8 reserved_at_0[0x60e0]; }; diff --git a/include/linux/phy.h b/include/linux/phy.h index 736e1d1a47c4..96e43fbb2dd8 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -155,6 +155,40 @@ typedef enum { PHY_INTERFACE_MODE_MAX, } phy_interface_t; +/* PHY interface mode bitmap handling */ +#define DECLARE_PHY_INTERFACE_MASK(name) \ + DECLARE_BITMAP(name, PHY_INTERFACE_MODE_MAX) + +static inline void phy_interface_zero(unsigned long *intf) +{ + bitmap_zero(intf, PHY_INTERFACE_MODE_MAX); +} + +static inline bool phy_interface_empty(const unsigned long *intf) +{ + return bitmap_empty(intf, PHY_INTERFACE_MODE_MAX); +} + +static inline void phy_interface_and(unsigned long *dst, const unsigned long *a, + const unsigned long *b) +{ + bitmap_and(dst, a, b, PHY_INTERFACE_MODE_MAX); +} + +static inline void phy_interface_or(unsigned long *dst, const unsigned long *a, + const unsigned long *b) +{ + bitmap_or(dst, a, b, PHY_INTERFACE_MODE_MAX); +} + +static inline void phy_interface_set_rgmii(unsigned long *intf) +{ + __set_bit(PHY_INTERFACE_MODE_RGMII, intf); + __set_bit(PHY_INTERFACE_MODE_RGMII_ID, intf); + __set_bit(PHY_INTERFACE_MODE_RGMII_RXID, intf); + __set_bit(PHY_INTERFACE_MODE_RGMII_TXID, intf); +} + /* * phy_supported_speeds - return all speeds currently supported by a PHY device */ @@ -1584,6 +1618,7 @@ int genphy_c45_config_aneg(struct phy_device *phydev); int genphy_c45_loopback(struct phy_device *phydev, bool enable); int genphy_c45_pma_resume(struct phy_device *phydev); int genphy_c45_pma_suspend(struct phy_device *phydev); +int genphy_c45_fast_retrain(struct phy_device *phydev, bool enable); /* Generic C45 PHY driver */ extern struct phy_driver genphy_c45_driver; diff --git a/include/linux/phylink.h b/include/linux/phylink.h index f7b5ed06a815..f037470b6fb3 100644 --- a/include/linux/phylink.h +++ b/include/linux/phylink.h @@ -67,6 +67,8 @@ enum phylink_op_type { * @ovr_an_inband: if true, override PCS to MLO_AN_INBAND * @get_fixed_state: callback to execute to determine the fixed link state, * if MAC link is at %MLO_AN_FIXED mode. + * @supported_interfaces: bitmap describing which PHY_INTERFACE_MODE_xxx + * are supported by the MAC/PCS. */ struct phylink_config { struct device *dev; @@ -76,6 +78,7 @@ struct phylink_config { bool ovr_an_inband; void (*get_fixed_state)(struct phylink_config *config, struct phylink_link_state *state); + DECLARE_PHY_INTERFACE_MASK(supported_interfaces); }; /** @@ -133,8 +136,14 @@ struct phylink_mac_ops { * based on @state->advertising and/or @state->speed and update * @state->interface accordingly. See phylink_helper_basex_speed(). * - * When @state->interface is %PHY_INTERFACE_MODE_NA, phylink expects the - * MAC driver to return all supported link modes. + * When @config->supported_interfaces has been set, phylink will iterate + * over the supported interfaces to determine the full capability of the + * MAC. The validation function must not print errors if @state->interface + * is set to an unexpected value. + * + * When @config->supported_interfaces is empty, phylink will call this + * function with @state->interface set to %PHY_INTERFACE_MODE_NA, and + * expects the MAC driver to return all supported link modes. * * If the @state->interface mode is not supported, then the @supported * mask must be cleared. diff --git a/include/linux/socket.h b/include/linux/socket.h index 7612d760b6a9..8ef26d89ef49 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -365,6 +365,7 @@ struct ucred { #define SOL_TLS 282 #define SOL_XDP 283 #define SOL_MPTCP 284 +#define SOL_MCTP 285 /* IPX options */ #define IPX_TYPE 1 diff --git a/include/net/busy_poll.h b/include/net/busy_poll.h index 40296ed976a9..4202c609bb0b 100644 --- a/include/net/busy_poll.h +++ b/include/net/busy_poll.h @@ -130,7 +130,8 @@ static inline void skb_mark_napi_id(struct sk_buff *skb, static inline void sk_mark_napi_id(struct sock *sk, const struct sk_buff *skb) { #ifdef CONFIG_NET_RX_BUSY_POLL - WRITE_ONCE(sk->sk_napi_id, skb->napi_id); + if (unlikely(READ_ONCE(sk->sk_napi_id) != skb->napi_id)) + WRITE_ONCE(sk->sk_napi_id, skb->napi_id); #endif sk_rx_queue_set(sk, skb); } diff --git a/include/net/devlink.h b/include/net/devlink.h index da3ceeb8b87b..1b1317d378de 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -468,7 +468,6 @@ struct devlink_param_item { const struct devlink_param *param; union devlink_param_value driverinit_value; bool driverinit_value_valid; - bool published; }; enum devlink_param_generic_id { @@ -1592,8 +1591,6 @@ int devlink_param_register(struct devlink *devlink, const struct devlink_param *param); void devlink_param_unregister(struct devlink *devlink, const struct devlink_param *param); -void devlink_params_publish(struct devlink *devlink); -void devlink_params_unpublish(struct devlink *devlink); int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id, union devlink_param_value *init_val); int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id, diff --git a/include/net/dsa.h b/include/net/dsa.h index 1cd9c2461f0d..badd214f7470 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -287,6 +287,7 @@ struct dsa_port { /* List of MAC addresses that must be forwarded on this port. * These are only valid on CPU ports and DSA links. */ + struct mutex addr_lists_lock; struct list_head fdbs; struct list_head mdbs; diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index 89163ef8cf4b..9e1111f5915b 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -207,11 +207,10 @@ struct inet_sock { __be32 inet_saddr; __s16 uc_ttl; __u16 cmsg_flags; + struct ip_options_rcu __rcu *inet_opt; __be16 inet_sport; __u16 inet_id; - struct ip_options_rcu __rcu *inet_opt; - int rx_dst_ifindex; __u8 tos; __u8 min_ttl; __u8 mc_ttl; diff --git a/include/net/ip.h b/include/net/ip.h index cf229a531194..b71e88507c4a 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -24,6 +24,7 @@ #include <linux/skbuff.h> #include <linux/jhash.h> #include <linux/sockptr.h> +#include <linux/static_key.h> #include <net/inet_sock.h> #include <net/route.h> @@ -750,6 +751,7 @@ void ip_cmsg_recv_offset(struct msghdr *msg, struct sock *sk, struct sk_buff *skb, int tlen, int offset); int ip_cmsg_send(struct sock *sk, struct msghdr *msg, struct ipcm_cookie *ipc, bool allow_ipv6); +DECLARE_STATIC_KEY_FALSE(ip4_min_ttl); int ip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, unsigned int optlen); int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, diff --git a/include/net/ipv6.h b/include/net/ipv6.h index f2d0ecc257bb..c19bf51ded1d 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -1092,6 +1092,7 @@ struct in6_addr *fl6_update_dst(struct flowi6 *fl6, /* * socket options (ipv6_sockglue.c) */ +DECLARE_STATIC_KEY_FALSE(ip6_min_hopcount); int ipv6_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, unsigned int optlen); diff --git a/include/net/mctp.h b/include/net/mctp.h index 2a83443bdfac..23bec708f4c7 100644 --- a/include/net/mctp.h +++ b/include/net/mctp.h @@ -11,6 +11,7 @@ #include <linux/bits.h> #include <linux/mctp.h> +#include <linux/netdevice.h> #include <net/net_namespace.h> #include <net/sock.h> @@ -58,6 +59,9 @@ struct mctp_sock { mctp_eid_t bind_addr; __u8 bind_type; + /* sendmsg()/recvmsg() uses struct sockaddr_mctp_ext */ + bool addr_ext; + /* list of mctp_sk_key, for incoming tag lookup. updates protected * by sk->net->keys_lock */ @@ -153,7 +157,10 @@ struct mctp_sk_key { struct mctp_skb_cb { unsigned int magic; unsigned int net; + int ifindex; /* extended/direct addressing if set */ mctp_eid_t src; + unsigned char halen; + unsigned char haddr[MAX_ADDR_LEN]; }; /* skb control-block accessors with a little extra debugging for initial @@ -177,6 +184,7 @@ static inline struct mctp_skb_cb *mctp_cb(struct sk_buff *skb) { struct mctp_skb_cb *cb = (void *)skb->cb; + BUILD_BUG_ON(sizeof(struct mctp_skb_cb) > sizeof(skb->cb)); WARN_ON(cb->magic != 0x4d435450); return (void *)(skb->cb); } @@ -189,8 +197,7 @@ static inline struct mctp_skb_cb *mctp_cb(struct sk_buff *skb) * * Updates to the route table are performed under rtnl; all reads under RCU, * so routes cannot be referenced over a RCU grace period. Specifically: A - * caller cannot block between mctp_route_lookup and passing the route to - * mctp_do_route. + * caller cannot block between mctp_route_lookup and mctp_route_release() */ struct mctp_route { mctp_eid_t min, max; @@ -210,8 +217,6 @@ struct mctp_route { struct mctp_route *mctp_route_lookup(struct net *net, unsigned int dnet, mctp_eid_t daddr); -int mctp_do_route(struct mctp_route *rt, struct sk_buff *skb); - int mctp_local_output(struct sock *sk, struct mctp_route *rt, struct sk_buff *skb, mctp_eid_t daddr, u8 req_tag); diff --git a/include/net/neighbour.h b/include/net/neighbour.h index e8e48be66755..38a0c1d24570 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h @@ -516,10 +516,15 @@ static inline int neigh_output(struct neighbour *n, struct sk_buff *skb, { const struct hh_cache *hh = &n->hh; - if ((n->nud_state & NUD_CONNECTED) && hh->hh_len && !skip_cache) + /* n->nud_state and hh->hh_len could be changed under us. + * neigh_hh_output() is taking care of the race later. + */ + if (!skip_cache && + (READ_ONCE(n->nud_state) & NUD_CONNECTED) && + READ_ONCE(hh->hh_len)) return neigh_hh_output(hh, skb); - else - return n->output(n, skb); + + return n->output(n, skb); } static inline struct neighbour * diff --git a/include/net/sock.h b/include/net/sock.h index 596ba85611bc..ff4e62aa62e5 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -259,6 +259,8 @@ struct bpf_local_storage; * @sk_rcvbuf: size of receive buffer in bytes * @sk_wq: sock wait queue and async head * @sk_rx_dst: receive input route used by early demux + * @sk_rx_dst_ifindex: ifindex for @sk_rx_dst + * @sk_rx_dst_cookie: cookie for @sk_rx_dst * @sk_dst_cache: destination cache * @sk_dst_pending_confirm: need to confirm neighbour * @sk_policy: flow policy @@ -430,6 +432,9 @@ struct sock { struct xfrm_policy __rcu *sk_policy[2]; #endif struct dst_entry *sk_rx_dst; + int sk_rx_dst_ifindex; + u32 sk_rx_dst_cookie; + struct dst_entry __rcu *sk_dst_cache; atomic_t sk_omem_alloc; int sk_sndbuf; @@ -1911,10 +1916,8 @@ static inline void sk_rx_queue_set(struct sock *sk, const struct sk_buff *skb) if (skb_rx_queue_recorded(skb)) { u16 rx_queue = skb_get_rx_queue(skb); - if (WARN_ON_ONCE(rx_queue == NO_QUEUE_MAPPING)) - return; - - sk->sk_rx_queue_mapping = rx_queue; + if (unlikely(READ_ONCE(sk->sk_rx_queue_mapping) != rx_queue)) + WRITE_ONCE(sk->sk_rx_queue_mapping, rx_queue); } #endif } @@ -1922,15 +1925,19 @@ static inline void sk_rx_queue_set(struct sock *sk, const struct sk_buff *skb) static inline void sk_rx_queue_clear(struct sock *sk) { #ifdef CONFIG_SOCK_RX_QUEUE_MAPPING - sk->sk_rx_queue_mapping = NO_QUEUE_MAPPING; + WRITE_ONCE(sk->sk_rx_queue_mapping, NO_QUEUE_MAPPING); #endif } static inline int sk_rx_queue_get(const struct sock *sk) { #ifdef CONFIG_SOCK_RX_QUEUE_MAPPING - if (sk && sk->sk_rx_queue_mapping != NO_QUEUE_MAPPING) - return sk->sk_rx_queue_mapping; + if (sk) { + int res = READ_ONCE(sk->sk_rx_queue_mapping); + + if (res != NO_QUEUE_MAPPING) + return res; + } #endif return -1; @@ -2415,9 +2422,6 @@ static inline void sk_stream_moderate_sndbuf(struct sock *sk) WRITE_ONCE(sk->sk_sndbuf, max_t(u32, val, SOCK_MIN_SNDBUF)); } -struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp, - bool force_schedule); - /** * sk_page_frag - return an appropriate page_frag * @sk: socket diff --git a/include/net/tcp.h b/include/net/tcp.h index d62467a0094f..701587af6852 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -337,6 +337,8 @@ void tcp_twsk_destructor(struct sock *sk); ssize_t tcp_splice_read(struct socket *sk, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags); +struct sk_buff *tcp_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp, + bool force_schedule); void tcp_enter_quickack_mode(struct sock *sk, unsigned int max_quickacks); static inline void tcp_dec_quickack_mode(struct sock *sk, diff --git a/include/net/tls.h b/include/net/tls.h index b6d40642afdd..adab19a8aed7 100644 --- a/include/net/tls.h +++ b/include/net/tls.h @@ -221,6 +221,8 @@ union tls_crypto_context { struct tls12_crypto_info_aes_gcm_128 aes_gcm_128; struct tls12_crypto_info_aes_gcm_256 aes_gcm_256; struct tls12_crypto_info_chacha20_poly1305 chacha20_poly1305; + struct tls12_crypto_info_sm4_gcm sm4_gcm; + struct tls12_crypto_info_sm4_ccm sm4_ccm; }; }; diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 9b872da0c246..fef3a36b0210 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -675,6 +675,9 @@ struct ocelot { struct delayed_work stats_work; struct workqueue_struct *stats_queue; + /* Lock for serializing access to the MAC table */ + struct mutex mact_lock; + struct workqueue_struct *owq; u8 ptp:1; diff --git a/include/uapi/linux/can/netlink.h b/include/uapi/linux/can/netlink.h index f730d443b918..75b85c60efb2 100644 --- a/include/uapi/linux/can/netlink.h +++ b/include/uapi/linux/can/netlink.h @@ -101,6 +101,8 @@ struct can_ctrlmode { #define CAN_CTRLMODE_PRESUME_ACK 0x40 /* Ignore missing CAN ACKs */ #define CAN_CTRLMODE_FD_NON_ISO 0x80 /* CAN FD in non-ISO mode */ #define CAN_CTRLMODE_CC_LEN8_DLC 0x100 /* Classic CAN DLC option */ +#define CAN_CTRLMODE_TDC_AUTO 0x200 /* CAN transiver automatically calculates TDCV */ +#define CAN_CTRLMODE_TDC_MANUAL 0x400 /* TDCV is manually set up by user */ /* * CAN device statistics @@ -134,10 +136,35 @@ enum { IFLA_CAN_BITRATE_CONST, IFLA_CAN_DATA_BITRATE_CONST, IFLA_CAN_BITRATE_MAX, - __IFLA_CAN_MAX + IFLA_CAN_TDC, + + /* add new constants above here */ + __IFLA_CAN_MAX, + IFLA_CAN_MAX = __IFLA_CAN_MAX - 1 }; -#define IFLA_CAN_MAX (__IFLA_CAN_MAX - 1) +/* + * CAN FD Transmitter Delay Compensation (TDC) + * + * Please refer to struct can_tdc_const and can_tdc in + * include/linux/can/bittiming.h for further details. + */ +enum { + IFLA_CAN_TDC_UNSPEC, + IFLA_CAN_TDC_TDCV_MIN, /* u32 */ + IFLA_CAN_TDC_TDCV_MAX, /* u32 */ + IFLA_CAN_TDC_TDCO_MIN, /* u32 */ + IFLA_CAN_TDC_TDCO_MAX, /* u32 */ + IFLA_CAN_TDC_TDCF_MIN, /* u32 */ + IFLA_CAN_TDC_TDCF_MAX, /* u32 */ + IFLA_CAN_TDC_TDCV, /* u32 */ + IFLA_CAN_TDC_TDCO, /* u32 */ + IFLA_CAN_TDC_TDCF, /* u32 */ + + /* add new constants above here */ + __IFLA_CAN_TDC, + IFLA_CAN_TDC_MAX = __IFLA_CAN_TDC - 1 +}; /* u16 termination range: 1..65535 Ohms */ #define CAN_TERMINATION_DISABLED 0 diff --git a/include/uapi/linux/mctp.h b/include/uapi/linux/mctp.h index 6acd4ccafbf7..07b0318716fc 100644 --- a/include/uapi/linux/mctp.h +++ b/include/uapi/linux/mctp.h @@ -11,6 +11,7 @@ #include <linux/types.h> #include <linux/socket.h> +#include <linux/netdevice.h> typedef __u8 mctp_eid_t; @@ -28,6 +29,14 @@ struct sockaddr_mctp { __u8 __smctp_pad1; }; +struct sockaddr_mctp_ext { + struct sockaddr_mctp smctp_base; + int smctp_ifindex; + __u8 smctp_halen; + __u8 __smctp_pad0[3]; + __u8 smctp_haddr[MAX_ADDR_LEN]; +}; + #define MCTP_NET_ANY 0x0 #define MCTP_ADDR_NULL 0x00 @@ -36,4 +45,6 @@ struct sockaddr_mctp { #define MCTP_TAG_MASK 0x07 #define MCTP_TAG_OWNER 0x08 +#define MCTP_OPT_ADDR_EXT 1 + #endif /* __UAPI_MCTP_H */ diff --git a/include/uapi/linux/mdio.h b/include/uapi/linux/mdio.h index bdf77dffa5a4..c54e6eae5366 100644 --- a/include/uapi/linux/mdio.h +++ b/include/uapi/linux/mdio.h @@ -53,12 +53,14 @@ #define MDIO_AN_EEE_LPABLE 61 /* EEE link partner ability */ #define MDIO_AN_EEE_ADV2 62 /* EEE advertisement 2 */ #define MDIO_AN_EEE_LPABLE2 63 /* EEE link partner ability 2 */ +#define MDIO_AN_CTRL2 64 /* AN THP bypass request control */ /* Media-dependent registers. */ #define MDIO_PMA_10GBT_SWAPPOL 130 /* 10GBASE-T pair swap & polarity */ #define MDIO_PMA_10GBT_TXPWR 131 /* 10GBASE-T TX power control */ #define MDIO_PMA_10GBT_SNR 133 /* 10GBASE-T SNR margin, lane A. * Lanes B-D are numbered 134-136. */ +#define MDIO_PMA_10GBR_FSRT_CSR 147 /* 10GBASE-R fast retrain status and control */ #define MDIO_PMA_10GBR_FECABLE 170 /* 10GBASE-R FEC ability */ #define MDIO_PCS_10GBX_STAT1 24 /* 10GBASE-X PCS status 1 */ #define MDIO_PCS_10GBRT_STAT1 32 /* 10GBASE-R/-T PCS status 1 */ @@ -239,6 +241,9 @@ #define MDIO_PMA_10GBR_FECABLE_ABLE 0x0001 /* FEC ability */ #define MDIO_PMA_10GBR_FECABLE_ERRABLE 0x0002 /* FEC error indic. ability */ +/* PMA 10GBASE-R Fast Retrain status and control register. */ +#define MDIO_PMA_10GBR_FSRT_ENABLE 0x0001 /* Fast retrain enable */ + /* PCS 10GBASE-R/-T status register 1. */ #define MDIO_PCS_10GBRT_STAT1_BLKLK 0x0001 /* Block lock attained */ @@ -247,6 +252,7 @@ #define MDIO_PCS_10GBRT_STAT2_BER 0x3f00 /* AN 10GBASE-T control register. */ +#define MDIO_AN_10GBT_CTRL_ADVFSRT2_5G 0x0020 /* Advertise 2.5GBASE-T fast retrain */ #define MDIO_AN_10GBT_CTRL_ADV2_5G 0x0080 /* Advertise 2.5GBASE-T */ #define MDIO_AN_10GBT_CTRL_ADV5G 0x0100 /* Advertise 5GBASE-T */ #define MDIO_AN_10GBT_CTRL_ADV10G 0x1000 /* Advertise 10GBASE-T */ @@ -289,6 +295,9 @@ #define MDIO_EEE_2_5GT 0x0001 /* 2.5GT EEE cap */ #define MDIO_EEE_5GT 0x0002 /* 5GT EEE cap */ +/* AN MultiGBASE-T AN control 2 */ +#define MDIO_AN_THP_BP2_5GT 0x0008 /* 2.5GT THP bypass request */ + /* 2.5G/5G Extended abilities register. */ #define MDIO_PMA_NG_EXTABLE_2_5GBT 0x0001 /* 2.5GBASET ability */ #define MDIO_PMA_NG_EXTABLE_5GBT 0x0002 /* 5GBASET ability */ diff --git a/net/atm/br2684.c b/net/atm/br2684.c index 11854fde52db..f666f2f98ba5 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -577,10 +577,12 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) pr_debug("vcc=%p, encaps=%d, brvcc=%p\n", atmvcc, be.encaps, brvcc); if (list_empty(&brdev->brvccs) && !brdev->mac_was_set) { unsigned char *esi = atmvcc->dev->esi; + const u8 one = 1; + if (esi[0] | esi[1] | esi[2] | esi[3] | esi[4] | esi[5]) dev_addr_set(net_dev, esi); else - net_dev->dev_addr[2] = 1; + dev_addr_mod(net_dev, 2, &one, 1); } list_add(&brvcc->brvccs, &brdev->brvccs); write_unlock_irq(&devs_lock); diff --git a/net/atm/lec.c b/net/atm/lec.c index 8eaea4a4bbd6..6257bf12e5a0 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -340,12 +340,12 @@ static int lec_close(struct net_device *dev) static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) { + static const u8 zero_addr[ETH_ALEN] = {}; unsigned long flags; struct net_device *dev = (struct net_device *)vcc->proto_data; struct lec_priv *priv = netdev_priv(dev); struct atmlec_msg *mesg; struct lec_arp_table *entry; - int i; char *tmp; /* FIXME */ WARN_ON(refcount_sub_and_test(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc)); @@ -358,8 +358,7 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) eth_hw_addr_set(dev, mesg->content.normal.mac_addr); break; case l_del_mac_addr: - for (i = 0; i < 6; i++) - dev->dev_addr[i] = 0; + eth_hw_addr_set(dev, zero_addr); break; case l_addr_delete: lec_addr_delete(priv, mesg->content.normal.atm_addr, diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index fd164a248569..133d7ea063fb 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c @@ -663,6 +663,7 @@ static struct l2cap_chan *add_peer_chan(struct l2cap_chan *chan, static int setup_netdev(struct l2cap_chan *chan, struct lowpan_btle_dev **dev) { struct net_device *netdev; + bdaddr_t addr; int err; netdev = alloc_netdev(LOWPAN_PRIV_SIZE(sizeof(struct lowpan_btle_dev)), @@ -672,7 +673,8 @@ static int setup_netdev(struct l2cap_chan *chan, struct lowpan_btle_dev **dev) return -ENOMEM; netdev->addr_assign_type = NET_ADDR_PERM; - baswap((void *)netdev->dev_addr, &chan->src); + baswap(&addr, &chan->src); + __dev_addr_set(netdev, &addr, sizeof(addr)); netdev->netdev_ops = &netdev_ops; SET_NETDEV_DEV(netdev, &chan->conn->hcon->hdev->dev); diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 72f47b372705..c9add7753b9f 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -594,7 +594,7 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) * ie. eh.h_dest is our local address. */ memcpy(s->eh.h_dest, &src, ETH_ALEN); memcpy(s->eh.h_source, &dst, ETH_ALEN); - memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN); + eth_hw_addr_set(dev, s->eh.h_dest); s->dev = dev; s->sock = sock; diff --git a/net/caif/caif_usb.c b/net/caif/caif_usb.c index b02e1292f7f1..4be6b04879a1 100644 --- a/net/caif/caif_usb.c +++ b/net/caif/caif_usb.c @@ -81,7 +81,7 @@ static void cfusbl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, layr->up->ctrlcmd(layr->up, ctrl, layr->id); } -static struct cflayer *cfusbl_create(int phyid, u8 ethaddr[ETH_ALEN], +static struct cflayer *cfusbl_create(int phyid, const u8 ethaddr[ETH_ALEN], u8 braddr[ETH_ALEN]) { struct cfusbl *this = kmalloc(sizeof(struct cfusbl), GFP_ATOMIC); diff --git a/net/can/bcm.c b/net/can/bcm.c index 508f67de0b80..bc88d901a1c0 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -625,7 +625,7 @@ static enum hrtimer_restart bcm_rx_thr_handler(struct hrtimer *hrtimer) struct bcm_op *op = container_of(hrtimer, struct bcm_op, thrtimer); if (bcm_rx_thr_flush(op)) { - hrtimer_forward(hrtimer, ktime_get(), op->kt_ival2); + hrtimer_forward_now(hrtimer, op->kt_ival2); return HRTIMER_RESTART; } else { /* rearm throttle handling */ diff --git a/net/core/devlink.c b/net/core/devlink.c index 3464854015a2..f38ef4b26f70 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -4600,8 +4600,6 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink, return -EOPNOTSUPP; param_value[i] = param_item->driverinit_value; } else { - if (!param_item->published) - continue; ctx.cmode = i; err = devlink_param_get(devlink, param, &ctx); if (err) @@ -4677,6 +4675,7 @@ static void devlink_param_notify(struct devlink *devlink, WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL && cmd != DEVLINK_CMD_PORT_PARAM_NEW && cmd != DEVLINK_CMD_PORT_PARAM_DEL); + ASSERT_DEVLINK_REGISTERED(devlink); msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) @@ -4948,7 +4947,6 @@ static int devlink_param_register_one(struct devlink *devlink, param_item->param = param; list_add_tail(¶m_item->list, param_list); - devlink_param_notify(devlink, port_index, param_item, cmd); return 0; } @@ -4962,7 +4960,6 @@ static void devlink_param_unregister_one(struct devlink *devlink, param_item = devlink_param_find_by_name(param_list, param->name); WARN_ON(!param_item); - devlink_param_notify(devlink, port_index, param_item, cmd); list_del(¶m_item->list); kfree(param_item); } @@ -9076,6 +9073,7 @@ static void devlink_notify_register(struct devlink *devlink) { struct devlink_trap_policer_item *policer_item; struct devlink_trap_group_item *group_item; + struct devlink_param_item *param_item; struct devlink_trap_item *trap_item; struct devlink_port *devlink_port; struct devlink_rate *rate_node; @@ -9102,19 +9100,24 @@ static void devlink_notify_register(struct devlink *devlink) list_for_each_entry(region, &devlink->region_list, list) devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW); - devlink_params_publish(devlink); + list_for_each_entry(param_item, &devlink->param_list, list) + devlink_param_notify(devlink, 0, param_item, + DEVLINK_CMD_PARAM_NEW); } static void devlink_notify_unregister(struct devlink *devlink) { struct devlink_trap_policer_item *policer_item; struct devlink_trap_group_item *group_item; + struct devlink_param_item *param_item; struct devlink_trap_item *trap_item; struct devlink_port *devlink_port; struct devlink_rate *rate_node; struct devlink_region *region; - devlink_params_unpublish(devlink); + list_for_each_entry_reverse(param_item, &devlink->param_list, list) + devlink_param_notify(devlink, 0, param_item, + DEVLINK_CMD_PARAM_DEL); list_for_each_entry_reverse(region, &devlink->region_list, list) devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL); @@ -10169,6 +10172,8 @@ int devlink_params_register(struct devlink *devlink, const struct devlink_param *params, size_t params_count) { + ASSERT_DEVLINK_NOT_REGISTERED(devlink); + return __devlink_params_register(devlink, 0, &devlink->param_list, params, params_count, DEVLINK_CMD_PARAM_NEW, @@ -10186,6 +10191,8 @@ void devlink_params_unregister(struct devlink *devlink, const struct devlink_param *params, size_t params_count) { + ASSERT_DEVLINK_NOT_REGISTERED(devlink); + return __devlink_params_unregister(devlink, 0, &devlink->param_list, params, params_count, DEVLINK_CMD_PARAM_DEL); @@ -10206,6 +10213,8 @@ int devlink_param_register(struct devlink *devlink, { int err; + ASSERT_DEVLINK_NOT_REGISTERED(devlink); + mutex_lock(&devlink->lock); err = __devlink_param_register_one(devlink, 0, &devlink->param_list, param, DEVLINK_CMD_PARAM_NEW); @@ -10222,6 +10231,8 @@ EXPORT_SYMBOL_GPL(devlink_param_register); void devlink_param_unregister(struct devlink *devlink, const struct devlink_param *param) { + ASSERT_DEVLINK_NOT_REGISTERED(devlink); + mutex_lock(&devlink->lock); devlink_param_unregister_one(devlink, 0, &devlink->param_list, param, DEVLINK_CMD_PARAM_DEL); @@ -10230,51 +10241,6 @@ void devlink_param_unregister(struct devlink *devlink, EXPORT_SYMBOL_GPL(devlink_param_unregister); /** - * devlink_params_publish - publish configuration parameters - * - * @devlink: devlink - * - * Publish previously registered configuration parameters. - */ -void devlink_params_publish(struct devlink *devlink) -{ - struct devlink_param_item *param_item; - - if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED)) - return; - - list_for_each_entry(param_item, &devlink->param_list, list) { - if (param_item->published) - continue; - param_item->published = true; - devlink_param_notify(devlink, 0, param_item, - DEVLINK_CMD_PARAM_NEW); - } -} -EXPORT_SYMBOL_GPL(devlink_params_publish); - -/** - * devlink_params_unpublish - unpublish configuration parameters - * - * @devlink: devlink - * - * Unpublish previously registered configuration parameters. - */ -void devlink_params_unpublish(struct devlink *devlink) -{ - struct devlink_param_item *param_item; - - list_for_each_entry(param_item, &devlink->param_list, list) { - if (!param_item->published) - continue; - param_item->published = false; - devlink_param_notify(devlink, 0, param_item, - DEVLINK_CMD_PARAM_DEL); - } -} -EXPORT_SYMBOL_GPL(devlink_params_unpublish); - -/** * devlink_param_driverinit_value_get - get configuration parameter * value for driver initializing * @@ -10328,6 +10294,8 @@ int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id, { struct devlink_param_item *param_item; + ASSERT_DEVLINK_NOT_REGISTERED(devlink); + param_item = devlink_param_find_by_id(&devlink->param_list, param_id); if (!param_item) return -EINVAL; @@ -10341,8 +10309,6 @@ int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id, else param_item->driverinit_value = init_val; param_item->driverinit_value_valid = true; - - devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW); return 0; } EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_set); @@ -10788,8 +10754,7 @@ devlink_trap_group_notify(struct devlink *devlink, WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_GROUP_NEW && cmd != DEVLINK_CMD_TRAP_GROUP_DEL); - if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED)) - return; + ASSERT_DEVLINK_REGISTERED(devlink); msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) @@ -11116,9 +11081,6 @@ devlink_trap_group_register(struct devlink *devlink, } list_add_tail(&group_item->list, &devlink->trap_group_list); - devlink_trap_group_notify(devlink, group_item, - DEVLINK_CMD_TRAP_GROUP_NEW); - return 0; err_group_init: @@ -11139,8 +11101,6 @@ devlink_trap_group_unregister(struct devlink *devlink, if (WARN_ON_ONCE(!group_item)) return; - devlink_trap_group_notify(devlink, group_item, - DEVLINK_CMD_TRAP_GROUP_DEL); list_del(&group_item->list); free_percpu(group_item->stats); kfree(group_item); @@ -11160,6 +11120,8 @@ int devlink_trap_groups_register(struct devlink *devlink, { int i, err; + ASSERT_DEVLINK_NOT_REGISTERED(devlink); + mutex_lock(&devlink->lock); for (i = 0; i < groups_count; i++) { const struct devlink_trap_group *group = &groups[i]; @@ -11197,6 +11159,8 @@ void devlink_trap_groups_unregister(struct devlink *devlink, { int i; + ASSERT_DEVLINK_NOT_REGISTERED(devlink); + mutex_lock(&devlink->lock); for (i = groups_count - 1; i >= 0; i--) devlink_trap_group_unregister(devlink, &groups[i]); @@ -11214,8 +11178,7 @@ devlink_trap_policer_notify(struct devlink *devlink, WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_POLICER_NEW && cmd != DEVLINK_CMD_TRAP_POLICER_DEL); - if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED)) - return; + ASSERT_DEVLINK_REGISTERED(devlink); msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) @@ -11257,9 +11220,6 @@ devlink_trap_policer_register(struct devlink *devlink, } list_add_tail(&policer_item->list, &devlink->trap_policer_list); - devlink_trap_policer_notify(devlink, policer_item, - DEVLINK_CMD_TRAP_POLICER_NEW); - return 0; err_policer_init: @@ -11277,8 +11237,6 @@ devlink_trap_policer_unregister(struct devlink *devlink, if (WARN_ON_ONCE(!policer_item)) return; - devlink_trap_policer_notify(devlink, policer_item, - DEVLINK_CMD_TRAP_POLICER_DEL); list_del(&policer_item->list); if (devlink->ops->trap_policer_fini) devlink->ops->trap_policer_fini(devlink, policer); @@ -11300,6 +11258,8 @@ devlink_trap_policers_register(struct devlink *devlink, { int i, err; + ASSERT_DEVLINK_NOT_REGISTERED(devlink); + mutex_lock(&devlink->lock); for (i = 0; i < policers_count; i++) { const struct devlink_trap_policer *policer = &policers[i]; @@ -11341,6 +11301,8 @@ devlink_trap_policers_unregister(struct devlink *devlink, { int i; + ASSERT_DEVLINK_NOT_REGISTERED(devlink); + mutex_lock(&devlink->lock); for (i = policers_count - 1; i >= 0; i--) devlink_trap_policer_unregister(devlink, &policers[i]); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 79477dcae7c2..2af8aeeadadf 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -3204,8 +3204,8 @@ struct net_device *rtnl_create_link(struct net *net, const char *ifname, dev->mtu = mtu; } if (tb[IFLA_ADDRESS]) { - memcpy(dev->dev_addr, nla_data(tb[IFLA_ADDRESS]), - nla_len(tb[IFLA_ADDRESS])); + __dev_addr_set(dev, nla_data(tb[IFLA_ADDRESS]), + nla_len(tb[IFLA_ADDRESS])); dev->addr_assign_type = NET_ADDR_SET; } if (tb[IFLA_BROADCAST]) diff --git a/net/core/selftests.c b/net/core/selftests.c index 9077fa969892..acb1ee97bbd3 100644 --- a/net/core/selftests.c +++ b/net/core/selftests.c @@ -15,8 +15,8 @@ #include <net/udp.h> struct net_packet_attrs { - unsigned char *src; - unsigned char *dst; + const unsigned char *src; + const unsigned char *dst; u32 ip_src; u32 ip_dst; bool tcp; @@ -173,8 +173,8 @@ static int net_test_loopback_validate(struct sk_buff *skb, struct net_device *orig_ndev) { struct net_test_priv *tpriv = pt->af_packet_priv; - unsigned char *src = tpriv->packet->src; - unsigned char *dst = tpriv->packet->dst; + const unsigned char *src = tpriv->packet->src; + const unsigned char *dst = tpriv->packet->dst; struct netsfhdr *shdr; struct ethhdr *ehdr; struct udphdr *uhdr; diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index f5270114dcb8..826957b6442b 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -433,6 +433,7 @@ static int dsa_port_setup(struct dsa_port *dp) if (dp->setup) return 0; + mutex_init(&dp->addr_lists_lock); INIT_LIST_HEAD(&dp->fdbs); INIT_LIST_HEAD(&dp->mdbs); diff --git a/net/dsa/port.c b/net/dsa/port.c index bf671306b560..c0e630f7f0bd 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -380,6 +380,8 @@ void dsa_port_pre_bridge_leave(struct dsa_port *dp, struct net_device *br) switchdev_bridge_port_unoffload(brport_dev, dp, &dsa_slave_switchdev_notifier, &dsa_slave_switchdev_blocking_notifier); + + dsa_flush_workqueue(); } void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br) diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 9d9fef668eba..dbda0e0fbffa 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -2413,7 +2413,6 @@ static void dsa_slave_switchdev_event_work(struct work_struct *work) dp = dsa_to_port(ds, switchdev_work->port); - rtnl_lock(); switch (switchdev_work->event) { case SWITCHDEV_FDB_ADD_TO_DEVICE: if (switchdev_work->host_addr) @@ -2448,9 +2447,7 @@ static void dsa_slave_switchdev_event_work(struct work_struct *work) break; } - rtnl_unlock(); - dev_put(switchdev_work->dev); kfree(switchdev_work); } @@ -2523,8 +2520,6 @@ static int dsa_slave_fdb_event(struct net_device *dev, switchdev_work->vid = fdb_info->vid; switchdev_work->host_addr = host_addr; - /* Hold a reference for dsa_fdb_offload_notify */ - dev_hold(dev); dsa_schedule_work(&switchdev_work->work); return 0; diff --git a/net/dsa/switch.c b/net/dsa/switch.c index 2b1b21bde830..bb155a16d454 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c @@ -215,26 +215,30 @@ static int dsa_port_do_mdb_add(struct dsa_port *dp, struct dsa_switch *ds = dp->ds; struct dsa_mac_addr *a; int port = dp->index; - int err; + int err = 0; /* No need to bother with refcounting for user ports */ if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) return ds->ops->port_mdb_add(ds, port, mdb); + mutex_lock(&dp->addr_lists_lock); + a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid); if (a) { refcount_inc(&a->refcount); - return 0; + goto out; } a = kzalloc(sizeof(*a), GFP_KERNEL); - if (!a) - return -ENOMEM; + if (!a) { + err = -ENOMEM; + goto out; + } err = ds->ops->port_mdb_add(ds, port, mdb); if (err) { kfree(a); - return err; + goto out; } ether_addr_copy(a->addr, mdb->addr); @@ -242,7 +246,10 @@ static int dsa_port_do_mdb_add(struct dsa_port *dp, refcount_set(&a->refcount, 1); list_add_tail(&a->list, &dp->mdbs); - return 0; +out: + mutex_unlock(&dp->addr_lists_lock); + + return err; } static int dsa_port_do_mdb_del(struct dsa_port *dp, @@ -251,29 +258,36 @@ static int dsa_port_do_mdb_del(struct dsa_port *dp, struct dsa_switch *ds = dp->ds; struct dsa_mac_addr *a; int port = dp->index; - int err; + int err = 0; /* No need to bother with refcounting for user ports */ if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) return ds->ops->port_mdb_del(ds, port, mdb); + mutex_lock(&dp->addr_lists_lock); + a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid); - if (!a) - return -ENOENT; + if (!a) { + err = -ENOENT; + goto out; + } if (!refcount_dec_and_test(&a->refcount)) - return 0; + goto out; err = ds->ops->port_mdb_del(ds, port, mdb); if (err) { - refcount_inc(&a->refcount); - return err; + refcount_set(&a->refcount, 1); + goto out; } list_del(&a->list); kfree(a); - return 0; +out: + mutex_unlock(&dp->addr_lists_lock); + + return err; } static int dsa_port_do_fdb_add(struct dsa_port *dp, const unsigned char *addr, @@ -282,26 +296,30 @@ static int dsa_port_do_fdb_add(struct dsa_port *dp, const unsigned char *addr, struct dsa_switch *ds = dp->ds; struct dsa_mac_addr *a; int port = dp->index; - int err; + int err = 0; /* No need to bother with refcounting for user ports */ if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) return ds->ops->port_fdb_add(ds, port, addr, vid); + mutex_lock(&dp->addr_lists_lock); + a = dsa_mac_addr_find(&dp->fdbs, addr, vid); if (a) { refcount_inc(&a->refcount); - return 0; + goto out; } a = kzalloc(sizeof(*a), GFP_KERNEL); - if (!a) - return -ENOMEM; + if (!a) { + err = -ENOMEM; + goto out; + } err = ds->ops->port_fdb_add(ds, port, addr, vid); if (err) { kfree(a); - return err; + goto out; } ether_addr_copy(a->addr, addr); @@ -309,7 +327,10 @@ static int dsa_port_do_fdb_add(struct dsa_port *dp, const unsigned char *addr, refcount_set(&a->refcount, 1); list_add_tail(&a->list, &dp->fdbs); - return 0; +out: + mutex_unlock(&dp->addr_lists_lock); + + return err; } static int dsa_port_do_fdb_del(struct dsa_port *dp, const unsigned char *addr, @@ -318,29 +339,36 @@ static int dsa_port_do_fdb_del(struct dsa_port *dp, const unsigned char *addr, struct dsa_switch *ds = dp->ds; struct dsa_mac_addr *a; int port = dp->index; - int err; + int err = 0; /* No need to bother with refcounting for user ports */ if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) return ds->ops->port_fdb_del(ds, port, addr, vid); + mutex_lock(&dp->addr_lists_lock); + a = dsa_mac_addr_find(&dp->fdbs, addr, vid); - if (!a) - return -ENOENT; + if (!a) { + err = -ENOENT; + goto out; + } if (!refcount_dec_and_test(&a->refcount)) - return 0; + goto out; err = ds->ops->port_fdb_del(ds, port, addr, vid); if (err) { - refcount_inc(&a->refcount); - return err; + refcount_set(&a->refcount, 1); + goto out; } list_del(&a->list); kfree(a); - return 0; +out: + mutex_unlock(&dp->addr_lists_lock); + + return err; } static int dsa_switch_host_fdb_add(struct dsa_switch *ds, diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index bf6e8c2f9bf7..44430b6ab843 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -336,7 +336,7 @@ EXPORT_SYMBOL(ethtool_intersect_link_masks); void ethtool_convert_legacy_u32_to_link_mode(unsigned long *dst, u32 legacy_u32) { - bitmap_zero(dst, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(dst); dst[0] = legacy_u32; } EXPORT_SYMBOL(ethtool_convert_legacy_u32_to_link_mode); @@ -351,11 +351,10 @@ bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32, if (__ETHTOOL_LINK_MODE_MASK_NBITS > 32) { __ETHTOOL_DECLARE_LINK_MODE_MASK(ext); - bitmap_zero(ext, __ETHTOOL_LINK_MODE_MASK_NBITS); + linkmode_zero(ext); bitmap_fill(ext, 32); bitmap_complement(ext, ext, __ETHTOOL_LINK_MODE_MASK_NBITS); - if (bitmap_intersects(ext, src, - __ETHTOOL_LINK_MODE_MASK_NBITS)) { + if (linkmode_intersects(ext, src)) { /* src mask goes beyond bit 31 */ retval = false; } diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c index e00fbb16391f..737e4f17e1c6 100644 --- a/net/hsr/hsr_device.c +++ b/net/hsr/hsr_device.c @@ -309,9 +309,9 @@ static void send_hsr_supervision_frame(struct hsr_port *master, } spin_unlock_irqrestore(&master->hsr->seqnr_lock, irqflags); - hsr_stag->HSR_TLV_type = type; + hsr_stag->tlv.HSR_TLV_type = type; /* TODO: Why 12 in HSRv0? */ - hsr_stag->HSR_TLV_length = hsr->prot_version ? + hsr_stag->tlv.HSR_TLV_length = hsr->prot_version ? sizeof(struct hsr_sup_payload) : 12; /* Payload: MacAddressA */ @@ -350,8 +350,8 @@ static void send_prp_supervision_frame(struct hsr_port *master, spin_lock_irqsave(&master->hsr->seqnr_lock, irqflags); hsr_stag->sequence_nr = htons(hsr->sup_sequence_nr); hsr->sup_sequence_nr++; - hsr_stag->HSR_TLV_type = PRP_TLV_LIFE_CHECK_DD; - hsr_stag->HSR_TLV_length = sizeof(struct hsr_sup_payload); + hsr_stag->tlv.HSR_TLV_type = PRP_TLV_LIFE_CHECK_DD; + hsr_stag->tlv.HSR_TLV_length = sizeof(struct hsr_sup_payload); /* Payload: MacAddressA */ hsr_sp = skb_put(skb, sizeof(struct hsr_sup_payload)); diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c index ceb8afb2a62f..e59cbb4f0cd1 100644 --- a/net/hsr/hsr_forward.c +++ b/net/hsr/hsr_forward.c @@ -37,6 +37,8 @@ static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb) struct ethhdr *eth_hdr; struct hsr_sup_tag *hsr_sup_tag; struct hsrv1_ethhdr_sp *hsr_V1_hdr; + struct hsr_sup_tlv *hsr_sup_tlv; + u16 total_length = 0; WARN_ON_ONCE(!skb_mac_header_was_set(skb)); eth_hdr = (struct ethhdr *)skb_mac_header(skb); @@ -53,23 +55,63 @@ static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb) /* Get the supervision header from correct location. */ if (eth_hdr->h_proto == htons(ETH_P_HSR)) { /* Okay HSRv1. */ + total_length = sizeof(struct hsrv1_ethhdr_sp); + if (!pskb_may_pull(skb, total_length)) + return false; + hsr_V1_hdr = (struct hsrv1_ethhdr_sp *)skb_mac_header(skb); if (hsr_V1_hdr->hsr.encap_proto != htons(ETH_P_PRP)) return false; hsr_sup_tag = &hsr_V1_hdr->hsr_sup; } else { + total_length = sizeof(struct hsrv0_ethhdr_sp); + if (!pskb_may_pull(skb, total_length)) + return false; + hsr_sup_tag = &((struct hsrv0_ethhdr_sp *)skb_mac_header(skb))->hsr_sup; } - if (hsr_sup_tag->HSR_TLV_type != HSR_TLV_ANNOUNCE && - hsr_sup_tag->HSR_TLV_type != HSR_TLV_LIFE_CHECK && - hsr_sup_tag->HSR_TLV_type != PRP_TLV_LIFE_CHECK_DD && - hsr_sup_tag->HSR_TLV_type != PRP_TLV_LIFE_CHECK_DA) + if (hsr_sup_tag->tlv.HSR_TLV_type != HSR_TLV_ANNOUNCE && + hsr_sup_tag->tlv.HSR_TLV_type != HSR_TLV_LIFE_CHECK && + hsr_sup_tag->tlv.HSR_TLV_type != PRP_TLV_LIFE_CHECK_DD && + hsr_sup_tag->tlv.HSR_TLV_type != PRP_TLV_LIFE_CHECK_DA) return false; - if (hsr_sup_tag->HSR_TLV_length != 12 && - hsr_sup_tag->HSR_TLV_length != sizeof(struct hsr_sup_payload)) + if (hsr_sup_tag->tlv.HSR_TLV_length != 12 && + hsr_sup_tag->tlv.HSR_TLV_length != sizeof(struct hsr_sup_payload)) + return false; + + /* Get next tlv */ + total_length += sizeof(struct hsr_sup_tlv) + hsr_sup_tag->tlv.HSR_TLV_length; + if (!pskb_may_pull(skb, total_length)) + return false; + skb_pull(skb, total_length); + hsr_sup_tlv = (struct hsr_sup_tlv *)skb->data; + skb_push(skb, total_length); + + /* if this is a redbox supervision frame we need to verify + * that more data is available + */ + if (hsr_sup_tlv->HSR_TLV_type == PRP_TLV_REDBOX_MAC) { + /* tlv length must be a length of a mac address */ + if (hsr_sup_tlv->HSR_TLV_length != sizeof(struct hsr_sup_payload)) + return false; + + /* make sure another tlv follows */ + total_length += sizeof(struct hsr_sup_tlv) + hsr_sup_tlv->HSR_TLV_length; + if (!pskb_may_pull(skb, total_length)) + return false; + + /* get next tlv */ + skb_pull(skb, total_length); + hsr_sup_tlv = (struct hsr_sup_tlv *)skb->data; + skb_push(skb, total_length); + } + + /* end of tlvs must follow at the end */ + if (hsr_sup_tlv->HSR_TLV_type == HSR_TLV_EOT && + hsr_sup_tlv->HSR_TLV_length != 0) return false; return true; diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c index e31949479305..0775f0f95dbf 100644 --- a/net/hsr/hsr_framereg.c +++ b/net/hsr/hsr_framereg.c @@ -76,8 +76,8 @@ static struct hsr_node *find_node_by_addr_A(struct list_head *node_db, * frames from self that's been looped over the HSR ring. */ int hsr_create_self_node(struct hsr_priv *hsr, - unsigned char addr_a[ETH_ALEN], - unsigned char addr_b[ETH_ALEN]) + const unsigned char addr_a[ETH_ALEN], + const unsigned char addr_b[ETH_ALEN]) { struct list_head *self_node_db = &hsr->self_node_db; struct hsr_node *node, *oldnode; @@ -265,11 +265,14 @@ void hsr_handle_sup_frame(struct hsr_frame_info *frame) struct hsr_port *port_rcv = frame->port_rcv; struct hsr_priv *hsr = port_rcv->hsr; struct hsr_sup_payload *hsr_sp; + struct hsr_sup_tlv *hsr_sup_tlv; struct hsr_node *node_real; struct sk_buff *skb = NULL; struct list_head *node_db; struct ethhdr *ethhdr; int i; + unsigned int pull_size = 0; + unsigned int total_pull_size = 0; /* Here either frame->skb_hsr or frame->skb_prp should be * valid as supervision frame always will have protocol @@ -284,18 +287,26 @@ void hsr_handle_sup_frame(struct hsr_frame_info *frame) if (!skb) return; - ethhdr = (struct ethhdr *)skb_mac_header(skb); - /* Leave the ethernet header. */ - skb_pull(skb, sizeof(struct ethhdr)); + pull_size = sizeof(struct ethhdr); + skb_pull(skb, pull_size); + total_pull_size += pull_size; + + ethhdr = (struct ethhdr *)skb_mac_header(skb); /* And leave the HSR tag. */ - if (ethhdr->h_proto == htons(ETH_P_HSR)) - skb_pull(skb, sizeof(struct hsr_tag)); + if (ethhdr->h_proto == htons(ETH_P_HSR)) { + pull_size = sizeof(struct ethhdr); + skb_pull(skb, pull_size); + total_pull_size += pull_size; + } /* And leave the HSR sup tag. */ - skb_pull(skb, sizeof(struct hsr_sup_tag)); + pull_size = sizeof(struct hsr_tag); + skb_pull(skb, pull_size); + total_pull_size += pull_size; + /* get HSR sup payload */ hsr_sp = (struct hsr_sup_payload *)skb->data; /* Merge node_curr (registered on macaddress_B) into node_real */ @@ -312,6 +323,37 @@ void hsr_handle_sup_frame(struct hsr_frame_info *frame) /* Node has already been merged */ goto done; + /* Leave the first HSR sup payload. */ + pull_size = sizeof(struct hsr_sup_payload); + skb_pull(skb, pull_size); + total_pull_size += pull_size; + + /* Get second supervision tlv */ + hsr_sup_tlv = (struct hsr_sup_tlv *)skb->data; + /* And check if it is a redbox mac TLV */ + if (hsr_sup_tlv->HSR_TLV_type == PRP_TLV_REDBOX_MAC) { + /* We could stop here after pushing hsr_sup_payload, + * or proceed and allow macaddress_B and for redboxes. + */ + /* Sanity check length */ + if (hsr_sup_tlv->HSR_TLV_length != 6) + goto done; + + /* Leave the second HSR sup tlv. */ + pull_size = sizeof(struct hsr_sup_tlv); + skb_pull(skb, pull_size); + total_pull_size += pull_size; + + /* Get redbox mac address. */ + hsr_sp = (struct hsr_sup_payload *)skb->data; + + /* Check if redbox mac and node mac are equal. */ + if (!ether_addr_equal(node_real->macaddress_A, hsr_sp->macaddress_A)) { + /* This is a redbox supervision frame for a VDAN! */ + goto done; + } + } + ether_addr_copy(node_real->macaddress_B, ethhdr->h_source); for (i = 0; i < HSR_PT_PORTS; i++) { if (!node_curr->time_in_stale[i] && @@ -331,11 +373,8 @@ void hsr_handle_sup_frame(struct hsr_frame_info *frame) kfree_rcu(node_curr, rcu_head); done: - /* PRP uses v0 header */ - if (ethhdr->h_proto == htons(ETH_P_HSR)) - skb_push(skb, sizeof(struct hsrv1_ethhdr_sp)); - else - skb_push(skb, sizeof(struct hsrv0_ethhdr_sp)); + /* Push back here */ + skb_push(skb, total_pull_size); } /* 'skb' is a frame meant for this host, that is to be passed to upper layers. diff --git a/net/hsr/hsr_framereg.h b/net/hsr/hsr_framereg.h index d9628e7a5f05..bdbb8c822ba1 100644 --- a/net/hsr/hsr_framereg.h +++ b/net/hsr/hsr_framereg.h @@ -48,8 +48,8 @@ int hsr_register_frame_out(struct hsr_port *port, struct hsr_node *node, void hsr_prune_nodes(struct timer_list *t); int hsr_create_self_node(struct hsr_priv *hsr, - unsigned char addr_a[ETH_ALEN], - unsigned char addr_b[ETH_ALEN]); + const unsigned char addr_a[ETH_ALEN], + const unsigned char addr_b[ETH_ALEN]); void *hsr_get_next_node(struct hsr_priv *hsr, void *_pos, unsigned char addr[ETH_ALEN]); diff --git a/net/hsr/hsr_main.h b/net/hsr/hsr_main.h index 53d1f7a82463..043e4e9a1694 100644 --- a/net/hsr/hsr_main.h +++ b/net/hsr/hsr_main.h @@ -35,13 +35,15 @@ * HSR_NODE_FORGET_TIME? */ #define PRUNE_PERIOD 3000 /* ms */ - +#define HSR_TLV_EOT 0 /* End of TLVs */ #define HSR_TLV_ANNOUNCE 22 #define HSR_TLV_LIFE_CHECK 23 /* PRP V1 life check for Duplicate discard */ #define PRP_TLV_LIFE_CHECK_DD 20 /* PRP V1 life check for Duplicate Accept */ #define PRP_TLV_LIFE_CHECK_DA 21 +/* PRP V1 life redundancy box MAC address */ +#define PRP_TLV_REDBOX_MAC 30 /* HSR Tag. * As defined in IEC-62439-3:2010, the HSR tag is really { ethertype = 0x88FB, @@ -94,14 +96,18 @@ struct hsr_vlan_ethhdr { struct hsr_tag hsr_tag; } __packed; +struct hsr_sup_tlv { + u8 HSR_TLV_type; + u8 HSR_TLV_length; +}; + /* HSR/PRP Supervision Frame data types. * Field names as defined in the IEC:2010 standard for HSR. */ struct hsr_sup_tag { - __be16 path_and_HSR_ver; - __be16 sequence_nr; - __u8 HSR_TLV_type; - __u8 HSR_TLV_length; + __be16 path_and_HSR_ver; + __be16 sequence_nr; + struct hsr_sup_tlv tlv; } __packed; struct hsr_sup_payload { diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index b297bb28556e..38d29b175ca6 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -886,6 +886,8 @@ static int compat_ip_mcast_join_leave(struct sock *sk, int optname, return ip_mc_leave_group(sk, &mreq); } +DEFINE_STATIC_KEY_FALSE(ip4_min_ttl); + static int do_ip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, unsigned int optlen) { @@ -1352,7 +1354,14 @@ static int do_ip_setsockopt(struct sock *sk, int level, int optname, goto e_inval; if (val < 0 || val > 255) goto e_inval; - inet->min_ttl = val; + + if (val) + static_branch_enable(&ip4_min_ttl); + + /* tcp_v4_err() and tcp_v4_rcv() might read min_ttl + * while we are changint it. + */ + WRITE_ONCE(inet->min_ttl, val); break; default: diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index c2d9830136d2..d0b848ff5c0f 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -856,18 +856,15 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, } EXPORT_SYMBOL(tcp_splice_read); -struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp, - bool force_schedule) +struct sk_buff *tcp_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp, + bool force_schedule) { struct sk_buff *skb; - /* The TCP header must be at least 32-bit aligned. */ - size = ALIGN(size, 4); - if (unlikely(tcp_under_memory_pressure(sk))) sk_mem_reclaim_partial(sk); - skb = alloc_skb_fclone(size + sk->sk_prot->max_header, gfp); + skb = alloc_skb_fclone(size + MAX_TCP_HEADER, gfp); if (likely(skb)) { bool mem_scheduled; @@ -878,7 +875,7 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp, mem_scheduled = sk_wmem_schedule(sk, skb->truesize); } if (likely(mem_scheduled)) { - skb_reserve(skb, sk->sk_prot->max_header); + skb_reserve(skb, MAX_TCP_HEADER); /* * Make sure that we have exactly size bytes * available to the caller, no more, no less. @@ -938,7 +935,7 @@ int tcp_send_mss(struct sock *sk, int *size_goal, int flags) */ void tcp_remove_empty_skb(struct sock *sk, struct sk_buff *skb) { - if (skb && !skb->len) { + if (skb && TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) { tcp_unlink_write_queue(skb, sk); if (tcp_write_queue_empty(sk)) tcp_chrono_stop(sk, TCP_CHRONO_BUSY); @@ -960,8 +957,8 @@ new_segment: if (!sk_stream_memory_free(sk)) return NULL; - skb = sk_stream_alloc_skb(sk, 0, sk->sk_allocation, - tcp_rtx_and_write_queues_empty(sk)); + skb = tcp_stream_alloc_skb(sk, 0, sk->sk_allocation, + tcp_rtx_and_write_queues_empty(sk)); if (!skb) return NULL; @@ -1289,8 +1286,8 @@ new_segment: goto restart; } first_skb = tcp_rtx_and_write_queues_empty(sk); - skb = sk_stream_alloc_skb(sk, 0, sk->sk_allocation, - first_skb); + skb = tcp_stream_alloc_skb(sk, 0, sk->sk_allocation, + first_skb); if (!skb) goto wait_for_space; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 5e6d8cb82ce5..13d868c43284 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -508,9 +508,12 @@ int tcp_v4_err(struct sk_buff *skb, u32 info) if (sk->sk_state == TCP_CLOSE) goto out; - if (unlikely(iph->ttl < inet_sk(sk)->min_ttl)) { - __NET_INC_STATS(net, LINUX_MIB_TCPMINTTLDROP); - goto out; + if (static_branch_unlikely(&ip4_min_ttl)) { + /* min_ttl can be changed concurrently from do_ip_setsockopt() */ + if (unlikely(iph->ttl < READ_ONCE(inet_sk(sk)->min_ttl))) { + __NET_INC_STATS(net, LINUX_MIB_TCPMINTTLDROP); + goto out; + } } tp = tcp_sk(sk); @@ -1703,7 +1706,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) sock_rps_save_rxhash(sk, skb); sk_mark_napi_id(sk, skb); if (dst) { - if (inet_sk(sk)->rx_dst_ifindex != skb->skb_iif || + if (sk->sk_rx_dst_ifindex != skb->skb_iif || !INDIRECT_CALL_1(dst->ops->check, ipv4_dst_check, dst, 0)) { dst_release(dst); @@ -1788,7 +1791,7 @@ int tcp_v4_early_demux(struct sk_buff *skb) if (dst) dst = dst_check(dst, 0); if (dst && - inet_sk(sk)->rx_dst_ifindex == skb->skb_iif) + sk->sk_rx_dst_ifindex == skb->skb_iif) skb_dst_set_noref(skb, dst); } } @@ -2068,9 +2071,13 @@ process: return 0; } } - if (unlikely(iph->ttl < inet_sk(sk)->min_ttl)) { - __NET_INC_STATS(net, LINUX_MIB_TCPMINTTLDROP); - goto discard_and_relse; + + if (static_branch_unlikely(&ip4_min_ttl)) { + /* min_ttl can be changed concurrently from do_ip_setsockopt() */ + if (unlikely(iph->ttl < READ_ONCE(inet_sk(sk)->min_ttl))) { + __NET_INC_STATS(net, LINUX_MIB_TCPMINTTLDROP); + goto discard_and_relse; + } } if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) @@ -2195,7 +2202,7 @@ void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) if (dst && dst_hold_safe(dst)) { sk->sk_rx_dst = dst; - inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; + sk->sk_rx_dst_ifindex = skb->skb_iif; } } EXPORT_SYMBOL(inet_sk_rx_dst_set); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 3a01e5593a17..c0c55a8be8f7 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1564,7 +1564,7 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue, return -ENOMEM; /* Get a new skb... force flag on. */ - buff = sk_stream_alloc_skb(sk, nsize, gfp, true); + buff = tcp_stream_alloc_skb(sk, nsize, gfp, true); if (!buff) return -ENOMEM; /* We'll just try again later. */ skb_copy_decrypted(buff, skb); @@ -2121,7 +2121,7 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len, return tcp_fragment(sk, TCP_FRAG_IN_WRITE_QUEUE, skb, len, mss_now, gfp); - buff = sk_stream_alloc_skb(sk, 0, gfp, true); + buff = tcp_stream_alloc_skb(sk, 0, gfp, true); if (unlikely(!buff)) return -ENOMEM; skb_copy_decrypted(buff, skb); @@ -2388,7 +2388,7 @@ static int tcp_mtu_probe(struct sock *sk) return -1; /* We're allowed to probe. Build it now. */ - nskb = sk_stream_alloc_skb(sk, probe_size, GFP_ATOMIC, false); + nskb = tcp_stream_alloc_skb(sk, probe_size, GFP_ATOMIC, false); if (!nskb) return -1; sk_wmem_queued_add(sk, nskb->truesize); @@ -3754,7 +3754,7 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn) /* limit to order-0 allocations */ space = min_t(size_t, space, SKB_MAX_HEAD(MAX_TCP_HEADER)); - syn_data = sk_stream_alloc_skb(sk, space, sk->sk_allocation, false); + syn_data = tcp_stream_alloc_skb(sk, space, sk->sk_allocation, false); if (!syn_data) goto fallback; syn_data->ip_summed = CHECKSUM_PARTIAL; @@ -3835,7 +3835,7 @@ int tcp_connect(struct sock *sk) return 0; } - buff = sk_stream_alloc_skb(sk, 0, sk->sk_allocation, true); + buff = tcp_stream_alloc_skb(sk, 0, sk->sk_allocation, true); if (unlikely(!buff)) return -ENOBUFS; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index d4fae16deec4..9e1463a2acae 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3110,6 +3110,9 @@ static void add_v4_addrs(struct inet6_dev *idev) memcpy(&addr.s6_addr32[3], idev->dev->dev_addr + offset, 4); if (idev->dev->flags&IFF_POINTOPOINT) { + if (idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_NONE) + return; + addr.s6_addr32[0] = htonl(0xfe800000); scope = IFA_LINK; plen = 64; diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index e4bdb09c5586..41efca817db4 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -55,6 +55,8 @@ struct ip6_ra_chain *ip6_ra_chain; DEFINE_RWLOCK(ip6_ra_lock); +DEFINE_STATIC_KEY_FALSE(ip6_min_hopcount); + int ip6_ra_control(struct sock *sk, int sel) { struct ip6_ra_chain *ra, *new_ra, **rap; @@ -950,7 +952,14 @@ done: goto e_inval; if (val < 0 || val > 255) goto e_inval; - np->min_hopcount = val; + + if (val) + static_branch_enable(&ip6_min_hopcount); + + /* tcp_v6_err() and tcp_v6_rcv() might read min_hopcount + * while we are changing it. + */ + WRITE_ONCE(np->min_hopcount, val); retv = 0; break; case IPV6_DONTFRAG: diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 1ef27cd7dbff..c678e778c1fb 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -108,8 +108,8 @@ static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) const struct rt6_info *rt = (const struct rt6_info *)dst; sk->sk_rx_dst = dst; - inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; - tcp_inet6_sk(sk)->rx_dst_cookie = rt6_get_cookie(rt); + sk->sk_rx_dst_ifindex = skb->skb_iif; + sk->sk_rx_dst_cookie = rt6_get_cookie(rt); } } @@ -414,9 +414,12 @@ static int tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (sk->sk_state == TCP_CLOSE) goto out; - if (ipv6_hdr(skb)->hop_limit < tcp_inet6_sk(sk)->min_hopcount) { - __NET_INC_STATS(net, LINUX_MIB_TCPMINTTLDROP); - goto out; + if (static_branch_unlikely(&ip6_min_hopcount)) { + /* min_hopcount can be changed concurrently from do_ipv6_setsockopt() */ + if (ipv6_hdr(skb)->hop_limit < READ_ONCE(tcp_inet6_sk(sk)->min_hopcount)) { + __NET_INC_STATS(net, LINUX_MIB_TCPMINTTLDROP); + goto out; + } } tp = tcp_sk(sk); @@ -569,7 +572,7 @@ done: static void tcp_v6_reqsk_destructor(struct request_sock *req) { kfree(inet_rsk(req)->ipv6_opt); - kfree_skb(inet_rsk(req)->pktopts); + consume_skb(inet_rsk(req)->pktopts); } #ifdef CONFIG_TCP_MD5SIG @@ -1509,9 +1512,9 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) sock_rps_save_rxhash(sk, skb); sk_mark_napi_id(sk, skb); if (dst) { - if (inet_sk(sk)->rx_dst_ifindex != skb->skb_iif || + if (sk->sk_rx_dst_ifindex != skb->skb_iif || INDIRECT_CALL_1(dst->ops->check, ip6_dst_check, - dst, np->rx_dst_cookie) == NULL) { + dst, sk->sk_rx_dst_cookie) == NULL) { dst_release(dst); sk->sk_rx_dst = NULL; } @@ -1591,7 +1594,7 @@ ipv6_pktoptions: } } - kfree_skb(opt_skb); + consume_skb(opt_skb); return 0; } @@ -1726,9 +1729,13 @@ process: return 0; } } - if (hdr->hop_limit < tcp_inet6_sk(sk)->min_hopcount) { - __NET_INC_STATS(net, LINUX_MIB_TCPMINTTLDROP); - goto discard_and_relse; + + if (static_branch_unlikely(&ip6_min_hopcount)) { + /* min_hopcount can be changed concurrently from do_ipv6_setsockopt() */ + if (hdr->hop_limit < READ_ONCE(tcp_inet6_sk(sk)->min_hopcount)) { + __NET_INC_STATS(net, LINUX_MIB_TCPMINTTLDROP); + goto discard_and_relse; + } } if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) @@ -1872,9 +1879,9 @@ INDIRECT_CALLABLE_SCOPE void tcp_v6_early_demux(struct sk_buff *skb) struct dst_entry *dst = READ_ONCE(sk->sk_rx_dst); if (dst) - dst = dst_check(dst, tcp_inet6_sk(sk)->rx_dst_cookie); + dst = dst_check(dst, sk->sk_rx_dst_cookie); if (dst && - inet_sk(sk)->rx_dst_ifindex == skb->skb_iif) + sk->sk_rx_dst_ifindex == skb->skb_iif) skb_dst_set_noref(skb, dst); } } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 8d785232b479..14a94cddcf0b 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -884,7 +884,7 @@ static void udp6_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst) if (udp_sk_rx_dst_set(sk, dst)) { const struct rt6_info *rt = (const struct rt6_info *)dst; - inet6_sk(sk)->rx_dst_cookie = rt6_get_cookie(rt); + sk->sk_rx_dst_cookie = rt6_get_cookie(rt); } } @@ -1073,7 +1073,7 @@ INDIRECT_CALLABLE_SCOPE void udp_v6_early_demux(struct sk_buff *skb) dst = READ_ONCE(sk->sk_rx_dst); if (dst) - dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie); + dst = dst_check(dst, sk->sk_rx_dst_cookie); if (dst) { /* set noref for now. * any place which wants to hold dst has to call diff --git a/net/mctp/af_mctp.c b/net/mctp/af_mctp.c index 66a411d60b6c..d344b02a1cde 100644 --- a/net/mctp/af_mctp.c +++ b/net/mctp/af_mctp.c @@ -77,6 +77,7 @@ static int mctp_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) const int hlen = MCTP_HEADER_MAXLEN + sizeof(struct mctp_hdr); int rc, addrlen = msg->msg_namelen; struct sock *sk = sock->sk; + struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk); struct mctp_skb_cb *cb; struct mctp_route *rt; struct sk_buff *skb; @@ -100,11 +101,6 @@ static int mctp_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) if (addr->smctp_network == MCTP_NET_ANY) addr->smctp_network = mctp_default_net(sock_net(sk)); - rt = mctp_route_lookup(sock_net(sk), addr->smctp_network, - addr->smctp_addr.s_addr); - if (!rt) - return -EHOSTUNREACH; - skb = sock_alloc_send_skb(sk, hlen + 1 + len, msg->msg_flags & MSG_DONTWAIT, &rc); if (!skb) @@ -116,19 +112,45 @@ static int mctp_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) *(u8 *)skb_put(skb, 1) = addr->smctp_type; rc = memcpy_from_msg((void *)skb_put(skb, len), msg, len); - if (rc < 0) { - kfree_skb(skb); - return rc; - } + if (rc < 0) + goto err_free; /* set up cb */ cb = __mctp_cb(skb); cb->net = addr->smctp_network; + /* direct addressing */ + if (msk->addr_ext && addrlen >= sizeof(struct sockaddr_mctp_ext)) { + DECLARE_SOCKADDR(struct sockaddr_mctp_ext *, + extaddr, msg->msg_name); + + if (extaddr->smctp_halen > sizeof(cb->haddr)) { + rc = -EINVAL; + goto err_free; + } + + cb->ifindex = extaddr->smctp_ifindex; + cb->halen = extaddr->smctp_halen; + memcpy(cb->haddr, extaddr->smctp_haddr, cb->halen); + + rt = NULL; + } else { + rt = mctp_route_lookup(sock_net(sk), addr->smctp_network, + addr->smctp_addr.s_addr); + if (!rt) { + rc = -EHOSTUNREACH; + goto err_free; + } + } + rc = mctp_local_output(sk, rt, skb, addr->smctp_addr.s_addr, addr->smctp_tag); return rc ? : len; + +err_free: + kfree_skb(skb); + return rc; } static int mctp_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, @@ -136,6 +158,7 @@ static int mctp_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, { DECLARE_SOCKADDR(struct sockaddr_mctp *, addr, msg->msg_name); struct sock *sk = sock->sk; + struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk); struct sk_buff *skb; size_t msglen; u8 type; @@ -181,6 +204,16 @@ static int mctp_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, addr->smctp_tag = hdr->flags_seq_tag & (MCTP_HDR_TAG_MASK | MCTP_HDR_FLAG_TO); msg->msg_namelen = sizeof(*addr); + + if (msk->addr_ext) { + DECLARE_SOCKADDR(struct sockaddr_mctp_ext *, ae, + msg->msg_name); + msg->msg_namelen = sizeof(*ae); + ae->smctp_ifindex = cb->ifindex; + ae->smctp_halen = cb->halen; + memset(ae->smctp_haddr, 0x0, sizeof(ae->smctp_haddr)); + memcpy(ae->smctp_haddr, cb->haddr, cb->halen); + } } rc = len; @@ -196,12 +229,45 @@ out_free: static int mctp_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval, unsigned int optlen) { - return -EINVAL; + struct mctp_sock *msk = container_of(sock->sk, struct mctp_sock, sk); + int val; + + if (level != SOL_MCTP) + return -EINVAL; + + if (optname == MCTP_OPT_ADDR_EXT) { + if (optlen != sizeof(int)) + return -EINVAL; + if (copy_from_sockptr(&val, optval, sizeof(int))) + return -EFAULT; + msk->addr_ext = val; + return 0; + } + + return -ENOPROTOOPT; } static int mctp_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { + struct mctp_sock *msk = container_of(sock->sk, struct mctp_sock, sk); + int len, val; + + if (level != SOL_MCTP) + return -EINVAL; + + if (get_user(len, optlen)) + return -EFAULT; + + if (optname == MCTP_OPT_ADDR_EXT) { + if (len != sizeof(int)) + return -EINVAL; + val = !!msk->addr_ext; + if (copy_to_user(optval, &val, len)) + return -EFAULT; + return 0; + } + return -EINVAL; } diff --git a/net/mctp/route.c b/net/mctp/route.c index 82fb5ae524f6..c23ab3547ee5 100644 --- a/net/mctp/route.c +++ b/net/mctp/route.c @@ -434,6 +434,7 @@ static unsigned int mctp_route_mtu(struct mctp_route *rt) static int mctp_route_output(struct mctp_route *route, struct sk_buff *skb) { + struct mctp_skb_cb *cb = mctp_cb(skb); struct mctp_hdr *hdr = mctp_hdr(skb); char daddr_buf[MAX_ADDR_LEN]; char *daddr = NULL; @@ -448,9 +449,14 @@ static int mctp_route_output(struct mctp_route *route, struct sk_buff *skb) return -EMSGSIZE; } - /* If lookup fails let the device handle daddr==NULL */ - if (mctp_neigh_lookup(route->dev, hdr->dest, daddr_buf) == 0) - daddr = daddr_buf; + if (cb->ifindex) { + /* direct route; use the hwaddr we stashed in sendmsg */ + daddr = cb->haddr; + } else { + /* If lookup fails let the device handle daddr==NULL */ + if (mctp_neigh_lookup(route->dev, hdr->dest, daddr_buf) == 0) + daddr = daddr_buf; + } rc = dev_hard_header(skb, skb->dev, ntohs(skb->protocol), daddr, skb->dev->dev_addr, skb->len); @@ -649,16 +655,6 @@ static struct mctp_route *mctp_route_lookup_null(struct net *net, return NULL; } -/* sends a skb to rt and releases the route. */ -int mctp_do_route(struct mctp_route *rt, struct sk_buff *skb) -{ - int rc; - - rc = rt->output(rt, skb); - mctp_route_release(rt); - return rc; -} - static int mctp_do_fragment_route(struct mctp_route *rt, struct sk_buff *skb, unsigned int mtu, u8 tag) { @@ -725,7 +721,7 @@ static int mctp_do_fragment_route(struct mctp_route *rt, struct sk_buff *skb, /* copy message payload */ skb_copy_bits(skb, pos, skb_transport_header(skb2), size); - /* do route, but don't drop the rt reference */ + /* do route */ rc = rt->output(rt, skb2); if (rc) break; @@ -734,7 +730,6 @@ static int mctp_do_fragment_route(struct mctp_route *rt, struct sk_buff *skb, pos += size; } - mctp_route_release(rt); consume_skb(skb); return rc; } @@ -744,15 +739,51 @@ int mctp_local_output(struct sock *sk, struct mctp_route *rt, { struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk); struct mctp_skb_cb *cb = mctp_cb(skb); + struct mctp_route tmp_rt; + struct net_device *dev; struct mctp_hdr *hdr; unsigned long flags; unsigned int mtu; mctp_eid_t saddr; + bool ext_rt; int rc; u8 tag; - if (WARN_ON(!rt->dev)) + rc = -ENODEV; + + if (rt) { + ext_rt = false; + dev = NULL; + + if (WARN_ON(!rt->dev)) + goto out_release; + + } else if (cb->ifindex) { + ext_rt = true; + rt = &tmp_rt; + + rcu_read_lock(); + dev = dev_get_by_index_rcu(sock_net(sk), cb->ifindex); + if (!dev) { + rcu_read_unlock(); + return rc; + } + + rt->dev = __mctp_dev_get(dev); + rcu_read_unlock(); + + if (!rt->dev) + goto out_release; + + /* establish temporary route - we set up enough to keep + * mctp_route_output happy + */ + rt->output = mctp_route_output; + rt->mtu = 0; + + } else { return -EINVAL; + } spin_lock_irqsave(&rt->dev->addrs_lock, flags); if (rt->dev->num_addrs == 0) { @@ -765,18 +796,17 @@ int mctp_local_output(struct sock *sk, struct mctp_route *rt, spin_unlock_irqrestore(&rt->dev->addrs_lock, flags); if (rc) - return rc; + goto out_release; if (req_tag & MCTP_HDR_FLAG_TO) { rc = mctp_alloc_local_tag(msk, saddr, daddr, &tag); if (rc) - return rc; + goto out_release; tag |= MCTP_HDR_FLAG_TO; } else { tag = req_tag; } - skb->protocol = htons(ETH_P_MCTP); skb->priority = 0; skb_reset_transport_header(skb); @@ -796,12 +826,22 @@ int mctp_local_output(struct sock *sk, struct mctp_route *rt, mtu = mctp_route_mtu(rt); if (skb->len + sizeof(struct mctp_hdr) <= mtu) { - hdr->flags_seq_tag = MCTP_HDR_FLAG_SOM | MCTP_HDR_FLAG_EOM | - tag; - return mctp_do_route(rt, skb); + hdr->flags_seq_tag = MCTP_HDR_FLAG_SOM | + MCTP_HDR_FLAG_EOM | tag; + rc = rt->output(rt, skb); } else { - return mctp_do_fragment_route(rt, skb, mtu, tag); + rc = mctp_do_fragment_route(rt, skb, mtu, tag); } + +out_release: + if (!ext_rt) + mctp_route_release(rt); + + if (dev) + dev_put(dev); + + return rc; + } /* route management */ @@ -942,8 +982,15 @@ static int mctp_pkttype_receive(struct sk_buff *skb, struct net_device *dev, if (mh->ver < MCTP_VER_MIN || mh->ver > MCTP_VER_MAX) goto err_drop; - cb = __mctp_cb(skb); + /* MCTP drivers must populate halen/haddr */ + if (dev->type == ARPHRD_MCTP) { + cb = mctp_cb(skb); + } else { + cb = __mctp_cb(skb); + cb->halen = 0; + } cb->net = READ_ONCE(mdev->net); + cb->ifindex = dev->ifindex; rt = mctp_route_lookup(net, cb->net, mh->dest); @@ -954,7 +1001,8 @@ static int mctp_pkttype_receive(struct sk_buff *skb, struct net_device *dev, if (!rt) goto err_drop; - mctp_do_route(rt, skb); + rt->output(rt, skb); + mctp_route_release(rt); return NET_RX_SUCCESS; diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index 8f7a9837349c..d1f2d3c8d2b1 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c @@ -155,6 +155,16 @@ unsigned int nf_confirm(struct sk_buff *skb, unsigned int protoff, } EXPORT_SYMBOL_GPL(nf_confirm); +static bool in_vrf_postrouting(const struct nf_hook_state *state) +{ +#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV) + if (state->hook == NF_INET_POST_ROUTING && + netif_is_l3_master(state->out)) + return true; +#endif + return false; +} + static unsigned int ipv4_confirm(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) @@ -166,6 +176,9 @@ static unsigned int ipv4_confirm(void *priv, if (!ct || ctinfo == IP_CT_RELATED_REPLY) return nf_conntrack_confirm(skb); + if (in_vrf_postrouting(state)) + return NF_ACCEPT; + return nf_confirm(skb, skb_network_offset(skb) + ip_hdrlen(skb), ct, ctinfo); @@ -374,6 +387,9 @@ static unsigned int ipv6_confirm(void *priv, if (!ct || ctinfo == IP_CT_RELATED_REPLY) return nf_conntrack_confirm(skb); + if (in_vrf_postrouting(state)) + return NF_ACCEPT; + protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &pnum, &frag_off); if (protoff < 0 || (frag_off & htons(~0x7)) != 0) { diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c index 273117683922..4d50d51db796 100644 --- a/net/netfilter/nf_nat_core.c +++ b/net/netfilter/nf_nat_core.c @@ -699,6 +699,16 @@ unsigned int nf_nat_packet(struct nf_conn *ct, } EXPORT_SYMBOL_GPL(nf_nat_packet); +static bool in_vrf_postrouting(const struct nf_hook_state *state) +{ +#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV) + if (state->hook == NF_INET_POST_ROUTING && + netif_is_l3_master(state->out)) + return true; +#endif + return false; +} + unsigned int nf_nat_inet_fn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) @@ -715,7 +725,7 @@ nf_nat_inet_fn(void *priv, struct sk_buff *skb, * packet filter it out, or implement conntrack/NAT for that * protocol. 8) --RR */ - if (!ct) + if (!ct || in_vrf_postrouting(state)) return NF_ACCEPT; nat = nfct_nat(ct); diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c index d44399efeac6..278192ee133e 100644 --- a/net/tls/tls_main.c +++ b/net/tls/tls_main.c @@ -421,6 +421,48 @@ static int do_tls_getsockopt_conf(struct sock *sk, char __user *optval, rc = -EFAULT; break; } + case TLS_CIPHER_AES_CCM_128: { + struct tls12_crypto_info_aes_ccm_128 *aes_ccm_128 = + container_of(crypto_info, + struct tls12_crypto_info_aes_ccm_128, info); + + if (len != sizeof(*aes_ccm_128)) { + rc = -EINVAL; + goto out; + } + lock_sock(sk); + memcpy(aes_ccm_128->iv, + cctx->iv + TLS_CIPHER_AES_CCM_128_SALT_SIZE, + TLS_CIPHER_AES_CCM_128_IV_SIZE); + memcpy(aes_ccm_128->rec_seq, cctx->rec_seq, + TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE); + release_sock(sk); + if (copy_to_user(optval, aes_ccm_128, sizeof(*aes_ccm_128))) + rc = -EFAULT; + break; + } + case TLS_CIPHER_CHACHA20_POLY1305: { + struct tls12_crypto_info_chacha20_poly1305 *chacha20_poly1305 = + container_of(crypto_info, + struct tls12_crypto_info_chacha20_poly1305, + info); + + if (len != sizeof(*chacha20_poly1305)) { + rc = -EINVAL; + goto out; + } + lock_sock(sk); + memcpy(chacha20_poly1305->iv, + cctx->iv + TLS_CIPHER_CHACHA20_POLY1305_SALT_SIZE, + TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE); + memcpy(chacha20_poly1305->rec_seq, cctx->rec_seq, + TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE); + release_sock(sk); + if (copy_to_user(optval, chacha20_poly1305, + sizeof(*chacha20_poly1305))) + rc = -EFAULT; + break; + } case TLS_CIPHER_SM4_GCM: { struct tls12_crypto_info_sm4_gcm *sm4_gcm_info = container_of(crypto_info, diff --git a/tools/testing/selftests/drivers/net/dsa/test_bridge_fdb_stress.sh b/tools/testing/selftests/drivers/net/dsa/test_bridge_fdb_stress.sh new file mode 100755 index 000000000000..dca8be6092b9 --- /dev/null +++ b/tools/testing/selftests/drivers/net/dsa/test_bridge_fdb_stress.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +# Bridge FDB entries can be offloaded to DSA switches without holding the +# rtnl_mutex. Traditionally this mutex has conferred drivers implicit +# serialization, which means their code paths are not well tested in the +# presence of concurrency. +# This test creates a background task that stresses the FDB by adding and +# deleting an entry many times in a row without the rtnl_mutex held. +# It then tests the driver resistance to concurrency by calling .ndo_fdb_dump +# (with rtnl_mutex held) from a foreground task. +# Since either the FDB dump or the additions/removals can fail, but the +# additions and removals are performed in deferred as opposed to process +# context, we cannot simply check for user space error codes. + +WAIT_TIME=1 +NUM_NETIFS=1 +REQUIRE_JQ="no" +REQUIRE_MZ="no" +NETIF_CREATE="no" +lib_dir=$(dirname $0)/../../../net/forwarding +source $lib_dir/lib.sh + +cleanup() { + echo "Cleaning up" + kill $pid && wait $pid &> /dev/null + ip link del br0 + echo "Please check kernel log for errors" +} +trap 'cleanup' EXIT + +eth=${NETIFS[p1]} + +ip link del br0 2&>1 >/dev/null || : +ip link add br0 type bridge && ip link set $eth master br0 + +(while :; do + bridge fdb add 00:01:02:03:04:05 dev $eth master static + bridge fdb del 00:01:02:03:04:05 dev $eth master static +done) & +pid=$! + +for i in $(seq 1 50); do + bridge fdb show > /dev/null + sleep 3 + echo "$((${i} * 2))% complete..." +done diff --git a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_control.sh b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_control.sh index a37273473c1b..d3a891d421ab 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_control.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_control.sh @@ -87,6 +87,7 @@ ALL_TESTS=" NUM_NETIFS=4 source $lib_dir/lib.sh source $lib_dir/devlink_lib.sh +source mlxsw_lib.sh h1_create() { @@ -626,8 +627,7 @@ ipv6_redirect_test() ptp_event_test() { - # PTP is only supported on Spectrum-1, for now. - [[ "$DEVLINK_VIDDID" != "15b3:cb84" ]] && return + mlxsw_only_on_spectrum 1 || return # PTP Sync (0) devlink_trap_stats_test "PTP Time-Critical Event Message" "ptp_event" \ @@ -638,8 +638,7 @@ ptp_event_test() ptp_general_test() { - # PTP is only supported on Spectrum-1, for now. - [[ "$DEVLINK_VIDDID" != "15b3:cb84" ]] && return + mlxsw_only_on_spectrum 1 || return # PTP Announce (b) devlink_trap_stats_test "PTP General Message" "ptp_general" \ diff --git a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_policer.sh b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_policer.sh index 508a702f0021..0bd5ffc218ac 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_policer.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_policer.sh @@ -272,13 +272,17 @@ __rate_test() rate_test() { - local id + local last_policer=$(devlink -j -p trap policer show | + jq '[.[]["'$DEVLINK_DEV'"][].policer] | max') - for id in $(devlink_trap_policer_ids_get); do - echo - log_info "Running rate test for policer $id" - __rate_test $id - done + log_info "Running rate test for policer 1" + __rate_test 1 + + log_info "Running rate test for policer $((last_policer / 2))" + __rate_test $((last_policer / 2)) + + log_info "Running rate test for policer $last_policer" + __rate_test $last_policer } __burst_test() @@ -342,13 +346,17 @@ __burst_test() burst_test() { - local id + local last_policer=$(devlink -j -p trap policer show | + jq '[.[]["'$DEVLINK_DEV'"][].policer] | max') + + log_info "Running burst test for policer 1" + __burst_test 1 + + log_info "Running burst test for policer $((last_policer / 2))" + __burst_test $((last_policer / 2)) - for id in $(devlink_trap_policer_ids_get); do - echo - log_info "Running burst size test for policer $id" - __burst_test $id - done + log_info "Running burst test for policer $last_policer" + __burst_test $last_policer } trap cleanup EXIT diff --git a/tools/testing/selftests/drivers/net/mlxsw/mlxsw_lib.sh b/tools/testing/selftests/drivers/net/mlxsw/mlxsw_lib.sh index cbe50f260a40..a95856aafd2a 100644 --- a/tools/testing/selftests/drivers/net/mlxsw/mlxsw_lib.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/mlxsw_lib.sh @@ -11,3 +11,53 @@ if [[ ! -v MLXSW_CHIP ]]; then exit 1 fi fi + +MLXSW_SPECTRUM_REV=$(case $MLXSW_CHIP in + mlxsw_spectrum) + echo 1 ;; + mlxsw_spectrum*) + echo ${MLXSW_CHIP#mlxsw_spectrum} ;; + *) + echo "Couldn't determine Spectrum chip revision." \ + > /dev/stderr ;; + esac) + +mlxsw_on_spectrum() +{ + local rev=$1; shift + local op="==" + local rev2=${rev%+} + + if [[ $rev2 != $rev ]]; then + op=">=" + fi + + ((MLXSW_SPECTRUM_REV $op rev2)) +} + +__mlxsw_only_on_spectrum() +{ + local rev=$1; shift + local caller=$1; shift + local src=$1; shift + + if ! mlxsw_on_spectrum "$rev"; then + log_test_skip $src:$caller "(Spectrum-$rev only)" + return 1 + fi +} + +mlxsw_only_on_spectrum() +{ + local caller=${FUNCNAME[1]} + local src=${BASH_SOURCE[1]} + local rev + + for rev in "$@"; do + if __mlxsw_only_on_spectrum "$rev" "$caller" "$src"; then + return 0 + fi + done + + return 1 +} diff --git a/tools/testing/selftests/drivers/net/mlxsw/rif_mac_profile_scale.sh b/tools/testing/selftests/drivers/net/mlxsw/rif_mac_profile_scale.sh new file mode 100644 index 000000000000..71e7681f15f6 --- /dev/null +++ b/tools/testing/selftests/drivers/net/mlxsw/rif_mac_profile_scale.sh @@ -0,0 +1,72 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +# Test for RIF MAC profiles resource. The test adds VLAN netdevices according to +# the maximum number of RIF MAC profiles, sets each of them with a random +# MAC address, and checks that eventually the number of occupied RIF MAC +# profiles equals the maximum number of RIF MAC profiles. + + +RIF_MAC_PROFILE_NUM_NETIFS=2 + +rif_mac_profiles_create() +{ + local count=$1; shift + local should_fail=$1; shift + local batch_file="$(mktemp)" + + for ((i = 1; i <= count; i++)); do + vlan=$(( i*10 )) + m=$(( i*11 )) + + cat >> $batch_file <<-EOF + link add link $h1 name $h1.$vlan \ + address 00:$m:$m:$m:$m:$m type vlan id $vlan + address add 192.0.$m.1/24 dev $h1.$vlan + EOF + done + + ip -b $batch_file &> /dev/null + check_err_fail $should_fail $? "RIF creation" + + rm -f $batch_file +} + +rif_mac_profile_test() +{ + local count=$1; shift + local should_fail=$1; shift + + rif_mac_profiles_create $count $should_fail + + occ=$(devlink -j resource show $DEVLINK_DEV \ + | jq '.[][][] | select(.name=="rif_mac_profiles") |.["occ"]') + + [[ $occ -eq $count ]] + check_err_fail $should_fail $? "Attempt to use $count profiles (actual result $occ)" +} + +rif_mac_profile_setup_prepare() +{ + h1=${NETIFS[p1]} + h2=${NETIFS[p2]} + + # Disable IPv6 on the two interfaces to avoid IPv6 link-local addresses + # being generated and RIFs being created. + sysctl_set net.ipv6.conf.$h1.disable_ipv6 1 + sysctl_set net.ipv6.conf.$h2.disable_ipv6 1 + + ip link set $h1 up + ip link set $h2 up +} + +rif_mac_profile_cleanup() +{ + pre_cleanup + + ip link set $h2 down + ip link set $h1 down + + sysctl_restore net.ipv6.conf.$h2.disable_ipv6 + sysctl_restore net.ipv6.conf.$h1.disable_ipv6 +} diff --git a/tools/testing/selftests/drivers/net/mlxsw/rif_mac_profiles.sh b/tools/testing/selftests/drivers/net/mlxsw/rif_mac_profiles.sh new file mode 100755 index 000000000000..c18340cee55d --- /dev/null +++ b/tools/testing/selftests/drivers/net/mlxsw/rif_mac_profiles.sh @@ -0,0 +1,213 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +lib_dir=$(dirname $0)/../../../net/forwarding + +ALL_TESTS=" + mac_profile_test +" +NUM_NETIFS=4 +source $lib_dir/lib.sh +source $lib_dir/tc_common.sh +source $lib_dir/devlink_lib.sh + +h1_create() +{ + simple_if_init $h1 192.0.2.1/24 + ip route add 198.51.100.0/24 vrf v$h1 nexthop via 192.0.2.2 + + tc qdisc add dev $h1 ingress +} + +h1_destroy() +{ + tc qdisc del dev $h1 ingress + + ip route del 198.51.100.0/24 vrf v$h1 + simple_if_fini $h1 192.0.2.1/24 +} + +h2_create() +{ + simple_if_init $h2 198.51.100.1/24 + ip route add 192.0.2.0/24 vrf v$h2 nexthop via 198.51.100.2 + + tc qdisc add dev $h2 ingress +} + +h2_destroy() +{ + tc qdisc del dev $h2 ingress + + ip route del 192.0.2.0/24 vrf v$h2 + simple_if_fini $h2 198.51.100.1/24 +} + +router_create() +{ + ip link set dev $rp1 up + ip link set dev $rp2 up + + tc qdisc add dev $rp1 clsact + tc qdisc add dev $rp2 clsact + ip address add 192.0.2.2/24 dev $rp1 + ip address add 198.51.100.2/24 dev $rp2 +} + +router_destroy() +{ + ip address del 198.51.100.2/24 dev $rp2 + ip address del 192.0.2.2/24 dev $rp1 + tc qdisc del dev $rp2 clsact + tc qdisc del dev $rp1 clsact + + ip link set dev $rp2 down + ip link set dev $rp1 down +} + +setup_prepare() +{ + h1=${NETIFS[p1]} + rp1=${NETIFS[p2]} + + rp2=${NETIFS[p3]} + h2=${NETIFS[p4]} + + vrf_prepare + + h1_create + h2_create + + router_create + + forwarding_enable +} + +cleanup() +{ + pre_cleanup + + forwarding_restore + + router_destroy + + h2_destroy + h1_destroy + + vrf_cleanup +} + +h1_to_h2() +{ + local test_name=$@; shift + local smac=$(mac_get $rp2) + + RET=0 + + # Replace neighbour to avoid first packet being forwarded in software + ip neigh replace dev $rp2 198.51.100.1 lladdr $(mac_get $h2) + + # Add a filter to ensure that packets are forwarded in hardware. Cannot + # match on source MAC because it is not set in eACL after routing + tc filter add dev $rp2 egress proto ip pref 1 handle 101 \ + flower skip_sw ip_proto udp src_port 12345 dst_port 54321 \ + action pass + + # Add a filter to ensure that packets are received with the correct + # source MAC + tc filter add dev $h2 ingress proto ip pref 1 handle 101 \ + flower skip_sw src_mac $smac ip_proto udp src_port 12345 \ + dst_port 54321 action pass + + $MZ $h1 -a own -b $(mac_get $rp1) -t udp "sp=12345,dp=54321" \ + -A 192.0.2.1 -B 198.51.100.1 -c 10 -p 100 -d 1msec -q + + tc_check_packets "dev $rp2 egress" 101 10 + check_err $? "packets not forwarded in hardware" + + tc_check_packets "dev $h2 ingress" 101 10 + check_err $? "packets not forwarded with correct source mac" + + log_test "h1->h2: $test_name" + + tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower + tc filter del dev $rp2 egress protocol ip pref 1 handle 101 flower + ip neigh del dev $rp2 198.51.100.1 lladdr $(mac_get $h2) +} + +h2_to_h1() +{ + local test_name=$@; shift + local rp1_mac=$(mac_get $rp1) + + RET=0 + + ip neigh replace dev $rp1 192.0.2.1 lladdr $(mac_get $h1) + + tc filter add dev $rp1 egress proto ip pref 1 handle 101 \ + flower skip_sw ip_proto udp src_port 54321 dst_port 12345 \ + action pass + + tc filter add dev $h1 ingress proto ip pref 1 handle 101 \ + flower skip_sw src_mac $rp1_mac ip_proto udp src_port 54321 \ + dst_port 12345 action pass + + $MZ $h2 -a own -b $(mac_get $rp2) -t udp "sp=54321,dp=12345" \ + -A 198.51.100.1 -B 192.0.2.1 -c 10 -p 100 -d 1msec -q + + tc_check_packets "dev $rp1 egress" 101 10 + check_err $? "packets not forwarded in hardware" + + tc_check_packets "dev $h1 ingress" 101 10 + check_err $? "packets not forwarded with correct source mac" + + log_test "h2->h1: $test_name" + + tc filter del dev $h1 ingress protocol ip pref 1 handle 101 flower + tc filter del dev $rp1 egress protocol ip pref 1 handle 101 flower + ip neigh del dev $rp1 192.0.2.1 lladdr $(mac_get $h1) +} + +smac_test() +{ + local test_name=$@; shift + + # Test that packets forwarded to $h2 via $rp2 are forwarded with the + # current source MAC of $rp2 + h1_to_h2 $test_name + + # Test that packets forwarded to $h1 via $rp1 are forwarded with the + # current source MAC of $rp1. This MAC is never changed during the test, + # but given the shared nature of MAC profile, the point is to see that + # changes to the MAC of $rp2 do not affect that of $rp1 + h2_to_h1 $test_name +} + +mac_profile_test() +{ + local rp2_mac=$(mac_get $rp2) + + # Test behavior when the RIF backing $rp2 is transitioned to use + # a new MAC profile + ip link set dev $rp2 addr 00:11:22:33:44:55 + smac_test "new mac profile" + + # Test behavior when the MAC profile used by the RIF is edited + ip link set dev $rp2 address 00:22:22:22:22:22 + smac_test "edit mac profile" + + # Restore original MAC + ip link set dev $rp2 addr $rp2_mac +} + +trap cleanup EXIT + +setup_prepare +setup_wait + +mac_profiles=$(devlink_resource_size_get rif_mac_profiles) +if [[ $mac_profiles -ne 1 ]]; then + tests_run +fi + +exit $EXIT_STATUS diff --git a/tools/testing/selftests/drivers/net/mlxsw/rif_mac_profiles_occ.sh b/tools/testing/selftests/drivers/net/mlxsw/rif_mac_profiles_occ.sh new file mode 100755 index 000000000000..b513f64d9092 --- /dev/null +++ b/tools/testing/selftests/drivers/net/mlxsw/rif_mac_profiles_occ.sh @@ -0,0 +1,117 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +lib_dir=$(dirname $0)/../../../net/forwarding + +ALL_TESTS=" + rif_mac_profile_edit_test +" +NUM_NETIFS=2 +source $lib_dir/lib.sh +source $lib_dir/devlink_lib.sh + +setup_prepare() +{ + h1=${NETIFS[p1]} + h2=${NETIFS[p2]} + + # Disable IPv6 on the two interfaces to avoid IPv6 link-local addresses + # being generated and RIFs being created + sysctl_set net.ipv6.conf.$h1.disable_ipv6 1 + sysctl_set net.ipv6.conf.$h2.disable_ipv6 1 + + ip link set $h1 up + ip link set $h2 up +} + +cleanup() +{ + pre_cleanup + + ip link set $h2 down + ip link set $h1 down + + sysctl_restore net.ipv6.conf.$h2.disable_ipv6 + sysctl_restore net.ipv6.conf.$h1.disable_ipv6 + + # Reload in order to clean all the RIFs and RIF MAC profiles created + devlink_reload +} + +create_max_rif_mac_profiles() +{ + local count=$1; shift + local batch_file="$(mktemp)" + + for ((i = 1; i <= count; i++)); do + vlan=$(( i*10 )) + m=$(( i*11 )) + + cat >> $batch_file <<-EOF + link add link $h1 name $h1.$vlan \ + address 00:$m:$m:$m:$m:$m type vlan id $vlan + address add 192.0.$m.1/24 dev $h1.$vlan + EOF + done + + ip -b $batch_file &> /dev/null + rm -f $batch_file +} + +rif_mac_profile_replacement_test() +{ + local h1_10_mac=$(mac_get $h1.10) + + RET=0 + + ip link set $h1.10 address 00:12:34:56:78:99 + check_err $? + + log_test "RIF MAC profile replacement" + + ip link set $h1.10 address $h1_10_mac +} + +rif_mac_profile_shared_replacement_test() +{ + local count=$1; shift + local i=$((count + 1)) + local vlan=$(( i*10 )) + local m=11 + + RET=0 + + # Create a VLAN netdevice that has the same MAC as the first one. + ip link add link $h1 name $h1.$vlan address 00:$m:$m:$m:$m:$m \ + type vlan id $vlan + ip address add 192.0.$m.1/24 dev $h1.$vlan + + # MAC replacement should fail because all the MAC profiles are in use + # and the profile is shared between multiple RIFs + m=$(( i*11 )) + ip link set $h1.$vlan address 00:$m:$m:$m:$m:$m &> /dev/null + check_fail $? + + log_test "RIF MAC profile shared replacement" + + ip link del dev $h1.$vlan +} + +rif_mac_profile_edit_test() +{ + local count=$(devlink_resource_size_get rif_mac_profiles) + + create_max_rif_mac_profiles $count + + rif_mac_profile_replacement_test + rif_mac_profile_shared_replacement_test $count +} + +trap cleanup EXIT + +setup_prepare +setup_wait + +tests_run + +exit $EXIT_STATUS diff --git a/tools/testing/selftests/drivers/net/mlxsw/rtnetlink.sh b/tools/testing/selftests/drivers/net/mlxsw/rtnetlink.sh index a217f9f6775b..04f03ae9d8fb 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/rtnetlink.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/rtnetlink.sh @@ -10,9 +10,7 @@ lib_dir=$(dirname $0)/../../../net/forwarding ALL_TESTS=" - rif_set_addr_test rif_vrf_set_addr_test - rif_inherit_bridge_addr_test rif_non_inherit_bridge_addr_test vlan_interface_deletion_test bridge_deletion_test @@ -60,55 +58,6 @@ cleanup() ip link set dev $swp1 down } -rif_set_addr_test() -{ - local swp1_mac=$(mac_get $swp1) - local swp2_mac=$(mac_get $swp2) - - RET=0 - - # $swp1 and $swp2 likely got their IPv6 local addresses already, but - # here we need to test the transition to RIF. - ip addr flush dev $swp1 - ip addr flush dev $swp2 - sleep .1 - - ip addr add dev $swp1 192.0.2.1/28 - check_err $? - - ip link set dev $swp1 addr 00:11:22:33:44:55 - check_err $? - - # IP address enablement should be rejected if the MAC address prefix - # doesn't match other RIFs. - ip addr add dev $swp2 192.0.2.2/28 &>/dev/null - check_fail $? "IP address addition passed for a device with a wrong MAC" - ip addr add dev $swp2 192.0.2.2/28 2>&1 >/dev/null \ - | grep -q mlxsw_spectrum - check_err $? "no extack for IP address addition" - - ip link set dev $swp2 addr 00:11:22:33:44:66 - check_err $? - ip addr add dev $swp2 192.0.2.2/28 &>/dev/null - check_err $? - - # Change of MAC address of a RIF should be forbidden if the new MAC - # doesn't share the prefix with other MAC addresses. - ip link set dev $swp2 addr 00:11:22:33:00:66 &>/dev/null - check_fail $? "change of MAC address passed for a wrong MAC" - ip link set dev $swp2 addr 00:11:22:33:00:66 2>&1 >/dev/null \ - | grep -q mlxsw_spectrum - check_err $? "no extack for MAC address change" - - log_test "RIF - bad MAC change" - - ip addr del dev $swp2 192.0.2.2/28 - ip addr del dev $swp1 192.0.2.1/28 - - ip link set dev $swp2 addr $swp2_mac - ip link set dev $swp1 addr $swp1_mac -} - rif_vrf_set_addr_test() { # Test that it is possible to set an IP address on a VRF upper despite @@ -128,45 +77,6 @@ rif_vrf_set_addr_test() ip link del dev vrf-test } -rif_inherit_bridge_addr_test() -{ - RET=0 - - # Create first RIF - ip addr add dev $swp1 192.0.2.1/28 - check_err $? - - # Create a FID RIF - ip link add name br1 up type bridge vlan_filtering 0 - ip link set dev $swp2 master br1 - ip addr add dev br1 192.0.2.17/28 - check_err $? - - # Prepare a device with a low MAC address - ip link add name d up type dummy - ip link set dev d addr 00:11:22:33:44:55 - - # Attach the device to br1. That prompts bridge address change, which - # should be vetoed, thus preventing the attachment. - ip link set dev d master br1 &>/dev/null - check_fail $? "Device with low MAC was permitted to attach a bridge with RIF" - ip link set dev d master br1 2>&1 >/dev/null \ - | grep -q mlxsw_spectrum - check_err $? "no extack for bridge attach rejection" - - ip link set dev $swp2 addr 00:11:22:33:44:55 &>/dev/null - check_fail $? "Changing swp2's MAC address permitted" - ip link set dev $swp2 addr 00:11:22:33:44:55 2>&1 >/dev/null \ - | grep -q mlxsw_spectrum - check_err $? "no extack for bridge port MAC address change rejection" - - log_test "RIF - attach port with bad MAC to bridge" - - ip link del dev d - ip link del dev br1 - ip addr del dev $swp1 192.0.2.1/28 -} - rif_non_inherit_bridge_addr_test() { local swp2_mac=$(mac_get $swp2) @@ -779,7 +689,7 @@ nexthop_obj_offload_test() setup_wait ip nexthop add id 1 via 192.0.2.2 dev $swp1 - ip neigh replace 192.0.2.2 lladdr 00:11:22:33:44:55 nud reachable \ + ip neigh replace 192.0.2.2 lladdr 00:11:22:33:44:55 nud perm \ dev $swp1 busywait "$TIMEOUT" wait_for_offload \ @@ -791,7 +701,7 @@ nexthop_obj_offload_test() ip nexthop show id 1 check_err $? "nexthop marked as offloaded after setting neigh to failed state" - ip neigh replace 192.0.2.2 lladdr 00:11:22:33:44:55 nud reachable \ + ip neigh replace 192.0.2.2 lladdr 00:11:22:33:44:55 nud perm \ dev $swp1 busywait "$TIMEOUT" wait_for_offload \ ip nexthop show id 1 @@ -828,11 +738,11 @@ nexthop_obj_group_offload_test() ip nexthop add id 1 via 192.0.2.2 dev $swp1 ip nexthop add id 2 via 2001:db8:1::2 dev $swp1 ip nexthop add id 10 group 1/2 - ip neigh replace 192.0.2.2 lladdr 00:11:22:33:44:55 nud reachable \ + ip neigh replace 192.0.2.2 lladdr 00:11:22:33:44:55 nud perm \ dev $swp1 - ip neigh replace 192.0.2.3 lladdr 00:11:22:33:44:55 nud reachable \ + ip neigh replace 192.0.2.3 lladdr 00:11:22:33:44:55 nud perm \ dev $swp1 - ip neigh replace 2001:db8:1::2 lladdr 00:11:22:33:44:55 nud reachable \ + ip neigh replace 2001:db8:1::2 lladdr 00:11:22:33:44:55 nud perm \ dev $swp1 busywait "$TIMEOUT" wait_for_offload \ @@ -888,11 +798,11 @@ nexthop_obj_bucket_offload_test() ip nexthop add id 1 via 192.0.2.2 dev $swp1 ip nexthop add id 2 via 2001:db8:1::2 dev $swp1 ip nexthop add id 10 group 1/2 type resilient buckets 32 idle_timer 0 - ip neigh replace 192.0.2.2 lladdr 00:11:22:33:44:55 nud reachable \ + ip neigh replace 192.0.2.2 lladdr 00:11:22:33:44:55 nud perm \ dev $swp1 - ip neigh replace 192.0.2.3 lladdr 00:11:22:33:44:55 nud reachable \ + ip neigh replace 192.0.2.3 lladdr 00:11:22:33:44:55 nud perm \ dev $swp1 - ip neigh replace 2001:db8:1::2 lladdr 00:11:22:33:44:55 nud reachable \ + ip neigh replace 2001:db8:1::2 lladdr 00:11:22:33:44:55 nud perm \ dev $swp1 busywait "$TIMEOUT" wait_for_offload \ @@ -921,7 +831,7 @@ nexthop_obj_bucket_offload_test() check_err $? "nexthop bucket not marked as offloaded after revalidating nexthop" # Revalidate nexthop id 2 by changing its neighbour - ip neigh replace 2001:db8:1::2 lladdr 00:11:22:33:44:55 nud reachable \ + ip neigh replace 2001:db8:1::2 lladdr 00:11:22:33:44:55 nud perm \ dev $swp1 busywait "$TIMEOUT" wait_for_offload \ ip nexthop bucket show nhid 2 @@ -971,9 +881,9 @@ nexthop_obj_route_offload_test() setup_wait ip nexthop add id 1 via 192.0.2.2 dev $swp1 - ip neigh replace 192.0.2.2 lladdr 00:11:22:33:44:55 nud reachable \ + ip neigh replace 192.0.2.2 lladdr 00:11:22:33:44:55 nud perm \ dev $swp1 - ip neigh replace 192.0.2.3 lladdr 00:11:22:33:44:55 nud reachable \ + ip neigh replace 192.0.2.3 lladdr 00:11:22:33:44:55 nud perm \ dev $swp1 ip route replace 198.51.100.0/24 nhid 1 diff --git a/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh b/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh index dd90cd87d4f9..f260f01db0e8 100644 --- a/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh @@ -73,6 +73,7 @@ CHECK_TC="yes" lib_dir=$(dirname $0)/../../../net/forwarding source $lib_dir/lib.sh source $lib_dir/devlink_lib.sh +source mlxsw_lib.sh source qos_lib.sh ipaddr() @@ -479,10 +480,7 @@ do_ecn_test_perband() local vlan=$1; shift local limit=$1; shift - # Per-band ECN counters are not supported on Spectrum-1 and Spectrum-2. - [[ "$DEVLINK_VIDDID" == "15b3:cb84" || - "$DEVLINK_VIDDID" == "15b3:cf6c" ]] && return - + mlxsw_only_on_spectrum 3+ || return __do_ecn_test get_qdisc_nmarked "$vlan" "$limit" "per-band ECN" } @@ -584,6 +582,8 @@ do_mark_test() local should_fail=$1; shift local base + mlxsw_only_on_spectrum 2+ || return + RET=0 start_tcp_traffic $h1.$vlan $(ipaddr 1 $vlan) $(ipaddr 3 $vlan) \ @@ -632,6 +632,8 @@ do_drop_test() local base local now + mlxsw_only_on_spectrum 2+ || return + RET=0 start_traffic $h1.$vlan $(ipaddr 1 $vlan) $(ipaddr 3 $vlan) $h3_mac diff --git a/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/resource_scale.sh b/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/resource_scale.sh index 50654f8a8c37..e9f65bd2e299 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/resource_scale.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/resource_scale.sh @@ -7,12 +7,9 @@ NUM_NETIFS=6 source $lib_dir/lib.sh source $lib_dir/tc_common.sh source $lib_dir/devlink_lib.sh +source ../mlxsw_lib.sh -if [[ "$DEVLINK_VIDDID" != "15b3:cf6c" && \ - "$DEVLINK_VIDDID" != "15b3:cf70" ]]; then - echo "SKIP: test is tailored for Mellanox Spectrum-2 and Spectrum-3" - exit 1 -fi +mlxsw_only_on_spectrum 2+ || exit 1 current_test="" @@ -28,7 +25,7 @@ cleanup() trap cleanup EXIT -ALL_TESTS="router tc_flower mirror_gre tc_police port" +ALL_TESTS="router tc_flower mirror_gre tc_police port rif_mac_profile" for current_test in ${TESTS:-$ALL_TESTS}; do RET_FIN=0 source ${current_test}_scale.sh diff --git a/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/rif_mac_profile_scale.sh b/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/rif_mac_profile_scale.sh new file mode 100644 index 000000000000..303d7cbe3c45 --- /dev/null +++ b/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/rif_mac_profile_scale.sh @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +source ../rif_mac_profile_scale.sh + +rif_mac_profile_get_target() +{ + local should_fail=$1 + local target + + target=$(devlink_resource_size_get rif_mac_profiles) + + if ((! should_fail)); then + echo $target + else + echo $((target + 1)) + fi +} diff --git a/tools/testing/selftests/drivers/net/mlxsw/spectrum/devlink_lib_spectrum.sh b/tools/testing/selftests/drivers/net/mlxsw/spectrum/devlink_lib_spectrum.sh index 73035e25085d..06a80f40daa4 100644 --- a/tools/testing/selftests/drivers/net/mlxsw/spectrum/devlink_lib_spectrum.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/spectrum/devlink_lib_spectrum.sh @@ -2,11 +2,9 @@ # SPDX-License-Identifier: GPL-2.0 source "../../../../net/forwarding/devlink_lib.sh" +source ../mlxsw_lib.sh -if [ "$DEVLINK_VIDDID" != "15b3:cb84" ]; then - echo "SKIP: test is tailored for Mellanox Spectrum" - exit 1 -fi +mlxsw_only_on_spectrum 1 || exit 1 # Needed for returning to default declare -A KVD_DEFAULTS diff --git a/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh b/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh index 685dfb3478b3..bcb110e830ce 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh @@ -22,7 +22,7 @@ cleanup() devlink_sp_read_kvd_defaults trap cleanup EXIT -ALL_TESTS="router tc_flower mirror_gre tc_police port" +ALL_TESTS="router tc_flower mirror_gre tc_police port rif_mac_profile" for current_test in ${TESTS:-$ALL_TESTS}; do RET_FIN=0 source ${current_test}_scale.sh diff --git a/tools/testing/selftests/drivers/net/mlxsw/spectrum/rif_mac_profile_scale.sh b/tools/testing/selftests/drivers/net/mlxsw/spectrum/rif_mac_profile_scale.sh new file mode 100644 index 000000000000..303d7cbe3c45 --- /dev/null +++ b/tools/testing/selftests/drivers/net/mlxsw/spectrum/rif_mac_profile_scale.sh @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +source ../rif_mac_profile_scale.sh + +rif_mac_profile_get_target() +{ + local should_fail=$1 + local target + + target=$(devlink_resource_size_get rif_mac_profiles) + + if ((! should_fail)); then + echo $target + else + echo $((target + 1)) + fi +} diff --git a/tools/testing/selftests/drivers/net/mlxsw/tc_restrictions.sh b/tools/testing/selftests/drivers/net/mlxsw/tc_restrictions.sh index 5ec3beb637c8..0441a18f098b 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/tc_restrictions.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/tc_restrictions.sh @@ -20,6 +20,7 @@ NUM_NETIFS=2 source $lib_dir/tc_common.sh source $lib_dir/lib.sh source $lib_dir/devlink_lib.sh +source mlxsw_lib.sh switch_create() { @@ -169,7 +170,7 @@ matchall_sample_egress_test() # It is forbidden in mlxsw driver to have matchall with sample action # bound on egress. Spectrum-1 specific restriction - [[ "$DEVLINK_VIDDID" != "15b3:cb84" ]] && return + mlxsw_only_on_spectrum 1 || return tc qdisc add dev $swp1 clsact diff --git a/tools/testing/selftests/drivers/net/mlxsw/tc_sample.sh b/tools/testing/selftests/drivers/net/mlxsw/tc_sample.sh index 373d5f2a846e..83a0210e7544 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/tc_sample.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/tc_sample.sh @@ -51,6 +51,7 @@ NUM_NETIFS=8 CAPTURE_FILE=$(mktemp) source $lib_dir/lib.sh source $lib_dir/devlink_lib.sh +source mlxsw_lib.sh # Available at https://github.com/Mellanox/libpsample require_command psample @@ -431,7 +432,7 @@ tc_sample_md_out_tc_test() RET=0 # Output traffic class is not supported on Spectrum-1. - [[ "$DEVLINK_VIDDID" == "15b3:cb84" ]] && return + mlxsw_only_on_spectrum 2+ || return tc filter add dev $rp1 ingress protocol all pref 1 handle 101 matchall \ skip_sw action sample rate 5 group 1 @@ -477,7 +478,7 @@ tc_sample_md_out_tc_occ_test() RET=0 # Output traffic class occupancy is not supported on Spectrum-1. - [[ "$DEVLINK_VIDDID" == "15b3:cb84" ]] && return + mlxsw_only_on_spectrum 2+ || return tc filter add dev $rp1 ingress protocol all pref 1 handle 101 matchall \ skip_sw action sample rate 1024 group 1 @@ -521,7 +522,7 @@ tc_sample_md_latency_test() RET=0 # Egress sampling not supported on Spectrum-1. - [[ "$DEVLINK_VIDDID" == "15b3:cb84" ]] && return + mlxsw_only_on_spectrum 2+ || return tc filter add dev $rp2 egress protocol all pref 1 handle 101 matchall \ skip_sw action sample rate 5 group 1 @@ -550,7 +551,7 @@ tc_sample_acl_group_conflict_test() # port with different groups. # Policy-based sampling is not supported on Spectrum-1. - [[ "$DEVLINK_VIDDID" == "15b3:cb84" ]] && return + mlxsw_only_on_spectrum 2+ || return tc filter add dev $rp1 ingress protocol ip pref 1 handle 101 flower \ skip_sw action sample rate 1024 group 1 @@ -579,7 +580,7 @@ __tc_sample_acl_rate_test() RET=0 # Policy-based sampling is not supported on Spectrum-1. - [[ "$DEVLINK_VIDDID" == "15b3:cb84" ]] && return + mlxsw_only_on_spectrum 2+ || return tc filter add dev $port $bind protocol ip pref 1 handle 101 flower \ skip_sw dst_ip 198.51.100.1 action sample rate 32 group 1 @@ -631,7 +632,7 @@ tc_sample_acl_max_rate_test() RET=0 # Policy-based sampling is not supported on Spectrum-1. - [[ "$DEVLINK_VIDDID" == "15b3:cb84" ]] && return + mlxsw_only_on_spectrum 2+ || return tc filter add dev $rp1 ingress protocol ip pref 1 handle 101 flower \ skip_sw action sample rate $((2 ** 24 - 1)) group 1 diff --git a/tools/testing/selftests/net/forwarding/devlink_lib.sh b/tools/testing/selftests/net/forwarding/devlink_lib.sh index 2c14a86adaaa..de9944d42027 100644 --- a/tools/testing/selftests/net/forwarding/devlink_lib.sh +++ b/tools/testing/selftests/net/forwarding/devlink_lib.sh @@ -563,12 +563,6 @@ devlink_trap_group_policer_get() | jq '.[][][]["policer"]' } -devlink_trap_policer_ids_get() -{ - devlink -j -p trap policer show \ - | jq '.[]["'$DEVLINK_DEV'"][]["policer"]' -} - devlink_port_by_netdev() { local if_name=$1 diff --git a/tools/testing/selftests/net/forwarding/lib.sh b/tools/testing/selftests/net/forwarding/lib.sh index 92087d423bcf..dfd827b7a9f9 100644 --- a/tools/testing/selftests/net/forwarding/lib.sh +++ b/tools/testing/selftests/net/forwarding/lib.sh @@ -23,6 +23,8 @@ MC_CLI=${MC_CLI:=smcroutectl} PING_TIMEOUT=${PING_TIMEOUT:=5} WAIT_TIMEOUT=${WAIT_TIMEOUT:=20} INTERFACE_TIMEOUT=${INTERFACE_TIMEOUT:=600} +REQUIRE_JQ=${REQUIRE_JQ:=yes} +REQUIRE_MZ=${REQUIRE_MZ:=yes} relative_path="${BASH_SOURCE%/*}" if [[ "$relative_path" == "${BASH_SOURCE}" ]]; then @@ -141,8 +143,12 @@ require_command() fi } -require_command jq -require_command $MZ +if [[ "$REQUIRE_JQ" = "yes" ]]; then + require_command jq +fi +if [[ "$REQUIRE_MZ" = "yes" ]]; then + require_command $MZ +fi if [[ ! -v NUM_NETIFS ]]; then echo "SKIP: importer does not define \"NUM_NETIFS\"" @@ -280,6 +286,15 @@ log_test() return 0 } +log_test_skip() +{ + local test_name=$1 + local opt_str=$2 + + printf "TEST: %-60s [SKIP]\n" "$test_name $opt_str" + return 0 +} + log_info() { local msg=$1 |