]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
Merge tag 'apparmor-pr-2019-06-18' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 19 Jun 2019 18:39:00 +0000 (11:39 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 19 Jun 2019 18:39:00 +0000 (11:39 -0700)
Pull apparmor bug fixes from John Johansen:

 - fix PROFILE_MEDIATES for untrusted input

 - enforce nullbyte at end of tag string

 - reset pos on failure to unpack for various functions

* tag 'apparmor-pr-2019-06-18' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor:
  apparmor: reset pos on failure to unpack for various functions
  apparmor: enforce nullbyte at end of tag string
  apparmor: fix PROFILE_MEDIATES for untrusted input

235 files changed:
Documentation/ABI/testing/sysfs-class-net-qmi
Documentation/devicetree/bindings/net/can/microchip,mcp251x.txt
Documentation/devicetree/bindings/riscv/cpus.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/riscv/sifive.yaml [new file with mode: 0644]
Documentation/networking/af_xdp.rst
Documentation/networking/ip-sysctl.txt
Documentation/networking/rds.txt
MAINTAINERS
arch/arm/boot/dts/am335x-pcm-953.dtsi
arch/arm/boot/dts/am335x-wega.dtsi
arch/arm/boot/dts/am33xx-l4.dtsi
arch/arm/boot/dts/am437x-l4.dtsi
arch/arm/boot/dts/am57xx-idk-common.dtsi
arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts
arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts
arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
arch/arm/boot/dts/bcm4708-linksys-ea6300-v1.dts
arch/arm/boot/dts/bcm4708-linksys-ea6500-v2.dts
arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
arch/arm/boot/dts/bcm4708-netgear-r6250.dts
arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts
arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts
arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
arch/arm/boot/dts/bcm4709-linksys-ea9200.dts
arch/arm/boot/dts/bcm4709-netgear-r7000.dts
arch/arm/boot/dts/bcm4709-netgear-r8000.dts
arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts
arch/arm/boot/dts/bcm47094-phicomm-k3.dts
arch/arm/boot/dts/bcm94708.dts
arch/arm/boot/dts/bcm94709.dts
arch/arm/boot/dts/bcm963138dvt.dts
arch/arm/boot/dts/dra7-l4.dtsi
arch/arm/boot/dts/dra71-evm.dts
arch/arm/boot/dts/dra71x.dtsi [new file with mode: 0644]
arch/arm/boot/dts/dra72x.dtsi
arch/arm/boot/dts/dra76x-mmc-iodelay.dtsi
arch/arm/boot/dts/dra76x.dtsi
arch/arm/configs/mvebu_v7_defconfig
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-davinci/devices-da8xx.c
arch/arm/mach-imx/cpuidle-imx6sx.c
arch/arm/mach-ixp4xx/Kconfig
arch/arm/mach-ixp4xx/goramo_mlr.c
arch/arm/mach-ixp4xx/miccpt-pci.c
arch/arm/mach-ixp4xx/omixp-setup.c
arch/arm/mach-ixp4xx/vulcan-pci.c
arch/arm/mach-ixp4xx/vulcan-setup.c
arch/arm64/Kconfig.platforms
arch/powerpc/include/asm/ppc-opcode.h
arch/powerpc/net/bpf_jit.h
arch/powerpc/net/bpf_jit_comp64.c
arch/riscv/boot/dts/Makefile [new file with mode: 0644]
arch/riscv/boot/dts/sifive/Makefile [new file with mode: 0644]
arch/riscv/boot/dts/sifive/fu540-c000.dtsi [new file with mode: 0644]
arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts [new file with mode: 0644]
arch/riscv/configs/defconfig
arch/riscv/include/asm/bitops.h
arch/riscv/kernel/reset.c
arch/riscv/lib/delay.c
arch/riscv/mm/fault.c
arch/riscv/net/bpf_jit_comp.c
arch/x86/net/bpf_jit_comp.c
drivers/bus/ti-sysc.c
drivers/firmware/Kconfig
drivers/firmware/imx/imx-scu-irq.c
drivers/input/keyboard/imx_keypad.c
drivers/input/misc/uinput.c
drivers/input/mouse/elan_i2c_core.c
drivers/input/mouse/elantech.c
drivers/input/mouse/synaptics.c
drivers/input/touchscreen/iqs5xx.c
drivers/input/touchscreen/silead.c
drivers/irqchip/irq-ixp4xx.c
drivers/net/can/flexcan.c
drivers/net/can/m_can/m_can.c
drivers/net/can/spi/Kconfig
drivers/net/can/spi/mcp251x.c
drivers/net/can/usb/Kconfig
drivers/net/can/xilinx_can.c
drivers/net/dsa/Makefile
drivers/net/dsa/microchip/ksz_common.c
drivers/net/dsa/realtek-smi-core.c [moved from drivers/net/dsa/realtek-smi.c with 99% similarity]
drivers/net/dsa/realtek-smi-core.h [moved from drivers/net/dsa/realtek-smi.h with 100% similarity]
drivers/net/dsa/rtl8366.c
drivers/net/dsa/rtl8366rb.c
drivers/net/ethernet/8390/Kconfig
drivers/net/ethernet/emulex/benet/be_ethtool.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c
drivers/net/ethernet/mellanox/mlx5/core/cmd.c
drivers/net/ethernet/mellanox/mlx5/core/dev.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
drivers/net/ethernet/mellanox/mlxsw/reg.h
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/netronome/nfp/nfp_net_common.c
drivers/net/geneve.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/phy/Kconfig
drivers/net/phy/Makefile
drivers/net/phy/ax88796b.c [moved from drivers/net/phy/asix.c with 100% similarity]
drivers/net/usb/qmi_wwan.c
drivers/net/vxlan.c
drivers/net/wireless/intel/iwlwifi/fw/dbg.c
drivers/net/wireless/intel/iwlwifi/fw/dbg.h
drivers/net/wireless/intel/iwlwifi/iwl-drv.c
drivers/net/wireless/intel/iwlwifi/iwl-prph.h
drivers/net/wireless/intel/iwlwifi/mvm/d3.c
drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
drivers/net/wireless/intel/iwlwifi/mvm/fw.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/ops.c
drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
drivers/net/wireless/intel/iwlwifi/mvm/utils.c
drivers/net/wireless/intel/iwlwifi/pcie/internal.h
drivers/net/wireless/intel/iwlwifi/pcie/trans.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/marvell/mwifiex/ie.c
drivers/net/wireless/marvell/mwifiex/scan.c
drivers/net/wireless/realtek/rtw88/fw.c
drivers/net/wireless/realtek/rtw88/main.c
drivers/net/wireless/realtek/rtw88/phy.c
drivers/net/wireless/rsi/rsi_91x_sdio.c
drivers/soc/bcm/brcmstb/biuctrl.c
drivers/soc/ixp4xx/ixp4xx-npe.c
fs/btrfs/extent-tree.c
fs/btrfs/ioctl.c
fs/btrfs/reada.c
fs/btrfs/xattr.c
fs/namespace.c
fs/pnode.c
include/linux/bpf-cgroup.h
include/linux/bpf.h
include/linux/phylink.h
include/linux/skmsg.h
include/linux/sysctl.h
include/linux/tcp.h
include/net/addrconf.h
include/net/cfg80211.h
include/net/flow_dissector.h
include/net/netns/ipv4.h
include/net/sock.h
include/net/tcp.h
include/uapi/linux/bpf.h
include/uapi/linux/snmp.h
kernel/bpf/core.c
kernel/bpf/devmap.c
kernel/bpf/lpm_trie.c
kernel/bpf/syscall.c
kernel/bpf/verifier.c
kernel/sysctl.c
kernel/trace/bpf_trace.c
lib/test_stackinit.c
net/ax25/ax25_route.c
net/can/af_can.c
net/core/bpf_sk_storage.c
net/core/dev.c
net/core/ethtool.c
net/core/filter.c
net/core/neighbour.c
net/core/skbuff.c
net/core/sock.c
net/core/sysctl_net_core.c
net/ipv4/fib_semantics.c
net/ipv4/ip_output.c
net/ipv4/proc.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv4/tcp_timer.c
net/ipv4/udp.c
net/ipv6/icmp.c
net/ipv6/ip6_flowlabel.c
net/ipv6/ip6_output.c
net/ipv6/reassembly.c
net/ipv6/udp.c
net/lapb/lapb_iface.c
net/mac80211/ieee80211_i.h
net/mac80211/key.c
net/mac80211/mesh.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/tdls.c
net/mac80211/util.c
net/mac80211/wpa.c
net/mpls/Kconfig
net/mpls/mpls_iptunnel.c
net/nfc/netlink.c
net/openvswitch/vport-internal_dev.c
net/sched/cls_flower.c
net/sctp/sm_make_chunk.c
net/tipc/group.c
net/tls/tls_sw.c
net/vmw_vsock/hyperv_transport.c
net/vmw_vsock/virtio_transport_common.c
net/wireless/Makefile
net/wireless/core.c
net/wireless/nl80211.c
net/wireless/pmsr.c
net/wireless/scan.c
net/wireless/util.c
net/xdp/xdp_umem.c
samples/bpf/bpf_load.c
samples/bpf/task_fd_query_user.c
tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
tools/bpf/bpftool/Documentation/bpftool-prog.rst
tools/bpf/bpftool/bash-completion/bpftool
tools/bpf/bpftool/cgroup.c
tools/bpf/bpftool/map.c
tools/bpf/bpftool/prog.c
tools/include/uapi/linux/bpf.h
tools/lib/bpf/libbpf.c
tools/lib/bpf/libbpf_internal.h
tools/lib/bpf/libbpf_probes.c
tools/testing/selftests/bpf/Makefile
tools/testing/selftests/bpf/prog_tests/flow_dissector.c
tools/testing/selftests/bpf/test_lpm_map.c
tools/testing/selftests/bpf/test_section_names.c
tools/testing/selftests/bpf/test_sock_addr.c
tools/testing/selftests/bpf/verifier/div_overflow.c
tools/testing/selftests/bpf/verifier/subreg.c [new file with mode: 0644]
tools/testing/selftests/drivers/net/mlxsw/rtnetlink.sh
tools/testing/selftests/net/forwarding/tc_flower.sh

index 7122d6264c49d6c02c2c0074e145f19b93fc63dd..c310db4ccbc2eeb2aa7250438fd9f7b308b8fdbd 100644 (file)
@@ -29,7 +29,7 @@ Contact:      Bjørn Mork <bjorn@mork.no>
 Description:
                Unsigned integer.
 
-               Write a number ranging from 1 to 127 to add a qmap mux
+               Write a number ranging from 1 to 254 to add a qmap mux
                based network device, supported by recent Qualcomm based
                modems.
 
@@ -46,5 +46,5 @@ Contact:      Bjørn Mork <bjorn@mork.no>
 Description:
                Unsigned integer.
 
-               Write a number ranging from 1 to 127 to delete a previously
+               Write a number ranging from 1 to 254 to delete a previously
                created qmap mux based network device.
index 188c8bd4eb67709bdc05bc1014fe86d692256be4..5a0111d4de58c2e546ff257708c3ae5c07cf08e1 100644 (file)
@@ -4,6 +4,7 @@ Required properties:
  - compatible: Should be one of the following:
    - "microchip,mcp2510" for MCP2510.
    - "microchip,mcp2515" for MCP2515.
+   - "microchip,mcp25625" for MCP25625.
  - reg: SPI chip select.
  - clocks: The clock feeding the CAN controller.
  - interrupts: Should contain IRQ line for the CAN controller.
diff --git a/Documentation/devicetree/bindings/riscv/cpus.yaml b/Documentation/devicetree/bindings/riscv/cpus.yaml
new file mode 100644 (file)
index 0000000..27f02ec
--- /dev/null
@@ -0,0 +1,168 @@
+# SPDX-License-Identifier: (GPL-2.0 OR MIT)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/riscv/cpus.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: RISC-V bindings for 'cpus' DT nodes
+
+maintainers:
+  - Paul Walmsley <paul.walmsley@sifive.com>
+  - Palmer Dabbelt <palmer@sifive.com>
+
+allOf:
+  - $ref: /schemas/cpus.yaml#
+
+properties:
+  $nodename:
+    const: cpus
+    description: Container of cpu nodes
+
+  '#address-cells':
+    const: 1
+    description: |
+      A single unsigned 32-bit integer uniquely identifies each RISC-V
+      hart in a system.  (See the "reg" node under the "cpu" node,
+      below).
+
+  '#size-cells':
+    const: 0
+
+patternProperties:
+  '^cpu@[0-9a-f]+$':
+    properties:
+      compatible:
+        type: array
+        items:
+          - enum:
+              - sifive,rocket0
+              - sifive,e5
+              - sifive,e51
+              - sifive,u54-mc
+              - sifive,u54
+              - sifive,u5
+          - const: riscv
+        description:
+          Identifies that the hart uses the RISC-V instruction set
+          and identifies the type of the hart.
+
+      mmu-type:
+        allOf:
+          - $ref: "/schemas/types.yaml#/definitions/string"
+          - enum:
+              - riscv,sv32
+              - riscv,sv39
+              - riscv,sv48
+        description:
+          Identifies the MMU address translation mode used on this
+          hart.  These values originate from the RISC-V Privileged
+          Specification document, available from
+          https://riscv.org/specifications/
+
+      riscv,isa:
+        allOf:
+          - $ref: "/schemas/types.yaml#/definitions/string"
+          - enum:
+              - rv64imac
+              - rv64imafdc
+        description:
+          Identifies the specific RISC-V instruction set architecture
+          supported by the hart.  These are documented in the RISC-V
+          User-Level ISA document, available from
+          https://riscv.org/specifications/
+
+      timebase-frequency:
+        type: integer
+        minimum: 1
+        description:
+          Specifies the clock frequency of the system timer in Hz.
+          This value is common to all harts on a single system image.
+
+      interrupt-controller:
+        type: object
+        description: Describes the CPU's local interrupt controller
+
+        properties:
+          '#interrupt-cells':
+            const: 1
+
+          compatible:
+            const: riscv,cpu-intc
+
+          interrupt-controller: true
+
+        required:
+          - '#interrupt-cells'
+          - compatible
+          - interrupt-controller
+
+    required:
+      - riscv,isa
+      - timebase-frequency
+      - interrupt-controller
+
+examples:
+  - |
+    // Example 1: SiFive Freedom U540G Development Kit
+    cpus {
+        #address-cells = <1>;
+        #size-cells = <0>;
+        timebase-frequency = <1000000>;
+        cpu@0 {
+                clock-frequency = <0>;
+                compatible = "sifive,rocket0", "riscv";
+                device_type = "cpu";
+                i-cache-block-size = <64>;
+                i-cache-sets = <128>;
+                i-cache-size = <16384>;
+                reg = <0>;
+                riscv,isa = "rv64imac";
+                cpu_intc0: interrupt-controller {
+                        #interrupt-cells = <1>;
+                        compatible = "riscv,cpu-intc";
+                        interrupt-controller;
+                };
+        };
+        cpu@1 {
+                clock-frequency = <0>;
+                compatible = "sifive,rocket0", "riscv";
+                d-cache-block-size = <64>;
+                d-cache-sets = <64>;
+                d-cache-size = <32768>;
+                d-tlb-sets = <1>;
+                d-tlb-size = <32>;
+                device_type = "cpu";
+                i-cache-block-size = <64>;
+                i-cache-sets = <64>;
+                i-cache-size = <32768>;
+                i-tlb-sets = <1>;
+                i-tlb-size = <32>;
+                mmu-type = "riscv,sv39";
+                reg = <1>;
+                riscv,isa = "rv64imafdc";
+                tlb-split;
+                cpu_intc1: interrupt-controller {
+                        #interrupt-cells = <1>;
+                        compatible = "riscv,cpu-intc";
+                        interrupt-controller;
+                };
+        };
+    };
+
+  - |
+    // Example 2: Spike ISA Simulator with 1 Hart
+    cpus {
+            cpu@0 {
+                    device_type = "cpu";
+                    reg = <0>;
+                    compatible = "riscv";
+                    riscv,isa = "rv64imafdc";
+                    mmu-type = "riscv,sv48";
+                    interrupt-controller {
+                            #interrupt-cells = <1>;
+                            interrupt-controller;
+                            compatible = "riscv,cpu-intc";
+                    };
+            };
+    };
+...
diff --git a/Documentation/devicetree/bindings/riscv/sifive.yaml b/Documentation/devicetree/bindings/riscv/sifive.yaml
new file mode 100644 (file)
index 0000000..9d17dc2
--- /dev/null
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: (GPL-2.0 OR MIT)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/riscv/sifive.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: SiFive SoC-based boards
+
+maintainers:
+  - Paul Walmsley <paul.walmsley@sifive.com>
+  - Palmer Dabbelt <palmer@sifive.com>
+
+description:
+  SiFive SoC-based boards
+
+properties:
+  $nodename:
+    const: '/'
+  compatible:
+    items:
+      - enum:
+          - sifive,freedom-unleashed-a00
+      - const: sifive,fu540-c000
+      - const: sifive,fu540
+...
index e14d7d40fc75d0efca88a5aba77a4965ba93ff86..50bccbf68308594109e22dfeca6d91b48883e674 100644 (file)
@@ -316,16 +316,16 @@ A: When a netdev of a physical NIC is initialized, Linux usually
    all the traffic, you can force the netdev to only have 1 queue, queue
    id 0, and then bind to queue 0. You can use ethtool to do this::
 
-   sudo ethtool -L <interface> combined 1
+     sudo ethtool -L <interface> combined 1
 
    If you want to only see part of the traffic, you can program the
    NIC through ethtool to filter out your traffic to a single queue id
    that you can bind your XDP socket to. Here is one example in which
    UDP traffic to and from port 4242 are sent to queue 2::
 
-   sudo ethtool -N <interface> rx-flow-hash udp4 fn
-   sudo ethtool -N <interface> flow-type udp4 src-port 4242 dst-port \
-   4242 action 2
+     sudo ethtool -N <interface> rx-flow-hash udp4 fn
+     sudo ethtool -N <interface> flow-type udp4 src-port 4242 dst-port \
+     4242 action 2
 
    A number of other ways are possible all up to the capabilitites of
    the NIC you have.
index 14fe93049d28e965d7349b03c5c8782c3d386e7d..22f6b8b1110ad20c36e7ceea6d67fd2cc938eb7b 100644 (file)
@@ -255,6 +255,14 @@ tcp_base_mss - INTEGER
        Path MTU discovery (MTU probing).  If MTU probing is enabled,
        this is the initial MSS used by the connection.
 
+tcp_min_snd_mss - INTEGER
+       TCP SYN and SYNACK messages usually advertise an ADVMSS option,
+       as described in RFC 1122 and RFC 6691.
+       If this ADVMSS option is smaller than tcp_min_snd_mss,
+       it is silently capped to tcp_min_snd_mss.
+
+       Default : 48 (at least 8 bytes of payload per segment)
+
 tcp_congestion_control - STRING
        Set the congestion control algorithm to be used for new
        connections. The algorithm "reno" is always available, but
@@ -772,6 +780,14 @@ tcp_challenge_ack_limit - INTEGER
        in RFC 5961 (Improving TCP's Robustness to Blind In-Window Attacks)
        Default: 100
 
+tcp_rx_skb_cache - BOOLEAN
+       Controls a per TCP socket cache of one skb, that might help
+       performance of some workloads. This might be dangerous
+       on systems with a lot of TCP sockets, since it increases
+       memory usage.
+
+       Default: 0 (disabled)
+
 UDP variables:
 
 udp_l3mdev_accept - BOOLEAN
index 0235ae69af2a862938e550e61453b4fe81d7b2d3..f2a0147c933d1b7be6f9b09de38de2e8994e6e2f 100644 (file)
@@ -389,7 +389,7 @@ Multipath RDS (mprds)
   a common (to all paths) part, and a per-path struct rds_conn_path. All
   I/O workqs and reconnect threads are driven from the rds_conn_path.
   Transports such as TCP that are multipath capable may then set up a
-  TPC socket per rds_conn_path, and this is managed by the transport via
+  TCP socket per rds_conn_path, and this is managed by the transport via
   the transport privatee cp_transport_data pointer.
 
   Transports announce themselves as multipath capable by setting the
index 57f496cff9997358f6626d2207f09cacd2f0e237..ef58d9a881ee036169d7001e8a488b7d12c4dda6 100644 (file)
@@ -2085,7 +2085,7 @@ F:        drivers/tty/serial/msm_serial.c
 F:     drivers/usb/dwc3/dwc3-qcom.c
 F:     include/dt-bindings/*/qcom*
 F:     include/linux/*/qcom*
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/agross/linux.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git
 
 ARM/RADISYS ENP2611 MACHINE SUPPORT
 M:     Lennert Buytenhek <kernel@wantstofly.org>
@@ -3121,7 +3121,7 @@ F:        arch/arm/mach-bcm/
 
 BROADCOM BCM2835 ARM ARCHITECTURE
 M:     Eric Anholt <eric@anholt.net>
-M:     Stefan Wahren <stefan.wahren@i2se.com>
+M:     Stefan Wahren <wahrenst@gmx.net>
 L:     linux-rpi-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 T:     git git://github.com/anholt/linux
@@ -14335,6 +14335,15 @@ S:     Supported
 K:     sifive
 N:     sifive
 
+SIFIVE FU540 SYSTEM-ON-CHIP
+M:     Paul Walmsley <paul.walmsley@sifive.com>
+M:     Palmer Dabbelt <palmer@sifive.com>
+L:     linux-riscv@lists.infradead.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/pjw/sifive.git
+S:     Supported
+K:     fu540
+N:     fu540
+
 SILEAD TOUCHSCREEN DRIVER
 M:     Hans de Goede <hdegoede@redhat.com>
 L:     linux-input@vger.kernel.org
index baceaa7bb33b133731bdab2c55aea0fa30741678..20a3d982769234d982234e3ffe5d390bd443d0cd 100644 (file)
        bus-width = <4>;
        pinctrl-names = "default";
        pinctrl-0 = <&mmc1_pins>;
-       cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
+       cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
        status = "okay";
 };
 
index b7d28a20341fb5d0494d55cd5a261f2c20d87a2f..84581fed3d060e07852a1dfc8081cd0fc7052e6e 100644 (file)
        bus-width = <4>;
        pinctrl-names = "default";
        pinctrl-0 = <&mmc1_pins>;
-       cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
+       cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
        status = "okay";
 };
 
index ca6d9f02a800c8a0e042d43280fa762ebce6fef4..ced1a19d5f8982f11c12986dce5ea4d81decec3e 100644 (file)
                target-module@cc000 {                   /* 0x481cc000, ap 60 46.0 */
                        compatible = "ti,sysc-omap4", "ti,sysc";
                        ti,hwmods = "d_can0";
-                       reg = <0xcc000 0x4>;
-                       reg-names = "rev";
                        /* Domains (P, C): per_pwrdm, l4ls_clkdm */
-                       clocks = <&l4ls_clkctrl AM3_L4LS_D_CAN0_CLKCTRL 0>;
-                       clock-names = "fck";
+                       clocks = <&l4ls_clkctrl AM3_L4LS_D_CAN0_CLKCTRL 0>,
+                                <&dcan0_fck>;
+                       clock-names = "fck", "osc";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        ranges = <0x0 0xcc000 0x2000>;
                target-module@d0000 {                   /* 0x481d0000, ap 62 42.0 */
                        compatible = "ti,sysc-omap4", "ti,sysc";
                        ti,hwmods = "d_can1";
-                       reg = <0xd0000 0x4>;
-                       reg-names = "rev";
                        /* Domains (P, C): per_pwrdm, l4ls_clkdm */
-                       clocks = <&l4ls_clkctrl AM3_L4LS_D_CAN1_CLKCTRL 0>;
-                       clock-names = "fck";
+                       clocks = <&l4ls_clkctrl AM3_L4LS_D_CAN1_CLKCTRL 0>,
+                                <&dcan1_fck>;
+                       clock-names = "fck", "osc";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        ranges = <0x0 0xd0000 0x2000>;
index 85c6f4ff18242f7a26c669bd4036c7cf4cab8633..989cb60b90295868f1b983ff4129c867c33fce6b 100644 (file)
                target-module@cc000 {                   /* 0x481cc000, ap 50 46.0 */
                        compatible = "ti,sysc-omap4", "ti,sysc";
                        ti,hwmods = "d_can0";
-                       reg = <0xcc000 0x4>;
-                       reg-names = "rev";
                        /* Domains (P, C): per_pwrdm, l4ls_clkdm */
                        clocks = <&l4ls_clkctrl AM4_L4LS_D_CAN0_CLKCTRL 0>;
                        clock-names = "fck";
                target-module@d0000 {                   /* 0x481d0000, ap 52 3a.0 */
                        compatible = "ti,sysc-omap4", "ti,sysc";
                        ti,hwmods = "d_can1";
-                       reg = <0xd0000 0x4>;
-                       reg-names = "rev";
                        /* Domains (P, C): per_pwrdm, l4ls_clkdm */
                        clocks = <&l4ls_clkctrl AM4_L4LS_D_CAN1_CLKCTRL 0>;
                        clock-names = "fck";
index f7bd26458915fbb1656c62e9668bda4a8d0ad6a3..42e433da79ec869c9029155585bbffb1913e8d03 100644 (file)
        vqmmc-supply = <&ldo1_reg>;
        bus-width = <4>;
        cd-gpios = <&gpio6 27 GPIO_ACTIVE_LOW>; /* gpio 219 */
+       no-1-8-v;
 };
 
 &mmc2 {
index 79d454ff3be4205f9cb816f7c5a819f91c6e140f..1c6f561ac52b2739570e3638f2855d920626748f 100644 (file)
@@ -20,6 +20,7 @@
        };
 
        memory {
+               device_type = "memory";
                reg = <0x00000000 0x08000000
                       0x88000000 0x08000000>;
        };
index 99365bb8c41ed39cce31583a2e7a3ae78113bfa7..e550799a6ae0529276ac520dde3ce95e86da2f7f 100644 (file)
@@ -20,6 +20,7 @@
        };
 
        memory {
+               device_type = "memory";
                reg = <0x00000000 0x08000000
                       0x88000000 0x08000000>;
        };
index bc330b1f6de094f0cd4bd94623f5ee929a337188..7bfa2238f70bc6b0b440dce02637d41cb45c229c 100644 (file)
@@ -20,6 +20,7 @@
        };
 
        memory {
+               device_type = "memory";
                reg = <0x00000000 0x08000000
                       0x88000000 0x18000000>;
        };
index 258d2b251900cd4b6ade3a6198b24a71655f6d23..fd361c9b1374361f23f932396f13a54fb688823a 100644 (file)
@@ -17,6 +17,7 @@
        };
 
        memory {
+               device_type = "memory";
                reg = <0x00000000 0x08000000>;
        };
 
index babcfec50dde23e5f60bf60c7530b003d2619476..7c34360d3285d5c2ce460089e62434775c50f688 100644 (file)
@@ -18,6 +18,7 @@
        };
 
        memory {
+               device_type = "memory";
                reg = <0x00000000 0x08000000>;
        };
 
index e7fdaed99bd0acd0607b5caf8cbbebb4aab0528f..969b8d78e4929b6db22bebaf8d932756aae7aa0c 100644 (file)
@@ -16,6 +16,7 @@
        };
 
        memory {
+               device_type = "memory";
                reg = <0x00000000 0x08000000>;
        };
 
index 42bafc6440130be6f729b1f69f1228b7cc72659e..b62854ee27abb4404d0e77bfda0a4a498adf76f7 100644 (file)
@@ -20,6 +20,7 @@
        };
 
        memory {
+               device_type = "memory";
                reg = <0x00000000 0x08000000>;
        };
 
index dce35eb79dbe55c3a14e4e8993b2c58a368c544c..75f7b4ef35da6b0021041202ae529ac5fa7e0ebd 100644 (file)
@@ -21,6 +21,7 @@
        };
 
        memory {
+               device_type = "memory";
                reg = <0x00000000 0x08000000
                       0x88000000 0x08000000>;
        };
index b7a024b7951bcada9c3eae17087048f0b2609020..148d16a9085e89d6176f05bef6512fca329ef9e3 100644 (file)
@@ -20,6 +20,7 @@
        };
 
        memory {
+               device_type = "memory";
                reg = <0x00000000 0x08000000
                       0x88000000 0x08000000>;
        };
index f7f834cd3448d0b4f7ea54869285a50f9455d409..eed3aab6679b783d09cad511235a27074fbfc6bb 100644 (file)
@@ -20,6 +20,7 @@
        };
 
        memory {
+               device_type = "memory";
                reg = <0x00000000 0x08000000
                       0x88000000 0x08000000>;
        };
index 4cb10f88a95eafc1e51c501d4591704a4256a971..8f1e565c3db45b709ba1a4be968d99aa174098ef 100644 (file)
@@ -20,6 +20,7 @@
        };
 
        memory {
+               device_type = "memory";
                reg = <0x00000000 0x08000000
                       0x88000000 0x08000000>;
        };
index 77d1687b4228b60950628de95a4f7d14c0b81325..ce888b1835d1f7e9a177067d8cd72372bd2eacc3 100644 (file)
@@ -20,6 +20,7 @@
        };
 
        memory {
+               device_type = "memory";
                reg = <0x00000000 0x08000000
                       0x88000000 0x18000000>;
        };
index 983149b55269c3be51227a4b645f9a8c9a9e843f..ed8619b54d692e7d52026d44a03aebdd6e7b6fb3 100644 (file)
@@ -17,6 +17,7 @@
        };
 
        memory {
+               device_type = "memory";
                reg = <0x00000000 0x08000000
                       0x88000000 0x08000000>;
        };
index ca41481b44bd1ff296b0de84dec67868a053225e..1f87993eae1d1a8407dd3e07256888806c1b882e 100644 (file)
@@ -20,6 +20,7 @@
        };
 
        memory {
+               device_type = "memory";
                reg = <0x00000000 0x08000000
                       0x88000000 0x08000000>;
        };
index aa69e656d395367fad0fc3beeb1633463ac9bd46..6c6199a53d0918d707c362aae413dd7fde837545 100644 (file)
@@ -31,6 +31,7 @@
        };
 
        memory {
+               device_type = "memory";
                reg = <0x00000000 0x08000000
                       0x88000000 0x08000000>;
        };
index b527d2ff987ed36b4564245974375b84b9617f06..f806be5da723779ebc9c40781191e711013cb926 100644 (file)
@@ -16,6 +16,7 @@
        };
 
        memory {
+               device_type = "memory";
                reg = <0x00000000 0x08000000>;
        };
 
index ec09c0426d16a8037828e0169a75a38ff7310a2a..456045f17a00d7239c3580266d20f039ac18a7ba 100644 (file)
@@ -14,6 +14,7 @@
        model = "Phicomm K3";
 
        memory {
+               device_type = "memory";
                reg = <0x00000000 0x08000000
                       0x88000000 0x18000000>;
        };
index 934f07adfe3c00b025097cfc4cb911ddfa061645..3d13e46c69494579dbbbc34d65d0fd78af14eaa3 100644 (file)
@@ -39,6 +39,7 @@
        compatible = "brcm,bcm94708", "brcm,bcm4708";
 
        memory {
+               device_type = "memory";
                reg = <0x00000000 0x08000000>;
        };
 };
index 31e4dd098776a490e0f0578f94e4c12697e0776f..5017b7b259cbe20463753cd8e8303de09e6258aa 100644 (file)
@@ -39,6 +39,7 @@
        compatible = "brcm,bcm94709", "brcm,bcm4709", "brcm,bcm4708";
 
        memory {
+               device_type = "memory";
                reg = <0x00000000 0x08000000>;
        };
 };
index 8dca97eeaf57e6a5a66b647c6c8f5b29f0f62421..29525686e51a060dd31130e0d2cc10f526d23780 100644 (file)
@@ -17,6 +17,7 @@
        };
 
        memory {
+               device_type = "memory";
                reg = <0x0 0x08000000>;
        };
 
index fe9f0bc29fec20df23b0bd0a6567d610f92f90dc..23faedec08abd04f215ba55d21391281d93e374f 100644 (file)
                        };
                };
 
-               target-module@38000 {                   /* 0x48838000, ap 29 12.0 */
+               rtctarget: target-module@38000 {                        /* 0x48838000, ap 29 12.0 */
                        compatible = "ti,sysc-omap4-simple", "ti,sysc";
                        ti,hwmods = "rtcss";
                        reg = <0x38074 0x4>,
                        timer12: timer@0 {
                                compatible = "ti,omap5430-timer";
                                reg = <0x0 0x80>;
-                               clocks = <&wkupaon_clkctrl DRA7_WKUPAON_TIMER12_CLKCTRL 24>;
-                               clock-names = "fck";
                                interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
                                ti,timer-alwon;
                                ti,timer-secure;
index 82cc7ec37af0a3204f32241642568f31272e7be8..c496ae83e27ea8a53b2c396074510ebdf6d59823 100644 (file)
@@ -6,7 +6,7 @@
  * published by the Free Software Foundation.
  */
 
-#include "dra72-evm-common.dtsi"
+#include "dra71x.dtsi"
 #include "dra7-mmc-iodelay.dtsi"
 #include "dra72x-mmc-iodelay.dtsi"
 #include <dt-bindings/net/ti-dp83867.h>
diff --git a/arch/arm/boot/dts/dra71x.dtsi b/arch/arm/boot/dts/dra71x.dtsi
new file mode 100644 (file)
index 0000000..695a08e
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "dra72-evm-common.dtsi"
+
+&rtctarget {
+       status = "disabled";
+};
+
+&usb4_tm {
+       status = "disabled";
+};
index 89831552cd86c5121a83e2ab23dbc467ae9d5c8b..9c39c6b9b5d60ad4b6b7aee41276424ea0711a4a 100644 (file)
@@ -62,3 +62,7 @@
 &pcie2_rc {
        compatible = "ti,dra726-pcie-rc", "ti,dra7-pcie";
 };
+
+&usb4_tm {
+       status = "disabled";
+};
index baba7b00eca7976c92847fe664e7b599364d83a7..fdca48186916097692406f8518e2af96765a5ce6 100644 (file)
@@ -22,7 +22,7 @@
  *
  * Datamanual Revisions:
  *
- * DRA76x Silicon Revision 1.0: SPRS993A, Revised July 2017
+ * DRA76x Silicon Revision 1.0: SPRS993E, Revised December 2018
  *
  */
 
        /* Corresponds to MMC2_HS200_MANUAL1 in datamanual */
        mmc2_iodelay_hs200_conf: mmc2_iodelay_hs200_conf {
                pinctrl-pin-array = <
-                       0x190 A_DELAY_PS(384) G_DELAY_PS(0)       /* CFG_GPMC_A19_OEN */
-                       0x194 A_DELAY_PS(0) G_DELAY_PS(174)       /* CFG_GPMC_A19_OUT */
-                       0x1a8 A_DELAY_PS(410) G_DELAY_PS(0)       /* CFG_GPMC_A20_OEN */
-                       0x1ac A_DELAY_PS(85) G_DELAY_PS(0)        /* CFG_GPMC_A20_OUT */
-                       0x1b4 A_DELAY_PS(468) G_DELAY_PS(0)       /* CFG_GPMC_A21_OEN */
-                       0x1b8 A_DELAY_PS(139) G_DELAY_PS(0)       /* CFG_GPMC_A21_OUT */
-                       0x1c0 A_DELAY_PS(676) G_DELAY_PS(0)       /* CFG_GPMC_A22_OEN */
-                       0x1c4 A_DELAY_PS(69) G_DELAY_PS(0)        /* CFG_GPMC_A22_OUT */
-                       0x1d0 A_DELAY_PS(1062) G_DELAY_PS(154)    /* CFG_GPMC_A23_OUT */
-                       0x1d8 A_DELAY_PS(640) G_DELAY_PS(0)       /* CFG_GPMC_A24_OEN */
-                       0x1dc A_DELAY_PS(0) G_DELAY_PS(0)         /* CFG_GPMC_A24_OUT */
-                       0x1e4 A_DELAY_PS(356) G_DELAY_PS(0)       /* CFG_GPMC_A25_OEN */
-                       0x1e8 A_DELAY_PS(0) G_DELAY_PS(0)         /* CFG_GPMC_A25_OUT */
-                       0x1f0 A_DELAY_PS(579) G_DELAY_PS(0)       /* CFG_GPMC_A26_OEN */
-                       0x1f4 A_DELAY_PS(0) G_DELAY_PS(0)         /* CFG_GPMC_A26_OUT */
-                       0x1fc A_DELAY_PS(435) G_DELAY_PS(0)       /* CFG_GPMC_A27_OEN */
-                       0x200 A_DELAY_PS(36) G_DELAY_PS(0)        /* CFG_GPMC_A27_OUT */
-                       0x364 A_DELAY_PS(759) G_DELAY_PS(0)       /* CFG_GPMC_CS1_OEN */
-                       0x368 A_DELAY_PS(72) G_DELAY_PS(0)        /* CFG_GPMC_CS1_OUT */
+                       0x190 A_DELAY_PS(384) G_DELAY_PS(0)     /* CFG_GPMC_A19_OEN */
+                       0x194 A_DELAY_PS(350) G_DELAY_PS(174)   /* CFG_GPMC_A19_OUT */
+                       0x1a8 A_DELAY_PS(410) G_DELAY_PS(0)     /* CFG_GPMC_A20_OEN */
+                       0x1ac A_DELAY_PS(335) G_DELAY_PS(0)     /* CFG_GPMC_A20_OUT */
+                       0x1b4 A_DELAY_PS(468) G_DELAY_PS(0)     /* CFG_GPMC_A21_OEN */
+                       0x1b8 A_DELAY_PS(339) G_DELAY_PS(0)     /* CFG_GPMC_A21_OUT */
+                       0x1c0 A_DELAY_PS(676) G_DELAY_PS(0)     /* CFG_GPMC_A22_OEN */
+                       0x1c4 A_DELAY_PS(219) G_DELAY_PS(0)     /* CFG_GPMC_A22_OUT */
+                       0x1d0 A_DELAY_PS(1062) G_DELAY_PS(154)  /* CFG_GPMC_A23_OUT */
+                       0x1d8 A_DELAY_PS(640) G_DELAY_PS(0)     /* CFG_GPMC_A24_OEN */
+                       0x1dc A_DELAY_PS(150) G_DELAY_PS(0)     /* CFG_GPMC_A24_OUT */
+                       0x1e4 A_DELAY_PS(356) G_DELAY_PS(0)     /* CFG_GPMC_A25_OEN */
+                       0x1e8 A_DELAY_PS(150) G_DELAY_PS(0)     /* CFG_GPMC_A25_OUT */
+                       0x1f0 A_DELAY_PS(579) G_DELAY_PS(0)     /* CFG_GPMC_A26_OEN */
+                       0x1f4 A_DELAY_PS(200) G_DELAY_PS(0)     /* CFG_GPMC_A26_OUT */
+                       0x1fc A_DELAY_PS(435) G_DELAY_PS(0)     /* CFG_GPMC_A27_OEN */
+                       0x200 A_DELAY_PS(236) G_DELAY_PS(0)     /* CFG_GPMC_A27_OUT */
+                       0x364 A_DELAY_PS(759) G_DELAY_PS(0)     /* CFG_GPMC_CS1_OEN */
+                       0x368 A_DELAY_PS(372) G_DELAY_PS(0)     /* CFG_GPMC_CS1_OUT */
              >;
        };
 
index 9ee45aa365d87d37689e3625648d13f5876a30bb..82b3dc90b7d6b6fb4a33b73850d89246fb564b44 100644 (file)
                reg = <0x3fc>;
        };
 };
+
+&rtctarget {
+       status = "disabled";
+};
+
+&usb4_tm {
+       status = "disabled";
+};
index 48f7b4277b8ddd83dd2b24f465ac6438cefb6a69..3ac2e84fdeaa465dba7659782904497659d53867 100644 (file)
@@ -131,6 +131,7 @@ CONFIG_MV_XOR=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_MEMORY=y
 CONFIG_PWM=y
+CONFIG_PHY_MVEBU_A38X_COMPHY=y
 CONFIG_EXT4_FS=y
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
index 4ee65a8a3b8035483f98e335cda7c12c54854bbf..31ae3be5741d60cf22407955923b7eaa5ca3d540 100644 (file)
@@ -1480,6 +1480,8 @@ static __init void da850_evm_init(void)
        if (ret)
                pr_warn("%s: dsp/rproc registration failed: %d\n",
                        __func__, ret);
+
+       regulator_has_full_constraints();
 }
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
index 9ff02de448c6d30b718a1779891de5f9b50b492b..2d69e704f7f6b656bfc55b12da7d5a95f623e386 100644 (file)
@@ -683,6 +683,9 @@ static struct platform_device da8xx_lcdc_device = {
        .id             = 0,
        .num_resources  = ARRAY_SIZE(da8xx_lcdc_resources),
        .resource       = da8xx_lcdc_resources,
+       .dev            = {
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       }
 };
 
 int __init da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata)
index fd0053e47a151179db824e1aac6fe1526d20327e..3708a71f30e62bce60661e9527d22fd307838c60 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "common.h"
 #include "cpuidle.h"
+#include "hardware.h"
 
 static int imx6sx_idle_finish(unsigned long val)
 {
@@ -110,7 +111,7 @@ int __init imx6sx_cpuidle_init(void)
         * except for power up sw2iso which need to be
         * larger than LDO ramp up time.
         */
-       imx_gpc_set_arm_power_up_timing(0xf, 1);
+       imx_gpc_set_arm_power_up_timing(cpu_is_imx6sx() ? 0xf : 0x2, 1);
        imx_gpc_set_arm_power_down_timing(1, 1);
 
        return cpuidle_register(&imx6sx_cpuidle_driver, NULL);
index 2f052c56cd9efdb11cd034f7cbbb2201f42126ab..fc5378b00f3ddf71ebc9dc3e41145214991310c6 100644 (file)
@@ -13,7 +13,6 @@ config MACH_IXP4XX_OF
        select I2C
        select I2C_IOP3XX
        select PCI
-       select SERIAL_OF_PLATFORM
        select TIMER_OF
        select USE_OF
        help
index 4d805080020e32937ceec454f5ce0dd4a8ac094c..a0e0b6b7dc5c39364a5bce02d6ecc5d99e9838e0 100644 (file)
@@ -18,6 +18,8 @@
 #include <asm/mach/pci.h>
 #include <asm/system_info.h>
 
+#include "irqs.h"
+
 #define SLOT_ETHA              0x0B    /* IDSEL = AD21 */
 #define SLOT_ETHB              0x0C    /* IDSEL = AD20 */
 #define SLOT_MPCI              0x0D    /* IDSEL = AD19 */
index d114ccd2017cebcd4d3eac80b59daeaeb8f36ebf..ca889ef068a5f3ca73f28a3a363552072a23c854 100644 (file)
@@ -25,6 +25,8 @@
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 
+#include "irqs.h"
+
 #define MAX_DEV                4
 #define IRQ_LINES      4
 
index 2d494b45437670d2ab5c8c4a366c75c43d5d5967..c02fa6f4838278047d35613866337e2718e48ca2 100644 (file)
@@ -27,6 +27,8 @@
 
 #include <mach/hardware.h>
 
+#include "irqs.h"
+
 static struct resource omixp_flash_resources[] = {
        {
                .flags  = IORESOURCE_MEM,
index a4220fa5e0c3ef7cafa6c3a93e4c5209a28ac277..6e41e5ece4e12bc4719c4da2ebcf2e5347763f78 100644 (file)
@@ -21,6 +21,8 @@
 #include <asm/mach/pci.h>
 #include <asm/mach-types.h>
 
+#include "irqs.h"
+
 /* PCI controller GPIO to IRQ pin mappings */
 #define INTA   2
 #define INTB   3
index 2c03d2f6b6479b2b1423e347b1b69998e65810a9..d2ebb7c675a8c59c311d1bbc3f04a31bdbd04455 100644 (file)
@@ -22,6 +22,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
+#include "irqs.h"
+
 static struct flash_platform_data vulcan_flash_data = {
        .map_name       = "cfi_probe",
        .width          = 2,
index c7ad684926c312642b265b508722f7580dda24b7..d07fc063c930b6a4f56545bae435da31d6300282 100644 (file)
@@ -89,6 +89,7 @@ config ARCH_K3
        bool "Texas Instruments Inc. K3 multicore SoC architecture"
        select PM_GENERIC_DOMAINS if PM
        select MAILBOX
+       select SOC_TI
        select TI_MESSAGE_MANAGER
        select TI_SCI_PROTOCOL
        select TI_SCI_INTR_IRQCHIP
@@ -168,6 +169,7 @@ config ARCH_MXC
        select IMX_GPCV2_PM_DOMAINS
        select PM
        select PM_GENERIC_DOMAINS
+       select SOC_BUS
        help
          This enables support for the ARMv8 based SoCs in the
          NXP i.MX family.
index 493c5c943acd02a2b5f9d894cbe2b3ec1cd562a9..2291daf39cd1500c196a88ae93577900e8ef113c 100644 (file)
 #define PPC_INST_MADDLD                        0x10000033
 #define PPC_INST_DIVWU                 0x7c000396
 #define PPC_INST_DIVD                  0x7c0003d2
+#define PPC_INST_DIVDU                 0x7c000392
 #define PPC_INST_RLWINM                        0x54000000
 #define PPC_INST_RLWINM_DOT            0x54000001
 #define PPC_INST_RLWIMI                        0x50000000
index 6026a7af031d1a924a54e489c20a63b197163145..55d4377ccfae3fe98555b7076b2cca12178afdff 100644 (file)
                                     ___PPC_RA(a) | IMM_L(i))
 #define PPC_DIVWU(d, a, b)     EMIT(PPC_INST_DIVWU | ___PPC_RT(d) |          \
                                     ___PPC_RA(a) | ___PPC_RB(b))
-#define PPC_DIVD(d, a, b)      EMIT(PPC_INST_DIVD | ___PPC_RT(d) |           \
+#define PPC_DIVDU(d, a, b)     EMIT(PPC_INST_DIVDU | ___PPC_RT(d) |          \
                                     ___PPC_RA(a) | ___PPC_RB(b))
 #define PPC_AND(d, a, b)       EMIT(PPC_INST_AND | ___PPC_RA(d) |            \
                                     ___PPC_RS(a) | ___PPC_RB(b))
index 63d05c499cacdfaf05f308054801d34fcee56d55..c2ee6041f02c46f8cbf0f8e91c202653d3e948b6 100644 (file)
@@ -395,12 +395,12 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
                case BPF_ALU64 | BPF_DIV | BPF_X: /* dst /= src */
                case BPF_ALU64 | BPF_MOD | BPF_X: /* dst %= src */
                        if (BPF_OP(code) == BPF_MOD) {
-                               PPC_DIVD(b2p[TMP_REG_1], dst_reg, src_reg);
+                               PPC_DIVDU(b2p[TMP_REG_1], dst_reg, src_reg);
                                PPC_MULD(b2p[TMP_REG_1], src_reg,
                                                b2p[TMP_REG_1]);
                                PPC_SUB(dst_reg, dst_reg, b2p[TMP_REG_1]);
                        } else
-                               PPC_DIVD(dst_reg, dst_reg, src_reg);
+                               PPC_DIVDU(dst_reg, dst_reg, src_reg);
                        break;
                case BPF_ALU | BPF_MOD | BPF_K: /* (u32) dst %= (u32) imm */
                case BPF_ALU | BPF_DIV | BPF_K: /* (u32) dst /= (u32) imm */
@@ -428,7 +428,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
                                break;
                        case BPF_ALU64:
                                if (BPF_OP(code) == BPF_MOD) {
-                                       PPC_DIVD(b2p[TMP_REG_2], dst_reg,
+                                       PPC_DIVDU(b2p[TMP_REG_2], dst_reg,
                                                        b2p[TMP_REG_1]);
                                        PPC_MULD(b2p[TMP_REG_1],
                                                        b2p[TMP_REG_1],
@@ -436,7 +436,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
                                        PPC_SUB(dst_reg, dst_reg,
                                                        b2p[TMP_REG_1]);
                                } else
-                                       PPC_DIVD(dst_reg, dst_reg,
+                                       PPC_DIVDU(dst_reg, dst_reg,
                                                        b2p[TMP_REG_1]);
                                break;
                        }
diff --git a/arch/riscv/boot/dts/Makefile b/arch/riscv/boot/dts/Makefile
new file mode 100644 (file)
index 0000000..dcc3ada
--- /dev/null
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+subdir-y += sifive
diff --git a/arch/riscv/boot/dts/sifive/Makefile b/arch/riscv/boot/dts/sifive/Makefile
new file mode 100644 (file)
index 0000000..baaeef9
--- /dev/null
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+dtb-y += hifive-unleashed-a00.dtb
diff --git a/arch/riscv/boot/dts/sifive/fu540-c000.dtsi b/arch/riscv/boot/dts/sifive/fu540-c000.dtsi
new file mode 100644 (file)
index 0000000..3c06ee4
--- /dev/null
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Copyright (c) 2018-2019 SiFive, Inc */
+
+/dts-v1/;
+
+#include <dt-bindings/clock/sifive-fu540-prci.h>
+
+/ {
+       #address-cells = <2>;
+       #size-cells = <2>;
+       compatible = "sifive,fu540-c000", "sifive,fu540";
+
+       aliases {
+               serial0 = &uart0;
+               serial1 = &uart1;
+       };
+
+       chosen {
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               timebase-frequency = <1000000>;
+               cpu0: cpu@0 {
+                       compatible = "sifive,e51", "sifive,rocket0", "riscv";
+                       device_type = "cpu";
+                       i-cache-block-size = <64>;
+                       i-cache-sets = <128>;
+                       i-cache-size = <16384>;
+                       reg = <0>;
+                       riscv,isa = "rv64imac";
+                       status = "disabled";
+                       cpu0_intc: interrupt-controller {
+                               #interrupt-cells = <1>;
+                               compatible = "riscv,cpu-intc";
+                               interrupt-controller;
+                       };
+               };
+               cpu1: cpu@1 {
+                       compatible = "sifive,u54-mc", "sifive,rocket0", "riscv";
+                       d-cache-block-size = <64>;
+                       d-cache-sets = <64>;
+                       d-cache-size = <32768>;
+                       d-tlb-sets = <1>;
+                       d-tlb-size = <32>;
+                       device_type = "cpu";
+                       i-cache-block-size = <64>;
+                       i-cache-sets = <64>;
+                       i-cache-size = <32768>;
+                       i-tlb-sets = <1>;
+                       i-tlb-size = <32>;
+                       mmu-type = "riscv,sv39";
+                       reg = <1>;
+                       riscv,isa = "rv64imafdc";
+                       tlb-split;
+                       cpu1_intc: interrupt-controller {
+                               #interrupt-cells = <1>;
+                               compatible = "riscv,cpu-intc";
+                               interrupt-controller;
+                       };
+               };
+               cpu2: cpu@2 {
+                       clock-frequency = <0>;
+                       compatible = "sifive,u54-mc", "sifive,rocket0", "riscv";
+                       d-cache-block-size = <64>;
+                       d-cache-sets = <64>;
+                       d-cache-size = <32768>;
+                       d-tlb-sets = <1>;
+                       d-tlb-size = <32>;
+                       device_type = "cpu";
+                       i-cache-block-size = <64>;
+                       i-cache-sets = <64>;
+                       i-cache-size = <32768>;
+                       i-tlb-sets = <1>;
+                       i-tlb-size = <32>;
+                       mmu-type = "riscv,sv39";
+                       reg = <2>;
+                       riscv,isa = "rv64imafdc";
+                       tlb-split;
+                       cpu2_intc: interrupt-controller {
+                               #interrupt-cells = <1>;
+                               compatible = "riscv,cpu-intc";
+                               interrupt-controller;
+                       };
+               };
+               cpu3: cpu@3 {
+                       clock-frequency = <0>;
+                       compatible = "sifive,u54-mc", "sifive,rocket0", "riscv";
+                       d-cache-block-size = <64>;
+                       d-cache-sets = <64>;
+                       d-cache-size = <32768>;
+                       d-tlb-sets = <1>;
+                       d-tlb-size = <32>;
+                       device_type = "cpu";
+                       i-cache-block-size = <64>;
+                       i-cache-sets = <64>;
+                       i-cache-size = <32768>;
+                       i-tlb-sets = <1>;
+                       i-tlb-size = <32>;
+                       mmu-type = "riscv,sv39";
+                       reg = <3>;
+                       riscv,isa = "rv64imafdc";
+                       tlb-split;
+                       cpu3_intc: interrupt-controller {
+                               #interrupt-cells = <1>;
+                               compatible = "riscv,cpu-intc";
+                               interrupt-controller;
+                       };
+               };
+               cpu4: cpu@4 {
+                       clock-frequency = <0>;
+                       compatible = "sifive,u54-mc", "sifive,rocket0", "riscv";
+                       d-cache-block-size = <64>;
+                       d-cache-sets = <64>;
+                       d-cache-size = <32768>;
+                       d-tlb-sets = <1>;
+                       d-tlb-size = <32>;
+                       device_type = "cpu";
+                       i-cache-block-size = <64>;
+                       i-cache-sets = <64>;
+                       i-cache-size = <32768>;
+                       i-tlb-sets = <1>;
+                       i-tlb-size = <32>;
+                       mmu-type = "riscv,sv39";
+                       reg = <4>;
+                       riscv,isa = "rv64imafdc";
+                       tlb-split;
+                       cpu4_intc: interrupt-controller {
+                               #interrupt-cells = <1>;
+                               compatible = "riscv,cpu-intc";
+                               interrupt-controller;
+                       };
+               };
+       };
+       soc {
+               #address-cells = <2>;
+               #size-cells = <2>;
+               compatible = "sifive,fu540-c000", "sifive,fu540", "simple-bus";
+               ranges;
+               plic0: interrupt-controller@c000000 {
+                       #interrupt-cells = <1>;
+                       compatible = "sifive,plic-1.0.0";
+                       reg = <0x0 0xc000000 0x0 0x4000000>;
+                       riscv,ndev = <53>;
+                       interrupt-controller;
+                       interrupts-extended = <
+                               &cpu0_intc 0xffffffff
+                               &cpu1_intc 0xffffffff &cpu1_intc 9
+                               &cpu2_intc 0xffffffff &cpu2_intc 9
+                               &cpu3_intc 0xffffffff &cpu3_intc 9
+                               &cpu4_intc 0xffffffff &cpu4_intc 9>;
+               };
+               prci: clock-controller@10000000 {
+                       compatible = "sifive,fu540-c000-prci";
+                       reg = <0x0 0x10000000 0x0 0x1000>;
+                       clocks = <&hfclk>, <&rtcclk>;
+                       #clock-cells = <1>;
+               };
+               uart0: serial@10010000 {
+                       compatible = "sifive,fu540-c000-uart", "sifive,uart0";
+                       reg = <0x0 0x10010000 0x0 0x1000>;
+                       interrupt-parent = <&plic0>;
+                       interrupts = <4>;
+                       clocks = <&prci PRCI_CLK_TLCLK>;
+               };
+               uart1: serial@10011000 {
+                       compatible = "sifive,fu540-c000-uart", "sifive,uart0";
+                       reg = <0x0 0x10011000 0x0 0x1000>;
+                       interrupt-parent = <&plic0>;
+                       interrupts = <5>;
+                       clocks = <&prci PRCI_CLK_TLCLK>;
+               };
+               i2c0: i2c@10030000 {
+                       compatible = "sifive,fu540-c000-i2c", "sifive,i2c0";
+                       reg = <0x0 0x10030000 0x0 0x1000>;
+                       interrupt-parent = <&plic0>;
+                       interrupts = <50>;
+                       clocks = <&prci PRCI_CLK_TLCLK>;
+                       reg-shift = <2>;
+                       reg-io-width = <1>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+               qspi0: spi@10040000 {
+                       compatible = "sifive,fu540-c000-spi", "sifive,spi0";
+                       reg = <0x0 0x10040000 0x0 0x1000
+                              0x0 0x20000000 0x0 0x10000000>;
+                       interrupt-parent = <&plic0>;
+                       interrupts = <51>;
+                       clocks = <&prci PRCI_CLK_TLCLK>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+               qspi1: spi@10041000 {
+                       compatible = "sifive,fu540-c000-spi", "sifive,spi0";
+                       reg = <0x0 0x10041000 0x0 0x1000
+                              0x0 0x30000000 0x0 0x10000000>;
+                       interrupt-parent = <&plic0>;
+                       interrupts = <52>;
+                       clocks = <&prci PRCI_CLK_TLCLK>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+               qspi2: spi@10050000 {
+                       compatible = "sifive,fu540-c000-spi", "sifive,spi0";
+                       reg = <0x0 0x10050000 0x0 0x1000>;
+                       interrupt-parent = <&plic0>;
+                       interrupts = <6>;
+                       clocks = <&prci PRCI_CLK_TLCLK>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+       };
+};
diff --git a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
new file mode 100644 (file)
index 0000000..4da8870
--- /dev/null
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Copyright (c) 2018-2019 SiFive, Inc */
+
+#include "fu540-c000.dtsi"
+
+/* Clock frequency (in Hz) of the PCB crystal for rtcclk */
+#define RTCCLK_FREQ            1000000
+
+/ {
+       #address-cells = <2>;
+       #size-cells = <2>;
+       model = "SiFive HiFive Unleashed A00";
+       compatible = "sifive,hifive-unleashed-a00", "sifive,fu540-c000";
+
+       chosen {
+       };
+
+       cpus {
+               timebase-frequency = <RTCCLK_FREQ>;
+       };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x0 0x80000000 0x2 0x00000000>;
+       };
+
+       soc {
+       };
+
+       hfclk: hfclk {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <33333333>;
+               clock-output-names = "hfclk";
+       };
+
+       rtcclk: rtcclk {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <RTCCLK_FREQ>;
+               clock-output-names = "rtcclk";
+       };
+};
+
+&qspi0 {
+       flash@0 {
+               compatible = "issi,is25wp256", "jedec,spi-nor";
+               reg = <0>;
+               spi-max-frequency = <50000000>;
+               m25p,fast-read;
+               spi-tx-bus-width = <4>;
+               spi-rx-bus-width = <4>;
+       };
+};
+
+&qspi2 {
+       status = "okay";
+       mmc@0 {
+               compatible = "mmc-spi-slot";
+               reg = <0>;
+               spi-max-frequency = <20000000>;
+               voltage-ranges = <3300 3300>;
+               disable-wp;
+       };
+};
index 2fd3461e50abc9311cfe546de626b3ae58cb7e88..4f02967e55defb55b2cfc40f3de537f5323e7803 100644 (file)
@@ -49,6 +49,8 @@ CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
+CONFIG_SERIAL_SIFIVE=y
+CONFIG_SERIAL_SIFIVE_CONSOLE=y
 CONFIG_HVC_RISCV_SBI=y
 # CONFIG_PTP_1588_CLOCK is not set
 CONFIG_DRM=y
@@ -64,6 +66,8 @@ CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_UAS=y
 CONFIG_VIRTIO_MMIO=y
+CONFIG_CLK_SIFIVE=y
+CONFIG_CLK_SIFIVE_FU540_PRCI=y
 CONFIG_SIFIVE_PLIC=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
index 3943be480af096688d47f59021e51b0e85e3a23e..396a3303c537489bc8b1b7a52a9334e07b5ceda3 100644 (file)
 #include <asm/barrier.h>
 #include <asm/bitsperlong.h>
 
-#ifndef smp_mb__before_clear_bit
-#define smp_mb__before_clear_bit()  smp_mb()
-#define smp_mb__after_clear_bit()   smp_mb()
-#endif /* smp_mb__before_clear_bit */
-
 #include <asm-generic/bitops/__ffs.h>
 #include <asm-generic/bitops/ffz.h>
 #include <asm-generic/bitops/fls.h>
index cfb6eb1d762d231c58145a6123589e92f2d62126..d0fe623bfb8f31c9a56e9f90ce25ec2b192a2a89 100644 (file)
@@ -13,6 +13,7 @@ static void default_power_off(void)
 }
 
 void (*pm_power_off)(void) = default_power_off;
+EXPORT_SYMBOL(pm_power_off);
 
 void machine_restart(char *cmd)
 {
index 7e893ae0f10edca35bae5796cebe7f87cdc6be5c..87ff89e88f2ca95bfc1fb47e10e0cb7e88b0880a 100644 (file)
@@ -80,7 +80,7 @@ EXPORT_SYMBOL(__delay);
 
 void udelay(unsigned long usecs)
 {
-       unsigned long ucycles = usecs * lpj_fine * UDELAY_MULT;
+       u64 ucycles = (u64)usecs * lpj_fine * UDELAY_MULT;
 
        if (unlikely(usecs > MAX_UDELAY_US)) {
                __delay((u64)usecs * riscv_timebase / 1000000ULL);
index fd7662afddeacf037a2de04acb094820dedf1022..3e2708c626a854884358ced1e6f60bbd1e5f5fa6 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <asm/pgalloc.h>
 #include <asm/ptrace.h>
+#include <asm/tlbflush.h>
 
 /*
  * This routine handles page faults.  It determines the address and the
@@ -265,6 +266,18 @@ vmalloc_fault:
                pte_k = pte_offset_kernel(pmd_k, addr);
                if (!pte_present(*pte_k))
                        goto no_context;
+
+               /*
+                * The kernel assumes that TLBs don't cache invalid
+                * entries, but in RISC-V, SFENCE.VMA specifies an
+                * ordering constraint, not a cache flush; it is
+                * necessary even after writing invalid entries.
+                * Relying on flush_tlb_fix_spurious_fault would
+                * suffice, but the extra traps reduce
+                * performance. So, eagerly SFENCE.VMA.
+                */
+               local_flush_tlb_page(addr);
+
                return;
        }
 }
index 80b12aa5e10d06627e223166558e4e814c695077..426d5c33ea9037e10fd7706dddb8ac18d5649c46 100644 (file)
@@ -751,22 +751,32 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
        case BPF_ALU | BPF_ADD | BPF_X:
        case BPF_ALU64 | BPF_ADD | BPF_X:
                emit(is64 ? rv_add(rd, rd, rs) : rv_addw(rd, rd, rs), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
        case BPF_ALU | BPF_SUB | BPF_X:
        case BPF_ALU64 | BPF_SUB | BPF_X:
                emit(is64 ? rv_sub(rd, rd, rs) : rv_subw(rd, rd, rs), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
        case BPF_ALU | BPF_AND | BPF_X:
        case BPF_ALU64 | BPF_AND | BPF_X:
                emit(rv_and(rd, rd, rs), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
        case BPF_ALU | BPF_OR | BPF_X:
        case BPF_ALU64 | BPF_OR | BPF_X:
                emit(rv_or(rd, rd, rs), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
        case BPF_ALU | BPF_XOR | BPF_X:
        case BPF_ALU64 | BPF_XOR | BPF_X:
                emit(rv_xor(rd, rd, rs), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
        case BPF_ALU | BPF_MUL | BPF_X:
        case BPF_ALU64 | BPF_MUL | BPF_X:
@@ -789,14 +799,20 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
        case BPF_ALU | BPF_LSH | BPF_X:
        case BPF_ALU64 | BPF_LSH | BPF_X:
                emit(is64 ? rv_sll(rd, rd, rs) : rv_sllw(rd, rd, rs), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
        case BPF_ALU | BPF_RSH | BPF_X:
        case BPF_ALU64 | BPF_RSH | BPF_X:
                emit(is64 ? rv_srl(rd, rd, rs) : rv_srlw(rd, rd, rs), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
        case BPF_ALU | BPF_ARSH | BPF_X:
        case BPF_ALU64 | BPF_ARSH | BPF_X:
                emit(is64 ? rv_sra(rd, rd, rs) : rv_sraw(rd, rd, rs), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
 
        /* dst = -dst */
@@ -804,6 +820,8 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
        case BPF_ALU64 | BPF_NEG:
                emit(is64 ? rv_sub(rd, RV_REG_ZERO, rd) :
                     rv_subw(rd, RV_REG_ZERO, rd), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
 
        /* dst = BSWAP##imm(dst) */
@@ -958,14 +976,20 @@ out_be:
        case BPF_ALU | BPF_LSH | BPF_K:
        case BPF_ALU64 | BPF_LSH | BPF_K:
                emit(is64 ? rv_slli(rd, rd, imm) : rv_slliw(rd, rd, imm), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
        case BPF_ALU | BPF_RSH | BPF_K:
        case BPF_ALU64 | BPF_RSH | BPF_K:
                emit(is64 ? rv_srli(rd, rd, imm) : rv_srliw(rd, rd, imm), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
        case BPF_ALU | BPF_ARSH | BPF_K:
        case BPF_ALU64 | BPF_ARSH | BPF_K:
                emit(is64 ? rv_srai(rd, rd, imm) : rv_sraiw(rd, rd, imm), ctx);
+               if (!is64)
+                       emit_zext_32(rd, ctx);
                break;
 
        /* JUMP off */
index 32bfab4e21ebe88fbaa5eafa2c25d0da31b5a1c9..eaaed5bfc4a4429a92e980252c2f993047eb90bb 100644 (file)
@@ -186,9 +186,7 @@ struct jit_context {
 #define BPF_MAX_INSN_SIZE      128
 #define BPF_INSN_SAFETY                64
 
-#define AUX_STACK_SPACE                40 /* Space for RBX, R13, R14, R15, tailcnt */
-
-#define PROLOGUE_SIZE          37
+#define PROLOGUE_SIZE          20
 
 /*
  * Emit x86-64 prologue code for BPF program and check its size.
@@ -199,44 +197,19 @@ static void emit_prologue(u8 **pprog, u32 stack_depth, bool ebpf_from_cbpf)
        u8 *prog = *pprog;
        int cnt = 0;
 
-       /* push rbp */
-       EMIT1(0x55);
-
-       /* mov rbp,rsp */
-       EMIT3(0x48, 0x89, 0xE5);
-
-       /* sub rsp, rounded_stack_depth + AUX_STACK_SPACE */
-       EMIT3_off32(0x48, 0x81, 0xEC,
-                   round_up(stack_depth, 8) + AUX_STACK_SPACE);
-
-       /* sub rbp, AUX_STACK_SPACE */
-       EMIT4(0x48, 0x83, 0xED, AUX_STACK_SPACE);
-
-       /* mov qword ptr [rbp+0],rbx */
-       EMIT4(0x48, 0x89, 0x5D, 0);
-       /* mov qword ptr [rbp+8],r13 */
-       EMIT4(0x4C, 0x89, 0x6D, 8);
-       /* mov qword ptr [rbp+16],r14 */
-       EMIT4(0x4C, 0x89, 0x75, 16);
-       /* mov qword ptr [rbp+24],r15 */
-       EMIT4(0x4C, 0x89, 0x7D, 24);
-
+       EMIT1(0x55);             /* push rbp */
+       EMIT3(0x48, 0x89, 0xE5); /* mov rbp, rsp */
+       /* sub rsp, rounded_stack_depth */
+       EMIT3_off32(0x48, 0x81, 0xEC, round_up(stack_depth, 8));
+       EMIT1(0x53);             /* push rbx */
+       EMIT2(0x41, 0x55);       /* push r13 */
+       EMIT2(0x41, 0x56);       /* push r14 */
+       EMIT2(0x41, 0x57);       /* push r15 */
        if (!ebpf_from_cbpf) {
-               /*
-                * Clear the tail call counter (tail_call_cnt): for eBPF tail
-                * calls we need to reset the counter to 0. It's done in two
-                * instructions, resetting RAX register to 0, and moving it
-                * to the counter location.
-                */
-
-               /* xor eax, eax */
-               EMIT2(0x31, 0xc0);
-               /* mov qword ptr [rbp+32], rax */
-               EMIT4(0x48, 0x89, 0x45, 32);
-
+               /* zero init tail_call_cnt */
+               EMIT2(0x6a, 0x00);
                BUILD_BUG_ON(cnt != PROLOGUE_SIZE);
        }
-
        *pprog = prog;
 }
 
@@ -281,13 +254,13 @@ static void emit_bpf_tail_call(u8 **pprog)
         * if (tail_call_cnt > MAX_TAIL_CALL_CNT)
         *      goto out;
         */
-       EMIT2_off32(0x8B, 0x85, 36);              /* mov eax, dword ptr [rbp + 36] */
+       EMIT2_off32(0x8B, 0x85, -36 - MAX_BPF_STACK); /* mov eax, dword ptr [rbp - 548] */
        EMIT3(0x83, 0xF8, MAX_TAIL_CALL_CNT);     /* cmp eax, MAX_TAIL_CALL_CNT */
 #define OFFSET2 (30 + RETPOLINE_RAX_BPF_JIT_SIZE)
        EMIT2(X86_JA, OFFSET2);                   /* ja out */
        label2 = cnt;
        EMIT3(0x83, 0xC0, 0x01);                  /* add eax, 1 */
-       EMIT2_off32(0x89, 0x85, 36);              /* mov dword ptr [rbp + 36], eax */
+       EMIT2_off32(0x89, 0x85, -36 - MAX_BPF_STACK); /* mov dword ptr [rbp -548], eax */
 
        /* prog = array->ptrs[index]; */
        EMIT4_off32(0x48, 0x8B, 0x84, 0xD6,       /* mov rax, [rsi + rdx * 8 + offsetof(...)] */
@@ -1036,19 +1009,14 @@ emit_jmp:
                        seen_exit = true;
                        /* Update cleanup_addr */
                        ctx->cleanup_addr = proglen;
-                       /* mov rbx, qword ptr [rbp+0] */
-                       EMIT4(0x48, 0x8B, 0x5D, 0);
-                       /* mov r13, qword ptr [rbp+8] */
-                       EMIT4(0x4C, 0x8B, 0x6D, 8);
-                       /* mov r14, qword ptr [rbp+16] */
-                       EMIT4(0x4C, 0x8B, 0x75, 16);
-                       /* mov r15, qword ptr [rbp+24] */
-                       EMIT4(0x4C, 0x8B, 0x7D, 24);
-
-                       /* add rbp, AUX_STACK_SPACE */
-                       EMIT4(0x48, 0x83, 0xC5, AUX_STACK_SPACE);
-                       EMIT1(0xC9); /* leave */
-                       EMIT1(0xC3); /* ret */
+                       if (!bpf_prog_was_classic(bpf_prog))
+                               EMIT1(0x5B); /* get rid of tail_call_cnt */
+                       EMIT2(0x41, 0x5F);   /* pop r15 */
+                       EMIT2(0x41, 0x5E);   /* pop r14 */
+                       EMIT2(0x41, 0x5D);   /* pop r13 */
+                       EMIT1(0x5B);         /* pop rbx */
+                       EMIT1(0xC9);         /* leave */
+                       EMIT1(0xC3);         /* ret */
                        break;
 
                default:
index 308475ed4b32ad97033cb7e9df26817c2e3a3986..b72741668c927680493369ae2678f12805dca2d4 100644 (file)
@@ -660,12 +660,6 @@ static int sysc_check_registers(struct sysc *ddata)
                nr_regs++;
        }
 
-       if (nr_regs < 1) {
-               dev_err(ddata->dev, "missing registers\n");
-
-               return -EINVAL;
-       }
-
        if (nr_matches > nr_regs) {
                dev_err(ddata->dev, "overlapping registers: (%i/%i)",
                        nr_regs, nr_matches);
@@ -691,12 +685,18 @@ static int sysc_ioremap(struct sysc *ddata)
 {
        int size;
 
-       size = max3(ddata->offsets[SYSC_REVISION],
-                   ddata->offsets[SYSC_SYSCONFIG],
-                   ddata->offsets[SYSC_SYSSTATUS]);
+       if (ddata->offsets[SYSC_REVISION] < 0 &&
+           ddata->offsets[SYSC_SYSCONFIG] < 0 &&
+           ddata->offsets[SYSC_SYSSTATUS] < 0) {
+               size = ddata->module_size;
+       } else {
+               size = max3(ddata->offsets[SYSC_REVISION],
+                           ddata->offsets[SYSC_SYSCONFIG],
+                           ddata->offsets[SYSC_SYSSTATUS]);
 
-       if (size < 0 || (size + sizeof(u32)) > ddata->module_size)
-               return -EINVAL;
+               if ((size + sizeof(u32)) > ddata->module_size)
+                       return -EINVAL;
+       }
 
        ddata->module_va = devm_ioremap(ddata->dev,
                                        ddata->module_pa,
@@ -1128,7 +1128,6 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
        SYSC_QUIRK("cpgmac", 0, 0x1200, 0x1208, 0x1204, 0x4edb1902,
                   0xffff00f0, 0),
        SYSC_QUIRK("dcan", 0, 0, -1, -1, 0xffffffff, 0xffffffff, 0),
-       SYSC_QUIRK("dcan", 0, 0, -1, -1, 0x00001401, 0xffffffff, 0),
        SYSC_QUIRK("dmic", 0, 0, 0x10, -1, 0x50010000, 0xffffffff, 0),
        SYSC_QUIRK("dwc3", 0, 0, 0x10, -1, 0x500a0200, 0xffffffff, 0),
        SYSC_QUIRK("epwmss", 0, 0, 0x4, -1, 0x47400001, 0xffffffff, 0),
index 9026df9235428801b5284750a91a42ff958f7700..d40ccc3af9e26a25dd99a99739f9553f234f7529 100644 (file)
@@ -256,7 +256,7 @@ config TI_SCI_PROTOCOL
 
 config TRUSTED_FOUNDATIONS
        bool "Trusted Foundations secure monitor support"
-       depends on ARM
+       depends on ARM && CPU_V7
        help
          Some devices (including most early Tegra-based consumer devices on
          the market) are booted with the Trusted Foundations secure monitor
index 043833ad3c1a1e1a1d97ff8c5be3458bef1feb1a..687121f8c4d5eb9ce9728a8dd783176316879737 100644 (file)
@@ -100,6 +100,9 @@ int imx_scu_irq_group_enable(u8 group, u32 mask, u8 enable)
        struct imx_sc_rpc_msg *hdr = &msg.hdr;
        int ret;
 
+       if (!imx_sc_irq_ipc_handle)
+               return -EPROBE_DEFER;
+
        hdr->ver = IMX_SC_RPC_VERSION;
        hdr->svc = IMX_SC_RPC_SVC_IRQ;
        hdr->func = IMX_SC_IRQ_FUNC_ENABLE;
index 539cb670de41d6955e6ea5353749dac27d96b798..ae9c51cc85f997b92a6581a74a0ba65f6a673cb1 100644 (file)
@@ -526,11 +526,12 @@ static int imx_keypad_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __maybe_unused imx_kbd_suspend(struct device *dev)
+static int __maybe_unused imx_kbd_noirq_suspend(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct imx_keypad *kbd = platform_get_drvdata(pdev);
        struct input_dev *input_dev = kbd->input_dev;
+       unsigned short reg_val = readw(kbd->mmio_base + KPSR);
 
        /* imx kbd can wake up system even clock is disabled */
        mutex_lock(&input_dev->mutex);
@@ -540,13 +541,20 @@ static int __maybe_unused imx_kbd_suspend(struct device *dev)
 
        mutex_unlock(&input_dev->mutex);
 
-       if (device_may_wakeup(&pdev->dev))
+       if (device_may_wakeup(&pdev->dev)) {
+               if (reg_val & KBD_STAT_KPKD)
+                       reg_val |= KBD_STAT_KRIE;
+               if (reg_val & KBD_STAT_KPKR)
+                       reg_val |= KBD_STAT_KDIE;
+               writew(reg_val, kbd->mmio_base + KPSR);
+
                enable_irq_wake(kbd->irq);
+       }
 
        return 0;
 }
 
-static int __maybe_unused imx_kbd_resume(struct device *dev)
+static int __maybe_unused imx_kbd_noirq_resume(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct imx_keypad *kbd = platform_get_drvdata(pdev);
@@ -570,7 +578,9 @@ err_clk:
        return ret;
 }
 
-static SIMPLE_DEV_PM_OPS(imx_kbd_pm_ops, imx_kbd_suspend, imx_kbd_resume);
+static const struct dev_pm_ops imx_kbd_pm_ops = {
+       SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_kbd_noirq_suspend, imx_kbd_noirq_resume)
+};
 
 static struct platform_driver imx_keypad_driver = {
        .driver         = {
index 2ed559dd5e2522155b036fff8d4659ec67151bd7..84051f20b18a7790fea756c76f00d6b522010f71 100644 (file)
@@ -1038,13 +1038,31 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 #ifdef CONFIG_COMPAT
 
-#define UI_SET_PHYS_COMPAT     _IOW(UINPUT_IOCTL_BASE, 108, compat_uptr_t)
+/*
+ * These IOCTLs change their size and thus their numbers between
+ * 32 and 64 bits.
+ */
+#define UI_SET_PHYS_COMPAT             \
+       _IOW(UINPUT_IOCTL_BASE, 108, compat_uptr_t)
+#define UI_BEGIN_FF_UPLOAD_COMPAT      \
+       _IOWR(UINPUT_IOCTL_BASE, 200, struct uinput_ff_upload_compat)
+#define UI_END_FF_UPLOAD_COMPAT                \
+       _IOW(UINPUT_IOCTL_BASE, 201, struct uinput_ff_upload_compat)
 
 static long uinput_compat_ioctl(struct file *file,
                                unsigned int cmd, unsigned long arg)
 {
-       if (cmd == UI_SET_PHYS_COMPAT)
+       switch (cmd) {
+       case UI_SET_PHYS_COMPAT:
                cmd = UI_SET_PHYS;
+               break;
+       case UI_BEGIN_FF_UPLOAD_COMPAT:
+               cmd = UI_BEGIN_FF_UPLOAD;
+               break;
+       case UI_END_FF_UPLOAD_COMPAT:
+               cmd = UI_END_FF_UPLOAD;
+               break;
+       }
 
        return uinput_ioctl_handler(file, cmd, arg, compat_ptr(arg));
 }
index f9525d6f0bfe810c9ab1c2bd0a2a971f2e9695b4..2c0561e20b7fa28767e4228c0ae0d2535ef4107d 100644 (file)
@@ -981,6 +981,8 @@ static irqreturn_t elan_isr(int irq, void *dev_id)
        if (error)
                goto out;
 
+       pm_wakeup_event(dev, 0);
+
        switch (report[ETP_REPORT_ID_OFFSET]) {
        case ETP_REPORT_ID:
                elan_report_absolute(data, report);
index a7f8b16145595bd004b5fec8fdf27e2d6cf7f441..530142b5a115457588a7330131f462ca4b7830c6 100644 (file)
@@ -1189,6 +1189,8 @@ static const char * const middle_button_pnp_ids[] = {
        "LEN2132", /* ThinkPad P52 */
        "LEN2133", /* ThinkPad P72 w/ NFC */
        "LEN2134", /* ThinkPad P72 */
+       "LEN0407",
+       "LEN0408",
        NULL
 };
 
index b6da0c1267e36e96cdc3b808e1fae122bec7add4..8e6077d8e434a30cf76598164aa95cffcf2439fb 100644 (file)
@@ -179,6 +179,8 @@ static const char * const smbus_pnp_ids[] = {
        "LEN0096", /* X280 */
        "LEN0097", /* X280 -> ALPS trackpoint */
        "LEN200f", /* T450s */
+       "LEN2054", /* E480 */
+       "LEN2055", /* E580 */
        "SYN3052", /* HP EliteBook 840 G4 */
        "SYN3221", /* HP 15-ay000 */
        NULL
index b832fe0626453ce8c8dd6104a131211db0b5bfc8..4f6fe8cc8efaefeb8cce55f52251c35f1963f4d5 100644 (file)
@@ -502,14 +502,6 @@ static int iqs5xx_axis_init(struct i2c_client *client)
                input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y);
                input_set_capability(input, EV_ABS, ABS_MT_PRESSURE);
 
-               error = input_mt_init_slots(input,
-                               IQS5XX_NUM_CONTACTS, INPUT_MT_DIRECT);
-               if (error) {
-                       dev_err(&client->dev,
-                               "Failed to initialize slots: %d\n", error);
-                       return error;
-               }
-
                input_set_drvdata(input, iqs5xx);
                iqs5xx->input = input;
        }
@@ -591,9 +583,19 @@ static int iqs5xx_axis_init(struct i2c_client *client)
        if (error)
                return error;
 
-       return iqs5xx_write_word(client,
-                                prop.swap_x_y ? IQS5XX_X_RES : IQS5XX_Y_RES,
-                                max_y);
+       error = iqs5xx_write_word(client,
+                                 prop.swap_x_y ? IQS5XX_X_RES : IQS5XX_Y_RES,
+                                 max_y);
+       if (error)
+               return error;
+
+       error = input_mt_init_slots(iqs5xx->input, IQS5XX_NUM_CONTACTS,
+                                   INPUT_MT_DIRECT);
+       if (error)
+               dev_err(&client->dev, "Failed to initialize slots: %d\n",
+                       error);
+
+       return error;
 }
 
 static int iqs5xx_dev_init(struct i2c_client *client)
index a67d5e93fb773b31db0d667cfe0733a65efb2adb..ad8b6a2bfd3640bcc55f07fdfbdb25649a9f0dbd 100644 (file)
@@ -609,6 +609,7 @@ static const struct acpi_device_id silead_ts_acpi_match[] = {
        { "MSSL1680", 0 },
        { "MSSL0001", 0 },
        { "MSSL0002", 0 },
+       { "MSSL0017", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(acpi, silead_ts_acpi_match);
index d576809429ac800a13930ac6d7501b900ddc3fdd..6751c35b7e1d7c001acc7cb88234dc34d1eab3df 100644 (file)
@@ -252,10 +252,10 @@ static const struct ixp4xx_irq_chunk ixp4xx_irq_chunks[] = {
  * @fwnode: Corresponding fwnode abstraction for this controller
  * @is_356: if this is an IXP43x, IXP45x or IXP46x SoC variant
  */
-static int ixp4xx_irq_setup(struct ixp4xx_irq *ixi,
-                           void __iomem *irqbase,
-                           struct fwnode_handle *fwnode,
-                           bool is_356)
+static int __init ixp4xx_irq_setup(struct ixp4xx_irq *ixi,
+                                  void __iomem *irqbase,
+                                  struct fwnode_handle *fwnode,
+                                  bool is_356)
 {
        int nr_irqs;
 
index 1c66fb2ad76bebbfbcdce793d0685fef5a627773..f2fe344593d58ce66697515326efae700dab22ce 100644 (file)
 #define FLEXCAN_MB_CNT_LENGTH(x)       (((x) & 0xf) << 16)
 #define FLEXCAN_MB_CNT_TIMESTAMP(x)    ((x) & 0xffff)
 
-#define FLEXCAN_TIMEOUT_US             (50)
+#define FLEXCAN_TIMEOUT_US             (250)
 
 /* FLEXCAN hardware feature flags
  *
@@ -1583,9 +1583,6 @@ static int flexcan_probe(struct platform_device *pdev)
                        dev_dbg(&pdev->dev, "failed to setup stop-mode\n");
        }
 
-       dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%d)\n",
-                priv->regs, dev->irq);
-
        return 0;
 
  failed_register:
index 9b449400376bc536cd0d53ea4abfe13d14515ba6..deb274a19ba003c9061f127e28ec57521c4f877b 100644 (file)
@@ -822,6 +822,27 @@ static int m_can_poll(struct napi_struct *napi, int quota)
        if (!irqstatus)
                goto end;
 
+       /* Errata workaround for issue "Needless activation of MRAF irq"
+        * During frame reception while the MCAN is in Error Passive state
+        * and the Receive Error Counter has the value MCAN_ECR.REC = 127,
+        * it may happen that MCAN_IR.MRAF is set although there was no
+        * Message RAM access failure.
+        * If MCAN_IR.MRAF is enabled, an interrupt to the Host CPU is generated
+        * The Message RAM Access Failure interrupt routine needs to check
+        * whether MCAN_ECR.RP = â€™1’ and MCAN_ECR.REC = 127.
+        * In this case, reset MCAN_IR.MRAF. No further action is required.
+        */
+       if ((priv->version <= 31) && (irqstatus & IR_MRAF) &&
+           (m_can_read(priv, M_CAN_ECR) & ECR_RP)) {
+               struct can_berr_counter bec;
+
+               __m_can_get_berr_counter(dev, &bec);
+               if (bec.rxerr == 127) {
+                       m_can_write(priv, M_CAN_IR, IR_MRAF);
+                       irqstatus &= ~IR_MRAF;
+               }
+       }
+
        psr = m_can_read(priv, M_CAN_PSR);
        if (irqstatus & IR_ERR_STATE)
                work_done += m_can_handle_state_errors(dev, psr);
index 2e7e535e9237850aaa02dfb058d87308a988dbf2..1c50788055cb6fcc11225c882be4e4c41e8553eb 100644 (file)
@@ -9,9 +9,10 @@ config CAN_HI311X
          Driver for the Holt HI311x SPI CAN controllers.
 
 config CAN_MCP251X
-       tristate "Microchip MCP251x SPI CAN controllers"
+       tristate "Microchip MCP251x and MCP25625 SPI CAN controllers"
        depends on HAS_DMA
        ---help---
-         Driver for the Microchip MCP251x SPI CAN controllers.
+         Driver for the Microchip MCP251x and MCP25625 SPI CAN
+         controllers.
 
 endmenu
index 78e29fa06fe615dbdd8c5710f8e5c445299638d0..44e99e3d713487ff8b9cbc5c15046276274d6c04 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * CAN bus driver for Microchip 251x CAN Controller with SPI Interface
+ * CAN bus driver for Microchip 251x/25625 CAN Controller with SPI Interface
  *
  * MCP2510 support and bug fixes by Christian Pellegrin
  * <chripell@evolware.org>
@@ -28,7 +28,7 @@
  * static struct spi_board_info spi_board_info[] = {
  *         {
  *                 .modalias = "mcp2510",
- *                     // or "mcp2515" depending on your controller
+ *                     // "mcp2515" or "mcp25625" depending on your controller
  *                 .platform_data = &mcp251x_info,
  *                 .irq = IRQ_EINT13,
  *                 .max_speed_hz = 2*1000*1000,
@@ -224,6 +224,7 @@ static const struct can_bittiming_const mcp251x_bittiming_const = {
 enum mcp251x_model {
        CAN_MCP251X_MCP2510     = 0x2510,
        CAN_MCP251X_MCP2515     = 0x2515,
+       CAN_MCP251X_MCP25625    = 0x25625,
 };
 
 struct mcp251x_priv {
@@ -266,7 +267,6 @@ static inline int mcp251x_is_##_model(struct spi_device *spi) \
 }
 
 MCP251X_IS(2510);
-MCP251X_IS(2515);
 
 static void mcp251x_clean(struct net_device *net)
 {
@@ -625,7 +625,7 @@ static int mcp251x_hw_reset(struct spi_device *spi)
 
        /* Wait for oscillator startup timer after reset */
        mdelay(MCP251X_OST_DELAY_MS);
-       
+
        reg = mcp251x_read_reg(spi, CANSTAT);
        if ((reg & CANCTRL_REQOP_MASK) != CANCTRL_REQOP_CONF)
                return -ENODEV;
@@ -806,9 +806,8 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
                /* receive buffer 0 */
                if (intf & CANINTF_RX0IF) {
                        mcp251x_hw_rx(spi, 0);
-                       /*
-                        * Free one buffer ASAP
-                        * (The MCP2515 does this automatically.)
+                       /* Free one buffer ASAP
+                        * (The MCP2515/25625 does this automatically.)
                         */
                        if (mcp251x_is_2510(spi))
                                mcp251x_write_bits(spi, CANINTF, CANINTF_RX0IF, 0x00);
@@ -817,7 +816,7 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
                /* receive buffer 1 */
                if (intf & CANINTF_RX1IF) {
                        mcp251x_hw_rx(spi, 1);
-                       /* the MCP2515 does this automatically */
+                       /* The MCP2515/25625 does this automatically. */
                        if (mcp251x_is_2510(spi))
                                clear_intf |= CANINTF_RX1IF;
                }
@@ -992,6 +991,10 @@ static const struct of_device_id mcp251x_of_match[] = {
                .compatible     = "microchip,mcp2515",
                .data           = (void *)CAN_MCP251X_MCP2515,
        },
+       {
+               .compatible     = "microchip,mcp25625",
+               .data           = (void *)CAN_MCP251X_MCP25625,
+       },
        { }
 };
 MODULE_DEVICE_TABLE(of, mcp251x_of_match);
@@ -1005,6 +1008,10 @@ static const struct spi_device_id mcp251x_id_table[] = {
                .name           = "mcp2515",
                .driver_data    = (kernel_ulong_t)CAN_MCP251X_MCP2515,
        },
+       {
+               .name           = "mcp25625",
+               .driver_data    = (kernel_ulong_t)CAN_MCP251X_MCP25625,
+       },
        { }
 };
 MODULE_DEVICE_TABLE(spi, mcp251x_id_table);
@@ -1245,5 +1252,5 @@ module_spi_driver(mcp251x_can_driver);
 
 MODULE_AUTHOR("Chris Elston <celston@katalix.com>, "
              "Christian Pellegrin <chripell@evolware.org>");
-MODULE_DESCRIPTION("Microchip 251x CAN driver");
+MODULE_DESCRIPTION("Microchip 251x/25625 CAN driver");
 MODULE_LICENSE("GPL v2");
index ac3522b773034d7072611af20fe9621b13deb79d..4b3d0ddcda7940815494e7d126a952eb7b44d6f9 100644 (file)
@@ -102,12 +102,6 @@ config CAN_PEAK_USB
 
          (see also http://www.peak-system.com).
 
-config CAN_MCBA_USB
-       tristate "Microchip CAN BUS Analyzer interface"
-       ---help---
-         This driver supports the CAN BUS Analyzer interface
-         from Microchip (http://www.microchip.com/development-tools/).
-
 config CAN_UCAN
        tristate "Theobroma Systems UCAN interface"
        ---help---
index f2024404b8d65c1200fbf08a2db224c0833c25f7..63203ff452b58450964d0dc2a9d5b221075001c5 100644 (file)
@@ -1435,7 +1435,7 @@ static const struct xcan_devtype_data xcan_canfd_data = {
                 XCAN_FLAG_RXMNF |
                 XCAN_FLAG_TX_MAILBOXES |
                 XCAN_FLAG_RX_FIFO_MULTI,
-       .bittiming_const = &xcan_bittiming_const,
+       .bittiming_const = &xcan_bittiming_const_canfd,
        .btr_ts2_shift = XCAN_BTR_TS2_SHIFT_CANFD,
        .btr_sjw_shift = XCAN_BTR_SJW_SHIFT_CANFD,
        .bus_clk_name = "s_axi_aclk",
index fefb6aaa82ba1d72bad2203c03f6bb1e659dca4b..d99dc6de0006b0e6ec6815d79c2a6ba5dd32fa50 100644 (file)
@@ -9,8 +9,8 @@ obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o
 obj-$(CONFIG_NET_DSA_MT7530)   += mt7530.o
 obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
 obj-$(CONFIG_NET_DSA_QCA8K)    += qca8k.o
-obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek.o
-realtek-objs                   := realtek-smi.o rtl8366.o rtl8366rb.o
+obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
+realtek-smi-objs               := realtek-smi-core.o rtl8366.o rtl8366rb.o
 obj-$(CONFIG_NET_DSA_SMSC_LAN9303) += lan9303-core.o
 obj-$(CONFIG_NET_DSA_SMSC_LAN9303_I2C) += lan9303_i2c.o
 obj-$(CONFIG_NET_DSA_SMSC_LAN9303_MDIO) += lan9303_mdio.o
index 39dace8e3512a4a49d5f5789e1b08477f92c030b..f46086fa906462e18913821153a7f1f936aa0799 100644 (file)
@@ -83,6 +83,9 @@ static void ksz_mib_read_work(struct work_struct *work)
        int i;
 
        for (i = 0; i < dev->mib_port_cnt; i++) {
+               if (dsa_is_unused_port(dev->ds, i))
+                       continue;
+
                p = &dev->ports[i];
                mib = &p->mib;
                mutex_lock(&mib->cnt_mutex);
similarity index 99%
rename from drivers/net/dsa/realtek-smi.c
rename to drivers/net/dsa/realtek-smi-core.c
index ad41ec63cc9f03aae553e43660afbe08dbc85522..dc0509c02d29405f54a5618d75605ec898b2fe91 100644 (file)
@@ -40,7 +40,7 @@
 #include <linux/bitops.h>
 #include <linux/if_bridge.h>
 
-#include "realtek-smi.h"
+#include "realtek-smi-core.h"
 
 #define REALTEK_SMI_ACK_RETRY_COUNT            5
 #define REALTEK_SMI_HW_STOP_DELAY              25      /* msecs */
index 6dedd43442cc5775980725bbda8c3c7d5ee68443..ca3d17e43ed8be057f3628b3548a58df11656c88 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/if_bridge.h>
 #include <net/dsa.h>
 
-#include "realtek-smi.h"
+#include "realtek-smi-core.h"
 
 int rtl8366_mc_is_used(struct realtek_smi *smi, int mc_index, int *used)
 {
@@ -307,7 +307,8 @@ int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
        struct rtl8366_vlan_4k vlan4k;
        int ret;
 
-       if (!smi->ops->is_vlan_valid(smi, port))
+       /* Use VLAN nr port + 1 since VLAN0 is not valid */
+       if (!smi->ops->is_vlan_valid(smi, port + 1))
                return -EINVAL;
 
        dev_info(smi->dev, "%s filtering on port %d\n",
@@ -318,12 +319,12 @@ int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
         * The hardware support filter ID (FID) 0..7, I have no clue how to
         * support this in the driver when the callback only says on/off.
         */
-       ret = smi->ops->get_vlan_4k(smi, port, &vlan4k);
+       ret = smi->ops->get_vlan_4k(smi, port + 1, &vlan4k);
        if (ret)
                return ret;
 
        /* Just set the filter to FID 1 for now then */
-       ret = rtl8366_set_vlan(smi, port,
+       ret = rtl8366_set_vlan(smi, port + 1,
                               vlan4k.member,
                               vlan4k.untag,
                               1);
index 40b3974970c686388f9505e08ccd6fa949b9350c..a268085ffad28cfdc8c6668c4e42595d03b0e363 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/of_irq.h>
 #include <linux/regmap.h>
 
-#include "realtek-smi.h"
+#include "realtek-smi-core.h"
 
 #define RTL8366RB_PORT_NUM_CPU         5
 #define RTL8366RB_NUM_PORTS            6
index bb09319feedf7a876750f9061a4f7e3ec23f2b7d..2a3e2450968eeb066a8636001442d12413f78f3c 100644 (file)
@@ -50,7 +50,7 @@ config XSURF100
        tristate "Amiga XSurf 100 AX88796/NE2000 clone support"
        depends on ZORRO
        select AX88796
-       select ASIX_PHY
+       select AX88796B_PHY
        help
          This driver is for the Individual Computers X-Surf 100 Ethernet
          card (based on the Asix AX88796 chip). If you have such a card,
index fb308b330dc1f6512f8a44cd99677bbd83d98d68..8a6785173228f3b5892522d6b338abee7a66bb15 100644 (file)
@@ -1101,7 +1101,7 @@ static int be_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
                cmd->data = be_get_rss_hash_opts(adapter, cmd->flow_type);
                break;
        case ETHTOOL_GRXRINGS:
-               cmd->data = adapter->num_rx_qs - 1;
+               cmd->data = adapter->num_rx_qs;
                break;
        default:
                return -EINVAL;
index 3da392bfd6594fe9c2fdb2105131e5324352eee0..3da6800732656477bd5d932373dde23d1b4dde9c 100644 (file)
@@ -428,9 +428,10 @@ static int reset_rx_pools(struct ibmvnic_adapter *adapter)
                if (rx_pool->buff_size != be64_to_cpu(size_array[i])) {
                        free_long_term_buff(adapter, &rx_pool->long_term_buff);
                        rx_pool->buff_size = be64_to_cpu(size_array[i]);
-                       alloc_long_term_buff(adapter, &rx_pool->long_term_buff,
-                                            rx_pool->size *
-                                            rx_pool->buff_size);
+                       rc = alloc_long_term_buff(adapter,
+                                                 &rx_pool->long_term_buff,
+                                                 rx_pool->size *
+                                                 rx_pool->buff_size);
                } else {
                        rc = reset_long_term_buff(adapter,
                                                  &rx_pool->long_term_buff);
@@ -696,9 +697,9 @@ static int init_tx_pools(struct net_device *netdev)
                        return rc;
                }
 
-               init_one_tx_pool(netdev, &adapter->tso_pool[i],
-                                IBMVNIC_TSO_BUFS,
-                                IBMVNIC_TSO_BUF_SZ);
+               rc = init_one_tx_pool(netdev, &adapter->tso_pool[i],
+                                     IBMVNIC_TSO_BUFS,
+                                     IBMVNIC_TSO_BUF_SZ);
                if (rc) {
                        release_tx_pools(adapter);
                        return rc;
@@ -1745,7 +1746,8 @@ static int do_reset(struct ibmvnic_adapter *adapter,
 
        ibmvnic_cleanup(netdev);
 
-       if (adapter->reset_reason != VNIC_RESET_MOBILITY &&
+       if (reset_state == VNIC_OPEN &&
+           adapter->reset_reason != VNIC_RESET_MOBILITY &&
            adapter->reset_reason != VNIC_RESET_FAILOVER) {
                rc = __ibmvnic_close(netdev);
                if (rc)
@@ -1844,6 +1846,9 @@ static int do_reset(struct ibmvnic_adapter *adapter,
                return 0;
        }
 
+       /* refresh device's multicast list */
+       ibmvnic_set_multi(netdev);
+
        /* kick napi */
        for (i = 0; i < adapter->req_rx_queues; i++)
                napi_schedule(&adapter->napi[i]);
index 392fd895f27826e81153f230603fa37b8e921fcc..ae2240074d8ef8c3ab763af481acb8936db7ff25 100644 (file)
@@ -1905,8 +1905,7 @@ static int mvpp2_prs_ip6_init(struct mvpp2 *priv)
 }
 
 /* Find tcam entry with matched pair <vid,port> */
-static int mvpp2_prs_vid_range_find(struct mvpp2 *priv, int pmap, u16 vid,
-                                   u16 mask)
+static int mvpp2_prs_vid_range_find(struct mvpp2_port *port, u16 vid, u16 mask)
 {
        unsigned char byte[2], enable[2];
        struct mvpp2_prs_entry pe;
@@ -1914,13 +1913,13 @@ static int mvpp2_prs_vid_range_find(struct mvpp2 *priv, int pmap, u16 vid,
        int tid;
 
        /* Go through the all entries with MVPP2_PRS_LU_VID */
-       for (tid = MVPP2_PE_VID_FILT_RANGE_START;
-            tid <= MVPP2_PE_VID_FILT_RANGE_END; tid++) {
-               if (!priv->prs_shadow[tid].valid ||
-                   priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VID)
+       for (tid = MVPP2_PRS_VID_PORT_FIRST(port->id);
+            tid <= MVPP2_PRS_VID_PORT_LAST(port->id); tid++) {
+               if (!port->priv->prs_shadow[tid].valid ||
+                   port->priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VID)
                        continue;
 
-               mvpp2_prs_init_from_hw(priv, &pe, tid);
+               mvpp2_prs_init_from_hw(port->priv, &pe, tid);
 
                mvpp2_prs_tcam_data_byte_get(&pe, 2, &byte[0], &enable[0]);
                mvpp2_prs_tcam_data_byte_get(&pe, 3, &byte[1], &enable[1]);
@@ -1950,7 +1949,7 @@ int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid)
        memset(&pe, 0, sizeof(pe));
 
        /* Scan TCAM and see if entry with this <vid,port> already exist */
-       tid = mvpp2_prs_vid_range_find(priv, (1 << port->id), vid, mask);
+       tid = mvpp2_prs_vid_range_find(port, vid, mask);
 
        reg_val = mvpp2_read(priv, MVPP2_MH_REG(port->id));
        if (reg_val & MVPP2_DSA_EXTENDED)
@@ -2008,7 +2007,7 @@ void mvpp2_prs_vid_entry_remove(struct mvpp2_port *port, u16 vid)
        int tid;
 
        /* Scan TCAM and see if entry with this <vid,port> already exist */
-       tid = mvpp2_prs_vid_range_find(priv, (1 << port->id), vid, 0xfff);
+       tid = mvpp2_prs_vid_range_find(port, vid, 0xfff);
 
        /* No such entry */
        if (tid < 0)
@@ -2026,8 +2025,10 @@ void mvpp2_prs_vid_remove_all(struct mvpp2_port *port)
 
        for (tid = MVPP2_PRS_VID_PORT_FIRST(port->id);
             tid <= MVPP2_PRS_VID_PORT_LAST(port->id); tid++) {
-               if (priv->prs_shadow[tid].valid)
-                       mvpp2_prs_vid_entry_remove(port, tid);
+               if (priv->prs_shadow[tid].valid) {
+                       mvpp2_prs_hw_inv(priv, tid);
+                       priv->prs_shadow[tid].valid = false;
+               }
        }
 }
 
index d2ab8cd8ad9f0869753ff2e601b213be6ada25f8..e94686c420004c2bd44417fd21b2f8d67a5e69b5 100644 (file)
@@ -441,6 +441,10 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
        case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
        case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
        case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
+       case MLX5_CMD_OP_CREATE_UCTX:
+       case MLX5_CMD_OP_DESTROY_UCTX:
+       case MLX5_CMD_OP_CREATE_UMEM:
+       case MLX5_CMD_OP_DESTROY_UMEM:
        case MLX5_CMD_OP_ALLOC_MEMIC:
                *status = MLX5_DRIVER_STATUS_ABORTED;
                *synd = MLX5_DRIVER_SYND;
@@ -629,6 +633,10 @@ const char *mlx5_command_str(int command)
        MLX5_COMMAND_STR_CASE(ALLOC_MEMIC);
        MLX5_COMMAND_STR_CASE(DEALLOC_MEMIC);
        MLX5_COMMAND_STR_CASE(QUERY_HOST_PARAMS);
+       MLX5_COMMAND_STR_CASE(CREATE_UCTX);
+       MLX5_COMMAND_STR_CASE(DESTROY_UCTX);
+       MLX5_COMMAND_STR_CASE(CREATE_UMEM);
+       MLX5_COMMAND_STR_CASE(DESTROY_UMEM);
        default: return "unknown command opcode";
        }
 }
index ebc046fa97d353bce5f9802eb1889faa755bede3..f6b1da99e6c26a1a3065c5b8fd64a184606b646f 100644 (file)
@@ -248,11 +248,32 @@ void mlx5_unregister_interface(struct mlx5_interface *intf)
 }
 EXPORT_SYMBOL(mlx5_unregister_interface);
 
+/* Must be called with intf_mutex held */
+static bool mlx5_has_added_dev_by_protocol(struct mlx5_core_dev *mdev, int protocol)
+{
+       struct mlx5_device_context *dev_ctx;
+       struct mlx5_interface *intf;
+       bool found = false;
+
+       list_for_each_entry(intf, &intf_list, list) {
+               if (intf->protocol == protocol) {
+                       dev_ctx = mlx5_get_device(intf, &mdev->priv);
+                       if (dev_ctx && test_bit(MLX5_INTERFACE_ADDED, &dev_ctx->state))
+                               found = true;
+                       break;
+               }
+       }
+
+       return found;
+}
+
 void mlx5_reload_interface(struct mlx5_core_dev *mdev, int protocol)
 {
        mutex_lock(&mlx5_intf_mutex);
-       mlx5_remove_dev_by_protocol(mdev, protocol);
-       mlx5_add_dev_by_protocol(mdev, protocol);
+       if (mlx5_has_added_dev_by_protocol(mdev, protocol)) {
+               mlx5_remove_dev_by_protocol(mdev, protocol);
+               mlx5_add_dev_by_protocol(mdev, protocol);
+       }
        mutex_unlock(&mlx5_intf_mutex);
 }
 
index 3a183d690e235e6457c6148eaf030627b5f6d2ed..cc6797e24571d76d680e871f955cdf233aabba02 100644 (file)
@@ -385,6 +385,7 @@ struct mlx5e_txqsq {
        /* control path */
        struct mlx5_wq_ctrl        wq_ctrl;
        struct mlx5e_channel      *channel;
+       int                        ch_ix;
        int                        txq_ix;
        u32                        rate_limit;
        struct work_struct         recover_work;
@@ -1112,6 +1113,7 @@ void mlx5e_del_vxlan_port(struct net_device *netdev, struct udp_tunnel_info *ti)
 netdev_features_t mlx5e_features_check(struct sk_buff *skb,
                                       struct net_device *netdev,
                                       netdev_features_t features);
+int mlx5e_set_features(struct net_device *netdev, netdev_features_t features);
 #ifdef CONFIG_MLX5_ESWITCH
 int mlx5e_set_vf_mac(struct net_device *dev, int vf, u8 *mac);
 int mlx5e_set_vf_rate(struct net_device *dev, int vf, int min_tx_rate, int max_tx_rate);
index fe5d4d7f15edc80426bed373e2bf646dfd39dde7..231e7cdfc6f7fb53e06c3aa92bdfc9ce4420622c 100644 (file)
@@ -11,24 +11,25 @@ static int get_route_and_out_devs(struct mlx5e_priv *priv,
                                  struct net_device **route_dev,
                                  struct net_device **out_dev)
 {
+       struct net_device *uplink_dev, *uplink_upper, *real_dev;
        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
-       struct net_device *uplink_dev, *uplink_upper;
        bool dst_is_lag_dev;
 
+       real_dev = is_vlan_dev(dev) ? vlan_dev_real_dev(dev) : dev;
        uplink_dev = mlx5_eswitch_uplink_get_proto_dev(esw, REP_ETH);
        uplink_upper = netdev_master_upper_dev_get(uplink_dev);
        dst_is_lag_dev = (uplink_upper &&
                          netif_is_lag_master(uplink_upper) &&
-                         dev == uplink_upper &&
+                         real_dev == uplink_upper &&
                          mlx5_lag_is_sriov(priv->mdev));
 
        /* if the egress device isn't on the same HW e-switch or
         * it's a LAG device, use the uplink
         */
-       if (!netdev_port_same_parent_id(priv->netdev, dev) ||
+       if (!netdev_port_same_parent_id(priv->netdev, real_dev) ||
            dst_is_lag_dev) {
-               *route_dev = uplink_dev;
-               *out_dev = *route_dev;
+               *route_dev = dev;
+               *out_dev = uplink_dev;
        } else {
                *route_dev = dev;
                if (is_vlan_dev(*route_dev))
index c65cefd84eda7de00bc82038924672bd23a9240f..a8e8350b38aa01a5bb401c7d927da37aaca460fd 100644 (file)
@@ -1082,6 +1082,7 @@ static int mlx5e_alloc_txqsq(struct mlx5e_channel *c,
        sq->clock     = &mdev->clock;
        sq->mkey_be   = c->mkey_be;
        sq->channel   = c;
+       sq->ch_ix     = c->ix;
        sq->txq_ix    = txq_ix;
        sq->uar_map   = mdev->mlx5e_res.bfreg.map;
        sq->min_inline_mode = params->tx_min_inline_mode;
@@ -3635,8 +3636,7 @@ static int mlx5e_handle_feature(struct net_device *netdev,
        return 0;
 }
 
-static int mlx5e_set_features(struct net_device *netdev,
-                             netdev_features_t features)
+int mlx5e_set_features(struct net_device *netdev, netdev_features_t features)
 {
        netdev_features_t oper_features = netdev->features;
        int err = 0;
@@ -5108,6 +5108,11 @@ static void mlx5e_detach(struct mlx5_core_dev *mdev, void *vpriv)
        struct mlx5e_priv *priv = vpriv;
        struct net_device *netdev = priv->netdev;
 
+#ifdef CONFIG_MLX5_ESWITCH
+       if (MLX5_ESWITCH_MANAGER(mdev) && vpriv == mdev)
+               return;
+#endif
+
        if (!netif_device_present(netdev))
                return;
 
index 9aea9c5b2ce85d94083fb0184ceadad2b8c55cc8..2f406b161bcfe503366f10ad20f7c80b8bf4905e 100644 (file)
@@ -1351,6 +1351,7 @@ static const struct net_device_ops mlx5e_netdev_ops_uplink_rep = {
        .ndo_get_vf_stats        = mlx5e_get_vf_stats,
        .ndo_set_vf_vlan         = mlx5e_uplink_rep_set_vf_vlan,
        .ndo_get_port_parent_id  = mlx5e_rep_get_port_parent_id,
+       .ndo_set_features        = mlx5e_set_features,
 };
 
 bool mlx5e_eswitch_rep(struct net_device *netdev)
@@ -1425,10 +1426,9 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev)
 
        netdev->watchdog_timeo    = 15 * HZ;
 
+       netdev->features       |= NETIF_F_NETNS_LOCAL;
 
-       netdev->features         |= NETIF_F_HW_TC | NETIF_F_NETNS_LOCAL;
-       netdev->hw_features      |= NETIF_F_HW_TC;
-
+       netdev->hw_features    |= NETIF_F_HW_TC;
        netdev->hw_features    |= NETIF_F_SG;
        netdev->hw_features    |= NETIF_F_IP_CSUM;
        netdev->hw_features    |= NETIF_F_IPV6_CSUM;
@@ -1437,7 +1437,9 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev)
        netdev->hw_features    |= NETIF_F_TSO6;
        netdev->hw_features    |= NETIF_F_RXCSUM;
 
-       if (rep->vport != MLX5_VPORT_UPLINK)
+       if (rep->vport == MLX5_VPORT_UPLINK)
+               netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
+       else
                netdev->features |= NETIF_F_VLAN_CHALLENGED;
 
        netdev->features |= netdev->hw_features;
index 31cd02f1149939bf6d2126583a49c01a5f310b73..e40c60d1631f803bee289b4fe6057038b9c5f555 100644 (file)
@@ -2812,9 +2812,6 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
        if (!flow_action_has_entries(flow_action))
                return -EINVAL;
 
-       attr->in_rep = rpriv->rep;
-       attr->in_mdev = priv->mdev;
-
        flow_action_for_each(i, act, flow_action) {
                switch (act->id) {
                case FLOW_ACTION_DROP:
index 195a7d903cecbb18bf14047b670bfb4552b27f52..701e5dc75bb05d61d442ad635de540f93ee4d87e 100644 (file)
@@ -113,13 +113,13 @@ static inline int mlx5e_get_dscp_up(struct mlx5e_priv *priv, struct sk_buff *skb
 u16 mlx5e_select_queue(struct net_device *dev, struct sk_buff *skb,
                       struct net_device *sb_dev)
 {
-       int channel_ix = netdev_pick_tx(dev, skb, NULL);
+       int txq_ix = netdev_pick_tx(dev, skb, NULL);
        struct mlx5e_priv *priv = netdev_priv(dev);
        u16 num_channels;
        int up = 0;
 
        if (!netdev_get_num_tc(dev))
-               return channel_ix;
+               return txq_ix;
 
 #ifdef CONFIG_MLX5_CORE_EN_DCB
        if (priv->dcbx_dp.trust_state == MLX5_QPTS_TRUST_DSCP)
@@ -129,14 +129,14 @@ u16 mlx5e_select_queue(struct net_device *dev, struct sk_buff *skb,
                if (skb_vlan_tag_present(skb))
                        up = skb_vlan_tag_get_prio(skb);
 
-       /* channel_ix can be larger than num_channels since
+       /* txq_ix can be larger than num_channels since
         * dev->num_real_tx_queues = num_channels * num_tc
         */
        num_channels = priv->channels.params.num_channels;
-       if (channel_ix >= num_channels)
-               channel_ix = reciprocal_scale(channel_ix, num_channels);
+       if (txq_ix >= num_channels)
+               txq_ix = priv->txq2sq[txq_ix]->ch_ix;
 
-       return priv->channel_tc2txq[channel_ix][up];
+       return priv->channel_tc2txq[txq_ix][up];
 }
 
 static inline int mlx5e_skb_l2_header_offset(struct sk_buff *skb)
index e8002bfc1e8f13a1d6352042f70f8a7c248c3a57..7ed63ed657c71dd1ef8e8f321d56fa5676b89200 100644 (file)
@@ -997,7 +997,7 @@ static inline void mlxsw_reg_spaft_pack(char *payload, u8 local_port,
        MLXSW_REG_ZERO(spaft, payload);
        mlxsw_reg_spaft_local_port_set(payload, local_port);
        mlxsw_reg_spaft_allow_untagged_set(payload, allow_untagged);
-       mlxsw_reg_spaft_allow_prio_tagged_set(payload, true);
+       mlxsw_reg_spaft_allow_prio_tagged_set(payload, allow_untagged);
        mlxsw_reg_spaft_allow_tagged_set(payload, true);
 }
 
index dfe6b44baf635701e155809b5b9304e55c63faae..23204356ad888254e86ea5baa8f20ef5eeecb33e 100644 (file)
@@ -4280,13 +4280,16 @@ static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp)
        }
 }
 
+#define MLXSW_SP_LAG_SEED_INIT 0xcafecafe
+
 static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp)
 {
        char slcr_pl[MLXSW_REG_SLCR_LEN];
        u32 seed;
        int err;
 
-       seed = jhash(mlxsw_sp->base_mac, sizeof(mlxsw_sp->base_mac), 0);
+       seed = jhash(mlxsw_sp->base_mac, sizeof(mlxsw_sp->base_mac),
+                    MLXSW_SP_LAG_SEED_INIT);
        mlxsw_reg_slcr_pack(slcr_pl, MLXSW_REG_SLCR_LAG_HASH_SMAC |
                                     MLXSW_REG_SLCR_LAG_HASH_DMAC |
                                     MLXSW_REG_SLCR_LAG_HASH_ETHERTYPE |
index 8512dd49e4201abbbda983b6cb2889ef2853e829..1537f70bc26d0fbef771b91e4c92f6d9dae1ac4f 100644 (file)
@@ -437,8 +437,8 @@ static const struct mlxsw_sp_sb_pr mlxsw_sp1_sb_prs[] = {
                           MLXSW_SP1_SB_PR_CPU_SIZE, true, false),
 };
 
-#define MLXSW_SP2_SB_PR_INGRESS_SIZE   40960000
-#define MLXSW_SP2_SB_PR_EGRESS_SIZE    40960000
+#define MLXSW_SP2_SB_PR_INGRESS_SIZE   38128752
+#define MLXSW_SP2_SB_PR_EGRESS_SIZE    38128752
 #define MLXSW_SP2_SB_PR_CPU_SIZE       (256 * 1000)
 
 /* Order according to mlxsw_sp2_sb_pool_dess */
index 15f804453cd614c8b6c7ff26a214b0a5c7f1ffdf..96b23c856f4de1db4f447743020898ca02e0240f 100644 (file)
@@ -247,8 +247,8 @@ static int mlxsw_sp_flower_parse_ip(struct mlxsw_sp *mlxsw_sp,
                                       match.mask->tos & 0x3);
 
        mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_IP_DSCP,
-                                      match.key->tos >> 6,
-                                      match.mask->tos >> 6);
+                                      match.key->tos >> 2,
+                                      match.mask->tos >> 2);
 
        return 0;
 }
index 1cda8a248b12e1a554ee713371eeedbdaa377a40..ef554739dd54fe1e5fbcc8992e6d02edde5f4259 100644 (file)
@@ -2363,7 +2363,7 @@ static void mlxsw_sp_router_probe_unresolved_nexthops(struct work_struct *work)
 static void
 mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp *mlxsw_sp,
                              struct mlxsw_sp_neigh_entry *neigh_entry,
-                             bool removing);
+                             bool removing, bool dead);
 
 static enum mlxsw_reg_rauht_op mlxsw_sp_rauht_op(bool adding)
 {
@@ -2507,7 +2507,8 @@ static void mlxsw_sp_router_neigh_event_work(struct work_struct *work)
 
        memcpy(neigh_entry->ha, ha, ETH_ALEN);
        mlxsw_sp_neigh_entry_update(mlxsw_sp, neigh_entry, entry_connected);
-       mlxsw_sp_nexthop_neigh_update(mlxsw_sp, neigh_entry, !entry_connected);
+       mlxsw_sp_nexthop_neigh_update(mlxsw_sp, neigh_entry, !entry_connected,
+                                     dead);
 
        if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list))
                mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry);
@@ -3472,13 +3473,79 @@ static void __mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp_nexthop *nh,
        nh->update = 1;
 }
 
+static int
+mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp,
+                                   struct mlxsw_sp_neigh_entry *neigh_entry)
+{
+       struct neighbour *n, *old_n = neigh_entry->key.n;
+       struct mlxsw_sp_nexthop *nh;
+       bool entry_connected;
+       u8 nud_state, dead;
+       int err;
+
+       nh = list_first_entry(&neigh_entry->nexthop_list,
+                             struct mlxsw_sp_nexthop, neigh_list_node);
+
+       n = neigh_lookup(nh->nh_grp->neigh_tbl, &nh->gw_addr, nh->rif->dev);
+       if (!n) {
+               n = neigh_create(nh->nh_grp->neigh_tbl, &nh->gw_addr,
+                                nh->rif->dev);
+               if (IS_ERR(n))
+                       return PTR_ERR(n);
+               neigh_event_send(n, NULL);
+       }
+
+       mlxsw_sp_neigh_entry_remove(mlxsw_sp, neigh_entry);
+       neigh_entry->key.n = n;
+       err = mlxsw_sp_neigh_entry_insert(mlxsw_sp, neigh_entry);
+       if (err)
+               goto err_neigh_entry_insert;
+
+       read_lock_bh(&n->lock);
+       nud_state = n->nud_state;
+       dead = n->dead;
+       read_unlock_bh(&n->lock);
+       entry_connected = nud_state & NUD_VALID && !dead;
+
+       list_for_each_entry(nh, &neigh_entry->nexthop_list,
+                           neigh_list_node) {
+               neigh_release(old_n);
+               neigh_clone(n);
+               __mlxsw_sp_nexthop_neigh_update(nh, !entry_connected);
+               mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp);
+       }
+
+       neigh_release(n);
+
+       return 0;
+
+err_neigh_entry_insert:
+       neigh_entry->key.n = old_n;
+       mlxsw_sp_neigh_entry_insert(mlxsw_sp, neigh_entry);
+       neigh_release(n);
+       return err;
+}
+
 static void
 mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp *mlxsw_sp,
                              struct mlxsw_sp_neigh_entry *neigh_entry,
-                             bool removing)
+                             bool removing, bool dead)
 {
        struct mlxsw_sp_nexthop *nh;
 
+       if (list_empty(&neigh_entry->nexthop_list))
+               return;
+
+       if (dead) {
+               int err;
+
+               err = mlxsw_sp_nexthop_dead_neigh_replace(mlxsw_sp,
+                                                         neigh_entry);
+               if (err)
+                       dev_err(mlxsw_sp->bus_info->dev, "Failed to replace dead neigh\n");
+               return;
+       }
+
        list_for_each_entry(nh, &neigh_entry->nexthop_list,
                            neigh_list_node) {
                __mlxsw_sp_nexthop_neigh_update(nh, removing);
index b82b684f52ce6d3de7f2fc3462955af2267f3a4b..36a3bd30cfd9455a727d6c190814fc22edff2aad 100644 (file)
@@ -1867,6 +1867,7 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
                        napi_gro_receive(&rx_ring->r_vec->napi, skb);
                } else {
                        skb->dev = netdev;
+                       skb_reset_network_header(skb);
                        __skb_push(skb, ETH_HLEN);
                        dev_queue_xmit(skb);
                }
index 98d1a45c06067d7aeaae5a31465a3cb036c7e080..25770122c2197298512a82af4ea94237bc44ad0a 100644 (file)
@@ -395,7 +395,7 @@ static int geneve_udp_encap_err_lookup(struct sock *sk, struct sk_buff *skb)
        u8 zero_vni[3] = { 0 };
        u8 *vni = zero_vni;
 
-       if (skb->len < GENEVE_BASE_HLEN)
+       if (!pskb_may_pull(skb, skb_transport_offset(skb) + GENEVE_BASE_HLEN))
                return -EINVAL;
 
        geneveh = geneve_hdr(skb);
index 03ea5a7ed3a49a9ad8eee05a4e9e2da268093b30..afdcc5664ea6a0c69cadd71034aaf3d15ceaf9b5 100644 (file)
@@ -2407,7 +2407,7 @@ static struct  hv_driver netvsc_drv = {
        .probe = netvsc_probe,
        .remove = netvsc_remove,
        .driver = {
-               .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+               .probe_type = PROBE_FORCE_SYNCHRONOUS,
        },
 };
 
index f99f27800fdba6c6a1603193ec6ef3c536ad5eb2..1d406c6df790d6cb9f5fa1821533cea57df1af6b 100644 (file)
@@ -254,7 +254,7 @@ config AQUANTIA_PHY
        ---help---
          Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405
 
-config ASIX_PHY
+config AX88796B_PHY
        tristate "Asix PHYs"
        help
          Currently supports the Asix Electronics PHY found in the X-Surf 100
index 27d7f9f3b0de4c820ce1fdb6f7b1237df3601f5a..5b5c8669499e95b5c01d1cf6e2d19b5ad6aa66f6 100644 (file)
@@ -52,7 +52,7 @@ ifdef CONFIG_HWMON
 aquantia-objs                  += aquantia_hwmon.o
 endif
 obj-$(CONFIG_AQUANTIA_PHY)     += aquantia.o
-obj-$(CONFIG_ASIX_PHY)         += asix.o
+obj-$(CONFIG_AX88796B_PHY)     += ax88796b.o
 obj-$(CONFIG_AT803X_PHY)       += at803x.o
 obj-$(CONFIG_BCM63XX_PHY)      += bcm63xx.o
 obj-$(CONFIG_BCM7XXX_PHY)      += bcm7xxx.o
index d9a6699abe592d8ef82d03f3040734f7cc3c6d0f..780c10ee359baf68fba9041c46d889b087c8ff2a 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/usb/cdc.h>
 #include <linux/usb/usbnet.h>
 #include <linux/usb/cdc-wdm.h>
+#include <linux/u64_stats_sync.h>
 
 /* This driver supports wwan (3G/LTE/?) devices using a vendor
  * specific management protocol called Qualcomm MSM Interface (QMI) -
@@ -75,6 +76,7 @@ struct qmimux_hdr {
 struct qmimux_priv {
        struct net_device *real_dev;
        u8 mux_id;
+       struct pcpu_sw_netstats __percpu *stats64;
 };
 
 static int qmimux_open(struct net_device *dev)
@@ -101,19 +103,65 @@ static netdev_tx_t qmimux_start_xmit(struct sk_buff *skb, struct net_device *dev
        struct qmimux_priv *priv = netdev_priv(dev);
        unsigned int len = skb->len;
        struct qmimux_hdr *hdr;
+       netdev_tx_t ret;
 
        hdr = skb_push(skb, sizeof(struct qmimux_hdr));
        hdr->pad = 0;
        hdr->mux_id = priv->mux_id;
        hdr->pkt_len = cpu_to_be16(len);
        skb->dev = priv->real_dev;
-       return dev_queue_xmit(skb);
+       ret = dev_queue_xmit(skb);
+
+       if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
+               struct pcpu_sw_netstats *stats64 = this_cpu_ptr(priv->stats64);
+
+               u64_stats_update_begin(&stats64->syncp);
+               stats64->tx_packets++;
+               stats64->tx_bytes += len;
+               u64_stats_update_end(&stats64->syncp);
+       } else {
+               dev->stats.tx_dropped++;
+       }
+
+       return ret;
+}
+
+static void qmimux_get_stats64(struct net_device *net,
+                              struct rtnl_link_stats64 *stats)
+{
+       struct qmimux_priv *priv = netdev_priv(net);
+       unsigned int start;
+       int cpu;
+
+       netdev_stats_to_stats64(stats, &net->stats);
+
+       for_each_possible_cpu(cpu) {
+               struct pcpu_sw_netstats *stats64;
+               u64 rx_packets, rx_bytes;
+               u64 tx_packets, tx_bytes;
+
+               stats64 = per_cpu_ptr(priv->stats64, cpu);
+
+               do {
+                       start = u64_stats_fetch_begin_irq(&stats64->syncp);
+                       rx_packets = stats64->rx_packets;
+                       rx_bytes = stats64->rx_bytes;
+                       tx_packets = stats64->tx_packets;
+                       tx_bytes = stats64->tx_bytes;
+               } while (u64_stats_fetch_retry_irq(&stats64->syncp, start));
+
+               stats->rx_packets += rx_packets;
+               stats->rx_bytes += rx_bytes;
+               stats->tx_packets += tx_packets;
+               stats->tx_bytes += tx_bytes;
+       }
 }
 
 static const struct net_device_ops qmimux_netdev_ops = {
-       .ndo_open       = qmimux_open,
-       .ndo_stop       = qmimux_stop,
-       .ndo_start_xmit = qmimux_start_xmit,
+       .ndo_open        = qmimux_open,
+       .ndo_stop        = qmimux_stop,
+       .ndo_start_xmit  = qmimux_start_xmit,
+       .ndo_get_stats64 = qmimux_get_stats64,
 };
 
 static void qmimux_setup(struct net_device *dev)
@@ -153,7 +201,7 @@ static bool qmimux_has_slaves(struct usbnet *dev)
 
 static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
-       unsigned int len, offset = 0;
+       unsigned int len, offset = 0, pad_len, pkt_len;
        struct qmimux_hdr *hdr;
        struct net_device *net;
        struct sk_buff *skbn;
@@ -171,10 +219,16 @@ static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                if (hdr->pad & 0x80)
                        goto skip;
 
+               /* extract padding length and check for valid length info */
+               pad_len = hdr->pad & 0x3f;
+               if (len == 0 || pad_len >= len)
+                       goto skip;
+               pkt_len = len - pad_len;
+
                net = qmimux_find_dev(dev, hdr->mux_id);
                if (!net)
                        goto skip;
-               skbn = netdev_alloc_skb(net, len);
+               skbn = netdev_alloc_skb(net, pkt_len);
                if (!skbn)
                        return 0;
                skbn->dev = net;
@@ -191,9 +245,20 @@ static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                        goto skip;
                }
 
-               skb_put_data(skbn, skb->data + offset + qmimux_hdr_sz, len);
-               if (netif_rx(skbn) != NET_RX_SUCCESS)
+               skb_put_data(skbn, skb->data + offset + qmimux_hdr_sz, pkt_len);
+               if (netif_rx(skbn) != NET_RX_SUCCESS) {
+                       net->stats.rx_errors++;
                        return 0;
+               } else {
+                       struct pcpu_sw_netstats *stats64;
+                       struct qmimux_priv *priv = netdev_priv(net);
+
+                       stats64 = this_cpu_ptr(priv->stats64);
+                       u64_stats_update_begin(&stats64->syncp);
+                       stats64->rx_packets++;
+                       stats64->rx_bytes += pkt_len;
+                       u64_stats_update_end(&stats64->syncp);
+               }
 
 skip:
                offset += len + qmimux_hdr_sz;
@@ -217,6 +282,12 @@ static int qmimux_register_device(struct net_device *real_dev, u8 mux_id)
        priv->mux_id = mux_id;
        priv->real_dev = real_dev;
 
+       priv->stats64 = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
+       if (!priv->stats64) {
+               err = -ENOBUFS;
+               goto out_free_newdev;
+       }
+
        err = register_netdevice(new_dev);
        if (err < 0)
                goto out_free_newdev;
@@ -241,13 +312,15 @@ out_free_newdev:
        return err;
 }
 
-static void qmimux_unregister_device(struct net_device *dev)
+static void qmimux_unregister_device(struct net_device *dev,
+                                    struct list_head *head)
 {
        struct qmimux_priv *priv = netdev_priv(dev);
        struct net_device *real_dev = priv->real_dev;
 
+       free_percpu(priv->stats64);
        netdev_upper_dev_unlink(real_dev, dev);
-       unregister_netdevice(dev);
+       unregister_netdevice_queue(dev, head);
 
        /* Get rid of the reference to real_dev */
        dev_put(real_dev);
@@ -356,8 +429,8 @@ static ssize_t add_mux_store(struct device *d,  struct device_attribute *attr, c
        if (kstrtou8(buf, 0, &mux_id))
                return -EINVAL;
 
-       /* mux_id [1 - 0x7f] range empirically found */
-       if (mux_id < 1 || mux_id > 0x7f)
+       /* mux_id [1 - 254] for compatibility with ip(8) and the rmnet driver */
+       if (mux_id < 1 || mux_id > 254)
                return -EINVAL;
 
        if (!rtnl_trylock())
@@ -418,7 +491,7 @@ static ssize_t del_mux_store(struct device *d,  struct device_attribute *attr, c
                ret = -EINVAL;
                goto err;
        }
-       qmimux_unregister_device(del_dev);
+       qmimux_unregister_device(del_dev, NULL);
 
        if (!qmimux_has_slaves(dev))
                info->flags &= ~QMI_WWAN_FLAG_MUX;
@@ -1428,6 +1501,7 @@ static void qmi_wwan_disconnect(struct usb_interface *intf)
        struct qmi_wwan_state *info;
        struct list_head *iter;
        struct net_device *ldev;
+       LIST_HEAD(list);
 
        /* called twice if separate control and data intf */
        if (!dev)
@@ -1440,8 +1514,9 @@ static void qmi_wwan_disconnect(struct usb_interface *intf)
                }
                rcu_read_lock();
                netdev_for_each_upper_dev_rcu(dev->net, ldev, iter)
-                       qmimux_unregister_device(ldev);
+                       qmimux_unregister_device(ldev, &list);
                rcu_read_unlock();
+               unregister_netdevice_many(&list);
                rtnl_unlock();
                info->flags &= ~QMI_WWAN_FLAG_MUX;
        }
index 5994d5415a03324944472a9a875e3c1471bf5641..4c9bc29fe3d5897761dfd47c983c863bdd5b7b59 100644 (file)
@@ -1766,7 +1766,7 @@ static int vxlan_err_lookup(struct sock *sk, struct sk_buff *skb)
        struct vxlanhdr *hdr;
        __be32 vni;
 
-       if (skb->len < VXLAN_HLEN)
+       if (!pskb_may_pull(skb, skb_transport_offset(skb) + VXLAN_HLEN))
                return -EINVAL;
 
        hdr = vxlan_hdr(skb);
index 5f52e40a29032dd290991324a8f31f512c99fd16..33d7bc5500dbf00191bac4c27d632b1ec4960c71 100644 (file)
@@ -2747,3 +2747,42 @@ void iwl_fw_dbg_periodic_trig_handler(struct timer_list *t)
                          jiffies + msecs_to_jiffies(collect_interval));
        }
 }
+
+#define FSEQ_REG(x) { .addr = (x), .str = #x, }
+
+void iwl_fw_error_print_fseq_regs(struct iwl_fw_runtime *fwrt)
+{
+       struct iwl_trans *trans = fwrt->trans;
+       unsigned long flags;
+       int i;
+       struct {
+               u32 addr;
+               const char *str;
+       } fseq_regs[] = {
+               FSEQ_REG(FSEQ_ERROR_CODE),
+               FSEQ_REG(FSEQ_TOP_INIT_VERSION),
+               FSEQ_REG(FSEQ_CNVIO_INIT_VERSION),
+               FSEQ_REG(FSEQ_OTP_VERSION),
+               FSEQ_REG(FSEQ_TOP_CONTENT_VERSION),
+               FSEQ_REG(FSEQ_ALIVE_TOKEN),
+               FSEQ_REG(FSEQ_CNVI_ID),
+               FSEQ_REG(FSEQ_CNVR_ID),
+               FSEQ_REG(CNVI_AUX_MISC_CHIP),
+               FSEQ_REG(CNVR_AUX_MISC_CHIP),
+               FSEQ_REG(CNVR_SCU_SD_REGS_SD_REG_DIG_DCDC_VTRIM),
+               FSEQ_REG(CNVR_SCU_SD_REGS_SD_REG_ACTIVE_VDIG_MIRROR),
+       };
+
+       if (!iwl_trans_grab_nic_access(trans, &flags))
+               return;
+
+       IWL_ERR(fwrt, "Fseq Registers:\n");
+
+       for (i = 0; i < ARRAY_SIZE(fseq_regs); i++)
+               IWL_ERR(fwrt, "0x%08X | %s\n",
+                       iwl_read_prph_no_grab(trans, fseq_regs[i].addr),
+                       fseq_regs[i].str);
+
+       iwl_trans_release_nic_access(trans, &flags);
+}
+IWL_EXPORT_SYMBOL(iwl_fw_error_print_fseq_regs);
index 2a9e560a906bb6c287190f68cb91ee0981262e0d..fd0ad220e961f5d51f64419ceb23e4ffbc9cc7c9 100644 (file)
@@ -471,4 +471,6 @@ static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt)
 }
 
 void iwl_fw_dbg_periodic_trig_handler(struct timer_list *t);
+
+void iwl_fw_error_print_fseq_regs(struct iwl_fw_runtime *fwrt);
 #endif  /* __iwl_fw_dbg_h__ */
index 852d3cbfc719925340c23457145c7b2a80b180e9..fba242284507b8212453400eeb1e37b702518ada 100644 (file)
@@ -1597,7 +1597,6 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
        goto free;
 
  out_free_fw:
-       iwl_dealloc_ucode(drv);
        release_firmware(ucode_raw);
  out_unbind:
        complete(&drv->request_firmware_complete);
index 8e6a0c363c0dd514cca2c064a4568b5eee2bb537..8d930bfe0727579788985d8622e7a9ab3a6a5daf 100644 (file)
@@ -395,7 +395,11 @@ enum {
        WFPM_AUX_CTL_AUX_IF_MAC_OWNER_MSK       = 0x80000000,
 };
 
-#define AUX_MISC_REG                   0xA200B0
+#define CNVI_AUX_MISC_CHIP                             0xA200B0
+#define CNVR_AUX_MISC_CHIP                             0xA2B800
+#define CNVR_SCU_SD_REGS_SD_REG_DIG_DCDC_VTRIM         0xA29890
+#define CNVR_SCU_SD_REGS_SD_REG_ACTIVE_VDIG_MIRROR     0xA29938
+
 enum {
        HW_STEP_LOCATION_BITS = 24,
 };
@@ -408,7 +412,12 @@ enum aux_misc_master1_en {
 #define AUX_MISC_MASTER1_SMPHR_STATUS  0xA20800
 #define RSA_ENABLE                     0xA24B08
 #define PREG_AUX_BUS_WPROT_0           0xA04CC0
-#define PREG_PRPH_WPROT_0              0xA04CE0
+
+/* device family 9000 WPROT register */
+#define PREG_PRPH_WPROT_9000           0xA04CE0
+/* device family 22000 WPROT register */
+#define PREG_PRPH_WPROT_22000          0xA04D00
+
 #define SB_CPU_1_STATUS                        0xA01E30
 #define SB_CPU_2_STATUS                        0xA01E34
 #define UMAG_SB_CPU_1_STATUS           0xA038C0
@@ -442,4 +451,13 @@ enum {
 
 #define UREG_DOORBELL_TO_ISR6          0xA05C04
 #define UREG_DOORBELL_TO_ISR6_NMI_BIT  BIT(0)
+
+#define FSEQ_ERROR_CODE                        0xA340C8
+#define FSEQ_TOP_INIT_VERSION          0xA34038
+#define FSEQ_CNVIO_INIT_VERSION                0xA3403C
+#define FSEQ_OTP_VERSION               0xA340FC
+#define FSEQ_TOP_CONTENT_VERSION       0xA340F4
+#define FSEQ_ALIVE_TOKEN               0xA340F0
+#define FSEQ_CNVI_ID                   0xA3408C
+#define FSEQ_CNVR_ID                   0xA34090
 #endif                         /* __iwl_prph_h__ */
index 60f5d337f16d4f8c2dd65ec13332a3684d4f1a69..e7e68fb2bd29aa9989e814ac64b5114f3a170c57 100644 (file)
@@ -1972,26 +1972,6 @@ out:
        }
 }
 
-static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm)
-{
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-       const struct fw_img *img = &mvm->fw->img[IWL_UCODE_WOWLAN];
-       u32 len = img->sec[IWL_UCODE_SECTION_DATA].len;
-       u32 offs = img->sec[IWL_UCODE_SECTION_DATA].offset;
-
-       if (!mvm->store_d3_resume_sram)
-               return;
-
-       if (!mvm->d3_resume_sram) {
-               mvm->d3_resume_sram = kzalloc(len, GFP_KERNEL);
-               if (!mvm->d3_resume_sram)
-                       return;
-       }
-
-       iwl_trans_read_mem_bytes(mvm->trans, offs, mvm->d3_resume_sram, len);
-#endif
-}
-
 static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac,
                                       struct ieee80211_vif *vif)
 {
@@ -2054,8 +2034,6 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
        }
 
        iwl_fw_dbg_read_d3_debug_data(&mvm->fwrt);
-       /* query SRAM first in case we want event logging */
-       iwl_mvm_read_d3_sram(mvm);
 
        if (iwl_mvm_check_rt_status(mvm, vif)) {
                set_bit(STATUS_FW_ERROR, &mvm->trans->status);
index d4ff6b44de2c45e0d718ee5a3887472d6f752760..5b1bb76c5d28cf46339d1cbb8e3a3e4f764722db 100644 (file)
@@ -1557,59 +1557,6 @@ static ssize_t iwl_dbgfs_bcast_filters_macs_write(struct iwl_mvm *mvm,
 }
 #endif
 
-#ifdef CONFIG_PM_SLEEP
-static ssize_t iwl_dbgfs_d3_sram_write(struct iwl_mvm *mvm, char *buf,
-                                      size_t count, loff_t *ppos)
-{
-       int store;
-
-       if (sscanf(buf, "%d", &store) != 1)
-               return -EINVAL;
-
-       mvm->store_d3_resume_sram = store;
-
-       return count;
-}
-
-static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf,
-                                     size_t count, loff_t *ppos)
-{
-       struct iwl_mvm *mvm = file->private_data;
-       const struct fw_img *img;
-       int ofs, len, pos = 0;
-       size_t bufsz, ret;
-       char *buf;
-       u8 *ptr = mvm->d3_resume_sram;
-
-       img = &mvm->fw->img[IWL_UCODE_WOWLAN];
-       len = img->sec[IWL_UCODE_SECTION_DATA].len;
-
-       bufsz = len * 4 + 256;
-       buf = kzalloc(bufsz, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
-       pos += scnprintf(buf, bufsz, "D3 SRAM capture: %sabled\n",
-                        mvm->store_d3_resume_sram ? "en" : "dis");
-
-       if (ptr) {
-               for (ofs = 0; ofs < len; ofs += 16) {
-                       pos += scnprintf(buf + pos, bufsz - pos,
-                                        "0x%.4x %16ph\n", ofs, ptr + ofs);
-               }
-       } else {
-               pos += scnprintf(buf + pos, bufsz - pos,
-                                "(no data captured)\n");
-       }
-
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-
-       kfree(buf);
-
-       return ret;
-}
-#endif
-
 #define PRINT_MVM_REF(ref) do {                                                \
        if (mvm->refs[ref])                                             \
                pos += scnprintf(buf + pos, bufsz - pos,                \
@@ -1940,9 +1887,6 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
 #endif
 
-#ifdef CONFIG_PM_SLEEP
-MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8);
-#endif
 #ifdef CONFIG_ACPI
 MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile);
 #endif
@@ -2159,7 +2103,6 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
 #endif
 
 #ifdef CONFIG_PM_SLEEP
-       MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, 0600);
        MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, 0400);
        debugfs_create_bool("d3_wake_sysassert", 0600, mvm->debugfs_dir,
                            &mvm->d3_wake_sysassert);
index ab68b5d53ec957d02156f3989c336d6b448a70be..153717587aebd31e89b69b4bf2853f8ac485910e 100644 (file)
@@ -311,6 +311,8 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
        int ret;
        enum iwl_ucode_type old_type = mvm->fwrt.cur_fw_img;
        static const u16 alive_cmd[] = { MVM_ALIVE };
+       bool run_in_rfkill =
+               ucode_type == IWL_UCODE_INIT || iwl_mvm_has_unified_ucode(mvm);
 
        if (ucode_type == IWL_UCODE_REGULAR &&
            iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_START_FROM_ALIVE) &&
@@ -328,7 +330,12 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
                                   alive_cmd, ARRAY_SIZE(alive_cmd),
                                   iwl_alive_fn, &alive_data);
 
-       ret = iwl_trans_start_fw(mvm->trans, fw, ucode_type == IWL_UCODE_INIT);
+       /*
+        * We want to load the INIT firmware even in RFKILL
+        * For the unified firmware case, the ucode_type is not
+        * INIT, but we still need to run it.
+        */
+       ret = iwl_trans_start_fw(mvm->trans, fw, run_in_rfkill);
        if (ret) {
                iwl_fw_set_current_image(&mvm->fwrt, old_type);
                iwl_remove_notification(&mvm->notif_wait, &alive_wait);
@@ -433,7 +440,8 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
         * commands
         */
        ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(SYSTEM_GROUP,
-                                               INIT_EXTENDED_CFG_CMD), 0,
+                                               INIT_EXTENDED_CFG_CMD),
+                                  CMD_SEND_IN_RFKILL,
                                   sizeof(init_cfg), &init_cfg);
        if (ret) {
                IWL_ERR(mvm, "Failed to run init config command: %d\n",
@@ -457,7 +465,8 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
        }
 
        ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(REGULATORY_AND_NVM_GROUP,
-                                               NVM_ACCESS_COMPLETE), 0,
+                                               NVM_ACCESS_COMPLETE),
+                                  CMD_SEND_IN_RFKILL,
                                   sizeof(nvm_complete), &nvm_complete);
        if (ret) {
                IWL_ERR(mvm, "Failed to run complete NVM access: %d\n",
@@ -482,6 +491,8 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
                }
        }
 
+       mvm->rfkill_safe_init_done = true;
+
        return 0;
 
 error:
@@ -526,7 +537,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
 
        lockdep_assert_held(&mvm->mutex);
 
-       if (WARN_ON_ONCE(mvm->calibrating))
+       if (WARN_ON_ONCE(mvm->rfkill_safe_init_done))
                return 0;
 
        iwl_init_notification_wait(&mvm->notif_wait,
@@ -576,7 +587,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
                goto remove_notif;
        }
 
-       mvm->calibrating = true;
+       mvm->rfkill_safe_init_done = true;
 
        /* Send TX valid antennas before triggering calibrations */
        ret = iwl_send_tx_ant_cfg(mvm, iwl_mvm_get_valid_tx_ant(mvm));
@@ -612,7 +623,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
 remove_notif:
        iwl_remove_notification(&mvm->notif_wait, &calib_wait);
 out:
-       mvm->calibrating = false;
+       mvm->rfkill_safe_init_done = false;
        if (iwlmvm_mod_params.init_dbg && !mvm->nvm_data) {
                /* we want to debug INIT and we have no NVM - fake */
                mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) +
index 5c52469288beb55ed5cd21f97a6c184b38c0c136..fdbabca0280e164e24e436fee97292976b7d1d20 100644 (file)
@@ -1209,7 +1209,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
 
        mvm->scan_status = 0;
        mvm->ps_disabled = false;
-       mvm->calibrating = false;
+       mvm->rfkill_safe_init_done = false;
 
        /* just in case one was running */
        iwl_mvm_cleanup_roc_te(mvm);
index 8dc2a9850bc584c4a009caed8fd2c9725a7853ae..02efcf2189c489ad92a0ff1acaf8de436d3cc758 100644 (file)
@@ -880,7 +880,7 @@ struct iwl_mvm {
        struct iwl_mvm_vif *bf_allowed_vif;
 
        bool hw_registered;
-       bool calibrating;
+       bool rfkill_safe_init_done;
        bool support_umac_log;
 
        u32 ampdu_ref;
@@ -1039,8 +1039,6 @@ struct iwl_mvm {
 #ifdef CONFIG_IWLWIFI_DEBUGFS
        bool d3_wake_sysassert;
        bool d3_test_active;
-       bool store_d3_resume_sram;
-       void *d3_resume_sram;
        u32 d3_test_pme_ptr;
        struct ieee80211_vif *keep_vif;
        u32 last_netdetect_scans; /* no. of scans in the last net-detect wake */
index acd2fda124665f651cb939281df40ef1c3163bc6..fad3bf563712e02c9ff0bbe426b3ca58ac46aab4 100644 (file)
@@ -918,9 +918,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
        kfree(mvm->error_recovery_buf);
        mvm->error_recovery_buf = NULL;
 
-#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS)
-       kfree(mvm->d3_resume_sram);
-#endif
        iwl_trans_op_mode_leave(mvm->trans);
 
        iwl_phy_db_free(mvm->phy_db);
@@ -1212,7 +1209,8 @@ void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state)
 static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
 {
        struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
-       bool calibrating = READ_ONCE(mvm->calibrating);
+       bool rfkill_safe_init_done = READ_ONCE(mvm->rfkill_safe_init_done);
+       bool unified = iwl_mvm_has_unified_ucode(mvm);
 
        if (state)
                set_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
@@ -1221,15 +1219,23 @@ static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
 
        iwl_mvm_set_rfkill_state(mvm);
 
-       /* iwl_run_init_mvm_ucode is waiting for results, abort it */
-       if (calibrating)
+        /* iwl_run_init_mvm_ucode is waiting for results, abort it. */
+       if (rfkill_safe_init_done)
                iwl_abort_notification_waits(&mvm->notif_wait);
 
+       /*
+        * Don't ask the transport to stop the firmware. We'll do it
+        * after cfg80211 takes us down.
+        */
+       if (unified)
+               return false;
+
        /*
         * Stop the device if we run OPERATIONAL firmware or if we are in the
         * middle of the calibrations.
         */
-       return state && (mvm->fwrt.cur_fw_img != IWL_UCODE_INIT || calibrating);
+       return state && (mvm->fwrt.cur_fw_img != IWL_UCODE_INIT ||
+                        rfkill_safe_init_done);
 }
 
 static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
index 659e21b2d4e7293ed913d60f9285c25d42862187..be62f499c59510676ed9c56d2bc40633dc15af55 100644 (file)
@@ -441,7 +441,8 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
         */
        sta->max_amsdu_len = max_amsdu_len;
 
-       ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cfg_cmd), &cfg_cmd);
+       ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, CMD_ASYNC, sizeof(cfg_cmd),
+                                  &cfg_cmd);
        if (ret)
                IWL_ERR(mvm, "Failed to send rate scale config (%d)\n", ret);
 }
index b9914efc55c4b2f027db3954877645c4b7c27fb0..cc56ab88fb4394e31e6ca28635547198352727b7 100644 (file)
@@ -596,6 +596,8 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
                iwl_mvm_dump_lmac_error_log(mvm, 1);
 
        iwl_mvm_dump_umac_error_log(mvm);
+
+       iwl_fw_error_print_fseq_regs(&mvm->fwrt);
 }
 
 int iwl_mvm_reconfig_scd(struct iwl_mvm *mvm, int queue, int fifo, int sta_id,
index b513037dc0661e9eaae98f162841fbbe2e86e779..85973dd572341be089e66effcd6821be93ddacd8 100644 (file)
@@ -928,7 +928,7 @@ static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
                                           MSIX_HW_INT_CAUSES_REG_RF_KILL);
        }
 
-       if (trans->cfg->device_family == IWL_DEVICE_FAMILY_9000) {
+       if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_9000) {
                /*
                 * On 9000-series devices this bit isn't enabled by default, so
                 * when we power down the device we need set the bit to allow it
index 803fcbac415255d39e995a299e3ed031988e7436..dfa1bed124aab719ad18b1e9c5faeda924fb4c00 100644 (file)
@@ -1698,26 +1698,26 @@ static int iwl_pcie_init_msix_handler(struct pci_dev *pdev,
        return 0;
 }
 
-static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power)
+static int iwl_trans_pcie_clear_persistence_bit(struct iwl_trans *trans)
 {
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       u32 hpm;
-       int err;
-
-       lockdep_assert_held(&trans_pcie->mutex);
+       u32 hpm, wprot;
 
-       err = iwl_pcie_prepare_card_hw(trans);
-       if (err) {
-               IWL_ERR(trans, "Error while preparing HW: %d\n", err);
-               return err;
+       switch (trans->cfg->device_family) {
+       case IWL_DEVICE_FAMILY_9000:
+               wprot = PREG_PRPH_WPROT_9000;
+               break;
+       case IWL_DEVICE_FAMILY_22000:
+               wprot = PREG_PRPH_WPROT_22000;
+               break;
+       default:
+               return 0;
        }
 
        hpm = iwl_read_umac_prph_no_grab(trans, HPM_DEBUG);
        if (hpm != 0xa5a5a5a0 && (hpm & PERSISTENCE_BIT)) {
-               int wfpm_val = iwl_read_umac_prph_no_grab(trans,
-                                                         PREG_PRPH_WPROT_0);
+               u32 wprot_val = iwl_read_umac_prph_no_grab(trans, wprot);
 
-               if (wfpm_val & PREG_WFPM_ACCESS) {
+               if (wprot_val & PREG_WFPM_ACCESS) {
                        IWL_ERR(trans,
                                "Error, can not clear persistence bit\n");
                        return -EPERM;
@@ -1726,6 +1726,26 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power)
                                            hpm & ~PERSISTENCE_BIT);
        }
 
+       return 0;
+}
+
+static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       int err;
+
+       lockdep_assert_held(&trans_pcie->mutex);
+
+       err = iwl_pcie_prepare_card_hw(trans);
+       if (err) {
+               IWL_ERR(trans, "Error while preparing HW: %d\n", err);
+               return err;
+       }
+
+       err = iwl_trans_pcie_clear_persistence_bit(trans);
+       if (err)
+               return err;
+
        iwl_trans_pcie_sw_reset(trans);
 
        err = iwl_pcie_apm_init(trans);
@@ -3526,7 +3546,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
                        hw_step |= ENABLE_WFPM;
                        iwl_write_umac_prph_no_grab(trans, WFPM_CTRL_REG,
                                                    hw_step);
-                       hw_step = iwl_read_prph_no_grab(trans, AUX_MISC_REG);
+                       hw_step = iwl_read_prph_no_grab(trans,
+                                                       CNVI_AUX_MISC_CHIP);
                        hw_step = (hw_step >> HW_STEP_LOCATION_BITS) & 0xF;
                        if (hw_step == 0x3)
                                trans->hw_rev = (trans->hw_rev & 0xFFFFFFF3) |
@@ -3577,7 +3598,9 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
                }
        } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
                   CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) &&
-                  (trans->cfg != &iwl_ax200_cfg_cc ||
+                  ((trans->cfg != &iwl_ax200_cfg_cc &&
+                   trans->cfg != &killer1650x_2ax_cfg &&
+                   trans->cfg != &killer1650w_2ax_cfg) ||
                    trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0)) {
                u32 hw_status;
 
index 60ca13e0f15b7b02aca1e425f8a971555ac172e3..b5274d1f30fa7e472aa85665a9cefdb3a233dfd1 100644 (file)
@@ -3851,6 +3851,7 @@ static int __init init_mac80211_hwsim(void)
                        break;
                case HWSIM_REGTEST_STRICT_ALL:
                        param.reg_strict = true;
+                       /* fall through */
                case HWSIM_REGTEST_DRIVER_REG_ALL:
                        param.reg_alpha2 = hwsim_alpha2s[0];
                        break;
index 6845eb57b39a1ae4bae60cd78c9777adc17c0d09..653d347a9a19d3e77eb3fbd1ad5d7da3278d6d4a 100644 (file)
@@ -329,6 +329,8 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
        struct ieee80211_vendor_ie *vendorhdr;
        u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0;
        int left_len, parsed_len = 0;
+       unsigned int token_len;
+       int err = 0;
 
        if (!info->tail || !info->tail_len)
                return 0;
@@ -344,6 +346,12 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
         */
        while (left_len > sizeof(struct ieee_types_header)) {
                hdr = (void *)(info->tail + parsed_len);
+               token_len = hdr->len + sizeof(struct ieee_types_header);
+               if (token_len > left_len) {
+                       err = -EINVAL;
+                       goto out;
+               }
+
                switch (hdr->element_id) {
                case WLAN_EID_SSID:
                case WLAN_EID_SUPP_RATES:
@@ -361,17 +369,20 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
                        if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
                                                    WLAN_OUI_TYPE_MICROSOFT_WMM,
                                                    (const u8 *)hdr,
-                                                   hdr->len + sizeof(struct ieee_types_header)))
+                                                   token_len))
                                break;
                        /* fall through */
                default:
-                       memcpy(gen_ie->ie_buffer + ie_len, hdr,
-                              hdr->len + sizeof(struct ieee_types_header));
-                       ie_len += hdr->len + sizeof(struct ieee_types_header);
+                       if (ie_len + token_len > IEEE_MAX_IE_SIZE) {
+                               err = -EINVAL;
+                               goto out;
+                       }
+                       memcpy(gen_ie->ie_buffer + ie_len, hdr, token_len);
+                       ie_len += token_len;
                        break;
                }
-               left_len -= hdr->len + sizeof(struct ieee_types_header);
-               parsed_len += hdr->len + sizeof(struct ieee_types_header);
+               left_len -= token_len;
+               parsed_len += token_len;
        }
 
        /* parse only WPA vendor IE from tail, WMM IE is configured by
@@ -381,15 +392,17 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
                                                    WLAN_OUI_TYPE_MICROSOFT_WPA,
                                                    info->tail, info->tail_len);
        if (vendorhdr) {
-               memcpy(gen_ie->ie_buffer + ie_len, vendorhdr,
-                      vendorhdr->len + sizeof(struct ieee_types_header));
-               ie_len += vendorhdr->len + sizeof(struct ieee_types_header);
+               token_len = vendorhdr->len + sizeof(struct ieee_types_header);
+               if (ie_len + token_len > IEEE_MAX_IE_SIZE) {
+                       err = -EINVAL;
+                       goto out;
+               }
+               memcpy(gen_ie->ie_buffer + ie_len, vendorhdr, token_len);
+               ie_len += token_len;
        }
 
-       if (!ie_len) {
-               kfree(gen_ie);
-               return 0;
-       }
+       if (!ie_len)
+               goto out;
 
        gen_ie->ie_index = cpu_to_le16(gen_idx);
        gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON |
@@ -399,13 +412,15 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
 
        if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, NULL,
                                         NULL, NULL)) {
-               kfree(gen_ie);
-               return -1;
+               err = -EINVAL;
+               goto out;
        }
 
        priv->gen_idx = gen_idx;
+
+ out:
        kfree(gen_ie);
-       return 0;
+       return err;
 }
 
 /* This function parses different IEs-head & tail IEs, beacon IEs,
index 935778ec9a1b4f419ecc672d703c67963ba9526f..c269a0de94137905d282b49d5d53664f969dd58f 100644 (file)
@@ -1247,6 +1247,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
                }
                switch (element_id) {
                case WLAN_EID_SSID:
+                       if (element_len > IEEE80211_MAX_SSID_LEN)
+                               return -EINVAL;
                        bss_entry->ssid.ssid_len = element_len;
                        memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
                               element_len);
@@ -1256,6 +1258,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
                        break;
 
                case WLAN_EID_SUPP_RATES:
+                       if (element_len > MWIFIEX_SUPPORTED_RATES)
+                               return -EINVAL;
                        memcpy(bss_entry->data_rates, current_ptr + 2,
                               element_len);
                        memcpy(bss_entry->supported_rates, current_ptr + 2,
@@ -1265,6 +1269,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
                        break;
 
                case WLAN_EID_FH_PARAMS:
+                       if (element_len + 2 < sizeof(*fh_param_set))
+                               return -EINVAL;
                        fh_param_set =
                                (struct ieee_types_fh_param_set *) current_ptr;
                        memcpy(&bss_entry->phy_param_set.fh_param_set,
@@ -1273,6 +1279,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
                        break;
 
                case WLAN_EID_DS_PARAMS:
+                       if (element_len + 2 < sizeof(*ds_param_set))
+                               return -EINVAL;
                        ds_param_set =
                                (struct ieee_types_ds_param_set *) current_ptr;
 
@@ -1284,6 +1292,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
                        break;
 
                case WLAN_EID_CF_PARAMS:
+                       if (element_len + 2 < sizeof(*cf_param_set))
+                               return -EINVAL;
                        cf_param_set =
                                (struct ieee_types_cf_param_set *) current_ptr;
                        memcpy(&bss_entry->ss_param_set.cf_param_set,
@@ -1292,6 +1302,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
                        break;
 
                case WLAN_EID_IBSS_PARAMS:
+                       if (element_len + 2 < sizeof(*ibss_param_set))
+                               return -EINVAL;
                        ibss_param_set =
                                (struct ieee_types_ibss_param_set *)
                                current_ptr;
@@ -1301,10 +1313,14 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
                        break;
 
                case WLAN_EID_ERP_INFO:
+                       if (!element_len)
+                               return -EINVAL;
                        bss_entry->erp_flags = *(current_ptr + 2);
                        break;
 
                case WLAN_EID_PWR_CONSTRAINT:
+                       if (!element_len)
+                               return -EINVAL;
                        bss_entry->local_constraint = *(current_ptr + 2);
                        bss_entry->sensed_11h = true;
                        break;
@@ -1345,6 +1361,9 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
                        break;
 
                case WLAN_EID_VENDOR_SPECIFIC:
+                       if (element_len + 2 < sizeof(vendor_ie->vend_hdr))
+                               return -EINVAL;
+
                        vendor_ie = (struct ieee_types_vendor_specific *)
                                        current_ptr;
 
index cf4265cda22468c9b99d2e14c7c3de8647d92849..6284779712131f41f6ef19b8e4f42157f81fbc1e 100644 (file)
@@ -8,7 +8,8 @@
 #include "reg.h"
 #include "debug.h"
 
-void rtw_fw_c2h_cmd_handle_ext(struct rtw_dev *rtwdev, struct sk_buff *skb)
+static void rtw_fw_c2h_cmd_handle_ext(struct rtw_dev *rtwdev,
+                                     struct sk_buff *skb)
 {
        struct rtw_c2h_cmd *c2h;
        u8 sub_cmd_id;
@@ -47,7 +48,8 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
        }
 }
 
-void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev, u8 *h2c)
+static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev,
+                                   u8 *h2c)
 {
        u8 box;
        u8 box_state;
index f447361f75734f37baa9a0fba35789535641c40b..b2dac460913802be8681199b85af0bf7ebd52192 100644 (file)
@@ -162,7 +162,8 @@ static void rtw_watch_dog_work(struct work_struct *work)
        rtwdev->stats.tx_cnt = 0;
        rtwdev->stats.rx_cnt = 0;
 
-       rtw_iterate_vifs(rtwdev, rtw_vif_watch_dog_iter, &data);
+       /* use atomic version to avoid taking local->iflist_mtx mutex */
+       rtw_iterate_vifs_atomic(rtwdev, rtw_vif_watch_dog_iter, &data);
 
        /* fw supports only one station associated to enter lps, if there are
         * more than two stations associated to the AP, then we can not enter
index 4381b360b5b5358cc49b93b1aebe6cbaf304f4dd..404d89432c96d946ed8bdf0edcc1391f0d2e8d66 100644 (file)
@@ -144,10 +144,10 @@ static void rtw_phy_stat_rssi_iter(void *data, struct ieee80211_sta *sta)
        struct rtw_phy_stat_iter_data *iter_data = data;
        struct rtw_dev *rtwdev = iter_data->rtwdev;
        struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
-       u8 rssi, rssi_level;
+       u8 rssi;
 
        rssi = ewma_rssi_read(&si->avg_rssi);
-       rssi_level = rtw_phy_get_rssi_level(si->rssi_level, rssi);
+       si->rssi_level = rtw_phy_get_rssi_level(si->rssi_level, rssi);
 
        rtw_fw_send_rssi_info(rtwdev, si);
 
@@ -423,6 +423,11 @@ static u64 rtw_phy_db_2_linear(u8 power_db)
        u8 i, j;
        u64 linear;
 
+       if (power_db > 96)
+               power_db = 96;
+       else if (power_db < 1)
+               return 1;
+
        /* 1dB ~ 96dB */
        i = (power_db - 1) >> 3;
        j = (power_db - 1) - (i << 3);
@@ -848,12 +853,13 @@ u8 rtw_vht_2s_rates[] = {
        DESC_RATEVHT2SS_MCS6, DESC_RATEVHT2SS_MCS7,
        DESC_RATEVHT2SS_MCS8, DESC_RATEVHT2SS_MCS9
 };
-u8 rtw_cck_size = ARRAY_SIZE(rtw_cck_rates);
-u8 rtw_ofdm_size = ARRAY_SIZE(rtw_ofdm_rates);
-u8 rtw_ht_1s_size = ARRAY_SIZE(rtw_ht_1s_rates);
-u8 rtw_ht_2s_size = ARRAY_SIZE(rtw_ht_2s_rates);
-u8 rtw_vht_1s_size = ARRAY_SIZE(rtw_vht_1s_rates);
-u8 rtw_vht_2s_size = ARRAY_SIZE(rtw_vht_2s_rates);
+
+static u8 rtw_cck_size = ARRAY_SIZE(rtw_cck_rates);
+static u8 rtw_ofdm_size = ARRAY_SIZE(rtw_ofdm_rates);
+static u8 rtw_ht_1s_size = ARRAY_SIZE(rtw_ht_1s_rates);
+static u8 rtw_ht_2s_size = ARRAY_SIZE(rtw_ht_2s_rates);
+static u8 rtw_vht_1s_size = ARRAY_SIZE(rtw_vht_1s_rates);
+static u8 rtw_vht_2s_size = ARRAY_SIZE(rtw_vht_2s_rates);
 u8 *rtw_rate_section[RTW_RATE_SECTION_MAX] = {
        rtw_cck_rates, rtw_ofdm_rates,
        rtw_ht_1s_rates, rtw_ht_2s_rates,
index f9c67ed473d1f286e4c1acc8d694ba102ebb6b38..b42cd50b837ec0c396456989a20a3ca40977553b 100644 (file)
@@ -929,11 +929,15 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
        u32 addr;
        u8 *data;
 
+       data = kzalloc(RSI_9116_REG_SIZE, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
        status = rsi_sdio_master_access_msword(adapter, TA_BASE_ADDR);
        if (status < 0) {
                rsi_dbg(ERR_ZONE,
                        "Unable to set ms word to common reg\n");
-               return status;
+               goto err;
        }
 
        rsi_dbg(INIT_ZONE, "%s: Bring TA out of reset\n", __func__);
@@ -944,7 +948,7 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
                                                  RSI_9116_REG_SIZE);
        if (status < 0) {
                rsi_dbg(ERR_ZONE, "Unable to hold TA threads\n");
-               return status;
+               goto err;
        }
 
        put_unaligned_le32(TA_SOFT_RST_CLR, data);
@@ -954,7 +958,7 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
                                                  RSI_9116_REG_SIZE);
        if (status < 0) {
                rsi_dbg(ERR_ZONE, "Unable to get TA out of reset\n");
-               return status;
+               goto err;
        }
 
        put_unaligned_le32(TA_PC_ZERO, data);
@@ -964,7 +968,8 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
                                                  RSI_9116_REG_SIZE);
        if (status < 0) {
                rsi_dbg(ERR_ZONE, "Unable to Reset TA PC value\n");
-               return -EINVAL;
+               status = -EINVAL;
+               goto err;
        }
 
        put_unaligned_le32(TA_RELEASE_THREAD_VALUE, data);
@@ -974,17 +979,19 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
                                                  RSI_9116_REG_SIZE);
        if (status < 0) {
                rsi_dbg(ERR_ZONE, "Unable to release TA threads\n");
-               return status;
+               goto err;
        }
 
        status = rsi_sdio_master_access_msword(adapter, MISC_CFG_BASE_ADDR);
        if (status < 0) {
                rsi_dbg(ERR_ZONE, "Unable to set ms word to common reg\n");
-               return status;
+               goto err;
        }
        rsi_dbg(INIT_ZONE, "***** TA Reset done *****\n");
 
-       return 0;
+err:
+       kfree(data);
+       return status;
 }
 
 static struct rsi_host_intf_ops sdio_host_intf_ops = {
index b3dbdb3657494cad111c4c64bdc33ed90fb0aae7..d326915e0f40f38322d5fe0fe742832254341ee8 100644 (file)
@@ -48,7 +48,7 @@ static inline void cbc_writel(u32 val, int reg)
        if (offset == -1)
                return;
 
-       writel_relaxed(val,  cpubiuctrl_base + offset);
+       writel(val, cpubiuctrl_base + offset);
 }
 
 enum cpubiuctrl_regs {
@@ -238,7 +238,9 @@ static int __init brcmstb_biuctrl_init(void)
        if (!np)
                return 0;
 
-       setup_hifcpubiuctrl_regs(np);
+       ret = setup_hifcpubiuctrl_regs(np);
+       if (ret)
+               return ret;
 
        ret = mcp_write_pairing_set();
        if (ret) {
index bc10e3194809a64666f48819d2a51a40a681dda3..ec90b44fa0cd327cf32fcc76ba3eb5ba916eba94 100644 (file)
@@ -695,8 +695,8 @@ static int ixp4xx_npe_probe(struct platform_device *pdev)
                        continue; /* NPE already disabled or not present */
                }
                npe->regs = devm_ioremap_resource(dev, res);
-               if (!npe->regs)
-                       return -ENOMEM;
+               if (IS_ERR(npe->regs))
+                       return PTR_ERR(npe->regs);
 
                if (npe_reset(npe)) {
                        dev_info(dev, "NPE%d at 0x%08x-0x%08x does not reset\n",
index c7adff343ba9a1ec3feeae0c3e044c3bc65e1749..5faf057f6f37f11adbfbb7ce48d9dacc74c52605 100644 (file)
@@ -10831,17 +10831,6 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
        remove_em = (atomic_read(&block_group->trimming) == 0);
        spin_unlock(&block_group->lock);
 
-       if (remove_em) {
-               struct extent_map_tree *em_tree;
-
-               em_tree = &fs_info->mapping_tree.map_tree;
-               write_lock(&em_tree->lock);
-               remove_extent_mapping(em_tree, em);
-               write_unlock(&em_tree->lock);
-               /* once for the tree */
-               free_extent_map(em);
-       }
-
        mutex_unlock(&fs_info->chunk_mutex);
 
        ret = remove_block_group_free_space(trans, block_group);
@@ -10858,6 +10847,19 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
                goto out;
 
        ret = btrfs_del_item(trans, root, path);
+       if (ret)
+               goto out;
+
+       if (remove_em) {
+               struct extent_map_tree *em_tree;
+
+               em_tree = &fs_info->mapping_tree.map_tree;
+               write_lock(&em_tree->lock);
+               remove_extent_mapping(em_tree, em);
+               write_unlock(&em_tree->lock);
+               /* once for the tree */
+               free_extent_map(em);
+       }
 out:
        if (remove_rsv)
                btrfs_delayed_refs_rsv_release(fs_info, 1);
index 6dafa857bbb9a9bd003fc55aa8a0677a86a22fd5..2a1be0d1a69866754fe2932ee72d03ff4fe98a0e 100644 (file)
@@ -312,8 +312,6 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
                        btrfs_abort_transaction(trans, ret);
                        goto out_end_trans;
                }
-               set_bit(BTRFS_INODE_COPY_EVERYTHING,
-                       &BTRFS_I(inode)->runtime_flags);
        } else {
                ret = btrfs_set_prop(trans, inode, "btrfs.compression", NULL,
                                     0, 0);
index 10d9589001a9d7a833b756214f2bc25ea742303a..bb5bd49573b4cc116274d92d0bef180b0c1ec19f 100644 (file)
@@ -747,6 +747,7 @@ static void __reada_start_machine(struct btrfs_fs_info *fs_info)
        u64 total = 0;
        int i;
 
+again:
        do {
                enqueued = 0;
                mutex_lock(&fs_devices->device_list_mutex);
@@ -758,6 +759,10 @@ static void __reada_start_machine(struct btrfs_fs_info *fs_info)
                mutex_unlock(&fs_devices->device_list_mutex);
                total += enqueued;
        } while (enqueued && total < 10000);
+       if (fs_devices->seed) {
+               fs_devices = fs_devices->seed;
+               goto again;
+       }
 
        if (enqueued == 0)
                return;
index 78b6ba2029e8f0bcfbbdc0dd66a153db442fa335..95d9aebff2c4b0270d7db51f1da30b8247079b6a 100644 (file)
@@ -213,6 +213,9 @@ int btrfs_setxattr(struct btrfs_trans_handle *trans, struct inode *inode,
        }
 out:
        btrfs_free_path(path);
+       if (!ret)
+               set_bit(BTRFS_INODE_COPY_EVERYTHING,
+                       &BTRFS_I(inode)->runtime_flags);
        return ret;
 }
 
@@ -236,7 +239,6 @@ int btrfs_setxattr_trans(struct inode *inode, const char *name,
 
        inode_inc_iversion(inode);
        inode->i_ctime = current_time(inode);
-       set_bit(BTRFS_INODE_COPY_EVERYTHING, &BTRFS_I(inode)->runtime_flags);
        ret = btrfs_update_inode(trans, root, inode);
        BUG_ON(ret);
 out:
@@ -388,8 +390,6 @@ static int btrfs_xattr_handler_set_prop(const struct xattr_handler *handler,
        if (!ret) {
                inode_inc_iversion(inode);
                inode->i_ctime = current_time(inode);
-               set_bit(BTRFS_INODE_COPY_EVERYTHING,
-                       &BTRFS_I(inode)->runtime_flags);
                ret = btrfs_update_inode(trans, root, inode);
                BUG_ON(ret);
        }
index b26778bdc236e83595d6c2129d4f61ae45dbc0f2..7660c2749c96f075c721b701e0ee4839fe62cb82 100644 (file)
@@ -2105,6 +2105,7 @@ static int attach_recursive_mnt(struct mount *source_mnt,
                /* Notice when we are propagating across user namespaces */
                if (child->mnt_parent->mnt_ns->user_ns != user_ns)
                        lock_mnt_tree(child);
+               child->mnt.mnt_flags &= ~MNT_LOCKED;
                commit_tree(child);
        }
        put_mountpoint(smp);
@@ -3445,6 +3446,7 @@ SYSCALL_DEFINE3(fsmount, int, fs_fd, unsigned int, flags,
        ns->root = mnt;
        ns->mounts = 1;
        list_add(&mnt->mnt_list, &ns->list);
+       mntget(newmount.mnt);
 
        /* Attach to an apparent O_PATH fd with a note that we need to unmount
         * it, not just simply put it.
index 595857a1883e1a68a207fb32beef9c20a8bcd0e2..49f6d7ff21394f5e15e440ade00ba3363e27cf68 100644 (file)
@@ -261,7 +261,6 @@ static int propagate_one(struct mount *m)
        child = copy_tree(last_source, last_source->mnt.mnt_root, type);
        if (IS_ERR(child))
                return PTR_ERR(child);
-       child->mnt.mnt_flags &= ~MNT_LOCKED;
        mnt_set_mountpoint(m, mp, child);
        last_dest = m;
        last_source = child;
index cb3c6b3b89c802941edea7f732e2009b00a4b356..a7f7a98ec39d39c6e55d1fb194bee482da4767c7 100644 (file)
@@ -238,6 +238,12 @@ int bpf_percpu_cgroup_storage_update(struct bpf_map *map, void *key,
 #define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, t_ctx)                       \
        BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_UDP6_SENDMSG, t_ctx)
 
+#define BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk, uaddr)                       \
+       BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_UDP4_RECVMSG, NULL)
+
+#define BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk, uaddr)                       \
+       BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_UDP6_RECVMSG, NULL)
+
 #define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops)                                \
 ({                                                                            \
        int __ret = 0;                                                         \
@@ -339,6 +345,8 @@ static inline int bpf_percpu_cgroup_storage_update(struct bpf_map *map,
 #define BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr) ({ 0; })
 #define BPF_CGROUP_RUN_PROG_UDP4_SENDMSG_LOCK(sk, uaddr, t_ctx) ({ 0; })
 #define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, t_ctx) ({ 0; })
+#define BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk, uaddr) ({ 0; })
+#define BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk, uaddr) ({ 0; })
 #define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops) ({ 0; })
 #define BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(type,major,minor,access) ({ 0; })
 #define BPF_CGROUP_RUN_PROG_SYSCTL(head,table,write,buf,count,pos,nbuf) ({ 0; })
index 5df8e9e2a3933949af17dda1d77a4daccd5df611..b92ef9f73e42f1bcf0141aa21d0e9c17c5c7f05b 100644 (file)
@@ -600,7 +600,6 @@ void bpf_map_area_free(void *base);
 void bpf_map_init_from_attr(struct bpf_map *map, union bpf_attr *attr);
 
 extern int sysctl_unprivileged_bpf_disabled;
-extern int sysctl_bpf_stats_enabled;
 
 int bpf_map_new_fd(struct bpf_map *map, int flags);
 int bpf_prog_new_fd(struct bpf_prog *prog);
index 6411c624f63acbc4f549ad7e884c4c36f9d26efe..2d2e55dfea9445ca56babf2cc1dad0089b4b647e 100644 (file)
@@ -123,11 +123,20 @@ int mac_link_state(struct net_device *ndev,
  * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND.
  * @state: a pointer to a &struct phylink_link_state.
  *
+ * Note - not all members of @state are valid.  In particular,
+ * @state->lp_advertising, @state->link, @state->an_complete are never
+ * guaranteed to be correct, and so any mac_config() implementation must
+ * never reference these fields.
+ *
  * The action performed depends on the currently selected mode:
  *
  * %MLO_AN_FIXED, %MLO_AN_PHY:
  *   Configure the specified @state->speed, @state->duplex and
- *   @state->pause (%MLO_PAUSE_TX / %MLO_PAUSE_RX) mode.
+ *   @state->pause (%MLO_PAUSE_TX / %MLO_PAUSE_RX) modes over a link
+ *   specified by @state->interface.  @state->advertising may be used,
+ *   but is not required.  Other members of @state must be ignored.
+ *
+ *   Valid state members: interface, speed, duplex, pause, advertising.
  *
  * %MLO_AN_INBAND:
  *   place the link in an inband negotiation mode (such as 802.3z
@@ -150,6 +159,8 @@ int mac_link_state(struct net_device *ndev,
  *   responsible for reading the configuration word and configuring
  *   itself accordingly.
  *
+ *   Valid state members: interface, an_enabled, pause, advertising.
+ *
  * Implementations are expected to update the MAC to reflect the
  * requested settings - i.o.w., if nothing has changed between two
  * calls, no action is expected.  If only flow control settings have
index 178a3933a71b871982a58b5052740ca38f4ea34a..50ced8aba9dbf6c2cd4a0a1ef1598bdd58822821 100644 (file)
@@ -351,6 +351,8 @@ static inline void sk_psock_update_proto(struct sock *sk,
 static inline void sk_psock_restore_proto(struct sock *sk,
                                          struct sk_psock *psock)
 {
+       sk->sk_write_space = psock->saved_write_space;
+
        if (psock->sk_proto) {
                sk->sk_prot = psock->sk_proto;
                psock->sk_proto = NULL;
index b769ecfcc3bd41aad6fd339ba824c6bb622ac24d..aadd310769d080f1d45db14b2a72fc8ad36f1196 100644 (file)
@@ -63,6 +63,9 @@ extern int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int,
                                      void __user *, size_t *, loff_t *);
 extern int proc_do_large_bitmap(struct ctl_table *, int,
                                void __user *, size_t *, loff_t *);
+extern int proc_do_static_key(struct ctl_table *table, int write,
+                             void __user *buffer, size_t *lenp,
+                             loff_t *ppos);
 
 /*
  * Register a set of sysctl names by calling register_sysctl_table
index 711361af9ce019f08c8b6accc33220b673b34d56..9a478a0cd3a20b40ed344f178e35228a0b8ee203 100644 (file)
@@ -484,4 +484,8 @@ static inline u16 tcp_mss_clamp(const struct tcp_sock *tp, u16 mss)
 
        return (user_mss && user_mss < mss) ? user_mss : mss;
 }
+
+int tcp_skb_shift(struct sk_buff *to, struct sk_buff *from, int pcount,
+                 int shiftlen);
+
 #endif /* _LINUX_TCP_H */
index 2f67ae854ff01e24bc57221c400613d096916d3b..becdad57685908a4b07bb3df890260483aa3e36a 100644 (file)
@@ -309,6 +309,22 @@ static inline struct inet6_dev *__in6_dev_get(const struct net_device *dev)
        return rcu_dereference_rtnl(dev->ip6_ptr);
 }
 
+/**
+ * __in6_dev_stats_get - get inet6_dev pointer for stats
+ * @dev: network device
+ * @skb: skb for original incoming interface if neeeded
+ *
+ * Caller must hold rcu_read_lock or RTNL, because this function
+ * does not take a reference on the inet6_dev.
+ */
+static inline struct inet6_dev *__in6_dev_stats_get(const struct net_device *dev,
+                                                   const struct sk_buff *skb)
+{
+       if (netif_is_l3_master(dev))
+               dev = dev_get_by_index_rcu(dev_net(dev), inet6_iif(skb));
+       return __in6_dev_get(dev);
+}
+
 /**
  * __in6_dev_get_safely - get inet6_dev pointer from netdevice
  * @dev: network device
index 87dae868707e2a7fb92e483651c4e6cb2a524011..948139690a5867e3665ba4883340221f23e9363b 100644 (file)
@@ -3839,7 +3839,8 @@ struct cfg80211_ops {
  *     on wiphy_new(), but can be changed by the driver if it has a good
  *     reason to override the default
  * @WIPHY_FLAG_4ADDR_AP: supports 4addr mode even on AP (with a single station
- *     on a VLAN interface)
+ *     on a VLAN interface). This flag also serves an extra purpose of
+ *     supporting 4ADDR AP mode on devices which do not support AP/VLAN iftype.
  * @WIPHY_FLAG_4ADDR_STATION: supports 4addr mode even as a station
  * @WIPHY_FLAG_CONTROL_PORT_PROTOCOL: This device supports setting the
  *     control port protocol ethertype. The device also honours the
index 7c5a8d9a8d2a77eb65d11b5358a4d26a11591bdb..dfabc0503446505472b3f156d770698dfb39b8f3 100644 (file)
@@ -46,6 +46,7 @@ struct flow_dissector_key_tags {
 
 struct flow_dissector_key_vlan {
        u16     vlan_id:12,
+               vlan_dei:1,
                vlan_priority:3;
        __be16  vlan_tpid;
 };
index 7698460a3dd1e5070e12d406b3ee58834688cdc9..623cfbb7b8dcbb2a6d8325ec010aff78bbdf8839 100644 (file)
@@ -117,6 +117,7 @@ struct netns_ipv4 {
 #endif
        int sysctl_tcp_mtu_probing;
        int sysctl_tcp_base_mss;
+       int sysctl_tcp_min_snd_mss;
        int sysctl_tcp_probe_threshold;
        u32 sysctl_tcp_probe_interval;
 
index e9d769c04637a3c0b967c9bfa6def724834796b9..6cbc16136357d158cf1e84b98ecb7e06898269a6 100644 (file)
@@ -1463,12 +1463,14 @@ static inline void sk_mem_uncharge(struct sock *sk, int size)
                __sk_mem_reclaim(sk, 1 << 20);
 }
 
+DECLARE_STATIC_KEY_FALSE(tcp_tx_skb_cache_key);
 static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb)
 {
        sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
        sk->sk_wmem_queued -= skb->truesize;
        sk_mem_uncharge(sk, skb->truesize);
-       if (!sk->sk_tx_skb_cache && !skb_cloned(skb)) {
+       if (static_branch_unlikely(&tcp_tx_skb_cache_key) &&
+           !sk->sk_tx_skb_cache && !skb_cloned(skb)) {
                skb_zcopy_clear(skb, true);
                sk->sk_tx_skb_cache = skb;
                return;
@@ -2433,13 +2435,11 @@ static inline void skb_setup_tx_timestamp(struct sk_buff *skb, __u16 tsflags)
  * This routine must be called with interrupts disabled or with the socket
  * locked so that the sk_buff queue operation is ok.
 */
+DECLARE_STATIC_KEY_FALSE(tcp_rx_skb_cache_key);
 static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb)
 {
        __skb_unlink(skb, &sk->sk_receive_queue);
-       if (
-#ifdef CONFIG_RPS
-           !static_branch_unlikely(&rps_needed) &&
-#endif
+       if (static_branch_unlikely(&tcp_rx_skb_cache_key) &&
            !sk->sk_rx_skb_cache) {
                sk->sk_rx_skb_cache = skb;
                skb_orphan(skb);
@@ -2534,6 +2534,8 @@ extern int sysctl_optmem_max;
 extern __u32 sysctl_wmem_default;
 extern __u32 sysctl_rmem_default;
 
+DECLARE_STATIC_KEY_FALSE(net_high_order_alloc_disable_key);
+
 static inline int sk_get_wmem0(const struct sock *sk, const struct proto *proto)
 {
        /* Does this proto have per netns sysctl_wmem ? */
index ac2f53fbfa6b4cbf1fc615c952a5e1cac1124300..582c0caa98116740b5bde8c5dbb5d94fc69d1caa 100644 (file)
@@ -51,6 +51,8 @@ void tcp_time_wait(struct sock *sk, int state, int timeo);
 
 #define MAX_TCP_HEADER (128 + MAX_HEADER)
 #define MAX_TCP_OPTION_SPACE 40
+#define TCP_MIN_SND_MSS                48
+#define TCP_MIN_GSO_SIZE       (TCP_MIN_SND_MSS - MAX_TCP_OPTION_SPACE)
 
 /*
  * Never offer a window over 32767 without using window scaling. Some
index 63e0cf66f01a9698ff6bc41ac5492809bb83d834..a8b823c30b434d8022ebeab666d7072a09473be5 100644 (file)
@@ -192,6 +192,8 @@ enum bpf_attach_type {
        BPF_LIRC_MODE2,
        BPF_FLOW_DISSECTOR,
        BPF_CGROUP_SYSCTL,
+       BPF_CGROUP_UDP4_RECVMSG,
+       BPF_CGROUP_UDP6_RECVMSG,
        __MAX_BPF_ATTACH_TYPE
 };
 
@@ -3376,8 +3378,8 @@ struct bpf_raw_tracepoint_args {
 /* DIRECT:  Skip the FIB rules and go to FIB table associated with device
  * OUTPUT:  Do lookup from egress perspective; default is ingress
  */
-#define BPF_FIB_LOOKUP_DIRECT  BIT(0)
-#define BPF_FIB_LOOKUP_OUTPUT  BIT(1)
+#define BPF_FIB_LOOKUP_DIRECT  (1U << 0)
+#define BPF_FIB_LOOKUP_OUTPUT  (1U << 1)
 
 enum {
        BPF_FIB_LKUP_RET_SUCCESS,      /* lookup successful */
index 86dc24a96c90ab047d5173d625450facd6c6dd79..fd42c1316d3d112ecd8a00d2b499d6f6901c5e81 100644 (file)
@@ -283,6 +283,7 @@ enum
        LINUX_MIB_TCPACKCOMPRESSED,             /* TCPAckCompressed */
        LINUX_MIB_TCPZEROWINDOWDROP,            /* TCPZeroWindowDrop */
        LINUX_MIB_TCPRCVQDROP,                  /* TCPRcvQDrop */
+       LINUX_MIB_TCPWQUEUETOOBIG,              /* TCPWqueueTooBig */
        __LINUX_MIB_MAX
 };
 
index 7c473f208a1058de97434a57a2d47e2360ae80a8..080e2bb644ccd761b3d54fbad9b58a881086231e 100644 (file)
@@ -2097,7 +2097,6 @@ int __weak skb_copy_bits(const struct sk_buff *skb, int offset, void *to,
 
 DEFINE_STATIC_KEY_FALSE(bpf_stats_enabled_key);
 EXPORT_SYMBOL(bpf_stats_enabled_key);
-int sysctl_bpf_stats_enabled __read_mostly;
 
 /* All definitions of tracepoints related to BPF. */
 #define CREATE_TRACE_POINTS
index 15dbc15c5b0c96fb9429c797abb539abd6fcc0a5..cd8297b3bdb9518a6c3498f81a88f792ebad7f60 100644 (file)
@@ -178,6 +178,7 @@ static void dev_map_free(struct bpf_map *map)
                if (!dev)
                        continue;
 
+               free_percpu(dev->bulkq);
                dev_put(dev->dev);
                kfree(dev);
        }
@@ -273,6 +274,7 @@ void __dev_map_flush(struct bpf_map *map)
        unsigned long *bitmap = this_cpu_ptr(dtab->flush_needed);
        u32 bit;
 
+       rcu_read_lock();
        for_each_set_bit(bit, bitmap, map->max_entries) {
                struct bpf_dtab_netdev *dev = READ_ONCE(dtab->netdev_map[bit]);
                struct xdp_bulk_queue *bq;
@@ -283,11 +285,12 @@ void __dev_map_flush(struct bpf_map *map)
                if (unlikely(!dev))
                        continue;
 
-               __clear_bit(bit, bitmap);
-
                bq = this_cpu_ptr(dev->bulkq);
                bq_xmit_all(dev, bq, XDP_XMIT_FLUSH, true);
+
+               __clear_bit(bit, bitmap);
        }
+       rcu_read_unlock();
 }
 
 /* rcu_read_lock (from syscall and BPF contexts) ensures that if a delete and/or
@@ -380,6 +383,7 @@ static void dev_map_flush_old(struct bpf_dtab_netdev *dev)
 
                int cpu;
 
+               rcu_read_lock();
                for_each_online_cpu(cpu) {
                        bitmap = per_cpu_ptr(dev->dtab->flush_needed, cpu);
                        __clear_bit(dev->bit, bitmap);
@@ -387,6 +391,7 @@ static void dev_map_flush_old(struct bpf_dtab_netdev *dev)
                        bq = per_cpu_ptr(dev->bulkq, cpu);
                        bq_xmit_all(dev, bq, XDP_XMIT_FLUSH, false);
                }
+               rcu_read_unlock();
        }
 }
 
index e61630c2e50b28a3e342c4684b9be8e8141784a9..864e2a496376207072125ab321fcdd73b74dc198 100644 (file)
@@ -716,9 +716,14 @@ find_leftmost:
         * have exact two children, so this function will never return NULL.
         */
        for (node = search_root; node;) {
-               if (!(node->flags & LPM_TREE_NODE_FLAG_IM))
+               if (node->flags & LPM_TREE_NODE_FLAG_IM) {
+                       node = rcu_dereference(node->child[0]);
+               } else {
                        next_node = node;
-               node = rcu_dereference(node->child[0]);
+                       node = rcu_dereference(node->child[0]);
+                       if (!node)
+                               node = rcu_dereference(next_node->child[1]);
+               }
        }
 do_copy:
        next_key->prefixlen = next_node->prefixlen;
index ef63d26622f2f58561c09c0760310da40ce11671..42d17f7307802a0c2196e59ee5d5abcb37184258 100644 (file)
@@ -1573,6 +1573,8 @@ bpf_prog_load_check_attach_type(enum bpf_prog_type prog_type,
                case BPF_CGROUP_INET6_CONNECT:
                case BPF_CGROUP_UDP4_SENDMSG:
                case BPF_CGROUP_UDP6_SENDMSG:
+               case BPF_CGROUP_UDP4_RECVMSG:
+               case BPF_CGROUP_UDP6_RECVMSG:
                        return 0;
                default:
                        return -EINVAL;
@@ -1867,6 +1869,8 @@ static int bpf_prog_attach(const union bpf_attr *attr)
        case BPF_CGROUP_INET6_CONNECT:
        case BPF_CGROUP_UDP4_SENDMSG:
        case BPF_CGROUP_UDP6_SENDMSG:
+       case BPF_CGROUP_UDP4_RECVMSG:
+       case BPF_CGROUP_UDP6_RECVMSG:
                ptype = BPF_PROG_TYPE_CGROUP_SOCK_ADDR;
                break;
        case BPF_CGROUP_SOCK_OPS:
@@ -1952,6 +1956,8 @@ static int bpf_prog_detach(const union bpf_attr *attr)
        case BPF_CGROUP_INET6_CONNECT:
        case BPF_CGROUP_UDP4_SENDMSG:
        case BPF_CGROUP_UDP6_SENDMSG:
+       case BPF_CGROUP_UDP4_RECVMSG:
+       case BPF_CGROUP_UDP6_RECVMSG:
                ptype = BPF_PROG_TYPE_CGROUP_SOCK_ADDR;
                break;
        case BPF_CGROUP_SOCK_OPS:
@@ -2003,6 +2009,8 @@ static int bpf_prog_query(const union bpf_attr *attr,
        case BPF_CGROUP_INET6_CONNECT:
        case BPF_CGROUP_UDP4_SENDMSG:
        case BPF_CGROUP_UDP6_SENDMSG:
+       case BPF_CGROUP_UDP4_RECVMSG:
+       case BPF_CGROUP_UDP6_RECVMSG:
        case BPF_CGROUP_SOCK_OPS:
        case BPF_CGROUP_DEVICE:
        case BPF_CGROUP_SYSCTL:
index d15cc4fafa89b5f7e144307350b4668b80c598f4..a5c369e60343d4239285078410cb6d5b470ff48c 100644 (file)
@@ -5353,9 +5353,12 @@ static int check_return_code(struct bpf_verifier_env *env)
        struct tnum range = tnum_range(0, 1);
 
        switch (env->prog->type) {
+       case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
+               if (env->prog->expected_attach_type == BPF_CGROUP_UDP4_RECVMSG ||
+                   env->prog->expected_attach_type == BPF_CGROUP_UDP6_RECVMSG)
+                       range = tnum_range(1, 1);
        case BPF_PROG_TYPE_CGROUP_SKB:
        case BPF_PROG_TYPE_CGROUP_SOCK:
-       case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
        case BPF_PROG_TYPE_SOCK_OPS:
        case BPF_PROG_TYPE_CGROUP_DEVICE:
        case BPF_PROG_TYPE_CGROUP_SYSCTL:
@@ -5372,16 +5375,17 @@ static int check_return_code(struct bpf_verifier_env *env)
        }
 
        if (!tnum_in(range, reg->var_off)) {
+               char tn_buf[48];
+
                verbose(env, "At program exit the register R0 ");
                if (!tnum_is_unknown(reg->var_off)) {
-                       char tn_buf[48];
-
                        tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off);
                        verbose(env, "has value %s", tn_buf);
                } else {
                        verbose(env, "has unknown scalar value");
                }
-               verbose(env, " should have been 0 or 1\n");
+               tnum_strn(tn_buf, sizeof(tn_buf), range);
+               verbose(env, " should have been in %s\n", tn_buf);
                return -EINVAL;
        }
        return 0;
index 7d1008be6173313c807b2abb23f3171ef05cddc8..1beca96fb6252ddc4af07b6292f9dd95c4f53afd 100644 (file)
@@ -230,11 +230,6 @@ static int proc_dostring_coredump(struct ctl_table *table, int write,
 #endif
 static int proc_dopipe_max_size(struct ctl_table *table, int write,
                void __user *buffer, size_t *lenp, loff_t *ppos);
-#ifdef CONFIG_BPF_SYSCALL
-static int proc_dointvec_minmax_bpf_stats(struct ctl_table *table, int write,
-                                         void __user *buffer, size_t *lenp,
-                                         loff_t *ppos);
-#endif
 
 #ifdef CONFIG_MAGIC_SYSRQ
 /* Note: sysrq code uses its own private copy */
@@ -1253,12 +1248,10 @@ static struct ctl_table kern_table[] = {
        },
        {
                .procname       = "bpf_stats_enabled",
-               .data           = &sysctl_bpf_stats_enabled,
-               .maxlen         = sizeof(sysctl_bpf_stats_enabled),
+               .data           = &bpf_stats_enabled_key.key,
+               .maxlen         = sizeof(bpf_stats_enabled_key),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec_minmax_bpf_stats,
-               .extra1         = &zero,
-               .extra2         = &one,
+               .proc_handler   = proc_do_static_key,
        },
 #endif
 #if defined(CONFIG_TREE_RCU) || defined(CONFIG_PREEMPT_RCU)
@@ -3374,26 +3367,35 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
 
 #endif /* CONFIG_PROC_SYSCTL */
 
-#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_SYSCTL)
-static int proc_dointvec_minmax_bpf_stats(struct ctl_table *table, int write,
-                                         void __user *buffer, size_t *lenp,
-                                         loff_t *ppos)
+#if defined(CONFIG_SYSCTL)
+int proc_do_static_key(struct ctl_table *table, int write,
+                      void __user *buffer, size_t *lenp,
+                      loff_t *ppos)
 {
-       int ret, bpf_stats = *(int *)table->data;
-       struct ctl_table tmp = *table;
+       struct static_key *key = (struct static_key *)table->data;
+       static DEFINE_MUTEX(static_key_mutex);
+       int val, ret;
+       struct ctl_table tmp = {
+               .data   = &val,
+               .maxlen = sizeof(val),
+               .mode   = table->mode,
+               .extra1 = &zero,
+               .extra2 = &one,
+       };
 
        if (write && !capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       tmp.data = &bpf_stats;
+       mutex_lock(&static_key_mutex);
+       val = static_key_enabled(key);
        ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
        if (write && !ret) {
-               *(int *)table->data = bpf_stats;
-               if (bpf_stats)
-                       static_branch_enable(&bpf_stats_enabled_key);
+               if (val)
+                       static_key_enable(key);
                else
-                       static_branch_disable(&bpf_stats_enabled_key);
+                       static_key_disable(key);
        }
+       mutex_unlock(&static_key_mutex);
        return ret;
 }
 #endif
index f92d6ad5e080671450b8eba785811718bddb1700..1c9a4745e596d91bde5fc5910fc4f8bcb318529e 100644 (file)
@@ -410,8 +410,6 @@ static const struct bpf_func_proto bpf_perf_event_read_value_proto = {
        .arg4_type      = ARG_CONST_SIZE,
 };
 
-static DEFINE_PER_CPU(struct perf_sample_data, bpf_trace_sd);
-
 static __always_inline u64
 __bpf_perf_event_output(struct pt_regs *regs, struct bpf_map *map,
                        u64 flags, struct perf_sample_data *sd)
@@ -442,24 +440,50 @@ __bpf_perf_event_output(struct pt_regs *regs, struct bpf_map *map,
        return perf_event_output(event, sd, regs);
 }
 
+/*
+ * Support executing tracepoints in normal, irq, and nmi context that each call
+ * bpf_perf_event_output
+ */
+struct bpf_trace_sample_data {
+       struct perf_sample_data sds[3];
+};
+
+static DEFINE_PER_CPU(struct bpf_trace_sample_data, bpf_trace_sds);
+static DEFINE_PER_CPU(int, bpf_trace_nest_level);
 BPF_CALL_5(bpf_perf_event_output, struct pt_regs *, regs, struct bpf_map *, map,
           u64, flags, void *, data, u64, size)
 {
-       struct perf_sample_data *sd = this_cpu_ptr(&bpf_trace_sd);
+       struct bpf_trace_sample_data *sds = this_cpu_ptr(&bpf_trace_sds);
+       int nest_level = this_cpu_inc_return(bpf_trace_nest_level);
        struct perf_raw_record raw = {
                .frag = {
                        .size = size,
                        .data = data,
                },
        };
+       struct perf_sample_data *sd;
+       int err;
 
-       if (unlikely(flags & ~(BPF_F_INDEX_MASK)))
-               return -EINVAL;
+       if (WARN_ON_ONCE(nest_level > ARRAY_SIZE(sds->sds))) {
+               err = -EBUSY;
+               goto out;
+       }
+
+       sd = &sds->sds[nest_level - 1];
+
+       if (unlikely(flags & ~(BPF_F_INDEX_MASK))) {
+               err = -EINVAL;
+               goto out;
+       }
 
        perf_sample_data_init(sd, 0, 0);
        sd->raw = &raw;
 
-       return __bpf_perf_event_output(regs, map, flags, sd);
+       err = __bpf_perf_event_output(regs, map, flags, sd);
+
+out:
+       this_cpu_dec(bpf_trace_nest_level);
+       return err;
 }
 
 static const struct bpf_func_proto bpf_perf_event_output_proto = {
@@ -822,16 +846,48 @@ pe_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 /*
  * bpf_raw_tp_regs are separate from bpf_pt_regs used from skb/xdp
  * to avoid potential recursive reuse issue when/if tracepoints are added
- * inside bpf_*_event_output, bpf_get_stackid and/or bpf_get_stack
+ * inside bpf_*_event_output, bpf_get_stackid and/or bpf_get_stack.
+ *
+ * Since raw tracepoints run despite bpf_prog_active, support concurrent usage
+ * in normal, irq, and nmi context.
  */
-static DEFINE_PER_CPU(struct pt_regs, bpf_raw_tp_regs);
+struct bpf_raw_tp_regs {
+       struct pt_regs regs[3];
+};
+static DEFINE_PER_CPU(struct bpf_raw_tp_regs, bpf_raw_tp_regs);
+static DEFINE_PER_CPU(int, bpf_raw_tp_nest_level);
+static struct pt_regs *get_bpf_raw_tp_regs(void)
+{
+       struct bpf_raw_tp_regs *tp_regs = this_cpu_ptr(&bpf_raw_tp_regs);
+       int nest_level = this_cpu_inc_return(bpf_raw_tp_nest_level);
+
+       if (WARN_ON_ONCE(nest_level > ARRAY_SIZE(tp_regs->regs))) {
+               this_cpu_dec(bpf_raw_tp_nest_level);
+               return ERR_PTR(-EBUSY);
+       }
+
+       return &tp_regs->regs[nest_level - 1];
+}
+
+static void put_bpf_raw_tp_regs(void)
+{
+       this_cpu_dec(bpf_raw_tp_nest_level);
+}
+
 BPF_CALL_5(bpf_perf_event_output_raw_tp, struct bpf_raw_tracepoint_args *, args,
           struct bpf_map *, map, u64, flags, void *, data, u64, size)
 {
-       struct pt_regs *regs = this_cpu_ptr(&bpf_raw_tp_regs);
+       struct pt_regs *regs = get_bpf_raw_tp_regs();
+       int ret;
+
+       if (IS_ERR(regs))
+               return PTR_ERR(regs);
 
        perf_fetch_caller_regs(regs);
-       return ____bpf_perf_event_output(regs, map, flags, data, size);
+       ret = ____bpf_perf_event_output(regs, map, flags, data, size);
+
+       put_bpf_raw_tp_regs();
+       return ret;
 }
 
 static const struct bpf_func_proto bpf_perf_event_output_proto_raw_tp = {
@@ -848,12 +904,18 @@ static const struct bpf_func_proto bpf_perf_event_output_proto_raw_tp = {
 BPF_CALL_3(bpf_get_stackid_raw_tp, struct bpf_raw_tracepoint_args *, args,
           struct bpf_map *, map, u64, flags)
 {
-       struct pt_regs *regs = this_cpu_ptr(&bpf_raw_tp_regs);
+       struct pt_regs *regs = get_bpf_raw_tp_regs();
+       int ret;
+
+       if (IS_ERR(regs))
+               return PTR_ERR(regs);
 
        perf_fetch_caller_regs(regs);
        /* similar to bpf_perf_event_output_tp, but pt_regs fetched differently */
-       return bpf_get_stackid((unsigned long) regs, (unsigned long) map,
-                              flags, 0, 0);
+       ret = bpf_get_stackid((unsigned long) regs, (unsigned long) map,
+                             flags, 0, 0);
+       put_bpf_raw_tp_regs();
+       return ret;
 }
 
 static const struct bpf_func_proto bpf_get_stackid_proto_raw_tp = {
@@ -868,11 +930,17 @@ static const struct bpf_func_proto bpf_get_stackid_proto_raw_tp = {
 BPF_CALL_4(bpf_get_stack_raw_tp, struct bpf_raw_tracepoint_args *, args,
           void *, buf, u32, size, u64, flags)
 {
-       struct pt_regs *regs = this_cpu_ptr(&bpf_raw_tp_regs);
+       struct pt_regs *regs = get_bpf_raw_tp_regs();
+       int ret;
+
+       if (IS_ERR(regs))
+               return PTR_ERR(regs);
 
        perf_fetch_caller_regs(regs);
-       return bpf_get_stack((unsigned long) regs, (unsigned long) buf,
-                            (unsigned long) size, flags, 0);
+       ret = bpf_get_stack((unsigned long) regs, (unsigned long) buf,
+                           (unsigned long) size, flags, 0);
+       put_bpf_raw_tp_regs();
+       return ret;
 }
 
 static const struct bpf_func_proto bpf_get_stack_proto_raw_tp = {
index e97dc54b4fdf3fae180c4f276814a5fa5cd1aafd..2d7d257a430e6d24c78f6193419f96578496126e 100644 (file)
@@ -12,7 +12,7 @@
 
 /* Exfiltration buffer. */
 #define MAX_VAR_SIZE   128
-static char check_buf[MAX_VAR_SIZE];
+static u8 check_buf[MAX_VAR_SIZE];
 
 /* Character array to trigger stack protector in all functions. */
 #define VAR_BUFFER      32
@@ -106,9 +106,18 @@ static noinline __init int test_ ## name (void)                    \
                                                                \
        /* Fill clone type with zero for per-field init. */     \
        memset(&zero, 0x00, sizeof(zero));                      \
+       /* Clear entire check buffer for 0xFF overlap test. */  \
+       memset(check_buf, 0x00, sizeof(check_buf));             \
        /* Fill stack with 0xFF. */                             \
        ignored = leaf_ ##name((unsigned long)&ignored, 1,      \
                                FETCH_ARG_ ## which(zero));     \
+       /* Verify all bytes overwritten with 0xFF. */           \
+       for (sum = 0, i = 0; i < target_size; i++)              \
+               sum += (check_buf[i] != 0xFF);                  \
+       if (sum) {                                              \
+               pr_err(#name ": leaf fill was not 0xFF!?\n");   \
+               return 1;                                       \
+       }                                                       \
        /* Clear entire check buffer for later bit tests. */    \
        memset(check_buf, 0x00, sizeof(check_buf));             \
        /* Extract stack-defined variable contents. */          \
@@ -126,9 +135,9 @@ static noinline __init int test_ ## name (void)                     \
                return 1;                                       \
        }                                                       \
                                                                \
-       /* Look for any set bits in the check region. */        \
-       for (i = 0; i < sizeof(check_buf); i++)                 \
-               sum += (check_buf[i] != 0);                     \
+       /* Look for any bytes still 0xFF in check region. */    \
+       for (sum = 0, i = 0; i < target_size; i++)              \
+               sum += (check_buf[i] == 0xFF);                  \
                                                                \
        if (sum == 0)                                           \
                pr_info(#name " ok\n");                         \
@@ -162,13 +171,13 @@ static noinline __init int leaf_ ## name(unsigned long sp,        \
         * Keep this buffer around to make sure we've got a     \
         * stack frame of SOME kind...                          \
         */                                                     \
-       memset(buf, (char)(sp && 0xff), sizeof(buf));           \
+       memset(buf, (char)(sp & 0xff), sizeof(buf));            \
        /* Fill variable with 0xFF. */                          \
        if (fill) {                                             \
                fill_start = &var;                              \
                fill_size = sizeof(var);                        \
                memset(fill_start,                              \
-                      (char)((sp && 0xff) | forced_mask),      \
+                      (char)((sp & 0xff) | forced_mask),       \
                       fill_size);                              \
        }                                                       \
                                                                \
index 09fdd0aac4b907b926b3ecc70d3cdde207b73b12..b40e0bce67ead7d1dd36f435aa51bb9c53fa0e19 100644 (file)
@@ -426,9 +426,11 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
        }
 
        if (ax25->sk != NULL) {
+               local_bh_disable();
                bh_lock_sock(ax25->sk);
                sock_reset_flag(ax25->sk, SOCK_ZAPPED);
                bh_unlock_sock(ax25->sk);
+               local_bh_enable();
        }
 
 put:
index e8fd5dc1780aeb0a5b2f6b888052938c931913a5..80281ef2ccbd227fcdb6a2f482c70c35dd1c1def 100644 (file)
@@ -99,6 +99,7 @@ EXPORT_SYMBOL(can_ioctl);
 static void can_sock_destruct(struct sock *sk)
 {
        skb_queue_purge(&sk->sk_receive_queue);
+       skb_queue_purge(&sk->sk_error_queue);
 }
 
 static const struct can_proto *can_get_proto(int protocol)
@@ -952,6 +953,8 @@ static struct pernet_operations can_pernet_ops __read_mostly = {
 
 static __init int can_init(void)
 {
+       int err;
+
        /* check for correct padding to be able to use the structs similarly */
        BUILD_BUG_ON(offsetof(struct can_frame, can_dlc) !=
                     offsetof(struct canfd_frame, len) ||
@@ -965,15 +968,31 @@ static __init int can_init(void)
        if (!rcv_cache)
                return -ENOMEM;
 
-       register_pernet_subsys(&can_pernet_ops);
+       err = register_pernet_subsys(&can_pernet_ops);
+       if (err)
+               goto out_pernet;
 
        /* protocol register */
-       sock_register(&can_family_ops);
-       register_netdevice_notifier(&can_netdev_notifier);
+       err = sock_register(&can_family_ops);
+       if (err)
+               goto out_sock;
+       err = register_netdevice_notifier(&can_netdev_notifier);
+       if (err)
+               goto out_notifier;
+
        dev_add_pack(&can_packet);
        dev_add_pack(&canfd_packet);
 
        return 0;
+
+out_notifier:
+       sock_unregister(PF_CAN);
+out_sock:
+       unregister_pernet_subsys(&can_pernet_ops);
+out_pernet:
+       kmem_cache_destroy(rcv_cache);
+
+       return err;
 }
 
 static __exit void can_exit(void)
index cc9597a877707f3de6e7bbfdec3d3c7ae9f56fbc..d1c4e1f3be2c71385e5c4414b8c831e4b2e4a91d 100644 (file)
@@ -633,7 +633,8 @@ static struct bpf_map *bpf_sk_storage_map_alloc(union bpf_attr *attr)
                return ERR_PTR(-ENOMEM);
        bpf_map_init_from_attr(&smap->map, attr);
 
-       smap->bucket_log = ilog2(roundup_pow_of_two(num_possible_cpus()));
+       /* Use at least 2 buckets, select_bucket() is undefined behavior with 1 bucket */
+       smap->bucket_log = max_t(u32, 1, ilog2(roundup_pow_of_two(num_possible_cpus())));
        nbuckets = 1U << smap->bucket_log;
        smap->buckets = kvcalloc(sizeof(*smap->buckets), nbuckets,
                                 GFP_USER | __GFP_NOWARN);
index eb7fb6daa1efcadf1723813161c14193785fbf83..d6edd218babdde1ee35da7c0823ddf90dd5ba7cb 100644 (file)
@@ -4923,8 +4923,36 @@ skip_classify:
        }
 
        if (unlikely(skb_vlan_tag_present(skb))) {
-               if (skb_vlan_tag_get_id(skb))
+check_vlan_id:
+               if (skb_vlan_tag_get_id(skb)) {
+                       /* Vlan id is non 0 and vlan_do_receive() above couldn't
+                        * find vlan device.
+                        */
                        skb->pkt_type = PACKET_OTHERHOST;
+               } else if (skb->protocol == cpu_to_be16(ETH_P_8021Q) ||
+                          skb->protocol == cpu_to_be16(ETH_P_8021AD)) {
+                       /* Outer header is 802.1P with vlan 0, inner header is
+                        * 802.1Q or 802.1AD and vlan_do_receive() above could
+                        * not find vlan dev for vlan id 0.
+                        */
+                       __vlan_hwaccel_clear_tag(skb);
+                       skb = skb_vlan_untag(skb);
+                       if (unlikely(!skb))
+                               goto out;
+                       if (vlan_do_receive(&skb))
+                               /* After stripping off 802.1P header with vlan 0
+                                * vlan dev is found for inner header.
+                                */
+                               goto another_round;
+                       else if (unlikely(!skb))
+                               goto out;
+                       else
+                               /* We have stripped outer 802.1P vlan 0 header.
+                                * But could not find vlan dev.
+                                * check again for vlan id to set OTHERHOST.
+                                */
+                               goto check_vlan_id;
+               }
                /* Note: we might in the future use prio bits
                 * and set skb->priority like in vlan_do_receive()
                 * For the time being, just ignore Priority Code Point
index d08b1e19ce9c1ea5913ad1a1949ee1033f0f1236..4d1011b2e24f5ebc2695d7aa7825564756d928f8 100644 (file)
@@ -3020,6 +3020,11 @@ ethtool_rx_flow_rule_create(const struct ethtool_rx_flow_spec_input *input)
                        match->mask.vlan.vlan_id =
                                ntohs(ext_m_spec->vlan_tci) & 0x0fff;
 
+                       match->key.vlan.vlan_dei =
+                               !!(ext_h_spec->vlan_tci & htons(0x1000));
+                       match->mask.vlan.vlan_dei =
+                               !!(ext_m_spec->vlan_tci & htons(0x1000));
+
                        match->key.vlan.vlan_priority =
                                (ntohs(ext_h_spec->vlan_tci) & 0xe000) >> 13;
                        match->mask.vlan.vlan_priority =
index cd09bf5d21f4d2de2afbf88489faf84907b8749c..f615e42cf4eff2336a699cf146be801a1efb1ef7 100644 (file)
@@ -5300,7 +5300,13 @@ __bpf_skc_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
        struct net *net;
        int sdif;
 
-       family = len == sizeof(tuple->ipv4) ? AF_INET : AF_INET6;
+       if (len == sizeof(tuple->ipv4))
+               family = AF_INET;
+       else if (len == sizeof(tuple->ipv6))
+               family = AF_INET6;
+       else
+               return NULL;
+
        if (unlikely(family == AF_UNSPEC || flags ||
                     !((s32)netns_id < 0 || netns_id <= S32_MAX)))
                goto out;
@@ -5333,8 +5339,14 @@ __bpf_sk_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
        struct sock *sk = __bpf_skc_lookup(skb, tuple, len, caller_net,
                                           ifindex, proto, netns_id, flags);
 
-       if (sk)
+       if (sk) {
                sk = sk_to_full_sk(sk);
+               if (!sk_fullsock(sk)) {
+                       if (!sock_flag(sk, SOCK_RCU_FREE))
+                               sock_gen_put(sk);
+                       return NULL;
+               }
+       }
 
        return sk;
 }
@@ -5365,8 +5377,14 @@ bpf_sk_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
        struct sock *sk = bpf_skc_lookup(skb, tuple, len, proto, netns_id,
                                         flags);
 
-       if (sk)
+       if (sk) {
                sk = sk_to_full_sk(sk);
+               if (!sk_fullsock(sk)) {
+                       if (!sock_flag(sk, SOCK_RCU_FREE))
+                               sock_gen_put(sk);
+                       return NULL;
+               }
+       }
 
        return sk;
 }
@@ -6726,6 +6744,7 @@ static bool sock_addr_is_valid_access(int off, int size,
                case BPF_CGROUP_INET4_BIND:
                case BPF_CGROUP_INET4_CONNECT:
                case BPF_CGROUP_UDP4_SENDMSG:
+               case BPF_CGROUP_UDP4_RECVMSG:
                        break;
                default:
                        return false;
@@ -6736,6 +6755,7 @@ static bool sock_addr_is_valid_access(int off, int size,
                case BPF_CGROUP_INET6_BIND:
                case BPF_CGROUP_INET6_CONNECT:
                case BPF_CGROUP_UDP6_SENDMSG:
+               case BPF_CGROUP_UDP6_RECVMSG:
                        break;
                default:
                        return false;
index 0e2c0735546396005406d3297f39bca58a9938cb..9e7fc929bc50914698d1af09525d4e87fd32b198 100644 (file)
@@ -3203,6 +3203,7 @@ static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
 }
 
 void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl, unsigned int neigh_seq_flags)
+       __acquires(tbl->lock)
        __acquires(rcu_bh)
 {
        struct neigh_seq_state *state = seq->private;
@@ -3213,6 +3214,7 @@ void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl
 
        rcu_read_lock_bh();
        state->nht = rcu_dereference_bh(tbl->nht);
+       read_lock(&tbl->lock);
 
        return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
 }
@@ -3246,8 +3248,13 @@ out:
 EXPORT_SYMBOL(neigh_seq_next);
 
 void neigh_seq_stop(struct seq_file *seq, void *v)
+       __releases(tbl->lock)
        __releases(rcu_bh)
 {
+       struct neigh_seq_state *state = seq->private;
+       struct neigh_table *tbl = state->tbl;
+
+       read_unlock(&tbl->lock);
        rcu_read_unlock_bh();
 }
 EXPORT_SYMBOL(neigh_seq_stop);
index 47c1aa9ee0454a4d6b4034e51f49fcaac8b2ac1a..c8cd99c3603f7874a9f8b5841d4117ba4ec4e5f2 100644 (file)
@@ -2337,6 +2337,7 @@ do_frag_list:
                kv.iov_base = skb->data + offset;
                kv.iov_len = slen;
                memset(&msg, 0, sizeof(msg));
+               msg.msg_flags = MSG_DONTWAIT;
 
                ret = kernel_sendmsg_locked(sk, &msg, &kv, 1, slen);
                if (ret <= 0)
index 2b3701958486219a26385c8fca1498c4e294dc1d..af09a23e48226337ebe0726c4358ee543c0e81b6 100644 (file)
@@ -1850,6 +1850,9 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
                        goto out;
                }
                RCU_INIT_POINTER(newsk->sk_reuseport_cb, NULL);
+#ifdef CONFIG_BPF_SYSCALL
+               RCU_INIT_POINTER(newsk->sk_bpf_storage, NULL);
+#endif
 
                newsk->sk_err      = 0;
                newsk->sk_err_soft = 0;
@@ -2320,6 +2323,7 @@ static void sk_leave_memory_pressure(struct sock *sk)
 
 /* On 32bit arches, an skb frag is limited to 2^15 */
 #define SKB_FRAG_PAGE_ORDER    get_order(32768)
+DEFINE_STATIC_KEY_FALSE(net_high_order_alloc_disable_key);
 
 /**
  * skb_page_frag_refill - check that a page_frag contains enough room
@@ -2344,7 +2348,8 @@ bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t gfp)
        }
 
        pfrag->offset = 0;
-       if (SKB_FRAG_PAGE_ORDER) {
+       if (SKB_FRAG_PAGE_ORDER &&
+           !static_branch_unlikely(&net_high_order_alloc_disable_key)) {
                /* Avoid direct reclaim but allow kswapd to wake */
                pfrag->page = alloc_pages((gfp & ~__GFP_DIRECT_RECLAIM) |
                                          __GFP_COMP | __GFP_NOWARN |
index 1a2685694abd537d7ae304754b84b237928fd298..f9204719aeeeb4700582d03fda244f2f8961f8a7 100644 (file)
@@ -562,6 +562,13 @@ static struct ctl_table net_core_table[] = {
                .extra1         = &zero,
                .extra2         = &two,
        },
+       {
+               .procname       = "high_order_alloc_disable",
+               .data           = &net_high_order_alloc_disable_key.key,
+               .maxlen         = sizeof(net_high_order_alloc_disable_key),
+               .mode           = 0644,
+               .proc_handler   = proc_do_static_key,
+       },
        { }
 };
 
index b80410673915094255824d4e4b5fbdad292fd4c8..bfa49a88d03ae570261646730eed24d4cc27e36c 100644 (file)
@@ -964,7 +964,7 @@ static int fib_check_nh_v4_gw(struct net *net, struct fib_nh *nh, u32 table,
 {
        struct net_device *dev;
        struct fib_result res;
-       int err;
+       int err = 0;
 
        if (nh->fib_nh_flags & RTNH_F_ONLINK) {
                unsigned int addr_type;
index 8c9189a41b136c6f170e146f8a425a7041efc5f8..16f9159234a2014491fdd7f7371d6cb06b978adc 100644 (file)
@@ -918,7 +918,7 @@ static int __ip_append_data(struct sock *sk,
                uarg = sock_zerocopy_realloc(sk, length, skb_zcopy(skb));
                if (!uarg)
                        return -ENOBUFS;
-               extra_uref = !skb;      /* only extra ref if !MSG_MORE */
+               extra_uref = !skb_zcopy(skb);   /* only ref on new uarg */
                if (rt->dst.dev->features & NETIF_F_SG &&
                    csummode == CHECKSUM_PARTIAL) {
                        paged = true;
index 4370f4246e86dfe06a9e07cace848baeaf6cc4da..073273b751f8fcda1c9c79cd1ab566f2939b2517 100644 (file)
@@ -287,6 +287,7 @@ static const struct snmp_mib snmp4_net_list[] = {
        SNMP_MIB_ITEM("TCPAckCompressed", LINUX_MIB_TCPACKCOMPRESSED),
        SNMP_MIB_ITEM("TCPZeroWindowDrop", LINUX_MIB_TCPZEROWINDOWDROP),
        SNMP_MIB_ITEM("TCPRcvQDrop", LINUX_MIB_TCPRCVQDROP),
+       SNMP_MIB_ITEM("TCPWqueueTooBig", LINUX_MIB_TCPWQUEUETOOBIG),
        SNMP_MIB_SENTINEL
 };
 
index 875867b64d6a6597bf4fcd3498ed55741cbe33f7..b6f14af926faf80f1686549bee7154c584dc63e6 100644 (file)
@@ -39,6 +39,8 @@ static int ip_local_port_range_min[] = { 1, 1 };
 static int ip_local_port_range_max[] = { 65535, 65535 };
 static int tcp_adv_win_scale_min = -31;
 static int tcp_adv_win_scale_max = 31;
+static int tcp_min_snd_mss_min = TCP_MIN_SND_MSS;
+static int tcp_min_snd_mss_max = 65535;
 static int ip_privileged_port_min;
 static int ip_privileged_port_max = 65535;
 static int ip_ttl_min = 1;
@@ -559,6 +561,18 @@ static struct ctl_table ipv4_table[] = {
                .extra1         = &sysctl_fib_sync_mem_min,
                .extra2         = &sysctl_fib_sync_mem_max,
        },
+       {
+               .procname       = "tcp_rx_skb_cache",
+               .data           = &tcp_rx_skb_cache_key.key,
+               .mode           = 0644,
+               .proc_handler   = proc_do_static_key,
+       },
+       {
+               .procname       = "tcp_tx_skb_cache",
+               .data           = &tcp_tx_skb_cache_key.key,
+               .mode           = 0644,
+               .proc_handler   = proc_do_static_key,
+       },
        { }
 };
 
@@ -757,6 +771,15 @@ static struct ctl_table ipv4_net_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
        },
+       {
+               .procname       = "tcp_min_snd_mss",
+               .data           = &init_net.ipv4.sysctl_tcp_min_snd_mss,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &tcp_min_snd_mss_min,
+               .extra2         = &tcp_min_snd_mss_max,
+       },
        {
                .procname       = "tcp_probe_threshold",
                .data           = &init_net.ipv4.sysctl_tcp_probe_threshold,
index f12d500ec85cf770b0b94cb5e08d16f77e4c126b..7dc9ab84bb69aa90953e98f9763287fcee3a1659 100644 (file)
@@ -317,6 +317,11 @@ struct tcp_splice_state {
 unsigned long tcp_memory_pressure __read_mostly;
 EXPORT_SYMBOL_GPL(tcp_memory_pressure);
 
+DEFINE_STATIC_KEY_FALSE(tcp_rx_skb_cache_key);
+EXPORT_SYMBOL(tcp_rx_skb_cache_key);
+
+DEFINE_STATIC_KEY_FALSE(tcp_tx_skb_cache_key);
+
 void tcp_enter_memory_pressure(struct sock *sk)
 {
        unsigned long val;
@@ -3868,6 +3873,7 @@ void __init tcp_init(void)
        unsigned long limit;
        unsigned int i;
 
+       BUILD_BUG_ON(TCP_MIN_SND_MSS <= MAX_TCP_OPTION_SPACE);
        BUILD_BUG_ON(sizeof(struct tcp_skb_cb) >
                     FIELD_SIZEOF(struct sk_buff, cb));
 
index 08a477e74cf3267b725294c66b46fdad12bd2b72..d95ee40df6c2b020d590018bc41833b8a6aefa4a 100644 (file)
@@ -1302,7 +1302,7 @@ static bool tcp_shifted_skb(struct sock *sk, struct sk_buff *prev,
        TCP_SKB_CB(skb)->seq += shifted;
 
        tcp_skb_pcount_add(prev, pcount);
-       BUG_ON(tcp_skb_pcount(skb) < pcount);
+       WARN_ON_ONCE(tcp_skb_pcount(skb) < pcount);
        tcp_skb_pcount_add(skb, -pcount);
 
        /* When we're adding to gso_segs == 1, gso_size will be zero,
@@ -1368,6 +1368,21 @@ static int skb_can_shift(const struct sk_buff *skb)
        return !skb_headlen(skb) && skb_is_nonlinear(skb);
 }
 
+int tcp_skb_shift(struct sk_buff *to, struct sk_buff *from,
+                 int pcount, int shiftlen)
+{
+       /* TCP min gso_size is 8 bytes (TCP_MIN_GSO_SIZE)
+        * Since TCP_SKB_CB(skb)->tcp_gso_segs is 16 bits, we need
+        * to make sure not storing more than 65535 * 8 bytes per skb,
+        * even if current MSS is bigger.
+        */
+       if (unlikely(to->len + shiftlen >= 65535 * TCP_MIN_GSO_SIZE))
+               return 0;
+       if (unlikely(tcp_skb_pcount(to) + pcount > 65535))
+               return 0;
+       return skb_shift(to, from, shiftlen);
+}
+
 /* Try collapsing SACK blocks spanning across multiple skbs to a single
  * skb.
  */
@@ -1473,7 +1488,7 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb,
        if (!after(TCP_SKB_CB(skb)->seq + len, tp->snd_una))
                goto fallback;
 
-       if (!skb_shift(prev, skb, len))
+       if (!tcp_skb_shift(prev, skb, pcount, len))
                goto fallback;
        if (!tcp_shifted_skb(sk, prev, skb, state, pcount, len, mss, dup_sack))
                goto out;
@@ -1491,11 +1506,10 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb,
                goto out;
 
        len = skb->len;
-       if (skb_shift(prev, skb, len)) {
-               pcount += tcp_skb_pcount(skb);
-               tcp_shifted_skb(sk, prev, skb, state, tcp_skb_pcount(skb),
+       pcount = tcp_skb_pcount(skb);
+       if (tcp_skb_shift(prev, skb, pcount, len))
+               tcp_shifted_skb(sk, prev, skb, state, pcount,
                                len, mss, 0);
-       }
 
 out:
        return prev;
@@ -2648,7 +2662,7 @@ static void tcp_process_loss(struct sock *sk, int flag, int num_dupack,
        struct tcp_sock *tp = tcp_sk(sk);
        bool recovered = !before(tp->snd_una, tp->high_seq);
 
-       if ((flag & FLAG_SND_UNA_ADVANCED) &&
+       if ((flag & FLAG_SND_UNA_ADVANCED || tp->fastopen_rsk) &&
            tcp_try_undo_loss(sk, false))
                return;
 
index bc86f9735f4577d50d94f42b10edb6ba95bb7a05..cfa81190a1b1af30d05f4f6cd84c05b025a6afeb 100644 (file)
@@ -2628,6 +2628,7 @@ static int __net_init tcp_sk_init(struct net *net)
        net->ipv4.sysctl_tcp_ecn_fallback = 1;
 
        net->ipv4.sysctl_tcp_base_mss = TCP_BASE_MSS;
+       net->ipv4.sysctl_tcp_min_snd_mss = TCP_MIN_SND_MSS;
        net->ipv4.sysctl_tcp_probe_threshold = TCP_PROBE_THRESHOLD;
        net->ipv4.sysctl_tcp_probe_interval = TCP_PROBE_INTERVAL;
 
index f429e856e2631a9e6de1d2e060406742f97e538e..00c01a01b547ec67c971dc25a74c9258563cf871 100644 (file)
@@ -1296,6 +1296,11 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue,
        if (nsize < 0)
                nsize = 0;
 
+       if (unlikely((sk->sk_wmem_queued >> 1) > sk->sk_sndbuf)) {
+               NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPWQUEUETOOBIG);
+               return -ENOMEM;
+       }
+
        if (skb_unclone(skb, gfp))
                return -ENOMEM;
 
@@ -1454,8 +1459,7 @@ static inline int __tcp_mtu_to_mss(struct sock *sk, int pmtu)
        mss_now -= icsk->icsk_ext_hdr_len;
 
        /* Then reserve room for full set of TCP options and 8 bytes of data */
-       if (mss_now < 48)
-               mss_now = 48;
+       mss_now = max(mss_now, sock_net(sk)->ipv4.sysctl_tcp_min_snd_mss);
        return mss_now;
 }
 
@@ -2747,7 +2751,7 @@ static bool tcp_collapse_retrans(struct sock *sk, struct sk_buff *skb)
                if (next_skb_size <= skb_availroom(skb))
                        skb_copy_bits(next_skb, 0, skb_put(skb, next_skb_size),
                                      next_skb_size);
-               else if (!skb_shift(skb, next_skb, next_skb_size))
+               else if (!tcp_skb_shift(skb, next_skb, 1, next_skb_size))
                        return false;
        }
        tcp_highest_sack_replace(sk, next_skb, skb);
index 5bad937ce779ef8dca42a26dcbb5f1d60a571c73..c801cd37cc2a9c11f2dd4b9681137755e501a538 100644 (file)
@@ -155,6 +155,7 @@ static void tcp_mtu_probing(struct inet_connection_sock *icsk, struct sock *sk)
                mss = tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low) >> 1;
                mss = min(net->ipv4.sysctl_tcp_base_mss, mss);
                mss = max(mss, 68 - tcp_sk(sk)->tcp_header_len);
+               mss = max(mss, net->ipv4.sysctl_tcp_min_snd_mss);
                icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, mss);
        }
        tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
index 7c6228fbf5dd8852f54da1d220ba26755d4695f2..eed59c8477228a72109718a7f35ef806ba6af826 100644 (file)
@@ -498,7 +498,11 @@ static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb,
 struct sock *udp4_lib_lookup_skb(struct sk_buff *skb,
                                 __be16 sport, __be16 dport)
 {
-       return __udp4_lib_lookup_skb(skb, sport, dport, &udp_table);
+       const struct iphdr *iph = ip_hdr(skb);
+
+       return __udp4_lib_lookup(dev_net(skb->dev), iph->saddr, sport,
+                                iph->daddr, dport, inet_iif(skb),
+                                inet_sdif(skb), &udp_table, NULL);
 }
 EXPORT_SYMBOL_GPL(udp4_lib_lookup_skb);
 
@@ -1773,6 +1777,10 @@ try_again:
                sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
                memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
                *addr_len = sizeof(*sin);
+
+               if (cgroup_bpf_enabled)
+                       BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk,
+                                                       (struct sockaddr *)sin);
        }
 
        if (udp_sk(sk)->gro_enabled)
index bafdd04a768d16b7c862db3ac84ad1633deafc09..375b4b4f9bf5dde6fee9f4fc2a9028738498504e 100644 (file)
@@ -393,23 +393,28 @@ relookup_failed:
        return ERR_PTR(err);
 }
 
-static int icmp6_iif(const struct sk_buff *skb)
+static struct net_device *icmp6_dev(const struct sk_buff *skb)
 {
-       int iif = skb->dev->ifindex;
+       struct net_device *dev = skb->dev;
 
        /* for local traffic to local address, skb dev is the loopback
         * device. Check if there is a dst attached to the skb and if so
         * get the real device index. Same is needed for replies to a link
         * local address on a device enslaved to an L3 master device
         */
-       if (unlikely(iif == LOOPBACK_IFINDEX || netif_is_l3_master(skb->dev))) {
+       if (unlikely(dev->ifindex == LOOPBACK_IFINDEX || netif_is_l3_master(skb->dev))) {
                const struct rt6_info *rt6 = skb_rt6_info(skb);
 
                if (rt6)
-                       iif = rt6->rt6i_idev->dev->ifindex;
+                       dev = rt6->rt6i_idev->dev;
        }
 
-       return iif;
+       return dev;
+}
+
+static int icmp6_iif(const struct sk_buff *skb)
+{
+       return icmp6_dev(skb)->ifindex;
 }
 
 /*
@@ -810,7 +815,7 @@ out:
 static int icmpv6_rcv(struct sk_buff *skb)
 {
        struct net *net = dev_net(skb->dev);
-       struct net_device *dev = skb->dev;
+       struct net_device *dev = icmp6_dev(skb);
        struct inet6_dev *idev = __in6_dev_get(dev);
        const struct in6_addr *saddr, *daddr;
        struct icmp6hdr *hdr;
index 2f3eb7dc45daa5012b4b29f34b0542e00c60d135..545e339b8c4fb5a372d4193361b4f5c9f9dd3b0b 100644 (file)
@@ -250,9 +250,9 @@ struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, __be32 label)
        rcu_read_lock_bh();
        for_each_sk_fl_rcu(np, sfl) {
                struct ip6_flowlabel *fl = sfl->fl;
-               if (fl->label == label) {
+
+               if (fl->label == label && atomic_inc_not_zero(&fl->users)) {
                        fl->lastuse = jiffies;
-                       atomic_inc(&fl->users);
                        rcu_read_unlock_bh();
                        return fl;
                }
@@ -618,7 +618,8 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
                                                goto done;
                                        }
                                        fl1 = sfl->fl;
-                                       atomic_inc(&fl1->users);
+                                       if (!atomic_inc_not_zero(&fl1->users))
+                                               fl1 = NULL;
                                        break;
                                }
                        }
index 934c88f128abbd22bb994d56a018da1748ff3a16..834475717110ecc53aa5bd2e3f275f2e8980fb05 100644 (file)
@@ -1340,7 +1340,7 @@ emsgsize:
                uarg = sock_zerocopy_realloc(sk, length, skb_zcopy(skb));
                if (!uarg)
                        return -ENOBUFS;
-               extra_uref = !skb;      /* only extra ref if !MSG_MORE */
+               extra_uref = !skb_zcopy(skb);   /* only ref on new uarg */
                if (rt->dst.dev->features & NETIF_F_SG &&
                    csummode == CHECKSUM_PARTIAL) {
                        paged = true;
index 22369694b2fbfff807211a22d1c06e02eb5093c2..b2b2c0c38b870515085b23e39e7c5c51707bf472 100644 (file)
@@ -298,7 +298,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *skb,
                           skb_network_header_len(skb));
 
        rcu_read_lock();
-       __IP6_INC_STATS(net, __in6_dev_get(dev), IPSTATS_MIB_REASMOKS);
+       __IP6_INC_STATS(net, __in6_dev_stats_get(dev, skb), IPSTATS_MIB_REASMOKS);
        rcu_read_unlock();
        fq->q.rb_fragments = RB_ROOT;
        fq->q.fragments_tail = NULL;
@@ -312,7 +312,7 @@ out_oom:
        net_dbg_ratelimited("ip6_frag_reasm: no memory for reassembly\n");
 out_fail:
        rcu_read_lock();
-       __IP6_INC_STATS(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS);
+       __IP6_INC_STATS(net, __in6_dev_stats_get(dev, skb), IPSTATS_MIB_REASMFAILS);
        rcu_read_unlock();
        inet_frag_kill(&fq->q);
        return -1;
index b3418a7c5c748275047b9a7bf53b78d80322568a..70b01bd950227897d69a397c63f53a937efeaccc 100644 (file)
@@ -239,7 +239,7 @@ struct sock *udp6_lib_lookup_skb(struct sk_buff *skb,
 
        return __udp6_lib_lookup(dev_net(skb->dev), &iph->saddr, sport,
                                 &iph->daddr, dport, inet6_iif(skb),
-                                inet6_sdif(skb), &udp_table, skb);
+                                inet6_sdif(skb), &udp_table, NULL);
 }
 EXPORT_SYMBOL_GPL(udp6_lib_lookup_skb);
 
@@ -365,6 +365,10 @@ try_again:
                                                    inet6_iif(skb));
                }
                *addr_len = sizeof(*sin6);
+
+               if (cgroup_bpf_enabled)
+                       BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk,
+                                               (struct sockaddr *)sin6);
        }
 
        if (udp_sk(sk)->gro_enabled)
@@ -511,7 +515,7 @@ int __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        struct net *net = dev_net(skb->dev);
 
        sk = __udp6_lib_lookup(net, daddr, uh->dest, saddr, uh->source,
-                              inet6_iif(skb), inet6_sdif(skb), udptable, skb);
+                              inet6_iif(skb), inet6_sdif(skb), udptable, NULL);
        if (!sk) {
                /* No socket for error: try tunnels before discarding */
                sk = ERR_PTR(-ENOENT);
index 03f0cd872dcec1596b413e41df89f3ee256bf153..5d2d1f746b9176b452487657a2dc164911411cf9 100644 (file)
@@ -177,6 +177,7 @@ int lapb_unregister(struct net_device *dev)
        lapb = __lapb_devtostruct(dev);
        if (!lapb)
                goto out;
+       lapb_put(lapb);
 
        lapb_stop_t1timer(lapb);
        lapb_stop_t2timer(lapb);
index 073a8235ae1bd8cfcd28640a31bbb66bb4d22f96..a86fcae279a64911ae22d8d3075e282c8e1e4afe 100644 (file)
@@ -1435,7 +1435,7 @@ ieee80211_get_sband(struct ieee80211_sub_if_data *sdata)
        rcu_read_lock();
        chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
 
-       if (WARN_ON(!chanctx_conf)) {
+       if (WARN_ON_ONCE(!chanctx_conf)) {
                rcu_read_unlock();
                return NULL;
        }
@@ -2037,6 +2037,13 @@ void __ieee80211_flush_queues(struct ieee80211_local *local,
 
 static inline bool ieee80211_can_run_worker(struct ieee80211_local *local)
 {
+       /*
+        * It's unsafe to try to do any work during reconfigure flow.
+        * When the flow ends the work will be requeued.
+        */
+       if (local->in_reconfig)
+               return false;
+
        /*
         * If quiescing is set, we are racing with __ieee80211_suspend.
         * __ieee80211_suspend flushes the workers after setting quiescing,
@@ -2225,6 +2232,9 @@ void ieee80211_tdls_cancel_channel_switch(struct wiphy *wiphy,
                                          const u8 *addr);
 void ieee80211_teardown_tdls_peers(struct ieee80211_sub_if_data *sdata);
 void ieee80211_tdls_chsw_work(struct work_struct *wk);
+void ieee80211_tdls_handle_disconnect(struct ieee80211_sub_if_data *sdata,
+                                     const u8 *peer, u16 reason);
+const char *ieee80211_get_reason_code_string(u16 reason_code);
 
 extern const struct ethtool_ops ieee80211_ethtool_ops;
 
index 20bf9db7a3886de7601fabd0e0ff2c721e54e30e..89f09a09efdb7c6a3bd13bf91f1e82c9186e766e 100644 (file)
@@ -268,11 +268,9 @@ int ieee80211_set_tx_key(struct ieee80211_key *key)
 {
        struct sta_info *sta = key->sta;
        struct ieee80211_local *local = key->local;
-       struct ieee80211_key *old;
 
        assert_key_lock(local);
 
-       old = key_mtx_dereference(local, sta->ptk[sta->ptk_idx]);
        sta->ptk_idx = key->conf.keyidx;
        ieee80211_check_fast_xmit(sta);
 
index 766e5e5bab8a51958a60cf909ffcca26e09b1006..fe44f0d98de02c3a22f03bab725e3905f95dd4f5 100644 (file)
@@ -929,6 +929,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
 
        /* flush STAs and mpaths on this iface */
        sta_info_flush(sdata);
+       ieee80211_free_keys(sdata, true);
        mesh_path_flush_by_iface(sdata);
 
        /* stop the beacon */
@@ -1220,7 +1221,8 @@ int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata)
        ifmsh->chsw_ttl = 0;
 
        /* Remove the CSA and MCSP elements from the beacon */
-       tmp_csa_settings = rcu_dereference(ifmsh->csa);
+       tmp_csa_settings = rcu_dereference_protected(ifmsh->csa,
+                                           lockdep_is_held(&sdata->wdev.mtx));
        RCU_INIT_POINTER(ifmsh->csa, NULL);
        if (tmp_csa_settings)
                kfree_rcu(tmp_csa_settings, rcu_head);
@@ -1242,6 +1244,8 @@ int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata,
        struct mesh_csa_settings *tmp_csa_settings;
        int ret = 0;
 
+       lockdep_assert_held(&sdata->wdev.mtx);
+
        tmp_csa_settings = kmalloc(sizeof(*tmp_csa_settings),
                                   GFP_ATOMIC);
        if (!tmp_csa_settings)
index b7a9fe3d5fcb75dfb15e27c536d19066993b0c6d..383b0df100e4b974f7a888b509f1973704a7816a 100644 (file)
@@ -2963,7 +2963,7 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
 #define case_WLAN(type) \
        case WLAN_REASON_##type: return #type
 
-static const char *ieee80211_get_reason_code_string(u16 reason_code)
+const char *ieee80211_get_reason_code_string(u16 reason_code)
 {
        switch (reason_code) {
        case_WLAN(UNSPECIFIED);
@@ -3028,6 +3028,11 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
        if (len < 24 + 2)
                return;
 
+       if (!ether_addr_equal(mgmt->bssid, mgmt->sa)) {
+               ieee80211_tdls_handle_disconnect(sdata, mgmt->sa, reason_code);
+               return;
+       }
+
        if (ifmgd->associated &&
            ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) {
                const u8 *bssid = ifmgd->associated->bssid;
@@ -3077,6 +3082,11 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
 
        reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
 
+       if (!ether_addr_equal(mgmt->bssid, mgmt->sa)) {
+               ieee80211_tdls_handle_disconnect(sdata, mgmt->sa, reason_code);
+               return;
+       }
+
        sdata_info(sdata, "disassociated from %pM (Reason: %u=%s)\n",
                   mgmt->sa, reason_code,
                   ieee80211_get_reason_code_string(reason_code));
index 25577ede2986ec5616a94501145a9734ec402521..fd3740000e877064360e9d3de7bcf8d8a76ca4cb 100644 (file)
@@ -3831,6 +3831,8 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
        case NL80211_IFTYPE_STATION:
                if (!bssid && !sdata->u.mgd.use_4addr)
                        return false;
+               if (ieee80211_is_robust_mgmt_frame(skb) && !rx->sta)
+                       return false;
                if (multicast)
                        return true;
                return ether_addr_equal(sdata->vif.addr, hdr->addr1);
index ca97e1598c28fe70f99f04e59e87ff2e28b66484..fca1f54773965ad36862ed148e667ef6856957a0 100644 (file)
@@ -1993,3 +1993,26 @@ void ieee80211_tdls_chsw_work(struct work_struct *wk)
        }
        rtnl_unlock();
 }
+
+void ieee80211_tdls_handle_disconnect(struct ieee80211_sub_if_data *sdata,
+                                     const u8 *peer, u16 reason)
+{
+       struct ieee80211_sta *sta;
+
+       rcu_read_lock();
+       sta = ieee80211_find_sta(&sdata->vif, peer);
+       if (!sta || !sta->tdls) {
+               rcu_read_unlock();
+               return;
+       }
+       rcu_read_unlock();
+
+       tdls_dbg(sdata, "disconnected from TDLS peer %pM (Reason: %u=%s)\n",
+                peer, reason,
+                ieee80211_get_reason_code_string(reason));
+
+       ieee80211_tdls_oper_request(&sdata->vif, peer,
+                                   NL80211_TDLS_TEARDOWN,
+                                   WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE,
+                                   GFP_ATOMIC);
+}
index cba4633cd6cfd02a838450bad524465579b18f8d..e2edc2a3cc8bae2fff296ab3190a58f218391386 100644 (file)
@@ -2480,6 +2480,10 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                mutex_lock(&local->mtx);
                ieee80211_start_next_roc(local);
                mutex_unlock(&local->mtx);
+
+               /* Requeue all works */
+               list_for_each_entry(sdata, &local->interfaces, list)
+                       ieee80211_queue_work(&local->hw, &sdata->work);
        }
 
        ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
@@ -3795,7 +3799,9 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
        }
 
        /* Always allow software iftypes */
-       if (local->hw.wiphy->software_iftypes & BIT(iftype)) {
+       if (local->hw.wiphy->software_iftypes & BIT(iftype) ||
+           (iftype == NL80211_IFTYPE_AP_VLAN &&
+            local->hw.wiphy->flags & WIPHY_FLAG_4ADDR_AP)) {
                if (radar_detect)
                        return -EINVAL;
                return 0;
index 58d0b258b684cdd8124266e1b392c4cd77fec5a7..5dd48f0a4b1bd1d5eb24489f72a126a146639f4d 100644 (file)
@@ -1175,7 +1175,7 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx)
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
        struct ieee80211_key *key = rx->key;
        struct ieee80211_mmie_16 *mmie;
-       u8 aad[GMAC_AAD_LEN], mic[GMAC_MIC_LEN], ipn[6], nonce[GMAC_NONCE_LEN];
+       u8 aad[GMAC_AAD_LEN], *mic, ipn[6], nonce[GMAC_NONCE_LEN];
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 
        if (!ieee80211_is_mgmt(hdr->frame_control))
@@ -1206,13 +1206,18 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx)
                memcpy(nonce, hdr->addr2, ETH_ALEN);
                memcpy(nonce + ETH_ALEN, ipn, 6);
 
+               mic = kmalloc(GMAC_MIC_LEN, GFP_ATOMIC);
+               if (!mic)
+                       return RX_DROP_UNUSABLE;
                if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce,
                                       skb->data + 24, skb->len - 24,
                                       mic) < 0 ||
                    crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
                        key->u.aes_gmac.icverrors++;
+                       kfree(mic);
                        return RX_DROP_UNUSABLE;
                }
+               kfree(mic);
        }
 
        memcpy(key->u.aes_gmac.rx_pn, ipn, 6);
index d9391beea980d0d262f7917d5db3acfac537b7f7..d1ad69b7942ac2b369efd7c363f8034d3ed0e985 100644 (file)
@@ -26,6 +26,7 @@ config NET_MPLS_GSO
 config MPLS_ROUTING
        tristate "MPLS: routing support"
        depends on NET_IP_TUNNEL || NET_IP_TUNNEL=n
+       depends on PROC_SYSCTL
        ---help---
         Add support for forwarding of mpls packets.
 
index 50059613076066e4cf3d901be05506b6370de7c3..d25e91d7bdc18526301c6228f5943aec7f9becc8 100644 (file)
@@ -23,7 +23,7 @@
 #include "internal.h"
 
 static const struct nla_policy mpls_iptunnel_policy[MPLS_IPTUNNEL_MAX + 1] = {
-       [MPLS_IPTUNNEL_DST]     = { .type = NLA_U32 },
+       [MPLS_IPTUNNEL_DST]     = { .len = sizeof(u32) },
        [MPLS_IPTUNNEL_TTL]     = { .type = NLA_U8 },
 };
 
index 1180b3e58a0abe940e6fdba4fc887ed4b4b80a7b..ea64c90b14e8c8c5385c8357b69efe1a1eac9d4c 100644 (file)
@@ -911,7 +911,8 @@ static int nfc_genl_deactivate_target(struct sk_buff *skb,
        u32 device_idx, target_idx;
        int rc;
 
-       if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
+       if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
+           !info->attrs[NFC_ATTR_TARGET_INDEX])
                return -EINVAL;
 
        device_idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
index 758bb1da31dfeb44a1f4151ba148c30cf9839e21..d2437b5b2f6ad093c0738e48ebe9261ead757e13 100644 (file)
@@ -157,7 +157,9 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
 {
        struct vport *vport;
        struct internal_dev *internal_dev;
+       struct net_device *dev;
        int err;
+       bool free_vport = true;
 
        vport = ovs_vport_alloc(0, &ovs_internal_vport_ops, parms);
        if (IS_ERR(vport)) {
@@ -165,8 +167,9 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
                goto error;
        }
 
-       vport->dev = alloc_netdev(sizeof(struct internal_dev),
-                                 parms->name, NET_NAME_USER, do_setup);
+       dev = alloc_netdev(sizeof(struct internal_dev),
+                          parms->name, NET_NAME_USER, do_setup);
+       vport->dev = dev;
        if (!vport->dev) {
                err = -ENOMEM;
                goto error_free_vport;
@@ -187,8 +190,10 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
 
        rtnl_lock();
        err = register_netdevice(vport->dev);
-       if (err)
+       if (err) {
+               free_vport = false;
                goto error_unlock;
+       }
 
        dev_set_promiscuity(vport->dev, 1);
        rtnl_unlock();
@@ -198,11 +203,12 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
 
 error_unlock:
        rtnl_unlock();
-       free_percpu(vport->dev->tstats);
+       free_percpu(dev->tstats);
 error_free_netdev:
-       free_netdev(vport->dev);
+       free_netdev(dev);
 error_free_vport:
-       ovs_vport_free(vport);
+       if (free_vport)
+               ovs_vport_free(vport);
 error:
        return ERR_PTR(err);
 }
index c388372df0e2f9f77b1e51dd2eb3c75138186a29..eedd5786c0844a363c081391b5afc679c89b0843 100644 (file)
@@ -320,10 +320,13 @@ static int fl_init(struct tcf_proto *tp)
        return rhashtable_init(&head->ht, &mask_ht_params);
 }
 
-static void fl_mask_free(struct fl_flow_mask *mask)
+static void fl_mask_free(struct fl_flow_mask *mask, bool mask_init_done)
 {
-       WARN_ON(!list_empty(&mask->filters));
-       rhashtable_destroy(&mask->ht);
+       /* temporary masks don't have their filters list and ht initialized */
+       if (mask_init_done) {
+               WARN_ON(!list_empty(&mask->filters));
+               rhashtable_destroy(&mask->ht);
+       }
        kfree(mask);
 }
 
@@ -332,7 +335,15 @@ static void fl_mask_free_work(struct work_struct *work)
        struct fl_flow_mask *mask = container_of(to_rcu_work(work),
                                                 struct fl_flow_mask, rwork);
 
-       fl_mask_free(mask);
+       fl_mask_free(mask, true);
+}
+
+static void fl_uninit_mask_free_work(struct work_struct *work)
+{
+       struct fl_flow_mask *mask = container_of(to_rcu_work(work),
+                                                struct fl_flow_mask, rwork);
+
+       fl_mask_free(mask, false);
 }
 
 static bool fl_mask_put(struct cls_fl_head *head, struct fl_flow_mask *mask)
@@ -1346,9 +1357,6 @@ static struct fl_flow_mask *fl_create_new_mask(struct cls_fl_head *head,
        if (err)
                goto errout_destroy;
 
-       /* Wait until any potential concurrent users of mask are finished */
-       synchronize_rcu();
-
        spin_lock(&head->masks_lock);
        list_add_tail_rcu(&newmask->list, &head->masks);
        spin_unlock(&head->masks_lock);
@@ -1375,11 +1383,7 @@ static int fl_check_assign_mask(struct cls_fl_head *head,
 
        /* Insert mask as temporary node to prevent concurrent creation of mask
         * with same key. Any concurrent lookups with same key will return
-        * -EAGAIN because mask's refcnt is zero. It is safe to insert
-        * stack-allocated 'mask' to masks hash table because we call
-        * synchronize_rcu() before returning from this function (either in case
-        * of error or after replacing it with heap-allocated mask in
-        * fl_create_new_mask()).
+        * -EAGAIN because mask's refcnt is zero.
         */
        fnew->mask = rhashtable_lookup_get_insert_fast(&head->ht,
                                                       &mask->ht_node,
@@ -1414,8 +1418,6 @@ static int fl_check_assign_mask(struct cls_fl_head *head,
 errout_cleanup:
        rhashtable_remove_fast(&head->ht, &mask->ht_node,
                               mask_ht_params);
-       /* Wait until any potential concurrent users of mask are finished */
-       synchronize_rcu();
        return ret;
 }
 
@@ -1644,7 +1646,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
        *arg = fnew;
 
        kfree(tb);
-       kfree(mask);
+       tcf_queue_work(&mask->rwork, fl_uninit_mask_free_work);
        return 0;
 
 errout_ht:
@@ -1664,7 +1666,7 @@ errout:
 errout_tb:
        kfree(tb);
 errout_mask_alloc:
-       kfree(mask);
+       tcf_queue_work(&mask->rwork, fl_uninit_mask_free_work);
 errout_fold:
        if (fold)
                __fl_put(fold);
index f17908f5c4f3c52c21614e24316f2e17c6fa1742..9b0e5b0d701ad9255327897b119634e1939276c7 100644 (file)
@@ -2583,6 +2583,8 @@ do_addr_param:
        case SCTP_PARAM_STATE_COOKIE:
                asoc->peer.cookie_len =
                        ntohs(param.p->length) - sizeof(struct sctp_paramhdr);
+               if (asoc->peer.cookie)
+                       kfree(asoc->peer.cookie);
                asoc->peer.cookie = kmemdup(param.cookie->body, asoc->peer.cookie_len, gfp);
                if (!asoc->peer.cookie)
                        retval = 0;
@@ -2647,6 +2649,8 @@ do_addr_param:
                        goto fall_through;
 
                /* Save peer's random parameter */
+               if (asoc->peer.peer_random)
+                       kfree(asoc->peer.peer_random);
                asoc->peer.peer_random = kmemdup(param.p,
                                            ntohs(param.p->length), gfp);
                if (!asoc->peer.peer_random) {
@@ -2660,6 +2664,8 @@ do_addr_param:
                        goto fall_through;
 
                /* Save peer's HMAC list */
+               if (asoc->peer.peer_hmacs)
+                       kfree(asoc->peer.peer_hmacs);
                asoc->peer.peer_hmacs = kmemdup(param.p,
                                            ntohs(param.p->length), gfp);
                if (!asoc->peer.peer_hmacs) {
@@ -2675,6 +2681,8 @@ do_addr_param:
                if (!ep->auth_enable)
                        goto fall_through;
 
+               if (asoc->peer.peer_chunks)
+                       kfree(asoc->peer.peer_chunks);
                asoc->peer.peer_chunks = kmemdup(param.p,
                                            ntohs(param.p->length), gfp);
                if (!asoc->peer.peer_chunks)
index 992be6113676988291157fb81c65b5ad605e522b..5f98d38bcf082742ef98b22da4b9a6074df4050f 100644 (file)
@@ -218,6 +218,7 @@ void tipc_group_delete(struct net *net, struct tipc_group *grp)
 
        rbtree_postorder_for_each_entry_safe(m, tmp, tree, tree_node) {
                tipc_group_proto_xmit(grp, m, GRP_LEAVE_MSG, &xmitq);
+               __skb_queue_purge(&m->deferredq);
                list_del(&m->list);
                kfree(m);
        }
index 960494f437ac34e27b2c8a55575003e273f9e1fc..455a782c7658f6de2d23a7f8978c63eda819d552 100644 (file)
@@ -1143,7 +1143,6 @@ static int tls_sw_do_sendpage(struct sock *sk, struct page *page,
 
                full_record = false;
                record_room = TLS_MAX_PAYLOAD_SIZE - msg_pl->sg.size;
-               copied = 0;
                copy = size;
                if (copy >= record_room) {
                        copy = record_room;
index 0a6fe064994529e1f8e5be4d48db494f8f0bd89b..fb2df6e068fa6accf7e678f42ab10620578a2c53 100644 (file)
@@ -335,8 +335,8 @@ static void hvs_open_connection(struct vmbus_channel *chan)
 
        struct sockaddr_vm addr;
        struct sock *sk, *new = NULL;
-       struct vsock_sock *vnew;
-       struct hvsock *hvs, *hvs_new;
+       struct vsock_sock *vnew = NULL;
+       struct hvsock *hvs, *hvs_new = NULL;
        int ret;
 
        if_type = &chan->offermsg.offer.if_type;
index f3f3d06cb6d8f69f9d4b082c07c7ddd488c30a1f..e30f53728725d1c5e80d22cfccaea4ffb17474a9 100644 (file)
@@ -871,8 +871,10 @@ virtio_transport_recv_connected(struct sock *sk,
                if (le32_to_cpu(pkt->hdr.flags) & VIRTIO_VSOCK_SHUTDOWN_SEND)
                        vsk->peer_shutdown |= SEND_SHUTDOWN;
                if (vsk->peer_shutdown == SHUTDOWN_MASK &&
-                   vsock_stream_has_data(vsk) <= 0)
+                   vsock_stream_has_data(vsk) <= 0) {
+                       sock_set_flag(sk, SOCK_DONE);
                        sk->sk_state = TCP_CLOSING;
+               }
                if (le32_to_cpu(pkt->hdr.flags))
                        sk->sk_state_change(sk);
                break;
index 72a224ce8e0a834d04d99c276de80a6956be9797..2eee93985ab0df8f9bbdcd2d4e146c34ac3899f5 100644 (file)
@@ -39,6 +39,7 @@ $(obj)/extra-certs.c: $(CONFIG_CFG80211_EXTRA_REGDB_KEYDIR:"%"=%) \
        @(set -e; \
          allf=""; \
          for f in $^ ; do \
+             test -f $$f || continue;\
              # similar to hexdump -v -e '1/1 "0x%.2x," "\n"' \
              thisf=$$(od -An -v -tx1 < $$f | \
                           sed -e 's/ /\n/g' | \
index 037816163e70d3a9d1e06498ed0f5bc6bcb3cb22..53ad3dbb76fe554089d6d3bf38b398ad64bafb79 100644 (file)
@@ -514,7 +514,7 @@ use_default_name:
                                   &rdev->rfkill_ops, rdev);
 
        if (!rdev->rfkill) {
-               kfree(rdev);
+               wiphy_free(&rdev->wiphy);
                return NULL;
        }
 
@@ -1397,8 +1397,12 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
                }
                break;
        case NETDEV_PRE_UP:
-               if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
+               if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)) &&
+                   !(wdev->iftype == NL80211_IFTYPE_AP_VLAN &&
+                     rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP &&
+                     wdev->use_4addr))
                        return notifier_from_errno(-EOPNOTSUPP);
+
                if (rfkill_blocked(rdev->rfkill))
                        return notifier_from_errno(-ERFKILL);
                break;
index c391b560d98631c222f3a03563f84fad5e8ac8f5..520d437aa8d15539f081f3964c31c3c73dec6519 100644 (file)
@@ -304,8 +304,11 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
        [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
 
-       [NL80211_ATTR_MAC] = { .len = ETH_ALEN },
-       [NL80211_ATTR_PREV_BSSID] = { .len = ETH_ALEN },
+       [NL80211_ATTR_MAC] = { .type = NLA_EXACT_LEN_WARN, .len = ETH_ALEN },
+       [NL80211_ATTR_PREV_BSSID] = {
+               .type = NLA_EXACT_LEN_WARN,
+               .len = ETH_ALEN
+       },
 
        [NL80211_ATTR_KEY] = { .type = NLA_NESTED, },
        [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
@@ -356,7 +359,10 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED },
        [NL80211_ATTR_SUPPORT_MESH_AUTH] = { .type = NLA_FLAG },
 
-       [NL80211_ATTR_HT_CAPABILITY] = { .len = NL80211_HT_CAPABILITY_LEN },
+       [NL80211_ATTR_HT_CAPABILITY] = {
+               .type = NLA_EXACT_LEN_WARN,
+               .len = NL80211_HT_CAPABILITY_LEN
+       },
 
        [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },
        [NL80211_ATTR_IE] = NLA_POLICY_VALIDATE_FN(NLA_BINARY,
@@ -386,7 +392,10 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
        [NL80211_ATTR_PID] = { .type = NLA_U32 },
        [NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
-       [NL80211_ATTR_PMKID] = { .len = WLAN_PMKID_LEN },
+       [NL80211_ATTR_PMKID] = {
+               .type = NLA_EXACT_LEN_WARN,
+               .len = WLAN_PMKID_LEN
+       },
        [NL80211_ATTR_DURATION] = { .type = NLA_U32 },
        [NL80211_ATTR_COOKIE] = { .type = NLA_U64 },
        [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED },
@@ -448,7 +457,10 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_WDEV] = { .type = NLA_U64 },
        [NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
        [NL80211_ATTR_AUTH_DATA] = { .type = NLA_BINARY, },
-       [NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN },
+       [NL80211_ATTR_VHT_CAPABILITY] = {
+               .type = NLA_EXACT_LEN_WARN,
+               .len = NL80211_VHT_CAPABILITY_LEN
+       },
        [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
        [NL80211_ATTR_P2P_CTWINDOW] = NLA_POLICY_MAX(NLA_U8, 127),
        [NL80211_ATTR_P2P_OPPPS] = NLA_POLICY_MAX(NLA_U8, 1),
@@ -484,7 +496,10 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
        [NL80211_ATTR_QOS_MAP] = { .type = NLA_BINARY,
                                   .len = IEEE80211_QOS_MAP_LEN_MAX },
-       [NL80211_ATTR_MAC_HINT] = { .len = ETH_ALEN },
+       [NL80211_ATTR_MAC_HINT] = {
+               .type = NLA_EXACT_LEN_WARN,
+               .len = ETH_ALEN
+       },
        [NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
        [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
        [NL80211_ATTR_SOCKET_OWNER] = { .type = NLA_FLAG },
@@ -495,7 +510,10 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
                NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_UPS - 1),
        [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
        [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
-       [NL80211_ATTR_MAC_MASK] = { .len = ETH_ALEN },
+       [NL80211_ATTR_MAC_MASK] = {
+               .type = NLA_EXACT_LEN_WARN,
+               .len = ETH_ALEN
+       },
        [NL80211_ATTR_WIPHY_SELF_MANAGED_REG] = { .type = NLA_FLAG },
        [NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 },
        [NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 },
@@ -507,15 +525,21 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_MU_MIMO_GROUP_DATA] = {
                .len = VHT_MUMIMO_GROUPS_DATA_LEN
        },
-       [NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = { .len = ETH_ALEN },
+       [NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = {
+               .type = NLA_EXACT_LEN_WARN,
+               .len = ETH_ALEN
+       },
        [NL80211_ATTR_NAN_MASTER_PREF] = NLA_POLICY_MIN(NLA_U8, 1),
        [NL80211_ATTR_BANDS] = { .type = NLA_U32 },
        [NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED },
        [NL80211_ATTR_FILS_KEK] = { .type = NLA_BINARY,
                                    .len = FILS_MAX_KEK_LEN },
-       [NL80211_ATTR_FILS_NONCES] = { .len = 2 * FILS_NONCE_LEN },
+       [NL80211_ATTR_FILS_NONCES] = {
+               .type = NLA_EXACT_LEN_WARN,
+               .len = 2 * FILS_NONCE_LEN
+       },
        [NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_FLAG, },
-       [NL80211_ATTR_BSSID] = { .len = ETH_ALEN },
+       [NL80211_ATTR_BSSID] = { .type = NLA_EXACT_LEN_WARN, .len = ETH_ALEN },
        [NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] = { .type = NLA_S8 },
        [NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST] = {
                .len = sizeof(struct nl80211_bss_select_rssi_adjust)
@@ -528,7 +552,7 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] = { .type = NLA_U16 },
        [NL80211_ATTR_FILS_ERP_RRK] = { .type = NLA_BINARY,
                                        .len = FILS_ERP_MAX_RRK_LEN },
-       [NL80211_ATTR_FILS_CACHE_ID] = { .len = 2 },
+       [NL80211_ATTR_FILS_CACHE_ID] = { .type = NLA_EXACT_LEN_WARN, .len = 2 },
        [NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
        [NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG },
        [NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG },
@@ -589,10 +613,13 @@ static const struct nla_policy
 nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {
        [NL80211_WOWLAN_TCP_SRC_IPV4] = { .type = NLA_U32 },
        [NL80211_WOWLAN_TCP_DST_IPV4] = { .type = NLA_U32 },
-       [NL80211_WOWLAN_TCP_DST_MAC] = { .len = ETH_ALEN },
+       [NL80211_WOWLAN_TCP_DST_MAC] = {
+               .type = NLA_EXACT_LEN_WARN,
+               .len = ETH_ALEN
+       },
        [NL80211_WOWLAN_TCP_SRC_PORT] = { .type = NLA_U16 },
        [NL80211_WOWLAN_TCP_DST_PORT] = { .type = NLA_U16 },
-       [NL80211_WOWLAN_TCP_DATA_PAYLOAD] = { .len = 1 },
+       [NL80211_WOWLAN_TCP_DATA_PAYLOAD] = { .type = NLA_MIN_LEN, .len = 1 },
        [NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ] = {
                .len = sizeof(struct nl80211_wowlan_tcp_data_seq)
        },
@@ -600,8 +627,8 @@ nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {
                .len = sizeof(struct nl80211_wowlan_tcp_data_token)
        },
        [NL80211_WOWLAN_TCP_DATA_INTERVAL] = { .type = NLA_U32 },
-       [NL80211_WOWLAN_TCP_WAKE_PAYLOAD] = { .len = 1 },
-       [NL80211_WOWLAN_TCP_WAKE_MASK] = { .len = 1 },
+       [NL80211_WOWLAN_TCP_WAKE_PAYLOAD] = { .type = NLA_MIN_LEN, .len = 1 },
+       [NL80211_WOWLAN_TCP_WAKE_MASK] = { .type = NLA_MIN_LEN, .len = 1 },
 };
 #endif /* CONFIG_PM */
 
@@ -619,9 +646,18 @@ nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = {
 /* policy for GTK rekey offload attributes */
 static const struct nla_policy
 nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
-       [NL80211_REKEY_DATA_KEK] = { .len = NL80211_KEK_LEN },
-       [NL80211_REKEY_DATA_KCK] = { .len = NL80211_KCK_LEN },
-       [NL80211_REKEY_DATA_REPLAY_CTR] = { .len = NL80211_REPLAY_CTR_LEN },
+       [NL80211_REKEY_DATA_KEK] = {
+               .type = NLA_EXACT_LEN_WARN,
+               .len = NL80211_KEK_LEN,
+       },
+       [NL80211_REKEY_DATA_KCK] = {
+               .type = NLA_EXACT_LEN_WARN,
+               .len = NL80211_KCK_LEN,
+       },
+       [NL80211_REKEY_DATA_REPLAY_CTR] = {
+               .type = NLA_EXACT_LEN_WARN,
+               .len = NL80211_REPLAY_CTR_LEN
+       },
 };
 
 static const struct nla_policy
@@ -635,7 +671,10 @@ static const struct nla_policy
 nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {
        [NL80211_SCHED_SCAN_MATCH_ATTR_SSID] = { .type = NLA_BINARY,
                                                 .len = IEEE80211_MAX_SSID_LEN },
-       [NL80211_SCHED_SCAN_MATCH_ATTR_BSSID] = { .len = ETH_ALEN },
+       [NL80211_SCHED_SCAN_MATCH_ATTR_BSSID] = {
+               .type = NLA_EXACT_LEN_WARN,
+               .len = ETH_ALEN
+       },
        [NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 },
        [NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI] =
                NLA_POLICY_NESTED(nl80211_match_band_rssi_policy),
@@ -667,7 +706,10 @@ nl80211_nan_func_policy[NL80211_NAN_FUNC_ATTR_MAX + 1] = {
        [NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE] = { .type = NLA_FLAG },
        [NL80211_NAN_FUNC_FOLLOW_UP_ID] = { .type = NLA_U8 },
        [NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] = { .type = NLA_U8 },
-       [NL80211_NAN_FUNC_FOLLOW_UP_DEST] = { .len = ETH_ALEN },
+       [NL80211_NAN_FUNC_FOLLOW_UP_DEST] = {
+               .type = NLA_EXACT_LEN_WARN,
+               .len = ETH_ALEN
+       },
        [NL80211_NAN_FUNC_CLOSE_RANGE] = { .type = NLA_FLAG },
        [NL80211_NAN_FUNC_TTL] = { .type = NLA_U32 },
        [NL80211_NAN_FUNC_SERVICE_INFO] = { .type = NLA_BINARY,
@@ -3420,8 +3462,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
        if (info->attrs[NL80211_ATTR_IFTYPE])
                type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
 
-       if (!rdev->ops->add_virtual_intf ||
-           !(rdev->wiphy.interface_modes & (1 << type)))
+       if (!rdev->ops->add_virtual_intf)
                return -EOPNOTSUPP;
 
        if ((type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN ||
@@ -3440,6 +3481,11 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
                        return err;
        }
 
+       if (!(rdev->wiphy.interface_modes & (1 << type)) &&
+           !(type == NL80211_IFTYPE_AP_VLAN && params.use_4addr &&
+             rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP))
+               return -EOPNOTSUPP;
+
        err = nl80211_parse_mon_options(rdev, type, info, &params);
        if (err < 0)
                return err;
@@ -4057,7 +4103,10 @@ static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = {
                                    .len = NL80211_MAX_SUPP_RATES },
        [NL80211_TXRATE_HT] = { .type = NLA_BINARY,
                                .len = NL80211_MAX_SUPP_HT_RATES },
-       [NL80211_TXRATE_VHT] = { .len = sizeof(struct nl80211_txrate_vht)},
+       [NL80211_TXRATE_VHT] = {
+               .type = NLA_EXACT_LEN_WARN,
+               .len = sizeof(struct nl80211_txrate_vht),
+       },
        [NL80211_TXRATE_GI] = { .type = NLA_U8 },
 };
 
@@ -4856,8 +4905,10 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
        struct nlattr *sinfoattr, *bss_param;
 
        hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
-       if (!hdr)
+       if (!hdr) {
+               cfg80211_sinfo_release_content(sinfo);
                return -1;
+       }
 
        if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
            nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) ||
index 1b190475359a794754b922acb485d07524cec777..c09fbf09549dfa6e9baa436c88e5adb7b9817dfb 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
  */
 #ifndef __PMSR_H
 #define __PMSR_H
@@ -448,7 +448,7 @@ static int nl80211_pmsr_send_result(struct sk_buff *msg,
 
        if (res->ap_tsf_valid &&
            nla_put_u64_64bit(msg, NL80211_PMSR_RESP_ATTR_AP_TSF,
-                             res->host_time, NL80211_PMSR_RESP_ATTR_PAD))
+                             res->ap_tsf, NL80211_PMSR_RESP_ATTR_PAD))
                goto error;
 
        if (res->final && nla_put_flag(msg, NL80211_PMSR_RESP_ATTR_FINAL))
index c04f5451f89b114cb98c43b1b3ce6724858f2a4f..aa571d727903f2481ce2ce1215d5a444ffd83927 100644 (file)
@@ -1601,12 +1601,12 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
                                continue;
                        }
 
-                       if (seen_indices & BIT(mbssid_index_ie[2]))
+                       if (seen_indices & BIT_ULL(mbssid_index_ie[2]))
                                /* We don't support legacy split of a profile */
                                net_dbg_ratelimited("Partial info for BSSID index %d\n",
                                                    mbssid_index_ie[2]);
 
-                       seen_indices |= BIT(mbssid_index_ie[2]);
+                       seen_indices |= BIT_ULL(mbssid_index_ie[2]);
 
                        non_tx_data->bssid_index = mbssid_index_ie[2];
                        non_tx_data->max_bssid_indicator = elem->data[0];
index cf63b635afc098eeafe7462bd41b86a7e433b85c..1c39d6a2e85011aff8a4991473fdec387c93bdac 100644 (file)
@@ -1246,7 +1246,7 @@ static u32 cfg80211_calculate_bitrate_he(struct rate_info *rate)
        if (rate->he_dcm)
                result /= 2;
 
-       return result;
+       return result / 10000;
 }
 
 u32 cfg80211_calculate_bitrate(struct rate_info *rate)
@@ -1998,7 +1998,7 @@ int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap,
                        continue;
 
                if (supp >= mcs_encoding) {
-                       max_vht_nss = i;
+                       max_vht_nss = i + 1;
                        break;
                }
        }
index 2b18223e7eb8cd3691290b4d0e7bdf17843bd683..9c6de4f114f84cc17b442294a2049d8a8cd87002 100644 (file)
@@ -143,6 +143,9 @@ static void xdp_umem_clear_dev(struct xdp_umem *umem)
        struct netdev_bpf bpf;
        int err;
 
+       if (!umem->dev)
+               return;
+
        if (umem->zc) {
                bpf.command = XDP_SETUP_XSK_UMEM;
                bpf.xsk.umem = NULL;
@@ -156,11 +159,9 @@ static void xdp_umem_clear_dev(struct xdp_umem *umem)
                        WARN(1, "failed to disable umem!\n");
        }
 
-       if (umem->dev) {
-               rtnl_lock();
-               xdp_clear_umem_at_qid(umem->dev, umem->queue_id);
-               rtnl_unlock();
-       }
+       rtnl_lock();
+       xdp_clear_umem_at_qid(umem->dev, umem->queue_id);
+       rtnl_unlock();
 
        if (umem->zc) {
                dev_put(umem->dev);
index eae7b635343d13182a4d458d3280464f6ffee4ca..6e87cc831e84287170f4ec77d8eb890e587cad6c 100644 (file)
@@ -678,7 +678,7 @@ void read_trace_pipe(void)
                static char buf[4096];
                ssize_t sz;
 
-               sz = read(trace_fd, buf, sizeof(buf));
+               sz = read(trace_fd, buf, sizeof(buf) - 1);
                if (sz > 0) {
                        buf[sz] = 0;
                        puts(buf);
index aff2b4ae914ee00acda73ef0c025a7500de42923..e3993805822355a544aa5af4b7f44804e27a965b 100644 (file)
@@ -216,7 +216,7 @@ static int test_debug_fs_uprobe(char *binary_path, long offset, bool is_return)
 {
        const char *event_type = "uprobe";
        struct perf_event_attr attr = {};
-       char buf[256], event_alias[256];
+       char buf[256], event_alias[sizeof("test_1234567890")];
        __u64 probe_offset, probe_addr;
        __u32 len, prog_id, fd_type;
        int err, res, kfd, efd;
index ac26876389c2383297185ddc1d3f3f1ac0067d8b..e744b3e4e56aa9030aa3027f1f594036a88bd105 100644 (file)
@@ -29,7 +29,7 @@ CGROUP COMMANDS
 |      *PROG* := { **id** *PROG_ID* | **pinned** *FILE* | **tag** *PROG_TAG* }
 |      *ATTACH_TYPE* := { **ingress** | **egress** | **sock_create** | **sock_ops** | **device** |
 |              **bind4** | **bind6** | **post_bind4** | **post_bind6** | **connect4** | **connect6** |
-|              **sendmsg4** | **sendmsg6** | **sysctl** }
+|              **sendmsg4** | **sendmsg6** | **recvmsg4** | **recvmsg6** | **sysctl** }
 |      *ATTACH_FLAGS* := { **multi** | **override** }
 
 DESCRIPTION
@@ -86,6 +86,10 @@ DESCRIPTION
                  unconnected udp4 socket (since 4.18);
                  **sendmsg6** call to sendto(2), sendmsg(2), sendmmsg(2) for an
                  unconnected udp6 socket (since 4.18);
+                 **recvmsg4** call to recvfrom(2), recvmsg(2), recvmmsg(2) for
+                  an unconnected udp4 socket (since 5.2);
+                 **recvmsg6** call to recvfrom(2), recvmsg(2), recvmmsg(2) for
+                  an unconnected udp6 socket (since 5.2);
                  **sysctl** sysctl access (since 5.2).
 
        **bpftool cgroup detach** *CGROUP* *ATTACH_TYPE* *PROG*
index e8118544d118282b63bfc27e515ea53ae9903d96..018ecef8dc139d0f2a84ddc6ec1ae85b6f87ffb2 100644 (file)
@@ -40,7 +40,7 @@ PROG COMMANDS
 |              **lwt_seg6local** | **sockops** | **sk_skb** | **sk_msg** | **lirc_mode2** |
 |              **cgroup/bind4** | **cgroup/bind6** | **cgroup/post_bind4** | **cgroup/post_bind6** |
 |              **cgroup/connect4** | **cgroup/connect6** | **cgroup/sendmsg4** | **cgroup/sendmsg6** |
-|              **cgroup/sysctl**
+|              **cgroup/recvmsg4** | **cgroup/recvmsg6** | **cgroup/sysctl**
 |      }
 |       *ATTACH_TYPE* := {
 |              **msg_verdict** | **stream_verdict** | **stream_parser** | **flow_dissector**
index 50e402a5a9c86276f2b37526f43c0ede5c1ba8a6..4300adf6e5ab48d8ea3dd0b0fe19b6b861e40ca2 100644 (file)
@@ -371,6 +371,7 @@ _bpftool()
                                 lirc_mode2 cgroup/bind4 cgroup/bind6 \
                                 cgroup/connect4 cgroup/connect6 \
                                 cgroup/sendmsg4 cgroup/sendmsg6 \
+                                cgroup/recvmsg4 cgroup/recvmsg6 \
                                 cgroup/post_bind4 cgroup/post_bind6 \
                                 cgroup/sysctl" -- \
                                                    "$cur" ) )
@@ -666,7 +667,7 @@ _bpftool()
                 attach|detach)
                     local ATTACH_TYPES='ingress egress sock_create sock_ops \
                         device bind4 bind6 post_bind4 post_bind6 connect4 \
-                        connect6 sendmsg4 sendmsg6 sysctl'
+                        connect6 sendmsg4 sendmsg6 recvmsg4 recvmsg6 sysctl'
                     local ATTACH_FLAGS='multi override'
                     local PROG_TYPE='id pinned tag'
                     case $prev in
@@ -676,7 +677,7 @@ _bpftool()
                             ;;
                         ingress|egress|sock_create|sock_ops|device|bind4|bind6|\
                         post_bind4|post_bind6|connect4|connect6|sendmsg4|\
-                        sendmsg6|sysctl)
+                        sendmsg6|recvmsg4|recvmsg6|sysctl)
                             COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
                                 "$cur" ) )
                             return 0
index 7e22f115c8c1af352984961a3a6c0dc336d4b864..73ec8ea33fb43af8f4286e2dfd4361eb4672fd07 100644 (file)
@@ -25,7 +25,8 @@
        "       ATTACH_TYPE := { ingress | egress | sock_create |\n"           \
        "                        sock_ops | device | bind4 | bind6 |\n"        \
        "                        post_bind4 | post_bind6 | connect4 |\n"       \
-       "                        connect6 | sendmsg4 | sendmsg6 | sysctl }"
+       "                        connect6 | sendmsg4 | sendmsg6 |\n"           \
+       "                        recvmsg4 | recvmsg6 | sysctl }"
 
 static const char * const attach_type_strings[] = {
        [BPF_CGROUP_INET_INGRESS] = "ingress",
@@ -42,6 +43,8 @@ static const char * const attach_type_strings[] = {
        [BPF_CGROUP_UDP4_SENDMSG] = "sendmsg4",
        [BPF_CGROUP_UDP6_SENDMSG] = "sendmsg6",
        [BPF_CGROUP_SYSCTL] = "sysctl",
+       [BPF_CGROUP_UDP4_RECVMSG] = "recvmsg4",
+       [BPF_CGROUP_UDP6_RECVMSG] = "recvmsg6",
        [__MAX_BPF_ATTACH_TYPE] = NULL,
 };
 
index 3ec82904ccec6aa974353d20f96875267a20ffee..5da5a7311f13050773e82194621c317c08d1c482 100644 (file)
@@ -716,12 +716,14 @@ static int dump_map_elem(int fd, void *key, void *value,
                return 0;
 
        if (json_output) {
+               jsonw_start_object(json_wtr);
                jsonw_name(json_wtr, "key");
                print_hex_data_json(key, map_info->key_size);
                jsonw_name(json_wtr, "value");
                jsonw_start_object(json_wtr);
                jsonw_string_field(json_wtr, "error", strerror(lookup_errno));
                jsonw_end_object(json_wtr);
+               jsonw_end_object(json_wtr);
        } else {
                const char *msg = NULL;
 
index 26336bad0442734d6a56fd94243c6412f9adca4f..7a4e21a315236eb8fe7f18ff3ceed8e9875af849 100644 (file)
@@ -1063,7 +1063,8 @@ static int do_help(int argc, char **argv)
                "                 sk_reuseport | flow_dissector | cgroup/sysctl |\n"
                "                 cgroup/bind4 | cgroup/bind6 | cgroup/post_bind4 |\n"
                "                 cgroup/post_bind6 | cgroup/connect4 | cgroup/connect6 |\n"
-               "                 cgroup/sendmsg4 | cgroup/sendmsg6 }\n"
+               "                 cgroup/sendmsg4 | cgroup/sendmsg6 | cgroup/recvmsg4 |\n"
+               "                 cgroup/recvmsg6 }\n"
                "       ATTACH_TYPE := { msg_verdict | stream_verdict | stream_parser |\n"
                "                        flow_dissector }\n"
                "       " HELP_SPEC_OPTIONS "\n"
index 63e0cf66f01a9698ff6bc41ac5492809bb83d834..a8b823c30b434d8022ebeab666d7072a09473be5 100644 (file)
@@ -192,6 +192,8 @@ enum bpf_attach_type {
        BPF_LIRC_MODE2,
        BPF_FLOW_DISSECTOR,
        BPF_CGROUP_SYSCTL,
+       BPF_CGROUP_UDP4_RECVMSG,
+       BPF_CGROUP_UDP6_RECVMSG,
        __MAX_BPF_ATTACH_TYPE
 };
 
@@ -3376,8 +3378,8 @@ struct bpf_raw_tracepoint_args {
 /* DIRECT:  Skip the FIB rules and go to FIB table associated with device
  * OUTPUT:  Do lookup from egress perspective; default is ingress
  */
-#define BPF_FIB_LOOKUP_DIRECT  BIT(0)
-#define BPF_FIB_LOOKUP_OUTPUT  BIT(1)
+#define BPF_FIB_LOOKUP_DIRECT  (1U << 0)
+#define BPF_FIB_LOOKUP_OUTPUT  (1U << 1)
 
 enum {
        BPF_FIB_LKUP_RET_SUCCESS,      /* lookup successful */
index 197b574406b3ac6599bb81e395ff88d9c0374661..151f7ac1882e52f09db4c2dce66686cc63d97e0a 100644 (file)
@@ -1645,14 +1645,16 @@ static int bpf_object__probe_btf_func(struct bpf_object *obj)
                /* FUNC x */                                    /* [3] */
                BTF_TYPE_ENC(5, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 0), 2),
        };
-       int res;
+       int btf_fd;
 
-       res = libbpf__probe_raw_btf((char *)types, sizeof(types),
-                                   strs, sizeof(strs));
-       if (res < 0)
-               return res;
-       if (res > 0)
+       btf_fd = libbpf__load_raw_btf((char *)types, sizeof(types),
+                                     strs, sizeof(strs));
+       if (btf_fd >= 0) {
                obj->caps.btf_func = 1;
+               close(btf_fd);
+               return 1;
+       }
+
        return 0;
 }
 
@@ -1670,14 +1672,16 @@ static int bpf_object__probe_btf_datasec(struct bpf_object *obj)
                BTF_TYPE_ENC(3, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4),
                BTF_VAR_SECINFO_ENC(2, 0, 4),
        };
-       int res;
+       int btf_fd;
 
-       res = libbpf__probe_raw_btf((char *)types, sizeof(types),
-                                   strs, sizeof(strs));
-       if (res < 0)
-               return res;
-       if (res > 0)
+       btf_fd = libbpf__load_raw_btf((char *)types, sizeof(types),
+                                     strs, sizeof(strs));
+       if (btf_fd >= 0) {
                obj->caps.btf_datasec = 1;
+               close(btf_fd);
+               return 1;
+       }
+
        return 0;
 }
 
@@ -3206,6 +3210,10 @@ static const struct {
                                                BPF_CGROUP_UDP4_SENDMSG),
        BPF_EAPROG_SEC("cgroup/sendmsg6",       BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
                                                BPF_CGROUP_UDP6_SENDMSG),
+       BPF_EAPROG_SEC("cgroup/recvmsg4",       BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
+                                               BPF_CGROUP_UDP4_RECVMSG),
+       BPF_EAPROG_SEC("cgroup/recvmsg6",       BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
+                                               BPF_CGROUP_UDP6_RECVMSG),
        BPF_EAPROG_SEC("cgroup/sysctl",         BPF_PROG_TYPE_CGROUP_SYSCTL,
                                                BPF_CGROUP_SYSCTL),
 };
index f3025b4d90e19806d028485aca99f35796cc8f13..dfab8012185c49c302fd528006ba28320e208729 100644 (file)
@@ -34,7 +34,7 @@ do {                          \
 #define pr_info(fmt, ...)      __pr(LIBBPF_INFO, fmt, ##__VA_ARGS__)
 #define pr_debug(fmt, ...)     __pr(LIBBPF_DEBUG, fmt, ##__VA_ARGS__)
 
-int libbpf__probe_raw_btf(const char *raw_types, size_t types_len,
-                         const char *str_sec, size_t str_len);
+int libbpf__load_raw_btf(const char *raw_types, size_t types_len,
+                        const char *str_sec, size_t str_len);
 
 #endif /* __LIBBPF_LIBBPF_INTERNAL_H */
index 5e2aa83f637a4726dd9b6c0b8628f1cd83bc225d..6635a31a7a164e7d03cdd697b599774d9c360969 100644 (file)
@@ -133,8 +133,8 @@ bool bpf_probe_prog_type(enum bpf_prog_type prog_type, __u32 ifindex)
        return errno != EINVAL && errno != EOPNOTSUPP;
 }
 
-int libbpf__probe_raw_btf(const char *raw_types, size_t types_len,
-                         const char *str_sec, size_t str_len)
+int libbpf__load_raw_btf(const char *raw_types, size_t types_len,
+                        const char *str_sec, size_t str_len)
 {
        struct btf_header hdr = {
                .magic = BTF_MAGIC,
@@ -157,14 +157,9 @@ int libbpf__probe_raw_btf(const char *raw_types, size_t types_len,
        memcpy(raw_btf + hdr.hdr_len + hdr.type_len, str_sec, hdr.str_len);
 
        btf_fd = bpf_load_btf(raw_btf, btf_len, NULL, 0, false);
-       if (btf_fd < 0) {
-               free(raw_btf);
-               return 0;
-       }
 
-       close(btf_fd);
        free(raw_btf);
-       return 1;
+       return btf_fd;
 }
 
 static int load_sk_storage_btf(void)
@@ -190,7 +185,7 @@ static int load_sk_storage_btf(void)
                BTF_MEMBER_ENC(23, 2, 32),/* struct bpf_spin_lock l; */
        };
 
-       return libbpf__probe_raw_btf((char *)types, sizeof(types),
+       return libbpf__load_raw_btf((char *)types, sizeof(types),
                                     strs, sizeof(strs));
 }
 
index 66f2dca1dee19cf73596757d8b39eab7b3651687..e36356e2377e9624b23002a8ab6e9786b2a7c518 100644 (file)
@@ -21,8 +21,8 @@ LDLIBS += -lcap -lelf -lrt -lpthread
 # Order correspond to 'make run_tests' order
 TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \
        test_align test_verifier_log test_dev_cgroup test_tcpbpf_user \
-       test_sock test_btf test_sockmap test_lirc_mode2_user get_cgroup_id_user \
-       test_socket_cookie test_cgroup_storage test_select_reuseport test_section_names \
+       test_sock test_btf test_sockmap get_cgroup_id_user test_socket_cookie \
+       test_cgroup_storage test_select_reuseport test_section_names \
        test_netcnt test_tcpnotify_user test_sock_fields test_sysctl
 
 BPF_OBJ_FILES = $(patsubst %.c,%.o, $(notdir $(wildcard progs/*.c)))
@@ -63,7 +63,8 @@ TEST_PROGS_EXTENDED := with_addr.sh \
 
 # Compile but not part of 'make run_tests'
 TEST_GEN_PROGS_EXTENDED = test_libbpf_open test_sock_addr test_skb_cgroup_id_user \
-       flow_dissector_load test_flow_dissector test_tcp_check_syncookie_user
+       flow_dissector_load test_flow_dissector test_tcp_check_syncookie_user \
+       test_lirc_mode2_user
 
 include ../lib.mk
 
index fbd1d88a6095325a5273f21b86ec88eae91d8994..c938283ac232a8bd1879af0a7e6e8c5de3b3169d 100644 (file)
@@ -3,6 +3,7 @@
 #include <error.h>
 #include <linux/if.h>
 #include <linux/if_tun.h>
+#include <sys/uio.h>
 
 #define CHECK_FLOW_KEYS(desc, got, expected)                           \
        CHECK_ATTR(memcmp(&got, &expected, sizeof(got)) != 0,           \
index 02d7c871862af26080e823a6936a54bbd182e454..006be39639778f9311fd849849a41ebe4e62f5c0 100644 (file)
@@ -573,13 +573,13 @@ static void test_lpm_get_next_key(void)
 
        /* add one more element (total two) */
        key_p->prefixlen = 24;
-       inet_pton(AF_INET, "192.168.0.0", key_p->data);
+       inet_pton(AF_INET, "192.168.128.0", key_p->data);
        assert(bpf_map_update_elem(map_fd, key_p, &value, 0) == 0);
 
        memset(key_p, 0, key_size);
        assert(bpf_map_get_next_key(map_fd, NULL, key_p) == 0);
        assert(key_p->prefixlen == 24 && key_p->data[0] == 192 &&
-              key_p->data[1] == 168 && key_p->data[2] == 0);
+              key_p->data[1] == 168 && key_p->data[2] == 128);
 
        memset(next_key_p, 0, key_size);
        assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0);
@@ -592,7 +592,7 @@ static void test_lpm_get_next_key(void)
 
        /* Add one more element (total three) */
        key_p->prefixlen = 24;
-       inet_pton(AF_INET, "192.168.128.0", key_p->data);
+       inet_pton(AF_INET, "192.168.0.0", key_p->data);
        assert(bpf_map_update_elem(map_fd, key_p, &value, 0) == 0);
 
        memset(key_p, 0, key_size);
@@ -643,6 +643,41 @@ static void test_lpm_get_next_key(void)
        assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == -1 &&
               errno == ENOENT);
 
+       /* Add one more element (total five) */
+       key_p->prefixlen = 28;
+       inet_pton(AF_INET, "192.168.1.128", key_p->data);
+       assert(bpf_map_update_elem(map_fd, key_p, &value, 0) == 0);
+
+       memset(key_p, 0, key_size);
+       assert(bpf_map_get_next_key(map_fd, NULL, key_p) == 0);
+       assert(key_p->prefixlen == 24 && key_p->data[0] == 192 &&
+              key_p->data[1] == 168 && key_p->data[2] == 0);
+
+       memset(next_key_p, 0, key_size);
+       assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0);
+       assert(next_key_p->prefixlen == 28 && next_key_p->data[0] == 192 &&
+              next_key_p->data[1] == 168 && next_key_p->data[2] == 1 &&
+              next_key_p->data[3] == 128);
+
+       memcpy(key_p, next_key_p, key_size);
+       assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0);
+       assert(next_key_p->prefixlen == 24 && next_key_p->data[0] == 192 &&
+              next_key_p->data[1] == 168 && next_key_p->data[2] == 1);
+
+       memcpy(key_p, next_key_p, key_size);
+       assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0);
+       assert(next_key_p->prefixlen == 24 && next_key_p->data[0] == 192 &&
+              next_key_p->data[1] == 168 && next_key_p->data[2] == 128);
+
+       memcpy(key_p, next_key_p, key_size);
+       assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == 0);
+       assert(next_key_p->prefixlen == 16 && next_key_p->data[0] == 192 &&
+              next_key_p->data[1] == 168);
+
+       memcpy(key_p, next_key_p, key_size);
+       assert(bpf_map_get_next_key(map_fd, key_p, next_key_p) == -1 &&
+              errno == ENOENT);
+
        /* no exact matching key should return the first one in post order */
        key_p->prefixlen = 22;
        inet_pton(AF_INET, "192.168.1.0", key_p->data);
index bebd4fbca1f43e7102ec9dd66c0828d3aebfc60a..dee2f2eceb0fa1f8fda230888f1c3d065a3a3b82 100644 (file)
@@ -119,6 +119,16 @@ static struct sec_name_test tests[] = {
                {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_SENDMSG},
                {0, BPF_CGROUP_UDP6_SENDMSG},
        },
+       {
+               "cgroup/recvmsg4",
+               {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP4_RECVMSG},
+               {0, BPF_CGROUP_UDP4_RECVMSG},
+       },
+       {
+               "cgroup/recvmsg6",
+               {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_RECVMSG},
+               {0, BPF_CGROUP_UDP6_RECVMSG},
+       },
        {
                "cgroup/sysctl",
                {0, BPF_PROG_TYPE_CGROUP_SYSCTL, BPF_CGROUP_SYSCTL},
index 3f110eaaf29cea214844ff98211697c764b8a870..4ecde2392327dfbcea82554821a4042ba9e9702e 100644 (file)
@@ -76,6 +76,7 @@ struct sock_addr_test {
        enum {
                LOAD_REJECT,
                ATTACH_REJECT,
+               ATTACH_OKAY,
                SYSCALL_EPERM,
                SYSCALL_ENOTSUPP,
                SUCCESS,
@@ -88,9 +89,13 @@ static int connect4_prog_load(const struct sock_addr_test *test);
 static int connect6_prog_load(const struct sock_addr_test *test);
 static int sendmsg_allow_prog_load(const struct sock_addr_test *test);
 static int sendmsg_deny_prog_load(const struct sock_addr_test *test);
+static int recvmsg_allow_prog_load(const struct sock_addr_test *test);
+static int recvmsg_deny_prog_load(const struct sock_addr_test *test);
 static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test);
+static int recvmsg4_rw_asm_prog_load(const struct sock_addr_test *test);
 static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test);
 static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test);
+static int recvmsg6_rw_asm_prog_load(const struct sock_addr_test *test);
 static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test);
 static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test);
 static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test);
@@ -507,6 +512,92 @@ static struct sock_addr_test tests[] = {
                SRC6_REWRITE_IP,
                SYSCALL_EPERM,
        },
+
+       /* recvmsg */
+       {
+               "recvmsg4: return code ok",
+               recvmsg_allow_prog_load,
+               BPF_CGROUP_UDP4_RECVMSG,
+               BPF_CGROUP_UDP4_RECVMSG,
+               AF_INET,
+               SOCK_DGRAM,
+               NULL,
+               0,
+               NULL,
+               0,
+               NULL,
+               ATTACH_OKAY,
+       },
+       {
+               "recvmsg4: return code !ok",
+               recvmsg_deny_prog_load,
+               BPF_CGROUP_UDP4_RECVMSG,
+               BPF_CGROUP_UDP4_RECVMSG,
+               AF_INET,
+               SOCK_DGRAM,
+               NULL,
+               0,
+               NULL,
+               0,
+               NULL,
+               LOAD_REJECT,
+       },
+       {
+               "recvmsg6: return code ok",
+               recvmsg_allow_prog_load,
+               BPF_CGROUP_UDP6_RECVMSG,
+               BPF_CGROUP_UDP6_RECVMSG,
+               AF_INET6,
+               SOCK_DGRAM,
+               NULL,
+               0,
+               NULL,
+               0,
+               NULL,
+               ATTACH_OKAY,
+       },
+       {
+               "recvmsg6: return code !ok",
+               recvmsg_deny_prog_load,
+               BPF_CGROUP_UDP6_RECVMSG,
+               BPF_CGROUP_UDP6_RECVMSG,
+               AF_INET6,
+               SOCK_DGRAM,
+               NULL,
+               0,
+               NULL,
+               0,
+               NULL,
+               LOAD_REJECT,
+       },
+       {
+               "recvmsg4: rewrite IP & port (asm)",
+               recvmsg4_rw_asm_prog_load,
+               BPF_CGROUP_UDP4_RECVMSG,
+               BPF_CGROUP_UDP4_RECVMSG,
+               AF_INET,
+               SOCK_DGRAM,
+               SERV4_REWRITE_IP,
+               SERV4_REWRITE_PORT,
+               SERV4_REWRITE_IP,
+               SERV4_REWRITE_PORT,
+               SERV4_IP,
+               SUCCESS,
+       },
+       {
+               "recvmsg6: rewrite IP & port (asm)",
+               recvmsg6_rw_asm_prog_load,
+               BPF_CGROUP_UDP6_RECVMSG,
+               BPF_CGROUP_UDP6_RECVMSG,
+               AF_INET6,
+               SOCK_DGRAM,
+               SERV6_REWRITE_IP,
+               SERV6_REWRITE_PORT,
+               SERV6_REWRITE_IP,
+               SERV6_REWRITE_PORT,
+               SERV6_IP,
+               SUCCESS,
+       },
 };
 
 static int mk_sockaddr(int domain, const char *ip, unsigned short port,
@@ -765,8 +856,8 @@ static int connect6_prog_load(const struct sock_addr_test *test)
        return load_path(test, CONNECT6_PROG_PATH);
 }
 
-static int sendmsg_ret_only_prog_load(const struct sock_addr_test *test,
-                                     int32_t rc)
+static int xmsg_ret_only_prog_load(const struct sock_addr_test *test,
+                                  int32_t rc)
 {
        struct bpf_insn insns[] = {
                /* return rc */
@@ -778,12 +869,22 @@ static int sendmsg_ret_only_prog_load(const struct sock_addr_test *test,
 
 static int sendmsg_allow_prog_load(const struct sock_addr_test *test)
 {
-       return sendmsg_ret_only_prog_load(test, /*rc*/ 1);
+       return xmsg_ret_only_prog_load(test, /*rc*/ 1);
 }
 
 static int sendmsg_deny_prog_load(const struct sock_addr_test *test)
 {
-       return sendmsg_ret_only_prog_load(test, /*rc*/ 0);
+       return xmsg_ret_only_prog_load(test, /*rc*/ 0);
+}
+
+static int recvmsg_allow_prog_load(const struct sock_addr_test *test)
+{
+       return xmsg_ret_only_prog_load(test, /*rc*/ 1);
+}
+
+static int recvmsg_deny_prog_load(const struct sock_addr_test *test)
+{
+       return xmsg_ret_only_prog_load(test, /*rc*/ 0);
 }
 
 static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test)
@@ -838,6 +939,47 @@ static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test)
        return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn));
 }
 
+static int recvmsg4_rw_asm_prog_load(const struct sock_addr_test *test)
+{
+       struct sockaddr_in src4_rw_addr;
+
+       if (mk_sockaddr(AF_INET, SERV4_IP, SERV4_PORT,
+                       (struct sockaddr *)&src4_rw_addr,
+                       sizeof(src4_rw_addr)) == -1)
+               return -1;
+
+       struct bpf_insn insns[] = {
+               BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+
+               /* if (sk.family == AF_INET && */
+               BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
+                           offsetof(struct bpf_sock_addr, family)),
+               BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET, 6),
+
+               /*     sk.type == SOCK_DGRAM)  { */
+               BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
+                           offsetof(struct bpf_sock_addr, type)),
+               BPF_JMP_IMM(BPF_JNE, BPF_REG_7, SOCK_DGRAM, 4),
+
+               /*      user_ip4 = src4_rw_addr.sin_addr */
+               BPF_MOV32_IMM(BPF_REG_7, src4_rw_addr.sin_addr.s_addr),
+               BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
+                           offsetof(struct bpf_sock_addr, user_ip4)),
+
+               /*      user_port = src4_rw_addr.sin_port */
+               BPF_MOV32_IMM(BPF_REG_7, src4_rw_addr.sin_port),
+               BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
+                           offsetof(struct bpf_sock_addr, user_port)),
+               /* } */
+
+               /* return 1 */
+               BPF_MOV64_IMM(BPF_REG_0, 1),
+               BPF_EXIT_INSN(),
+       };
+
+       return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn));
+}
+
 static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test)
 {
        return load_path(test, SENDMSG4_PROG_PATH);
@@ -901,6 +1043,39 @@ static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test)
        return sendmsg6_rw_dst_asm_prog_load(test, SERV6_REWRITE_IP);
 }
 
+static int recvmsg6_rw_asm_prog_load(const struct sock_addr_test *test)
+{
+       struct sockaddr_in6 src6_rw_addr;
+
+       if (mk_sockaddr(AF_INET6, SERV6_IP, SERV6_PORT,
+                       (struct sockaddr *)&src6_rw_addr,
+                       sizeof(src6_rw_addr)) == -1)
+               return -1;
+
+       struct bpf_insn insns[] = {
+               BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+
+               /* if (sk.family == AF_INET6) { */
+               BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
+                           offsetof(struct bpf_sock_addr, family)),
+               BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET6, 10),
+
+               STORE_IPV6(user_ip6, src6_rw_addr.sin6_addr.s6_addr32),
+
+               /*      user_port = dst6_rw_addr.sin6_port */
+               BPF_MOV32_IMM(BPF_REG_7, src6_rw_addr.sin6_port),
+               BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
+                           offsetof(struct bpf_sock_addr, user_port)),
+               /* } */
+
+               /* return 1 */
+               BPF_MOV64_IMM(BPF_REG_0, 1),
+               BPF_EXIT_INSN(),
+       };
+
+       return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn));
+}
+
 static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test)
 {
        return sendmsg6_rw_dst_asm_prog_load(test, SERV6_V4MAPPED_IP);
@@ -1282,13 +1457,13 @@ out:
        return err;
 }
 
-static int run_sendmsg_test_case(const struct sock_addr_test *test)
+static int run_xmsg_test_case(const struct sock_addr_test *test, int max_cmsg)
 {
        socklen_t addr_len = sizeof(struct sockaddr_storage);
-       struct sockaddr_storage expected_src_addr;
-       struct sockaddr_storage requested_addr;
        struct sockaddr_storage expected_addr;
-       struct sockaddr_storage real_src_addr;
+       struct sockaddr_storage server_addr;
+       struct sockaddr_storage sendmsg_addr;
+       struct sockaddr_storage recvmsg_addr;
        int clientfd = -1;
        int servfd = -1;
        int set_cmsg;
@@ -1297,20 +1472,19 @@ static int run_sendmsg_test_case(const struct sock_addr_test *test)
        if (test->type != SOCK_DGRAM)
                goto err;
 
-       if (init_addrs(test, &requested_addr, &expected_addr,
-                      &expected_src_addr))
+       if (init_addrs(test, &sendmsg_addr, &server_addr, &expected_addr))
                goto err;
 
        /* Prepare server to sendmsg to */
-       servfd = start_server(test->type, &expected_addr, addr_len);
+       servfd = start_server(test->type, &server_addr, addr_len);
        if (servfd == -1)
                goto err;
 
-       for (set_cmsg = 0; set_cmsg <= 1; ++set_cmsg) {
+       for (set_cmsg = 0; set_cmsg <= max_cmsg; ++set_cmsg) {
                if (clientfd >= 0)
                        close(clientfd);
 
-               clientfd = sendmsg_to_server(test->type, &requested_addr,
+               clientfd = sendmsg_to_server(test->type, &sendmsg_addr,
                                             addr_len, set_cmsg, /*flags*/0,
                                             &err);
                if (err)
@@ -1330,10 +1504,10 @@ static int run_sendmsg_test_case(const struct sock_addr_test *test)
                 * specific packet may differ from the one used by default and
                 * returned by getsockname(2).
                 */
-               if (recvmsg_from_client(servfd, &real_src_addr) == -1)
+               if (recvmsg_from_client(servfd, &recvmsg_addr) == -1)
                        goto err;
 
-               if (cmp_addr(&real_src_addr, &expected_src_addr, /*cmp_port*/0))
+               if (cmp_addr(&recvmsg_addr, &expected_addr, /*cmp_port*/0))
                        goto err;
        }
 
@@ -1366,6 +1540,9 @@ static int run_test_case(int cgfd, const struct sock_addr_test *test)
                goto out;
        } else if (test->expected_result == ATTACH_REJECT || err) {
                goto err;
+       } else if (test->expected_result == ATTACH_OKAY) {
+               err = 0;
+               goto out;
        }
 
        switch (test->attach_type) {
@@ -1379,7 +1556,11 @@ static int run_test_case(int cgfd, const struct sock_addr_test *test)
                break;
        case BPF_CGROUP_UDP4_SENDMSG:
        case BPF_CGROUP_UDP6_SENDMSG:
-               err = run_sendmsg_test_case(test);
+               err = run_xmsg_test_case(test, 1);
+               break;
+       case BPF_CGROUP_UDP4_RECVMSG:
+       case BPF_CGROUP_UDP6_RECVMSG:
+               err = run_xmsg_test_case(test, 0);
                break;
        default:
                goto err;
index bd3f38dbe79646bd4a0bb557739eb60fda924322..acab4f00819f331a6bd58e24d373e88a97b6dce5 100644 (file)
        "DIV64 overflow, check 1",
        .insns = {
        BPF_MOV64_IMM(BPF_REG_1, -1),
-       BPF_LD_IMM64(BPF_REG_0, LLONG_MIN),
-       BPF_ALU64_REG(BPF_DIV, BPF_REG_0, BPF_REG_1),
+       BPF_LD_IMM64(BPF_REG_2, LLONG_MIN),
+       BPF_ALU64_REG(BPF_DIV, BPF_REG_2, BPF_REG_1),
+       BPF_MOV32_IMM(BPF_REG_0, 0),
+       BPF_JMP_REG(BPF_JEQ, BPF_REG_0, BPF_REG_2, 1),
+       BPF_MOV32_IMM(BPF_REG_0, 1),
        BPF_EXIT_INSN(),
        },
        .prog_type = BPF_PROG_TYPE_SCHED_CLS,
 {
        "DIV64 overflow, check 2",
        .insns = {
-       BPF_LD_IMM64(BPF_REG_0, LLONG_MIN),
-       BPF_ALU64_IMM(BPF_DIV, BPF_REG_0, -1),
+       BPF_LD_IMM64(BPF_REG_1, LLONG_MIN),
+       BPF_ALU64_IMM(BPF_DIV, BPF_REG_1, -1),
+       BPF_MOV32_IMM(BPF_REG_0, 0),
+       BPF_JMP_REG(BPF_JEQ, BPF_REG_0, BPF_REG_1, 1),
+       BPF_MOV32_IMM(BPF_REG_0, 1),
        BPF_EXIT_INSN(),
        },
        .prog_type = BPF_PROG_TYPE_SCHED_CLS,
diff --git a/tools/testing/selftests/bpf/verifier/subreg.c b/tools/testing/selftests/bpf/verifier/subreg.c
new file mode 100644 (file)
index 0000000..4c4133c
--- /dev/null
@@ -0,0 +1,533 @@
+/* This file contains sub-register zero extension checks for insns defining
+ * sub-registers, meaning:
+ *   - All insns under BPF_ALU class. Their BPF_ALU32 variants or narrow width
+ *     forms (BPF_END) could define sub-registers.
+ *   - Narrow direct loads, BPF_B/H/W | BPF_LDX.
+ *   - BPF_LD is not exposed to JIT back-ends, so no need for testing.
+ *
+ * "get_prandom_u32" is used to initialize low 32-bit of some registers to
+ * prevent potential optimizations done by verifier or JIT back-ends which could
+ * optimize register back into constant when range info shows one register is a
+ * constant.
+ */
+{
+       "add32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_LD_IMM64(BPF_REG_0, 0x100000000ULL),
+       BPF_ALU32_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "add32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       /* An insn could have no effect on the low 32-bit, for example:
+        *   a = a + 0
+        *   a = a | 0
+        *   a = a & -1
+        * But, they should still zero high 32-bit.
+        */
+       BPF_ALU32_IMM(BPF_ADD, BPF_REG_0, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_ADD, BPF_REG_0, -2),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "sub32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_LD_IMM64(BPF_REG_0, 0x1ffffffffULL),
+       BPF_ALU32_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "sub32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_SUB, BPF_REG_0, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_SUB, BPF_REG_0, 1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "mul32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_LD_IMM64(BPF_REG_0, 0x100000001ULL),
+       BPF_ALU32_REG(BPF_MUL, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "mul32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_MUL, BPF_REG_0, 1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_MUL, BPF_REG_0, -1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "div32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_MOV64_IMM(BPF_REG_0, -1),
+       BPF_ALU32_REG(BPF_DIV, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "div32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_DIV, BPF_REG_0, 1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_DIV, BPF_REG_0, 2),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "or32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_LD_IMM64(BPF_REG_0, 0x100000001ULL),
+       BPF_ALU32_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "or32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_OR, BPF_REG_0, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_OR, BPF_REG_0, 1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "and32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x100000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_1, BPF_REG_0),
+       BPF_LD_IMM64(BPF_REG_0, 0x1ffffffffULL),
+       BPF_ALU32_REG(BPF_AND, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "and32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_AND, BPF_REG_0, -1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_AND, BPF_REG_0, -2),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "lsh32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x100000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_MOV64_IMM(BPF_REG_1, 1),
+       BPF_ALU32_REG(BPF_LSH, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "lsh32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_LSH, BPF_REG_0, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_LSH, BPF_REG_0, 1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "rsh32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_MOV64_IMM(BPF_REG_1, 1),
+       BPF_ALU32_REG(BPF_RSH, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "rsh32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_RSH, BPF_REG_0, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_RSH, BPF_REG_0, 1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "neg32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_NEG, BPF_REG_0, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "mod32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_MOV64_IMM(BPF_REG_0, -1),
+       BPF_ALU32_REG(BPF_MOD, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "mod32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_MOD, BPF_REG_0, 1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_MOD, BPF_REG_0, 2),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "xor32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_LD_IMM64(BPF_REG_0, 0x100000000ULL),
+       BPF_ALU32_REG(BPF_XOR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "xor32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_XOR, BPF_REG_0, 1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "mov32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x100000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_1, BPF_REG_0),
+       BPF_LD_IMM64(BPF_REG_0, 0x100000000ULL),
+       BPF_MOV32_REG(BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "mov32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_MOV32_IMM(BPF_REG_0, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_MOV32_IMM(BPF_REG_0, 1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "arsh32 reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_MOV64_IMM(BPF_REG_1, 1),
+       BPF_ALU32_REG(BPF_ARSH, BPF_REG_0, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "arsh32 imm zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_ARSH, BPF_REG_0, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_ALU32_IMM(BPF_ARSH, BPF_REG_0, 1),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "end16 (to_le) reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 32),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_ENDIAN(BPF_TO_LE, BPF_REG_0, 16),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "end32 (to_le) reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 32),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_ENDIAN(BPF_TO_LE, BPF_REG_0, 32),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "end16 (to_be) reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 32),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_ENDIAN(BPF_TO_BE, BPF_REG_0, 16),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "end32 (to_be) reg zero extend check",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 32),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_6),
+       BPF_ENDIAN(BPF_TO_BE, BPF_REG_0, 32),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "ldx_b zero extend check",
+       .insns = {
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -4),
+       BPF_ST_MEM(BPF_W, BPF_REG_6, 0, 0xfaceb00c),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_6, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "ldx_h zero extend check",
+       .insns = {
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -4),
+       BPF_ST_MEM(BPF_W, BPF_REG_6, 0, 0xfaceb00c),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_LDX_MEM(BPF_H, BPF_REG_0, BPF_REG_6, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
+{
+       "ldx_w zero extend check",
+       .insns = {
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -4),
+       BPF_ST_MEM(BPF_W, BPF_REG_6, 0, 0xfaceb00c),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
+       BPF_LD_IMM64(BPF_REG_1, 0x1000000000ULL),
+       BPF_ALU64_REG(BPF_OR, BPF_REG_0, BPF_REG_1),
+       BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, 0),
+       BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
index 1c30f302a1e75e42999ac97159673122cd026839..5c39e5f6a48005135b5385bf9862778365c6f1c3 100755 (executable)
@@ -28,6 +28,7 @@ ALL_TESTS="
        vlan_interface_uppers_test
        bridge_extern_learn_test
        neigh_offload_test
+       nexthop_offload_test
        devlink_reload_test
 "
 NUM_NETIFS=2
@@ -607,6 +608,52 @@ neigh_offload_test()
        ip -4 address del 192.0.2.1/24 dev $swp1
 }
 
+nexthop_offload_test()
+{
+       # Test that IPv4 and IPv6 nexthops are marked as offloaded
+       RET=0
+
+       sysctl_set net.ipv6.conf.$swp2.keep_addr_on_down 1
+       simple_if_init $swp1 192.0.2.1/24 2001:db8:1::1/64
+       simple_if_init $swp2 192.0.2.2/24 2001:db8:1::2/64
+       setup_wait
+
+       ip -4 route add 198.51.100.0/24 vrf v$swp1 \
+               nexthop via 192.0.2.2 dev $swp1
+       ip -6 route add 2001:db8:2::/64 vrf v$swp1 \
+               nexthop via 2001:db8:1::2 dev $swp1
+
+       ip -4 route show 198.51.100.0/24 vrf v$swp1 | grep -q offload
+       check_err $? "ipv4 nexthop not marked as offloaded when should"
+       ip -6 route show 2001:db8:2::/64 vrf v$swp1 | grep -q offload
+       check_err $? "ipv6 nexthop not marked as offloaded when should"
+
+       ip link set dev $swp2 down
+       sleep 1
+
+       ip -4 route show 198.51.100.0/24 vrf v$swp1 | grep -q offload
+       check_fail $? "ipv4 nexthop marked as offloaded when should not"
+       ip -6 route show 2001:db8:2::/64 vrf v$swp1 | grep -q offload
+       check_fail $? "ipv6 nexthop marked as offloaded when should not"
+
+       ip link set dev $swp2 up
+       setup_wait
+
+       ip -4 route show 198.51.100.0/24 vrf v$swp1 | grep -q offload
+       check_err $? "ipv4 nexthop not marked as offloaded after neigh add"
+       ip -6 route show 2001:db8:2::/64 vrf v$swp1 | grep -q offload
+       check_err $? "ipv6 nexthop not marked as offloaded after neigh add"
+
+       log_test "nexthop offload indication"
+
+       ip -6 route del 2001:db8:2::/64 vrf v$swp1
+       ip -4 route del 198.51.100.0/24 vrf v$swp1
+
+       simple_if_fini $swp2 192.0.2.2/24 2001:db8:1::2/64
+       simple_if_fini $swp1 192.0.2.1/24 2001:db8:1::1/64
+       sysctl_restore net.ipv6.conf.$swp2.keep_addr_on_down
+}
+
 devlink_reload_test()
 {
        # Test that after executing all the above configuration tests, a
index 29bcfa84aec710702cc82ceb1e64c6ee098a8803..124803eea4a9d7395489f1a9eec36524009f0ecd 100755 (executable)
@@ -2,7 +2,8 @@
 # SPDX-License-Identifier: GPL-2.0
 
 ALL_TESTS="match_dst_mac_test match_src_mac_test match_dst_ip_test \
-       match_src_ip_test match_ip_flags_test match_pcp_test match_vlan_test"
+       match_src_ip_test match_ip_flags_test match_pcp_test match_vlan_test \
+       match_ip_tos_test"
 NUM_NETIFS=2
 source tc_common.sh
 source lib.sh
@@ -276,6 +277,39 @@ match_vlan_test()
        log_test "VLAN match ($tcflags)"
 }
 
+match_ip_tos_test()
+{
+       RET=0
+
+       tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \
+               $tcflags dst_ip 192.0.2.2 ip_tos 0x20 action drop
+       tc filter add dev $h2 ingress protocol ip pref 2 handle 102 flower \
+               $tcflags dst_ip 192.0.2.2 ip_tos 0x18 action drop
+
+       $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
+               -t ip tos=18 -q
+
+       tc_check_packets "dev $h2 ingress" 101 1
+       check_fail $? "Matched on a wrong filter (0x18)"
+
+       tc_check_packets "dev $h2 ingress" 102 1
+       check_err $? "Did not match on correct filter (0x18)"
+
+       $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
+               -t ip tos=20 -q
+
+       tc_check_packets "dev $h2 ingress" 102 2
+       check_fail $? "Matched on a wrong filter (0x20)"
+
+       tc_check_packets "dev $h2 ingress" 101 1
+       check_err $? "Did not match on correct filter (0x20)"
+
+       tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower
+       tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower
+
+       log_test "ip_tos match ($tcflags)"
+}
+
 setup_prepare()
 {
        h1=${NETIFS[p1]}