Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
authorDavid S. Miller <davem@davemloft.net>
Tue, 6 Oct 2020 00:33:26 +0000 (17:33 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 6 Oct 2020 01:40:01 +0000 (18:40 -0700)
Rejecting non-native endian BTF overlapped with the addition
of support for it.

The rest were more simple overlapping changes, except the
renesas ravb binding update, which had to follow a file
move as well as a YAML conversion.

Signed-off-by: David S. Miller <davem@davemloft.net>
78 files changed:
1  2 
Documentation/devicetree/bindings/net/renesas,etheravb.yaml
MAINTAINERS
Makefile
drivers/net/dsa/microchip/ksz_common.c
drivers/net/dsa/ocelot/felix_vsc9959.c
drivers/net/dsa/ocelot/seville_vsc9953.c
drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
drivers/net/ethernet/freescale/dpaa2/dpni-cmd.h
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/intel/ice/ice_fw_update.c
drivers/net/ethernet/intel/ice/ice_lib.c
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/marvell/octeontx2/af/mbox.c
drivers/net/ethernet/marvell/octeontx2/af/mbox.h
drivers/net/ethernet/marvell/octeontx2/af/rvu.h
drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
drivers/net/ethernet/marvell/prestera/prestera_main.c
drivers/net/ethernet/mellanox/mlx5/core/cmd.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
drivers/net/ethernet/mellanox/mlx5/core/eq.c
drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h
drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/realtek/r8169_main.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/rocker/rocker_main.c
drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/via/via-rhine.c
drivers/net/mdio/Kconfig
drivers/net/phy/realtek.c
drivers/net/team/team.c
drivers/net/virtio_net.c
drivers/net/wan/x25_asy.c
drivers/net/wireless/mediatek/mt76/mt7615/init.c
drivers/net/wireless/quantenna/qtnfmac/core.c
fs/io_uring.c
include/linux/mlx5/driver.h
include/linux/net.h
include/linux/netdevice.h
include/net/genetlink.h
include/net/ip.h
include/net/xfrm.h
mm/filemap.c
mm/page_alloc.c
net/bridge/br_vlan.c
net/core/dev.c
net/core/skbuff.c
net/ipv4/syncookies.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/mptcp/options.c
net/mptcp/protocol.c
net/mptcp/protocol.h
net/mptcp/subflow.c
net/sched/act_api.c
net/sched/act_ct.c
net/sched/act_ctinfo.c
net/sched/act_gate.c
net/sched/act_mpls.c
net/sched/act_vlan.c
net/socket.c
net/xdp/xsk.c
net/xfrm/xfrm_state.c
tools/bpf/bpftool/Makefile
tools/lib/bpf/libbpf.c

index e136530,0000000..244befb
mode 100644,000000..100644
--- /dev/null
@@@ -1,261 -1,0 +1,262 @@@
 +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 +%YAML 1.2
 +---
 +$id: http://devicetree.org/schemas/net/renesas,etheravb.yaml#
 +$schema: http://devicetree.org/meta-schemas/core.yaml#
 +
 +title: Renesas Ethernet AVB
 +
 +maintainers:
 +  - Sergei Shtylyov <sergei.shtylyov@gmail.com>
 +
 +properties:
 +  compatible:
 +    oneOf:
 +      - items:
 +          - enum:
 +              - renesas,etheravb-r8a7742      # RZ/G1H
 +              - renesas,etheravb-r8a7743      # RZ/G1M
 +              - renesas,etheravb-r8a7744      # RZ/G1N
 +              - renesas,etheravb-r8a7745      # RZ/G1E
 +              - renesas,etheravb-r8a77470     # RZ/G1C
 +              - renesas,etheravb-r8a7790      # R-Car H2
 +              - renesas,etheravb-r8a7791      # R-Car M2-W
 +              - renesas,etheravb-r8a7792      # R-Car V2H
 +              - renesas,etheravb-r8a7793      # R-Car M2-N
 +              - renesas,etheravb-r8a7794      # R-Car E2
 +          - const: renesas,etheravb-rcar-gen2 # R-Car Gen2 and RZ/G1
 +
 +      - items:
 +          - enum:
 +              - renesas,etheravb-r8a774a1     # RZ/G2M
 +              - renesas,etheravb-r8a774b1     # RZ/G2N
 +              - renesas,etheravb-r8a774c0     # RZ/G2E
++              - renesas,etheravb-r8a774e1     # RZ/G2H
 +              - renesas,etheravb-r8a7795      # R-Car H3
 +              - renesas,etheravb-r8a7796      # R-Car M3-W
 +              - renesas,etheravb-r8a77961     # R-Car M3-W+
 +              - renesas,etheravb-r8a77965     # R-Car M3-N
 +              - renesas,etheravb-r8a77970     # R-Car V3M
 +              - renesas,etheravb-r8a77980     # R-Car V3H
 +              - renesas,etheravb-r8a77990     # R-Car E3
 +              - renesas,etheravb-r8a77995     # R-Car D3
 +          - const: renesas,etheravb-rcar-gen3 # R-Car Gen3 and RZ/G2
 +
 +  reg: true
 +
 +  interrupts: true
 +
 +  interrupt-names: true
 +
 +  clocks:
 +    maxItems: 1
 +
 +  iommus:
 +    maxItems: 1
 +
 +  power-domains:
 +    maxItems: 1
 +
 +  resets:
 +    maxItems: 1
 +
 +  phy-mode: true
 +
 +  phy-handle: true
 +
 +  '#address-cells':
 +    description: Number of address cells for the MDIO bus.
 +    const: 1
 +
 +  '#size-cells':
 +    description: Number of size cells on the MDIO bus.
 +    const: 0
 +
 +  renesas,no-ether-link:
 +    type: boolean
 +    description:
 +      Specify when a board does not provide a proper AVB_LINK signal.
 +
 +  renesas,ether-link-active-low:
 +    type: boolean
 +    description:
 +      Specify when the AVB_LINK signal is active-low instead of normal
 +      active-high.
 +
 +  rx-internal-delay-ps:
 +    enum: [0, 1800]
 +
 +  tx-internal-delay-ps:
 +    enum: [0, 2000]
 +
 +patternProperties:
 +  "^ethernet-phy@[0-9a-f]$":
 +    type: object
 +    $ref: ethernet-phy.yaml#
 +
 +required:
 +  - compatible
 +  - reg
 +  - interrupts
 +  - clocks
 +  - power-domains
 +  - resets
 +  - phy-mode
 +  - phy-handle
 +  - '#address-cells'
 +  - '#size-cells'
 +
 +allOf:
 +  - $ref: ethernet-controller.yaml#
 +
 +  - if:
 +      properties:
 +        compatible:
 +          contains:
 +            enum:
 +              - renesas,etheravb-rcar-gen2
 +              - renesas,etheravb-r8a7795
 +              - renesas,etheravb-r8a7796
 +              - renesas,etheravb-r8a77961
 +              - renesas,etheravb-r8a77965
 +    then:
 +      properties:
 +        reg:
 +          items:
 +            - description: MAC register block
 +            - description: Stream buffer
 +    else:
 +      properties:
 +        reg:
 +          items:
 +            - description: MAC register block
 +
 +  - if:
 +      properties:
 +        compatible:
 +          contains:
 +            const: renesas,etheravb-rcar-gen2
 +    then:
 +      properties:
 +        interrupts:
 +          maxItems: 1
 +        interrupt-names:
 +          items:
 +            - const: mux
 +        rx-internal-delay-ps: false
 +    else:
 +      properties:
 +        interrupts:
 +          minItems: 25
 +          maxItems: 25
 +        interrupt-names:
 +          items:
 +            pattern: '^ch[0-9]+$'
 +      required:
 +        - interrupt-names
 +        - rx-internal-delay-ps
 +
 +  - if:
 +      properties:
 +        compatible:
 +          contains:
 +            enum:
 +              - renesas,etheravb-r8a774a1
 +              - renesas,etheravb-r8a774b1
 +              - renesas,etheravb-r8a7795
 +              - renesas,etheravb-r8a7796
 +              - renesas,etheravb-r8a77961
 +              - renesas,etheravb-r8a77965
 +              - renesas,etheravb-r8a77970
 +              - renesas,etheravb-r8a77980
 +    then:
 +      required:
 +        - tx-internal-delay-ps
 +    else:
 +      properties:
 +        tx-internal-delay-ps: false
 +
 +  - if:
 +      properties:
 +        compatible:
 +          contains:
 +            const: renesas,etheravb-r8a77995
 +    then:
 +      properties:
 +        rx-internal-delay-ps:
 +          const: 1800
 +
 +  - if:
 +      properties:
 +        compatible:
 +          contains:
 +            const: renesas,etheravb-r8a77980
 +    then:
 +      properties:
 +        tx-internal-delay-ps:
 +          const: 2000
 +
 +additionalProperties: false
 +
 +examples:
 +  - |
 +    #include <dt-bindings/clock/r8a7795-cpg-mssr.h>
 +    #include <dt-bindings/interrupt-controller/arm-gic.h>
 +    #include <dt-bindings/power/r8a7795-sysc.h>
 +    #include <dt-bindings/gpio/gpio.h>
 +    aliases {
 +            ethernet0 = &avb;
 +    };
 +
 +    avb: ethernet@e6800000 {
 +            compatible = "renesas,etheravb-r8a7795",
 +                         "renesas,etheravb-rcar-gen3";
 +            reg = <0xe6800000 0x800>, <0xe6a00000 0x10000>;
 +            interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>,
 +                         <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
 +            interrupt-names = "ch0", "ch1", "ch2", "ch3", "ch4", "ch5", "ch6",
 +                              "ch7", "ch8", "ch9", "ch10", "ch11", "ch12",
 +                              "ch13", "ch14", "ch15", "ch16", "ch17", "ch18",
 +                              "ch19", "ch20", "ch21", "ch22", "ch23", "ch24";
 +            clocks = <&cpg CPG_MOD 812>;
 +            iommus = <&ipmmu_ds0 16>;
 +            power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 +            resets = <&cpg 812>;
 +            phy-mode = "rgmii";
 +            phy-handle = <&phy0>;
 +            rx-internal-delay-ps = <0>;
 +            tx-internal-delay-ps = <2000>;
 +            #address-cells = <1>;
 +            #size-cells = <0>;
 +
 +            phy0: ethernet-phy@0 {
 +                    rxc-skew-ps = <1500>;
 +                    reg = <0>;
 +                    interrupt-parent = <&gpio2>;
 +                    interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
 +                    reset-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
 +            };
 +    };
diff --cc MAINTAINERS
Simple merge
diff --cc Makefile
Simple merge
@@@ -815,40 -685,23 +815,40 @@@ static struct vcap_field vsc9959_vcap_i
        [VCAP_IS2_ACT_POLICE_ENA]               = {  9,  1},
        [VCAP_IS2_ACT_POLICE_IDX]               = { 10,  9},
        [VCAP_IS2_ACT_POLICE_VCAP_ONLY]         = { 19,  1},
-       [VCAP_IS2_ACT_PORT_MASK]                = { 20, 11},
-       [VCAP_IS2_ACT_REW_OP]                   = { 31,  9},
-       [VCAP_IS2_ACT_SMAC_REPLACE_ENA]         = { 40,  1},
-       [VCAP_IS2_ACT_RSV]                      = { 41,  2},
-       [VCAP_IS2_ACT_ACL_ID]                   = { 43,  6},
-       [VCAP_IS2_ACT_HIT_CNT]                  = { 49, 32},
+       [VCAP_IS2_ACT_PORT_MASK]                = { 20,  6},
+       [VCAP_IS2_ACT_REW_OP]                   = { 26,  9},
+       [VCAP_IS2_ACT_SMAC_REPLACE_ENA]         = { 35,  1},
+       [VCAP_IS2_ACT_RSV]                      = { 36,  2},
+       [VCAP_IS2_ACT_ACL_ID]                   = { 38,  6},
+       [VCAP_IS2_ACT_HIT_CNT]                  = { 44, 32},
  };
  
 -static const struct vcap_props vsc9959_vcap_props[] = {
 +static struct vcap_props vsc9959_vcap_props[] = {
 +      [VCAP_ES0] = {
 +              .action_type_width = 0,
 +              .action_table = {
 +                      [ES0_ACTION_TYPE_NORMAL] = {
 +                              .width = 72, /* HIT_STICKY not included */
 +                              .count = 1,
 +                      },
 +              },
 +              .target = S0,
 +              .keys = vsc9959_vcap_es0_keys,
 +              .actions = vsc9959_vcap_es0_actions,
 +      },
 +      [VCAP_IS1] = {
 +              .action_type_width = 0,
 +              .action_table = {
 +                      [IS1_ACTION_TYPE_NORMAL] = {
 +                              .width = 78, /* HIT_STICKY not included */
 +                              .count = 4,
 +                      },
 +              },
 +              .target = S1,
 +              .keys = vsc9959_vcap_is1_keys,
 +              .actions = vsc9959_vcap_is1_actions,
 +      },
        [VCAP_IS2] = {
 -              .tg_width = 2,
 -              .sw_count = 4,
 -              .entry_count = VSC9959_VCAP_IS2_CNT,
 -              .entry_width = VSC9959_VCAP_IS2_ENTRY_WIDTH,
 -              .action_count = VSC9959_VCAP_IS2_CNT +
 -                              VSC9959_VCAP_PORT_CNT + 2,
 -              .action_width = 89,
                .action_type_width = 1,
                .action_table = {
                        [IS2_ACTION_TYPE_NORMAL] = {
Simple merge
index 9bd57b8,0000000..0f20e07
mode 100644,000000..100644
--- /dev/null
@@@ -1,663 -1,0 +1,667 @@@
- static int prestera_lower_dev_walk(struct net_device *dev, void *data)
 +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
 +/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
 +
 +#include <linux/etherdevice.h>
 +#include <linux/jiffies.h>
 +#include <linux/list.h>
 +#include <linux/module.h>
 +#include <linux/netdev_features.h>
 +#include <linux/of.h>
 +#include <linux/of_net.h>
 +
 +#include "prestera.h"
 +#include "prestera_hw.h"
 +#include "prestera_rxtx.h"
 +#include "prestera_devlink.h"
 +#include "prestera_ethtool.h"
 +#include "prestera_switchdev.h"
 +
 +#define PRESTERA_MTU_DEFAULT  1536
 +
 +#define PRESTERA_STATS_DELAY_MS       1000
 +
 +#define PRESTERA_MAC_ADDR_NUM_MAX     255
 +
 +static struct workqueue_struct *prestera_wq;
 +
 +int prestera_port_pvid_set(struct prestera_port *port, u16 vid)
 +{
 +      enum prestera_accept_frm_type frm_type;
 +      int err;
 +
 +      frm_type = PRESTERA_ACCEPT_FRAME_TYPE_TAGGED;
 +
 +      if (vid) {
 +              err = prestera_hw_vlan_port_vid_set(port, vid);
 +              if (err)
 +                      return err;
 +
 +              frm_type = PRESTERA_ACCEPT_FRAME_TYPE_ALL;
 +      }
 +
 +      err = prestera_hw_port_accept_frm_type(port, frm_type);
 +      if (err && frm_type == PRESTERA_ACCEPT_FRAME_TYPE_ALL)
 +              prestera_hw_vlan_port_vid_set(port, port->pvid);
 +
 +      port->pvid = vid;
 +      return 0;
 +}
 +
 +struct prestera_port *prestera_port_find_by_hwid(struct prestera_switch *sw,
 +                                               u32 dev_id, u32 hw_id)
 +{
 +      struct prestera_port *port = NULL;
 +
 +      read_lock(&sw->port_list_lock);
 +      list_for_each_entry(port, &sw->port_list, list) {
 +              if (port->dev_id == dev_id && port->hw_id == hw_id)
 +                      break;
 +      }
 +      read_unlock(&sw->port_list_lock);
 +
 +      return port;
 +}
 +
 +struct prestera_port *prestera_find_port(struct prestera_switch *sw, u32 id)
 +{
 +      struct prestera_port *port = NULL;
 +
 +      read_lock(&sw->port_list_lock);
 +      list_for_each_entry(port, &sw->port_list, list) {
 +              if (port->id == id)
 +                      break;
 +      }
 +      read_unlock(&sw->port_list_lock);
 +
 +      return port;
 +}
 +
 +static int prestera_port_open(struct net_device *dev)
 +{
 +      struct prestera_port *port = netdev_priv(dev);
 +      int err;
 +
 +      err = prestera_hw_port_state_set(port, true);
 +      if (err)
 +              return err;
 +
 +      netif_start_queue(dev);
 +
 +      return 0;
 +}
 +
 +static int prestera_port_close(struct net_device *dev)
 +{
 +      struct prestera_port *port = netdev_priv(dev);
 +      int err;
 +
 +      netif_stop_queue(dev);
 +
 +      err = prestera_hw_port_state_set(port, false);
 +      if (err)
 +              return err;
 +
 +      return 0;
 +}
 +
 +static netdev_tx_t prestera_port_xmit(struct sk_buff *skb,
 +                                    struct net_device *dev)
 +{
 +      return prestera_rxtx_xmit(netdev_priv(dev), skb);
 +}
 +
 +static int prestera_is_valid_mac_addr(struct prestera_port *port, u8 *addr)
 +{
 +      if (!is_valid_ether_addr(addr))
 +              return -EADDRNOTAVAIL;
 +
 +      /* firmware requires that port's MAC address contains first 5 bytes
 +       * of the base MAC address
 +       */
 +      if (memcmp(port->sw->base_mac, addr, ETH_ALEN - 1))
 +              return -EINVAL;
 +
 +      return 0;
 +}
 +
 +static int prestera_port_set_mac_address(struct net_device *dev, void *p)
 +{
 +      struct prestera_port *port = netdev_priv(dev);
 +      struct sockaddr *addr = p;
 +      int err;
 +
 +      err = prestera_is_valid_mac_addr(port, addr->sa_data);
 +      if (err)
 +              return err;
 +
 +      err = prestera_hw_port_mac_set(port, addr->sa_data);
 +      if (err)
 +              return err;
 +
 +      ether_addr_copy(dev->dev_addr, addr->sa_data);
 +
 +      return 0;
 +}
 +
 +static int prestera_port_change_mtu(struct net_device *dev, int mtu)
 +{
 +      struct prestera_port *port = netdev_priv(dev);
 +      int err;
 +
 +      err = prestera_hw_port_mtu_set(port, mtu);
 +      if (err)
 +              return err;
 +
 +      dev->mtu = mtu;
 +
 +      return 0;
 +}
 +
 +static void prestera_port_get_stats64(struct net_device *dev,
 +                                    struct rtnl_link_stats64 *stats)
 +{
 +      struct prestera_port *port = netdev_priv(dev);
 +      struct prestera_port_stats *port_stats = &port->cached_hw_stats.stats;
 +
 +      stats->rx_packets = port_stats->broadcast_frames_received +
 +                              port_stats->multicast_frames_received +
 +                              port_stats->unicast_frames_received;
 +
 +      stats->tx_packets = port_stats->broadcast_frames_sent +
 +                              port_stats->multicast_frames_sent +
 +                              port_stats->unicast_frames_sent;
 +
 +      stats->rx_bytes = port_stats->good_octets_received;
 +
 +      stats->tx_bytes = port_stats->good_octets_sent;
 +
 +      stats->rx_errors = port_stats->rx_error_frame_received;
 +      stats->tx_errors = port_stats->mac_trans_error;
 +
 +      stats->rx_dropped = port_stats->buffer_overrun;
 +      stats->tx_dropped = 0;
 +
 +      stats->multicast = port_stats->multicast_frames_received;
 +      stats->collisions = port_stats->excessive_collision;
 +
 +      stats->rx_crc_errors = port_stats->bad_crc;
 +}
 +
 +static void prestera_port_get_hw_stats(struct prestera_port *port)
 +{
 +      prestera_hw_port_stats_get(port, &port->cached_hw_stats.stats);
 +}
 +
 +static void prestera_port_stats_update(struct work_struct *work)
 +{
 +      struct prestera_port *port =
 +              container_of(work, struct prestera_port,
 +                           cached_hw_stats.caching_dw.work);
 +
 +      prestera_port_get_hw_stats(port);
 +
 +      queue_delayed_work(prestera_wq, &port->cached_hw_stats.caching_dw,
 +                         msecs_to_jiffies(PRESTERA_STATS_DELAY_MS));
 +}
 +
 +static const struct net_device_ops prestera_netdev_ops = {
 +      .ndo_open = prestera_port_open,
 +      .ndo_stop = prestera_port_close,
 +      .ndo_start_xmit = prestera_port_xmit,
 +      .ndo_change_mtu = prestera_port_change_mtu,
 +      .ndo_get_stats64 = prestera_port_get_stats64,
 +      .ndo_set_mac_address = prestera_port_set_mac_address,
 +      .ndo_get_devlink_port = prestera_devlink_get_port,
 +};
 +
 +int prestera_port_autoneg_set(struct prestera_port *port, bool enable,
 +                            u64 adver_link_modes, u8 adver_fec)
 +{
 +      bool refresh = false;
 +      u64 link_modes;
 +      int err;
 +      u8 fec;
 +
 +      if (port->caps.type != PRESTERA_PORT_TYPE_TP)
 +              return enable ? -EINVAL : 0;
 +
 +      if (!enable)
 +              goto set_autoneg;
 +
 +      link_modes = port->caps.supp_link_modes & adver_link_modes;
 +      fec = port->caps.supp_fec & adver_fec;
 +
 +      if (!link_modes && !fec)
 +              return -EOPNOTSUPP;
 +
 +      if (link_modes && port->adver_link_modes != link_modes) {
 +              port->adver_link_modes = link_modes;
 +              refresh = true;
 +      }
 +
 +      if (fec && port->adver_fec != fec) {
 +              port->adver_fec = fec;
 +              refresh = true;
 +      }
 +
 +set_autoneg:
 +      if (port->autoneg == enable && !refresh)
 +              return 0;
 +
 +      err = prestera_hw_port_autoneg_set(port, enable, port->adver_link_modes,
 +                                         port->adver_fec);
 +      if (err)
 +              return err;
 +
 +      port->autoneg = enable;
 +
 +      return 0;
 +}
 +
 +static void prestera_port_list_add(struct prestera_port *port)
 +{
 +      write_lock(&port->sw->port_list_lock);
 +      list_add(&port->list, &port->sw->port_list);
 +      write_unlock(&port->sw->port_list_lock);
 +}
 +
 +static void prestera_port_list_del(struct prestera_port *port)
 +{
 +      write_lock(&port->sw->port_list_lock);
 +      list_del(&port->list);
 +      write_unlock(&port->sw->port_list_lock);
 +}
 +
 +static int prestera_port_create(struct prestera_switch *sw, u32 id)
 +{
 +      struct prestera_port *port;
 +      struct net_device *dev;
 +      int err;
 +
 +      dev = alloc_etherdev(sizeof(*port));
 +      if (!dev)
 +              return -ENOMEM;
 +
 +      port = netdev_priv(dev);
 +
 +      INIT_LIST_HEAD(&port->vlans_list);
 +      port->pvid = PRESTERA_DEFAULT_VID;
 +      port->dev = dev;
 +      port->id = id;
 +      port->sw = sw;
 +
 +      err = prestera_hw_port_info_get(port, &port->dev_id, &port->hw_id,
 +                                      &port->fp_id);
 +      if (err) {
 +              dev_err(prestera_dev(sw), "Failed to get port(%u) info\n", id);
 +              goto err_port_info_get;
 +      }
 +
 +      err = prestera_devlink_port_register(port);
 +      if (err)
 +              goto err_dl_port_register;
 +
 +      dev->features |= NETIF_F_NETNS_LOCAL;
 +      dev->netdev_ops = &prestera_netdev_ops;
 +      dev->ethtool_ops = &prestera_ethtool_ops;
 +
 +      netif_carrier_off(dev);
 +
 +      dev->mtu = min_t(unsigned int, sw->mtu_max, PRESTERA_MTU_DEFAULT);
 +      dev->min_mtu = sw->mtu_min;
 +      dev->max_mtu = sw->mtu_max;
 +
 +      err = prestera_hw_port_mtu_set(port, dev->mtu);
 +      if (err) {
 +              dev_err(prestera_dev(sw), "Failed to set port(%u) mtu(%d)\n",
 +                      id, dev->mtu);
 +              goto err_port_init;
 +      }
 +
 +      if (port->fp_id >= PRESTERA_MAC_ADDR_NUM_MAX)
 +              goto err_port_init;
 +
 +      /* firmware requires that port's MAC address consist of the first
 +       * 5 bytes of the base MAC address
 +       */
 +      memcpy(dev->dev_addr, sw->base_mac, dev->addr_len - 1);
 +      dev->dev_addr[dev->addr_len - 1] = port->fp_id;
 +
 +      err = prestera_hw_port_mac_set(port, dev->dev_addr);
 +      if (err) {
 +              dev_err(prestera_dev(sw), "Failed to set port(%u) mac addr\n", id);
 +              goto err_port_init;
 +      }
 +
 +      err = prestera_hw_port_cap_get(port, &port->caps);
 +      if (err) {
 +              dev_err(prestera_dev(sw), "Failed to get port(%u) caps\n", id);
 +              goto err_port_init;
 +      }
 +
 +      port->adver_fec = BIT(PRESTERA_PORT_FEC_OFF);
 +      prestera_port_autoneg_set(port, true, port->caps.supp_link_modes,
 +                                port->caps.supp_fec);
 +
 +      err = prestera_hw_port_state_set(port, false);
 +      if (err) {
 +              dev_err(prestera_dev(sw), "Failed to set port(%u) down\n", id);
 +              goto err_port_init;
 +      }
 +
 +      err = prestera_rxtx_port_init(port);
 +      if (err)
 +              goto err_port_init;
 +
 +      INIT_DELAYED_WORK(&port->cached_hw_stats.caching_dw,
 +                        &prestera_port_stats_update);
 +
 +      prestera_port_list_add(port);
 +
 +      err = register_netdev(dev);
 +      if (err)
 +              goto err_register_netdev;
 +
 +      prestera_devlink_port_set(port);
 +
 +      return 0;
 +
 +err_register_netdev:
 +      prestera_port_list_del(port);
 +err_port_init:
 +      prestera_devlink_port_unregister(port);
 +err_dl_port_register:
 +err_port_info_get:
 +      free_netdev(dev);
 +      return err;
 +}
 +
 +static void prestera_port_destroy(struct prestera_port *port)
 +{
 +      struct net_device *dev = port->dev;
 +
 +      cancel_delayed_work_sync(&port->cached_hw_stats.caching_dw);
 +      prestera_devlink_port_clear(port);
 +      unregister_netdev(dev);
 +      prestera_port_list_del(port);
 +      prestera_devlink_port_unregister(port);
 +      free_netdev(dev);
 +}
 +
 +static void prestera_destroy_ports(struct prestera_switch *sw)
 +{
 +      struct prestera_port *port, *tmp;
 +
 +      list_for_each_entry_safe(port, tmp, &sw->port_list, list)
 +              prestera_port_destroy(port);
 +}
 +
 +static int prestera_create_ports(struct prestera_switch *sw)
 +{
 +      struct prestera_port *port, *tmp;
 +      u32 port_idx;
 +      int err;
 +
 +      for (port_idx = 0; port_idx < sw->port_count; port_idx++) {
 +              err = prestera_port_create(sw, port_idx);
 +              if (err)
 +                      goto err_port_create;
 +      }
 +
 +      return 0;
 +
 +err_port_create:
 +      list_for_each_entry_safe(port, tmp, &sw->port_list, list)
 +              prestera_port_destroy(port);
 +
 +      return err;
 +}
 +
 +static void prestera_port_handle_event(struct prestera_switch *sw,
 +                                     struct prestera_event *evt, void *arg)
 +{
 +      struct delayed_work *caching_dw;
 +      struct prestera_port *port;
 +
 +      port = prestera_find_port(sw, evt->port_evt.port_id);
 +      if (!port || !port->dev)
 +              return;
 +
 +      caching_dw = &port->cached_hw_stats.caching_dw;
 +
 +      if (evt->id == PRESTERA_PORT_EVENT_STATE_CHANGED) {
 +              if (evt->port_evt.data.oper_state) {
 +                      netif_carrier_on(port->dev);
 +                      if (!delayed_work_pending(caching_dw))
 +                              queue_delayed_work(prestera_wq, caching_dw, 0);
 +              } else {
 +                      netif_carrier_off(port->dev);
 +                      if (delayed_work_pending(caching_dw))
 +                              cancel_delayed_work(caching_dw);
 +              }
 +      }
 +}
 +
 +static int prestera_event_handlers_register(struct prestera_switch *sw)
 +{
 +      return prestera_hw_event_handler_register(sw, PRESTERA_EVENT_TYPE_PORT,
 +                                                prestera_port_handle_event,
 +                                                NULL);
 +}
 +
 +static void prestera_event_handlers_unregister(struct prestera_switch *sw)
 +{
 +      prestera_hw_event_handler_unregister(sw, PRESTERA_EVENT_TYPE_PORT,
 +                                           prestera_port_handle_event);
 +}
 +
 +static int prestera_switch_set_base_mac_addr(struct prestera_switch *sw)
 +{
 +      struct device_node *base_mac_np;
 +      struct device_node *np;
 +      const char *base_mac;
 +
 +      np = of_find_compatible_node(NULL, NULL, "marvell,prestera");
 +      base_mac_np = of_parse_phandle(np, "base-mac-provider", 0);
 +
 +      base_mac = of_get_mac_address(base_mac_np);
 +      of_node_put(base_mac_np);
 +      if (!IS_ERR(base_mac))
 +              ether_addr_copy(sw->base_mac, base_mac);
 +
 +      if (!is_valid_ether_addr(sw->base_mac)) {
 +              eth_random_addr(sw->base_mac);
 +              dev_info(prestera_dev(sw), "using random base mac address\n");
 +      }
 +
 +      return prestera_hw_switch_mac_set(sw, sw->base_mac);
 +}
 +
 +bool prestera_netdev_check(const struct net_device *dev)
 +{
 +      return dev->netdev_ops == &prestera_netdev_ops;
 +}
 +
-       struct prestera_port **pport = data;
++static int prestera_lower_dev_walk(struct net_device *dev,
++                                 struct netdev_nested_priv *priv)
 +{
-       netdev_walk_all_lower_dev(dev, prestera_lower_dev_walk, &port);
++      struct prestera_port **pport = (struct prestera_port **)priv->data;
 +
 +      if (prestera_netdev_check(dev)) {
 +              *pport = netdev_priv(dev);
 +              return 1;
 +      }
 +
 +      return 0;
 +}
 +
 +struct prestera_port *prestera_port_dev_lower_find(struct net_device *dev)
 +{
 +      struct prestera_port *port = NULL;
++      struct netdev_nested_priv priv = {
++              .data = (void *)&port,
++      };
 +
 +      if (prestera_netdev_check(dev))
 +              return netdev_priv(dev);
 +
++      netdev_walk_all_lower_dev(dev, prestera_lower_dev_walk, &priv);
 +
 +      return port;
 +}
 +
 +static int prestera_netdev_port_event(struct net_device *dev,
 +                                    unsigned long event, void *ptr)
 +{
 +      switch (event) {
 +      case NETDEV_PRECHANGEUPPER:
 +      case NETDEV_CHANGEUPPER:
 +              return prestera_bridge_port_event(dev, event, ptr);
 +      default:
 +              return 0;
 +      }
 +}
 +
 +static int prestera_netdev_event_handler(struct notifier_block *nb,
 +                                       unsigned long event, void *ptr)
 +{
 +      struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 +      int err = 0;
 +
 +      if (prestera_netdev_check(dev))
 +              err = prestera_netdev_port_event(dev, event, ptr);
 +
 +      return notifier_from_errno(err);
 +}
 +
 +static int prestera_netdev_event_handler_register(struct prestera_switch *sw)
 +{
 +      sw->netdev_nb.notifier_call = prestera_netdev_event_handler;
 +
 +      return register_netdevice_notifier(&sw->netdev_nb);
 +}
 +
 +static void prestera_netdev_event_handler_unregister(struct prestera_switch *sw)
 +{
 +      unregister_netdevice_notifier(&sw->netdev_nb);
 +}
 +
 +static int prestera_switch_init(struct prestera_switch *sw)
 +{
 +      int err;
 +
 +      err = prestera_hw_switch_init(sw);
 +      if (err) {
 +              dev_err(prestera_dev(sw), "Failed to init Switch device\n");
 +              return err;
 +      }
 +
 +      rwlock_init(&sw->port_list_lock);
 +      INIT_LIST_HEAD(&sw->port_list);
 +
 +      err = prestera_switch_set_base_mac_addr(sw);
 +      if (err)
 +              return err;
 +
 +      err = prestera_netdev_event_handler_register(sw);
 +      if (err)
 +              return err;
 +
 +      err = prestera_switchdev_init(sw);
 +      if (err)
 +              goto err_swdev_register;
 +
 +      err = prestera_rxtx_switch_init(sw);
 +      if (err)
 +              goto err_rxtx_register;
 +
 +      err = prestera_event_handlers_register(sw);
 +      if (err)
 +              goto err_handlers_register;
 +
 +      err = prestera_devlink_register(sw);
 +      if (err)
 +              goto err_dl_register;
 +
 +      err = prestera_create_ports(sw);
 +      if (err)
 +              goto err_ports_create;
 +
 +      return 0;
 +
 +err_ports_create:
 +      prestera_devlink_unregister(sw);
 +err_dl_register:
 +      prestera_event_handlers_unregister(sw);
 +err_handlers_register:
 +      prestera_rxtx_switch_fini(sw);
 +err_rxtx_register:
 +      prestera_switchdev_fini(sw);
 +err_swdev_register:
 +      prestera_netdev_event_handler_unregister(sw);
 +      prestera_hw_switch_fini(sw);
 +
 +      return err;
 +}
 +
 +static void prestera_switch_fini(struct prestera_switch *sw)
 +{
 +      prestera_destroy_ports(sw);
 +      prestera_devlink_unregister(sw);
 +      prestera_event_handlers_unregister(sw);
 +      prestera_rxtx_switch_fini(sw);
 +      prestera_switchdev_fini(sw);
 +      prestera_netdev_event_handler_unregister(sw);
 +      prestera_hw_switch_fini(sw);
 +}
 +
 +int prestera_device_register(struct prestera_device *dev)
 +{
 +      struct prestera_switch *sw;
 +      int err;
 +
 +      sw = prestera_devlink_alloc();
 +      if (!sw)
 +              return -ENOMEM;
 +
 +      dev->priv = sw;
 +      sw->dev = dev;
 +
 +      err = prestera_switch_init(sw);
 +      if (err) {
 +              prestera_devlink_free(sw);
 +              return err;
 +      }
 +
 +      return 0;
 +}
 +EXPORT_SYMBOL(prestera_device_register);
 +
 +void prestera_device_unregister(struct prestera_device *dev)
 +{
 +      struct prestera_switch *sw = dev->priv;
 +
 +      prestera_switch_fini(sw);
 +      prestera_devlink_free(sw);
 +}
 +EXPORT_SYMBOL(prestera_device_unregister);
 +
 +static int __init prestera_module_init(void)
 +{
 +      prestera_wq = alloc_workqueue("prestera", 0, 0);
 +      if (!prestera_wq)
 +              return -ENOMEM;
 +
 +      return 0;
 +}
 +
 +static void __exit prestera_module_exit(void)
 +{
 +      destroy_workqueue(prestera_wq);
 +}
 +
 +module_init(prestera_module_init);
 +module_exit(prestera_module_exit);
 +
 +MODULE_LICENSE("Dual BSD/GPL");
 +MODULE_DESCRIPTION("Marvell Prestera switch driver");
Simple merge
index 840727c,0000000..27a2a4a
mode 100644,000000..100644
--- /dev/null
@@@ -1,242 -1,0 +1,243 @@@
 +# SPDX-License-Identifier: GPL-2.0-only
 +#
 +# MDIO Layer Configuration
 +#
 +
 +menuconfig MDIO_DEVICE
 +      tristate "MDIO bus device drivers"
 +      help
 +        MDIO devices and driver infrastructure code.
 +
 +if MDIO_DEVICE
 +
 +config MDIO_BUS
 +      tristate
 +      default m if PHYLIB=m
 +      default MDIO_DEVICE
 +      help
 +        This internal symbol is used for link time dependencies and it
 +        reflects whether the mdio_bus/mdio_device code is built as a
 +        loadable module or built-in.
 +
 +if MDIO_BUS
 +
 +config MDIO_DEVRES
 +      tristate
 +
 +config MDIO_SUN4I
 +      tristate "Allwinner sun4i MDIO interface support"
 +      depends on ARCH_SUNXI || COMPILE_TEST
 +      help
 +        This driver supports the MDIO interface found in the network
 +        interface units of the Allwinner SoC that have an EMAC (A10,
 +        A12, A10s, etc.)
 +
 +config MDIO_XGENE
 +      tristate "APM X-Gene SoC MDIO bus controller"
 +      depends on ARCH_XGENE || COMPILE_TEST
 +      help
 +        This module provides a driver for the MDIO busses found in the
 +        APM X-Gene SoC's.
 +
 +config MDIO_ASPEED
 +      tristate "ASPEED MDIO bus controller"
 +      depends on ARCH_ASPEED || COMPILE_TEST
 +      depends on OF_MDIO && HAS_IOMEM
 +      help
 +        This module provides a driver for the independent MDIO bus
 +        controllers found in the ASPEED AST2600 SoC. This is a driver for the
 +        third revision of the ASPEED MDIO register interface - the first two
 +        revisions are the "old" and "new" interfaces found in the AST2400 and
 +        AST2500, embedded in the MAC. For legacy reasons, FTGMAC100 driver
 +        continues to drive the embedded MDIO controller for the AST2400 and
 +        AST2500 SoCs, so say N if AST2600 support is not required.
 +
 +config MDIO_BITBANG
 +      tristate "Bitbanged MDIO buses"
 +      help
 +        This module implements the MDIO bus protocol in software,
 +        for use by low level drivers that export the ability to
 +        drive the relevant pins.
 +
 +        If in doubt, say N.
 +
 +config MDIO_BCM_IPROC
 +      tristate "Broadcom iProc MDIO bus controller"
 +      depends on ARCH_BCM_IPROC || COMPILE_TEST
 +      depends on HAS_IOMEM && OF_MDIO
 +      default ARCH_BCM_IPROC
 +      help
 +        This module provides a driver for the MDIO busses found in the
 +        Broadcom iProc SoC's.
 +
 +config MDIO_BCM_UNIMAC
 +      tristate "Broadcom UniMAC MDIO bus controller"
 +      depends on HAS_IOMEM
 +      help
 +        This module provides a driver for the Broadcom UniMAC MDIO busses.
 +        This hardware can be found in the Broadcom GENET Ethernet MAC
 +        controllers as well as some Broadcom Ethernet switches such as the
 +        Starfighter 2 switches.
 +
 +config MDIO_CAVIUM
 +      tristate
 +
 +config MDIO_GPIO
 +      tristate "GPIO lib-based bitbanged MDIO buses"
 +      depends on MDIO_BITBANG
 +      depends on GPIOLIB || COMPILE_TEST
 +      help
 +        Supports GPIO lib-based MDIO busses.
 +
 +        To compile this driver as a module, choose M here: the module
 +        will be called mdio-gpio.
 +
 +config MDIO_HISI_FEMAC
 +      tristate "Hisilicon FEMAC MDIO bus controller"
 +      depends on HAS_IOMEM && OF_MDIO
 +      help
 +        This module provides a driver for the MDIO busses found in the
 +        Hisilicon SoC that have an Fast Ethernet MAC.
 +
 +config MDIO_I2C
 +      tristate
 +      depends on I2C
 +      help
 +        Support I2C based PHYs.  This provides a MDIO bus bridged
 +        to I2C to allow PHYs connected in I2C mode to be accessed
 +        using the existing infrastructure.
 +
 +        This is library mode.
 +
 +config MDIO_MVUSB
 +      tristate "Marvell USB to MDIO Adapter"
 +      depends on USB
 +      select MDIO_DEVRES
 +      help
 +        A USB to MDIO converter present on development boards for
 +        Marvell's Link Street family of Ethernet switches.
 +
 +config MDIO_MSCC_MIIM
 +      tristate "Microsemi MIIM interface support"
 +      depends on HAS_IOMEM
 +      select MDIO_DEVRES
 +      help
 +        This driver supports the MIIM (MDIO) interface found in the network
 +        switches of the Microsemi SoCs; it is recommended to switch on
 +        CONFIG_HIGH_RES_TIMERS
 +
 +config MDIO_MOXART
 +      tristate "MOXA ART MDIO interface support"
 +      depends on ARCH_MOXART || COMPILE_TEST
 +      help
 +        This driver supports the MDIO interface found in the network
 +        interface units of the MOXA ART SoC
 +
 +config MDIO_OCTEON
 +      tristate "Octeon and some ThunderX SOCs MDIO buses"
 +      depends on (64BIT && OF_MDIO) || COMPILE_TEST
 +      depends on HAS_IOMEM
 +      select MDIO_CAVIUM
 +      select MDIO_DEVRES
 +      help
 +        This module provides a driver for the Octeon and ThunderX MDIO
 +        buses. It is required by the Octeon and ThunderX ethernet device
 +        drivers on some systems.
 +
 +config MDIO_IPQ4019
 +      tristate "Qualcomm IPQ4019 MDIO interface support"
 +      depends on HAS_IOMEM && OF_MDIO
 +      help
 +        This driver supports the MDIO interface found in Qualcomm
 +        IPQ40xx series Soc-s.
 +
 +config MDIO_IPQ8064
 +      tristate "Qualcomm IPQ8064 MDIO interface support"
 +      depends on HAS_IOMEM && OF_MDIO
 +      depends on MFD_SYSCON
 +      help
 +        This driver supports the MDIO interface found in the network
 +        interface units of the IPQ8064 SoC
 +
 +config MDIO_THUNDER
 +      tristate "ThunderX SOCs MDIO buses"
 +      depends on 64BIT
 +      depends on PCI
 +      select MDIO_CAVIUM
++      select MDIO_DEVRES
 +      help
 +        This driver supports the MDIO interfaces found on Cavium
 +        ThunderX SoCs when the MDIO bus device appears as a PCI
 +        device.
 +
 +comment "MDIO Multiplexers"
 +
 +config MDIO_BUS_MUX
 +      tristate
 +      depends on OF_MDIO
 +      help
 +        This module provides a driver framework for MDIO bus
 +        multiplexers which connect one of several child MDIO busses
 +        to a parent bus.  Switching between child busses is done by
 +        device specific drivers.
 +
 +config MDIO_BUS_MUX_MESON_G12A
 +      tristate "Amlogic G12a based MDIO bus multiplexer"
 +      depends on ARCH_MESON || COMPILE_TEST
 +      depends on OF_MDIO && HAS_IOMEM && COMMON_CLK
 +      select MDIO_BUS_MUX
 +      default m if ARCH_MESON
 +      help
 +        This module provides a driver for the MDIO multiplexer/glue of
 +        the amlogic g12a SoC. The multiplexers connects either the external
 +        or the internal MDIO bus to the parent bus.
 +
 +config MDIO_BUS_MUX_BCM_IPROC
 +      tristate "Broadcom iProc based MDIO bus multiplexers"
 +      depends on OF && OF_MDIO && (ARCH_BCM_IPROC || COMPILE_TEST)
 +      select MDIO_BUS_MUX
 +      default ARCH_BCM_IPROC
 +      help
 +        This module provides a driver for MDIO bus multiplexers found in
 +        iProc based Broadcom SoCs. This multiplexer connects one of several
 +        child MDIO bus to a parent bus. Buses could be internal as well as
 +        external and selection logic lies inside the same multiplexer.
 +
 +config MDIO_BUS_MUX_GPIO
 +      tristate "GPIO controlled MDIO bus multiplexers"
 +      depends on OF_GPIO && OF_MDIO
 +      select MDIO_BUS_MUX
 +      help
 +        This module provides a driver for MDIO bus multiplexers that
 +        are controlled via GPIO lines.  The multiplexer connects one of
 +        several child MDIO busses to a parent bus.  Child bus
 +        selection is under the control of GPIO lines.
 +
 +config MDIO_BUS_MUX_MULTIPLEXER
 +      tristate "MDIO bus multiplexer using kernel multiplexer subsystem"
 +      depends on OF_MDIO
 +      select MULTIPLEXER
 +      select MDIO_BUS_MUX
 +      help
 +        This module provides a driver for MDIO bus multiplexer
 +        that is controlled via the kernel multiplexer subsystem. The
 +        bus multiplexer connects one of several child MDIO busses to
 +        a parent bus.  Child bus selection is under the control of
 +        the kernel multiplexer subsystem.
 +
 +config MDIO_BUS_MUX_MMIOREG
 +      tristate "MMIO device-controlled MDIO bus multiplexers"
 +      depends on OF_MDIO && HAS_IOMEM
 +      select MDIO_BUS_MUX
 +      help
 +        This module provides a driver for MDIO bus multiplexers that
 +        are controlled via a simple memory-mapped device, like an FPGA.
 +        The multiplexer connects one of several child MDIO busses to a
 +        parent bus.  Child bus selection is under the control of one of
 +        the FPGA's registers.
 +
 +        Currently, only 8/16/32 bits registers are supported.
 +
 +
 +endif
 +endif
  #define RTL8211F_TX_DELAY                     BIT(8)
  #define RTL8211F_RX_DELAY                     BIT(3)
  
- #define RTL8211E_TX_DELAY                     BIT(1)
- #define RTL8211E_RX_DELAY                     BIT(2)
- #define RTL8211E_MODE_MII_GMII                        BIT(3)
 +#define RTL8211F_ALDPS_PLL_OFF                        BIT(1)
 +#define RTL8211F_ALDPS_ENABLE                 BIT(2)
 +#define RTL8211F_ALDPS_XTAL_OFF                       BIT(12)
 +
+ #define RTL8211E_CTRL_DELAY                   BIT(13)
+ #define RTL8211E_TX_DELAY                     BIT(12)
+ #define RTL8211E_RX_DELAY                     BIT(11)
  
  #define RTL8201F_ISR                          0x1e
  #define RTL8201F_IER                          0x13
Simple merge
Simple merge
Simple merge
diff --cc fs/io_uring.c
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -137,8 -138,7 +137,9 @@@ struct genl_small_ops 
   * @cmd: command identifier
   * @internal_flags: flags used by the family
   * @flags: flags
 + * @maxattr: maximum number of attributes supported
 + * @policy: netlink policy (takes precedence over family policy)
+  * @validate: validation flags from enum genl_validate_flags
   * @doit: standard command callback
   * @start: start callback for dumps
   * @dumpit: callback for dumpers
Simple merge
Simple merge
diff --cc mm/filemap.c
Simple merge
diff --cc mm/page_alloc.c
Simple merge
Simple merge
diff --cc net/core/dev.c
Simple merge
Simple merge
Simple merge
diff --cc net/ipv4/tcp.c
Simple merge
Simple merge
Simple merge
@@@ -112,205 -112,64 +112,205 @@@ static int __mptcp_socket_create(struc
        return 0;
  }
  
 -static void __mptcp_move_skb(struct mptcp_sock *msk, struct sock *ssk,
 -                           struct sk_buff *skb,
 -                           unsigned int offset, size_t copy_len)
 +static void mptcp_drop(struct sock *sk, struct sk_buff *skb)
 +{
 +      sk_drops_add(sk, skb);
 +      __kfree_skb(skb);
 +}
 +
 +static bool mptcp_try_coalesce(struct sock *sk, struct sk_buff *to,
 +                             struct sk_buff *from)
 +{
 +      bool fragstolen;
 +      int delta;
 +
 +      if (MPTCP_SKB_CB(from)->offset ||
 +          !skb_try_coalesce(to, from, &fragstolen, &delta))
 +              return false;
 +
 +      pr_debug("colesced seq %llx into %llx new len %d new end seq %llx",
 +               MPTCP_SKB_CB(from)->map_seq, MPTCP_SKB_CB(to)->map_seq,
 +               to->len, MPTCP_SKB_CB(from)->end_seq);
 +      MPTCP_SKB_CB(to)->end_seq = MPTCP_SKB_CB(from)->end_seq;
 +      kfree_skb_partial(from, fragstolen);
 +      atomic_add(delta, &sk->sk_rmem_alloc);
 +      sk_mem_charge(sk, delta);
 +      return true;
 +}
 +
 +static bool mptcp_ooo_try_coalesce(struct mptcp_sock *msk, struct sk_buff *to,
 +                                 struct sk_buff *from)
 +{
 +      if (MPTCP_SKB_CB(from)->map_seq != MPTCP_SKB_CB(to)->end_seq)
 +              return false;
 +
 +      return mptcp_try_coalesce((struct sock *)msk, to, from);
 +}
 +
 +/* "inspired" by tcp_data_queue_ofo(), main differences:
 + * - use mptcp seqs
 + * - don't cope with sacks
 + */
 +static void mptcp_data_queue_ofo(struct mptcp_sock *msk, struct sk_buff *skb)
  {
        struct sock *sk = (struct sock *)msk;
 -      struct sk_buff *tail;
 +      struct rb_node **p, *parent;
 +      u64 seq, end_seq, max_seq;
 +      struct sk_buff *skb1;
 +      int space;
 +
 +      seq = MPTCP_SKB_CB(skb)->map_seq;
 +      end_seq = MPTCP_SKB_CB(skb)->end_seq;
 +      space = tcp_space(sk);
 +      max_seq = space > 0 ? space + msk->ack_seq : msk->ack_seq;
 +
 +      pr_debug("msk=%p seq=%llx limit=%llx empty=%d", msk, seq, max_seq,
 +               RB_EMPTY_ROOT(&msk->out_of_order_queue));
 +      if (after64(seq, max_seq)) {
 +              /* out of window */
 +              mptcp_drop(sk, skb);
 +              MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_NODSSWINDOW);
 +              return;
 +      }
  
 -      __skb_unlink(skb, &ssk->sk_receive_queue);
 +      p = &msk->out_of_order_queue.rb_node;
 +      MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_OFOQUEUE);
 +      if (RB_EMPTY_ROOT(&msk->out_of_order_queue)) {
 +              rb_link_node(&skb->rbnode, NULL, p);
 +              rb_insert_color(&skb->rbnode, &msk->out_of_order_queue);
 +              msk->ooo_last_skb = skb;
 +              goto end;
 +      }
  
 -      skb_ext_reset(skb);
 -      skb_orphan(skb);
 -      WRITE_ONCE(msk->ack_seq, msk->ack_seq + copy_len);
 +      /* with 2 subflows, adding at end of ooo queue is quite likely
 +       * Use of ooo_last_skb avoids the O(Log(N)) rbtree lookup.
 +       */
 +      if (mptcp_ooo_try_coalesce(msk, msk->ooo_last_skb, skb)) {
 +              MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_OFOMERGE);
 +              MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_OFOQUEUETAIL);
 +              return;
 +      }
  
 -      tail = skb_peek_tail(&sk->sk_receive_queue);
 -      if (offset == 0 && tail) {
 -              bool fragstolen;
 -              int delta;
 +      /* Can avoid an rbtree lookup if we are adding skb after ooo_last_skb */
 +      if (!before64(seq, MPTCP_SKB_CB(msk->ooo_last_skb)->end_seq)) {
 +              MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_OFOQUEUETAIL);
 +              parent = &msk->ooo_last_skb->rbnode;
 +              p = &parent->rb_right;
 +              goto insert;
 +      }
  
 -              if (skb_try_coalesce(tail, skb, &fragstolen, &delta)) {
 -                      kfree_skb_partial(skb, fragstolen);
 -                      atomic_add(delta, &sk->sk_rmem_alloc);
 -                      sk_mem_charge(sk, delta);
 +      /* Find place to insert this segment. Handle overlaps on the way. */
 +      parent = NULL;
 +      while (*p) {
 +              parent = *p;
 +              skb1 = rb_to_skb(parent);
 +              if (before64(seq, MPTCP_SKB_CB(skb1)->map_seq)) {
 +                      p = &parent->rb_left;
 +                      continue;
 +              }
 +              if (before64(seq, MPTCP_SKB_CB(skb1)->end_seq)) {
 +                      if (!after64(end_seq, MPTCP_SKB_CB(skb1)->end_seq)) {
 +                              /* All the bits are present. Drop. */
 +                              mptcp_drop(sk, skb);
 +                              MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_DUPDATA);
 +                              return;
 +                      }
 +                      if (after64(seq, MPTCP_SKB_CB(skb1)->map_seq)) {
 +                              /* partial overlap:
 +                               *     |     skb      |
 +                               *  |     skb1    |
 +                               * continue traversing
 +                               */
 +                      } else {
 +                              /* skb's seq == skb1's seq and skb covers skb1.
 +                               * Replace skb1 with skb.
 +                               */
 +                              rb_replace_node(&skb1->rbnode, &skb->rbnode,
 +                                              &msk->out_of_order_queue);
 +                              mptcp_drop(sk, skb1);
 +                              MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_DUPDATA);
 +                              goto merge_right;
 +                      }
 +              } else if (mptcp_ooo_try_coalesce(msk, skb1, skb)) {
 +                      MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_OFOMERGE);
                        return;
                }
 +              p = &parent->rb_right;
        }
  
 -      skb_set_owner_r(skb, sk);
 -      __skb_queue_tail(&sk->sk_receive_queue, skb);
 -      MPTCP_SKB_CB(skb)->offset = offset;
 -}
 +insert:
 +      /* Insert segment into RB tree. */
 +      rb_link_node(&skb->rbnode, parent, p);
 +      rb_insert_color(&skb->rbnode, &msk->out_of_order_queue);
  
 -static void mptcp_stop_timer(struct sock *sk)
 -{
 -      struct inet_connection_sock *icsk = inet_csk(sk);
 +merge_right:
 +      /* Remove other segments covered by skb. */
 +      while ((skb1 = skb_rb_next(skb)) != NULL) {
 +              if (before64(end_seq, MPTCP_SKB_CB(skb1)->end_seq))
 +                      break;
 +              rb_erase(&skb1->rbnode, &msk->out_of_order_queue);
 +              mptcp_drop(sk, skb1);
 +              MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_DUPDATA);
 +      }
 +      /* If there is no skb after us, we are the last_skb ! */
 +      if (!skb1)
 +              msk->ooo_last_skb = skb;
  
 -      sk_stop_timer(sk, &icsk->icsk_retransmit_timer);
 -      mptcp_sk(sk)->timer_ival = 0;
 +end:
 +      skb_condense(skb);
 +      skb_set_owner_r(skb, sk);
  }
  
 -/* both sockets must be locked */
 -static bool mptcp_subflow_dsn_valid(const struct mptcp_sock *msk,
 -                                  struct sock *ssk)
 +static bool __mptcp_move_skb(struct mptcp_sock *msk, struct sock *ssk,
 +                           struct sk_buff *skb, unsigned int offset,
 +                           size_t copy_len)
  {
        struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
 -      u64 dsn = mptcp_subflow_get_mapped_dsn(subflow);
 +      struct sock *sk = (struct sock *)msk;
 +      struct sk_buff *tail;
  
 -      /* revalidate data sequence number.
 -       *
 -       * mptcp_subflow_data_available() is usually called
 -       * without msk lock.  Its unlikely (but possible)
 -       * that msk->ack_seq has been advanced since the last
 -       * call found in-sequence data.
 +      __skb_unlink(skb, &ssk->sk_receive_queue);
 +
 +      skb_ext_reset(skb);
 +      skb_orphan(skb);
 +
 +      /* the skb map_seq accounts for the skb offset:
 +       * mptcp_subflow_get_mapped_dsn() is based on the current tp->copied_seq
 +       * value
         */
 -      if (likely(dsn == msk->ack_seq))
 +      MPTCP_SKB_CB(skb)->map_seq = mptcp_subflow_get_mapped_dsn(subflow);
 +      MPTCP_SKB_CB(skb)->end_seq = MPTCP_SKB_CB(skb)->map_seq + copy_len;
 +      MPTCP_SKB_CB(skb)->offset = offset;
 +
 +      if (MPTCP_SKB_CB(skb)->map_seq == msk->ack_seq) {
 +              /* in sequence */
-               msk->ack_seq += copy_len;
++              WRITE_ONCE(msk->ack_seq, msk->ack_seq + copy_len);
 +              tail = skb_peek_tail(&sk->sk_receive_queue);
 +              if (tail && mptcp_try_coalesce(sk, tail, skb))
 +                      return true;
 +
 +              skb_set_owner_r(skb, sk);
 +              __skb_queue_tail(&sk->sk_receive_queue, skb);
                return true;
 +      } else if (after64(MPTCP_SKB_CB(skb)->map_seq, msk->ack_seq)) {
 +              mptcp_data_queue_ofo(msk, skb);
 +              return false;
 +      }
  
 -      subflow->data_avail = 0;
 -      return mptcp_subflow_data_available(ssk);
 +      /* old data, keep it simple and drop the whole pkt, sender
 +       * will retransmit as needed, if needed.
 +       */
 +      MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_DUPDATA);
 +      mptcp_drop(sk, skb);
 +      return false;
 +}
 +
 +static void mptcp_stop_timer(struct sock *sk)
 +{
 +      struct inet_connection_sock *icsk = inet_csk(sk);
 +
 +      sk_stop_timer(sk, &icsk->icsk_retransmit_timer);
 +      mptcp_sk(sk)->timer_ival = 0;
  }
  
  static void mptcp_check_data_fin_ack(struct sock *sk)
@@@ -407,8 -387,7 +407,8 @@@ void mptcp_data_ready(struct sock *sk, 
  bool mptcp_finish_join(struct sock *sk);
  void mptcp_data_acked(struct sock *sk);
  void mptcp_subflow_eof(struct sock *sk);
- bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq);
+ bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq, bool use_64bit);
 +void mptcp_destroy_common(struct mptcp_sock *msk);
  
  void __init mptcp_token_init(void);
  static inline void mptcp_token_init_request(struct request_sock *req)
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc net/socket.c
Simple merge
diff --cc net/xdp/xsk.c
Simple merge
Simple merge
Simple merge
Simple merge