Merge tag '6.6-rc4-ksmbd-server-fixes' of git://git.samba.org/ksmbd
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 8 Oct 2023 17:10:52 +0000 (10:10 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 8 Oct 2023 17:10:52 +0000 (10:10 -0700)
Pull smb server fixes from Steve French:
 "Six SMB3 server fixes for various races found by RO0T Lab of Huawei:

   - Fix oops when racing between oplock break ack and freeing file

   - Simultaneous request fixes for parallel logoffs, and for parallel
     lock requests

   - Fixes for tree disconnect race, session expire race, and close/open
     race"

* tag '6.6-rc4-ksmbd-server-fixes' of git://git.samba.org/ksmbd:
  ksmbd: fix race condition between tree conn lookup and disconnect
  ksmbd: fix race condition from parallel smb2 lock requests
  ksmbd: fix race condition from parallel smb2 logoff requests
  ksmbd: fix uaf in smb20_oplock_break_ack
  ksmbd: fix race condition with fp
  ksmbd: fix race condition between session lookup and expire

263 files changed:
.mailmap
Documentation/arch/arm64/silicon-errata.rst
Documentation/devicetree/bindings/bus/fsl,imx8qxp-pixel-link-msi-bus.yaml
Documentation/devicetree/bindings/cache/andestech,ax45mp-cache.yaml
Documentation/devicetree/bindings/display/imx/fsl,imx6-hdmi.yaml
Documentation/devicetree/bindings/iommu/arm,smmu.yaml
Documentation/devicetree/bindings/media/i2c/sony,imx415.yaml
Documentation/devicetree/bindings/media/i2c/toshiba,tc358746.yaml
Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml
Documentation/devicetree/bindings/media/renesas,vin.yaml
Documentation/devicetree/bindings/media/samsung,fimc.yaml
Documentation/devicetree/bindings/mfd/maxim,max77693.yaml
Documentation/devicetree/bindings/pci/brcm,iproc-pcie.yaml
Documentation/devicetree/bindings/riscv/cpus.yaml
Documentation/devicetree/bindings/trivial-devices.yaml
Documentation/filesystems/erofs.rst
Documentation/tools/rtla/rtla-timerlat-hist.rst
MAINTAINERS
arch/arm64/Kconfig
arch/arm64/include/asm/acpi.h
arch/arm64/include/asm/cputype.h
arch/arm64/kernel/cpu_errata.c
arch/arm64/kernel/entry.S
arch/arm64/tools/cpucaps
arch/parisc/include/asm/ldcw.h
arch/parisc/include/asm/spinlock_types.h
arch/parisc/kernel/smp.c
arch/s390/net/bpf_jit_comp.c
arch/x86/kernel/sev-shared.c
arch/x86/kernel/sev.c
drivers/acpi/nfit/core.c
drivers/acpi/processor_idle.c
drivers/base/regmap/regcache-rbtree.c
drivers/block/nbd.c
drivers/bluetooth/btusb.c
drivers/dma/ti/k3-udma-glue.c
drivers/gpio/gpio-aspeed.c
drivers/gpio/gpio-pxa.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
drivers/gpu/drm/amd/pm/amdgpu_pm.c
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
drivers/gpu/drm/drm_panel_orientation_quirks.c
drivers/gpu/drm/i915/gem/i915_gem_pages.c
drivers/gpu/drm/i915/gt/gen8_engine_cs.c
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_chan.c
drivers/gpu/drm/nouveau/nouveau_dma.h
drivers/gpu/drm/nouveau/nouveau_exec.c
drivers/gpu/drm/nouveau/nouveau_exec.h
drivers/gpu/drm/tests/drm_kunit_helpers.c
drivers/hid/Kconfig
drivers/hid/hid-holtek-kbd.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-logitech-hidpp.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-nintendo.c
drivers/hid/hid-nvidia-shield.c
drivers/hid/hid-sony.c
drivers/hid/hid-steelseries.c
drivers/hid/intel-ish-hid/ipc/pci-ish.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/cma_configfs.c
drivers/infiniband/core/nldev.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/hw/bnxt_re/ib_verbs.c
drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/erdma/erdma_verbs.c
drivers/infiniband/hw/mlx4/sysfs.c
drivers/infiniband/hw/mlx5/fs.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/mr.c
drivers/infiniband/sw/siw/siw_cm.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/iommu/apple-dart.c
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
drivers/iommu/intel/iommu.c
drivers/iommu/intel/iommu.h
drivers/iommu/mtk_iommu.c
drivers/leds/led-core.c
drivers/md/dm-zoned-target.c
drivers/md/raid5.c
drivers/media/pci/intel/Kconfig
drivers/media/pci/intel/ipu3/Kconfig
drivers/media/pci/intel/ivsc/Kconfig
drivers/media/platform/intel/pxa_camera.c
drivers/media/platform/mediatek/vcodec/encoder/venc_vpu_if.c
drivers/mfd/Kconfig
drivers/mtd/ubi/build.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/global1.c
drivers/net/dsa/mv88e6xxx/global1.h
drivers/net/dsa/mv88e6xxx/global2.c
drivers/net/dsa/mv88e6xxx/global2.h
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/intel/ice/ice_virtchnl.c
drivers/net/ethernet/marvell/sky2.h
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/microchip/Kconfig
drivers/net/ethernet/microsoft/mana/mana_en.c
drivers/net/ethernet/qlogic/qed/qed_ll2.h
drivers/net/ethernet/renesas/rswitch.c
drivers/net/ethernet/renesas/rswitch.h
drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
drivers/net/ethernet/ti/am65-cpsw-nuss.c
drivers/net/ethernet/ti/icssg/icssg_prueth.c
drivers/net/usb/smsc75xx.c
drivers/net/wan/fsl_ucc_hdlc.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
drivers/net/wireless/intel/iwlwifi/mvm/fw.c
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/scan.c
drivers/net/wireless/intel/iwlwifi/mvm/tx.c
drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
drivers/net/wireless/marvell/mwifiex/fw.h
drivers/net/wireless/marvell/mwifiex/sta_rx.c
drivers/net/wireless/mediatek/mt76/dma.c
drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c
drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c
drivers/net/wireless/realtek/rtw88/rtw8723d.h
drivers/of/dynamic.c
drivers/of/overlay.c
drivers/pci/controller/dwc/pcie-qcom.c
drivers/pci/of.c
drivers/pci/of_property.c
drivers/pci/pci-driver.c
drivers/perf/arm-cmn.c
drivers/platform/mellanox/mlxbf-tmfifo.c
drivers/platform/x86/hp/hp-bioscfg/bioscfg.c
drivers/platform/x86/hp/hp-wmi.c
drivers/platform/x86/intel/ifs/runtest.c
drivers/platform/x86/think-lmi.c
drivers/platform/x86/touchscreen_dmi.c
drivers/ptp/ptp_ocp.c
drivers/regulator/core.c
drivers/regulator/mt6358-regulator.c
drivers/s390/scsi/zfcp_aux.c
drivers/scsi/fnic/fnic.h
drivers/scsi/fnic/fnic_io.h
drivers/scsi/fnic/fnic_main.c
drivers/scsi/fnic/fnic_scsi.c
drivers/staging/media/atomisp/Kconfig
drivers/staging/media/tegra-video/vi.c
drivers/target/target_core_device.c
drivers/vhost/vringh.c
fs/btrfs/ctree.c
fs/btrfs/ioctl.c
fs/btrfs/super.c
fs/btrfs/transaction.h
fs/erofs/decompressor_lzma.c
fs/erofs/super.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/write.c
fs/overlayfs/export.c
fs/overlayfs/file.c
fs/overlayfs/ovl_entry.h
fs/overlayfs/params.c
fs/overlayfs/super.c
fs/smb/client/connect.c
fs/xfs/xfs_discard.c
fs/xfs/xfs_discard.h
fs/xfs/xfs_extent_busy.c
fs/xfs/xfs_extent_busy.h
fs/xfs/xfs_log_cil.c
fs/xfs/xfs_log_priv.h
include/linux/acpi.h
include/linux/bpf.h
include/linux/netfilter/nf_conntrack_sctp.h
include/net/bluetooth/hci_core.h
include/net/cfg80211.h
include/net/ip_fib.h
include/net/mana/mana.h
include/net/neighbour.h
include/net/page_pool/helpers.h
include/net/tcp.h
include/uapi/drm/nouveau_drm.h
io_uring/io-wq.c
io_uring/io_uring.c
io_uring/io_uring.h
io_uring/kbuf.c
kernel/bpf/memalloc.c
kernel/bpf/mprog.c
kernel/bpf/verifier.c
kernel/power/snapshot.c
kernel/sched/cpufreq_schedutil.c
kernel/sched/fair.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/hci_request.h
net/bluetooth/hci_sync.c
net/bluetooth/iso.c
net/bridge/br_netfilter_hooks.c
net/core/neighbour.c
net/core/sock_map.c
net/ethtool/plca.c
net/ipv4/fib_semantics.c
net/ipv4/fib_trie.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_bpf.c
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c
net/ipv6/tcp_ipv6.c
net/l2tp/l2tp_ip6.c
net/mac80211/cfg.c
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/key.c
net/mac80211/mesh.c
net/mac80211/mesh_plink.c
net/mac80211/mlme.c
net/mac80211/tx.c
net/mac80211/vht.c
net/mptcp/pm_userspace.c
net/mptcp/protocol.c
net/mptcp/protocol.h
net/mptcp/subflow.c
net/netfilter/ipvs/ip_vs_sync.c
net/netfilter/nf_conntrack_proto_sctp.c
net/netfilter/nf_tables_api.c
net/netfilter/nft_payload.c
net/netfilter/nft_set_rbtree.c
net/netlink/af_netlink.c
net/nfc/llcp_core.c
net/rds/tcp_connect.c
net/rds/tcp_listen.c
net/rfkill/core.c
net/sctp/associola.c
net/sctp/socket.c
net/socket.c
net/sunrpc/auth.c
net/sunrpc/auth_tls.c
net/sunrpc/clnt.c
net/sunrpc/xprtsock.c
net/tipc/crypto.c
net/wireless/core.c
net/wireless/core.h
net/wireless/mlme.c
net/wireless/nl80211.c
net/wireless/scan.c
security/integrity/ima/Kconfig
tools/testing/selftests/Makefile
tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c
tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
tools/testing/selftests/bpf/prog_tests/tc_opts.c
tools/testing/selftests/bpf/progs/bpf_cubic.c
tools/testing/selftests/netfilter/Makefile
tools/testing/selftests/netfilter/conntrack_sctp_collision.sh [new file with mode: 0755]
tools/testing/selftests/netfilter/nft_audit.sh
tools/testing/selftests/netfilter/sctp_collision.c [new file with mode: 0644]
tools/tracing/rtla/src/timerlat_aa.c
tools/tracing/rtla/src/timerlat_u.c

index a0a6efe..c80903e 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -377,6 +377,7 @@ Matthew Wilcox <willy@infradead.org> <willy@debian.org>
 Matthew Wilcox <willy@infradead.org> <willy@linux.intel.com>
 Matthew Wilcox <willy@infradead.org> <willy@parisc-linux.org>
 Matthias Fuchs <socketcan@esd.eu> <matthias.fuchs@esd.eu>
+Matthieu Baerts <matttbe@kernel.org> <matthieu.baerts@tessares.net>
 Matthieu CASTET <castet.matthieu@free.fr>
 Matti Vaittinen <mazziesaccount@gmail.com> <matti.vaittinen@fi.rohmeurope.com>
 Matt Ranostay <matt.ranostay@konsulko.com> <matt@ranostay.consulting>
index e96f057..f47f63b 100644 (file)
@@ -71,6 +71,8 @@ stable kernels.
 +----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Cortex-A510     | #2658417        | ARM64_ERRATUM_2658417       |
 +----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-A520     | #2966298        | ARM64_ERRATUM_2966298       |
++----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Cortex-A53      | #826319         | ARM64_ERRATUM_826319        |
 +----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Cortex-A53      | #827319         | ARM64_ERRATUM_827319        |
index b568d0c..7e1ffc5 100644 (file)
@@ -73,9 +73,6 @@ patternProperties:
   "^.*@[0-9a-f]+$":
     description: Devices attached to the bus
     type: object
-    properties:
-      reg:
-        maxItems: 1
 
     required:
       - reg
index 9ab5f0c..d2cbe49 100644 (file)
@@ -69,7 +69,7 @@ examples:
   - |
     #include <dt-bindings/interrupt-controller/irq.h>
 
-    cache-controller@2010000 {
+    cache-controller@13400000 {
         compatible = "andestech,ax45mp-cache", "cache";
         reg = <0x13400000 0x100000>;
         interrupts = <508 IRQ_TYPE_LEVEL_HIGH>;
index af7fe9c..7979cf0 100644 (file)
@@ -87,7 +87,7 @@ required:
   - interrupts
   - ports
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
index cf29ab1..b1b2cf8 100644 (file)
@@ -270,6 +270,7 @@ allOf:
           contains:
             enum:
               - qcom,msm8998-smmu-v2
+              - qcom,sdm630-smmu-v2
     then:
       anyOf:
         - properties:
@@ -311,7 +312,6 @@ allOf:
         compatible:
           contains:
             enum:
-              - qcom,sdm630-smmu-v2
               - qcom,sm6375-smmu-v2
     then:
       anyOf:
index ffccf5f..642f9b1 100644 (file)
@@ -54,6 +54,7 @@ properties:
 
   port:
     $ref: /schemas/graph.yaml#/$defs/port-base
+    unevaluatedProperties: false
 
     properties:
       endpoint:
index c5cab54..1c476b6 100644 (file)
@@ -69,6 +69,7 @@ properties:
     properties:
       port@0:
         $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
         description: Input port
 
         properties:
@@ -89,6 +90,7 @@ properties:
 
       port@1:
         $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
         description: Output port
 
         properties:
index 358019e..326284e 100644 (file)
@@ -59,7 +59,6 @@ allOf:
         compatible:
           contains:
             enum:
-              - fsl,imx8mq-csi
               - fsl,imx8mm-csi
     then:
       required:
index 324703b..5539d0f 100644 (file)
@@ -95,7 +95,7 @@ properties:
               synchronization is selected.
             default: 1
 
-          field-active-even: true
+          field-even-active: true
 
           bus-width: true
 
@@ -144,7 +144,7 @@ properties:
                   synchronization is selected.
                 default: 1
 
-              field-active-even: true
+              field-even-active: true
 
               bus-width: true
 
index 79ff6d8..b3486c3 100644 (file)
@@ -57,6 +57,7 @@ properties:
     patternProperties:
       "^port@[01]$":
         $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
         description:
           Camera A and camera B inputs.
 
index 9804d13..6a6f222 100644 (file)
@@ -31,10 +31,6 @@ properties:
   charger:
     $ref: /schemas/power/supply/maxim,max77693.yaml
 
-  connector:
-    $ref: /schemas/connector/usb-connector.yaml#
-    unevaluatedProperties: false
-
   led:
     $ref: /schemas/leds/maxim,max77693.yaml
 
index 0972868..0e07ab6 100644 (file)
@@ -12,7 +12,6 @@ maintainers:
 
 allOf:
   - $ref: /schemas/pci/pci-bus.yaml#
-  - $ref: /schemas/interrupt-controller/msi-controller.yaml#
 
 properties:
   compatible:
@@ -34,13 +33,6 @@ properties:
     description: >
        Base address and length of the PCIe controller I/O register space
 
-  interrupt-map: true
-
-  interrupt-map-mask: true
-
-  "#interrupt-cells":
-    const: 1
-
   ranges:
     minItems: 1
     maxItems: 2
@@ -54,16 +46,8 @@ properties:
     items:
       - const: pcie-phy
 
-  bus-range: true
-
   dma-coherent: true
 
-  "#address-cells": true
-
-  "#size-cells": true
-
-  device_type: true
-
   brcm,pcie-ob:
     type: boolean
     description: >
@@ -78,20 +62,24 @@ properties:
 
   msi:
     type: object
+    $ref: /schemas/interrupt-controller/msi-controller.yaml#
+    unevaluatedProperties: false
+
     properties:
       compatible:
         items:
           - const: brcm,iproc-msi
 
-  msi-parent: true
+      interrupts:
+        maxItems: 4
 
-  msi-controller: true
+      brcm,pcie-msi-inten:
+        type: boolean
+        description:
+          Needs to be present for some older iProc platforms that require the
+          interrupt enable registers to be set explicitly to enable MSI
 
-  brcm,pcie-msi-inten:
-    type: boolean
-    description: >
-      Needs to be present for some older iProc platforms that require the
-      interrupt enable registers to be set explicitly to enable MSI
+  msi-parent: true
 
 dependencies:
   brcm,pcie-ob-axi-offset: ["brcm,pcie-ob"]
@@ -117,68 +105,69 @@ unevaluatedProperties: false
 
 examples:
   - |
-   #include <dt-bindings/interrupt-controller/arm-gic.h>
-
-   bus {
-      #address-cells = <1>;
-      #size-cells = <1>;
-           pcie0: pcie@18012000 {
-              compatible = "brcm,iproc-pcie";
-              reg = <0x18012000 0x1000>;
-
-              #interrupt-cells = <1>;
-              interrupt-map-mask = <0 0 0 0>;
-              interrupt-map = <0 0 0 0 &gic GIC_SPI 100 IRQ_TYPE_NONE>;
-
-              linux,pci-domain = <0>;
-
-              bus-range = <0x00 0xff>;
-
-              #address-cells = <3>;
-              #size-cells = <2>;
-              device_type = "pci";
-              ranges = <0x81000000 0 0     0x28000000 0 0x00010000>,
-                   <0x82000000 0 0x20000000 0x20000000 0 0x04000000>;
-
-              phys = <&phy 0 5>;
-              phy-names = "pcie-phy";
-
-              brcm,pcie-ob;
-              brcm,pcie-ob-axi-offset = <0x00000000>;
-
-              msi-parent = <&msi0>;
-
-              /* iProc event queue based MSI */
-              msi0: msi {
-                 compatible = "brcm,iproc-msi";
-                 msi-controller;
-                 interrupt-parent = <&gic>;
-                 interrupts = <GIC_SPI 96 IRQ_TYPE_NONE>,
-                         <GIC_SPI 97 IRQ_TYPE_NONE>,
-                         <GIC_SPI 98 IRQ_TYPE_NONE>,
-                         <GIC_SPI 99 IRQ_TYPE_NONE>;
-              };
-           };
-
-           pcie1: pcie@18013000 {
-              compatible = "brcm,iproc-pcie";
-              reg = <0x18013000 0x1000>;
-
-              #interrupt-cells = <1>;
-              interrupt-map-mask = <0 0 0 0>;
-              interrupt-map = <0 0 0 0 &gic GIC_SPI 106 IRQ_TYPE_NONE>;
-
-              linux,pci-domain = <1>;
-
-              bus-range = <0x00 0xff>;
-
-              #address-cells = <3>;
-              #size-cells = <2>;
-              device_type = "pci";
-              ranges = <0x81000000 0 0     0x48000000 0 0x00010000>,
-                   <0x82000000 0 0x40000000 0x40000000 0 0x04000000>;
-
-              phys = <&phy 1 6>;
-              phy-names = "pcie-phy";
-           };
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    gic: interrupt-controller {
+        interrupt-controller;
+        #interrupt-cells = <3>;
+    };
+
+    pcie@18012000 {
+        compatible = "brcm,iproc-pcie";
+        reg = <0x18012000 0x1000>;
+
+        #interrupt-cells = <1>;
+        interrupt-map-mask = <0 0 0 0>;
+        interrupt-map = <0 0 0 0 &gic GIC_SPI 100 IRQ_TYPE_NONE>;
+
+        linux,pci-domain = <0>;
+
+        bus-range = <0x00 0xff>;
+
+        #address-cells = <3>;
+        #size-cells = <2>;
+        device_type = "pci";
+        ranges = <0x81000000 0          0 0x28000000 0 0x00010000>,
+                 <0x82000000 0 0x20000000 0x20000000 0 0x04000000>;
+
+        phys = <&phy 0 5>;
+        phy-names = "pcie-phy";
+
+        brcm,pcie-ob;
+        brcm,pcie-ob-axi-offset = <0x00000000>;
+
+        msi-parent = <&msi0>;
+
+        /* iProc event queue based MSI */
+        msi0: msi {
+            compatible = "brcm,iproc-msi";
+            msi-controller;
+            interrupt-parent = <&gic>;
+            interrupts = <GIC_SPI 96 IRQ_TYPE_NONE>,
+                    <GIC_SPI 97 IRQ_TYPE_NONE>,
+                    <GIC_SPI 98 IRQ_TYPE_NONE>,
+                    <GIC_SPI 99 IRQ_TYPE_NONE>;
+        };
+    };
+  - |
+    pcie@18013000 {
+        compatible = "brcm,iproc-pcie";
+        reg = <0x18013000 0x1000>;
+
+        #interrupt-cells = <1>;
+        interrupt-map-mask = <0 0 0 0>;
+        interrupt-map = <0 0 0 0 &gic GIC_SPI 106 IRQ_TYPE_NONE>;
+
+        linux,pci-domain = <1>;
+
+        bus-range = <0x00 0xff>;
+
+        #address-cells = <3>;
+        #size-cells = <2>;
+        device_type = "pci";
+        ranges = <0x81000000 0          0 0x48000000 0 0x00010000>,
+                 <0x82000000 0 0x40000000 0x40000000 0 0x04000000>;
+
+        phys = <&phy 1 6>;
+        phy-names = "pcie-phy";
     };
index 38c0b52..97e8441 100644 (file)
@@ -91,6 +91,7 @@ properties:
 
   interrupt-controller:
     type: object
+    additionalProperties: false
     description: Describes the CPU's local interrupt controller
 
     properties:
index cd58179..430a814 100644 (file)
@@ -232,7 +232,7 @@ properties:
             # MEMSIC magnetometer
           - memsic,mmc35240
             # MEMSIC 3-axis accelerometer
-          - memsic,mx4005
+          - memsic,mxc4005
             # MEMSIC 2-axis 8-bit digital accelerometer
           - memsic,mxc6225
             # MEMSIC 2-axis 8-bit digital accelerometer
index 4654ee5..f200d78 100644 (file)
@@ -58,12 +58,14 @@ Here are the main features of EROFS:
 
  - Support extended attributes as an option;
 
+ - Support a bloom filter that speeds up negative extended attribute lookups;
+
  - Support POSIX.1e ACLs by using extended attributes;
 
  - Support transparent data compression as an option:
-   LZ4 and MicroLZMA algorithms can be used on a per-file basis; In addition,
-   inplace decompression is also supported to avoid bounce compressed buffers
-   and page cache thrashing.
+   LZ4, MicroLZMA and DEFLATE algorithms can be used on a per-file basis; In
+   addition, inplace decompression is also supported to avoid bounce compressed
+   buffers and unnecessary page cache thrashing.
 
  - Support chunk-based data deduplication and rolling-hash compressed data
    deduplication;
@@ -268,6 +270,38 @@ details.)
 
 By the way, chunk-based files are all uncompressed for now.
 
+Long extended attribute name prefixes
+-------------------------------------
+There are use cases where extended attributes with different values can have
+only a few common prefixes (such as overlayfs xattrs).  The predefined prefixes
+work inefficiently in both image size and runtime performance in such cases.
+
+The long xattr name prefixes feature is introduced to address this issue.  The
+overall idea is that, apart from the existing predefined prefixes, the xattr
+entry could also refer to user-specified long xattr name prefixes, e.g.
+"trusted.overlay.".
+
+When referring to a long xattr name prefix, the highest bit (bit 7) of
+erofs_xattr_entry.e_name_index is set, while the lower bits (bit 0-6) as a whole
+represent the index of the referred long name prefix among all long name
+prefixes.  Therefore, only the trailing part of the name apart from the long
+xattr name prefix is stored in erofs_xattr_entry.e_name, which could be empty if
+the full xattr name matches exactly as its long xattr name prefix.
+
+All long xattr prefixes are stored one by one in the packed inode as long as
+the packed inode is valid, or in the meta inode otherwise.  The
+xattr_prefix_count (of the on-disk superblock) indicates the total number of
+long xattr name prefixes, while (xattr_prefix_start * 4) indicates the start
+offset of long name prefixes in the packed/meta inode.  Note that, long extended
+attribute name prefixes are disabled if xattr_prefix_count is 0.
+
+Each long name prefix is stored in the format: ALIGN({__le16 len, data}, 4),
+where len represents the total size of the data part.  The data part is actually
+represented by 'struct erofs_xattr_long_prefix', where base_index represents the
+index of the predefined xattr name prefix, e.g. EROFS_XATTR_INDEX_TRUSTED for
+"trusted.overlay." long name prefix, while the infix string keeps the string
+after stripping the short prefix, e.g. "overlay." for the example above.
+
 Data compression
 ----------------
 EROFS implements fixed-sized output compression which generates fixed-sized
index 057db78..03b7f3d 100644 (file)
@@ -36,11 +36,11 @@ EXAMPLE
 In the example below, **rtla timerlat hist** is set to run for *10* minutes,
 in the cpus *0-4*, *skipping zero* only lines. Moreover, **rtla timerlat
 hist** will change the priority of the *timerlat* threads to run under
-*SCHED_DEADLINE* priority, with a *10us* runtime every *1ms* period. The
+*SCHED_DEADLINE* priority, with a *100us* runtime every *1ms* period. The
 *1ms* period is also passed to the *timerlat* tracer. Auto-analysis is disabled
 to reduce overhead ::
 
-  [root@alien ~]# timerlat hist -d 10m -c 0-4 -P d:100us:1ms -p 1ms --no-aa
+  [root@alien ~]# timerlat hist -d 10m -c 0-4 -P d:100us:1ms -p 1000 --no-aa
   # RTLA timerlat histogram
   # Time unit is microseconds (us)
   # Duration:   0 00:10:00
index 35977b2..6c4cce4 100644 (file)
@@ -470,7 +470,6 @@ F:  drivers/hwmon/adm1029.c
 ADM8211 WIRELESS DRIVER
 L:     linux-wireless@vger.kernel.org
 S:     Orphan
-W:     https://wireless.wiki.kernel.org/
 F:     drivers/net/wireless/admtek/adm8211.*
 
 ADP1653 FLASH CONTROLLER DRIVER
@@ -5985,8 +5984,8 @@ F:        include/linux/devm-helpers.h
 DEVICE-MAPPER  (LVM)
 M:     Alasdair Kergon <agk@redhat.com>
 M:     Mike Snitzer <snitzer@kernel.org>
-M:     dm-devel@redhat.com
-L:     dm-devel@redhat.com
+M:     dm-devel@lists.linux.dev
+L:     dm-devel@lists.linux.dev
 S:     Maintained
 W:     http://sources.redhat.com/dm
 Q:     http://patchwork.kernel.org/project/dm-devel/list/
@@ -9531,10 +9530,8 @@ F:       Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml
 F:     drivers/iio/pressure/mprls0025pa.c
 
 HOST AP DRIVER
-M:     Jouni Malinen <j@w1.fi>
 L:     linux-wireless@vger.kernel.org
 S:     Obsolete
-W:     http://w1.fi/hostap-driver.html
 F:     drivers/net/wireless/intersil/hostap/
 
 HP BIOSCFG DRIVER
@@ -14947,7 +14944,7 @@ K:      macsec
 K:     \bmdo_
 
 NETWORKING [MPTCP]
-M:     Matthieu Baerts <matthieu.baerts@tessares.net>
+M:     Matthieu Baerts <matttbe@kernel.org>
 M:     Mat Martineau <martineau@kernel.org>
 L:     netdev@vger.kernel.org
 L:     mptcp@lists.linux.dev
@@ -17602,6 +17599,7 @@ M:      Kalle Valo <kvalo@kernel.org>
 M:     Jeff Johnson <quic_jjohnson@quicinc.com>
 L:     ath12k@lists.infradead.org
 S:     Supported
+W:     https://wireless.wiki.kernel.org/en/users/Drivers/ath12k
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
 F:     drivers/net/wireless/ath/ath12k/
 
@@ -18132,8 +18130,6 @@ REALTEK WIRELESS DRIVER (rtlwifi family)
 M:     Ping-Ke Shih <pkshih@realtek.com>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
-W:     https://wireless.wiki.kernel.org/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
 F:     drivers/net/wireless/realtek/rtlwifi/
 
 REALTEK WIRELESS DRIVER (rtw88)
@@ -18661,7 +18657,6 @@ F:      drivers/media/dvb-frontends/rtl2832_sdr*
 RTL8180 WIRELESS DRIVER
 L:     linux-wireless@vger.kernel.org
 S:     Orphan
-W:     https://wireless.wiki.kernel.org/
 F:     drivers/net/wireless/realtek/rtl818x/rtl8180/
 
 RTL8187 WIRELESS DRIVER
@@ -18669,14 +18664,12 @@ M:    Hin-Tak Leung <hintak.leung@gmail.com>
 M:     Larry Finger <Larry.Finger@lwfinger.net>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
-W:     https://wireless.wiki.kernel.org/
 F:     drivers/net/wireless/realtek/rtl818x/rtl8187/
 
 RTL8XXXU WIRELESS DRIVER (rtl8xxxu)
 M:     Jes Sorensen <Jes.Sorensen@gmail.com>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jes/linux.git rtl8xxxu-devel
 F:     drivers/net/wireless/realtek/rtl8xxxu/
 
 RTRS TRANSPORT DRIVERS
@@ -21658,7 +21651,6 @@ L:      linux-wireless@vger.kernel.org
 S:     Orphan
 W:     https://wireless.wiki.kernel.org/en/users/Drivers/wl12xx
 W:     https://wireless.wiki.kernel.org/en/users/Drivers/wl1251
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git
 F:     drivers/net/wireless/ti/
 
 TIMEKEEPING, CLOCKSOURCE CORE, NTP, ALARMTIMER
index b10515c..78f20e6 100644 (file)
@@ -1037,6 +1037,19 @@ config ARM64_ERRATUM_2645198
 
          If unsure, say Y.
 
+config ARM64_ERRATUM_2966298
+       bool "Cortex-A520: 2966298: workaround for speculatively executed unprivileged load"
+       default y
+       help
+         This option adds the workaround for ARM Cortex-A520 erratum 2966298.
+
+         On an affected Cortex-A520 core, a speculatively executed unprivileged
+         load might leak data from a privileged level via a cache side channel.
+
+         Work around this problem by executing a TLBI before returning to EL0.
+
+         If unsure, say Y.
+
 config CAVIUM_ERRATUM_22375
        bool "Cavium erratum 22375, 24313"
        default y
index 4d537d5..6792a1f 100644 (file)
@@ -9,6 +9,7 @@
 #ifndef _ASM_ACPI_H
 #define _ASM_ACPI_H
 
+#include <linux/cpuidle.h>
 #include <linux/efi.h>
 #include <linux/memblock.h>
 #include <linux/psci.h>
 
 #define ACPI_MADT_GICC_TRBE  (offsetof(struct acpi_madt_generic_interrupt, \
        trbe_interrupt) + sizeof(u16))
+/*
+ * Arm® Functional Fixed Hardware Specification Version 1.2.
+ * Table 2: Arm Architecture context loss flags
+ */
+#define CPUIDLE_CORE_CTXT              BIT(0) /* Core context Lost */
+
+static inline unsigned int arch_get_idle_state_flags(u32 arch_flags)
+{
+       if (arch_flags & CPUIDLE_CORE_CTXT)
+               return CPUIDLE_FLAG_TIMER_STOP;
+
+       return 0;
+}
+#define arch_get_idle_state_flags arch_get_idle_state_flags
+
+#define CPUIDLE_TRACE_CTXT             BIT(1) /* Trace context loss */
+#define CPUIDLE_GICR_CTXT              BIT(2) /* GICR */
+#define CPUIDLE_GICD_CTXT              BIT(3) /* GICD */
 
 /* Basic configuration for ACPI */
 #ifdef CONFIG_ACPI
index 5f6f848..74d00fe 100644 (file)
@@ -79,6 +79,7 @@
 #define ARM_CPU_PART_CORTEX_A78AE      0xD42
 #define ARM_CPU_PART_CORTEX_X1         0xD44
 #define ARM_CPU_PART_CORTEX_A510       0xD46
+#define ARM_CPU_PART_CORTEX_A520       0xD80
 #define ARM_CPU_PART_CORTEX_A710       0xD47
 #define ARM_CPU_PART_CORTEX_A715       0xD4D
 #define ARM_CPU_PART_CORTEX_X2         0xD48
 #define MIDR_CORTEX_A78AE      MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78AE)
 #define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1)
 #define MIDR_CORTEX_A510 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A510)
+#define MIDR_CORTEX_A520 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A520)
 #define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710)
 #define MIDR_CORTEX_A715 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A715)
 #define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2)
index be66e94..5706e74 100644 (file)
@@ -730,6 +730,14 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
                .cpu_enable = cpu_clear_bf16_from_user_emulation,
        },
 #endif
+#ifdef CONFIG_ARM64_ERRATUM_2966298
+       {
+               .desc = "ARM erratum 2966298",
+               .capability = ARM64_WORKAROUND_2966298,
+               /* Cortex-A520 r0p0 - r0p1 */
+               ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A520, 0, 0, 1),
+       },
+#endif
 #ifdef CONFIG_AMPERE_ERRATUM_AC03_CPU_38
        {
                .desc = "AmpereOne erratum AC03_CPU_38",
index 6ad61de..a603091 100644 (file)
@@ -428,6 +428,10 @@ alternative_else_nop_endif
        ldp     x28, x29, [sp, #16 * 14]
 
        .if     \el == 0
+alternative_if ARM64_WORKAROUND_2966298
+       tlbi    vale1, xzr
+       dsb     nsh
+alternative_else_nop_endif
 alternative_if_not ARM64_UNMAP_KERNEL_AT_EL0
        ldr     lr, [sp, #S_LR]
        add     sp, sp, #PT_REGS_SIZE           // restore sp
index c3f06fd..dea3dc8 100644 (file)
@@ -84,6 +84,7 @@ WORKAROUND_2077057
 WORKAROUND_2457168
 WORKAROUND_2645198
 WORKAROUND_2658417
+WORKAROUND_2966298
 WORKAROUND_AMPERE_AC03_CPU_38
 WORKAROUND_TRBE_OVERWRITE_FILL_MODE
 WORKAROUND_TSB_FLUSH_FAILURE
index 6d28b55..ee9e071 100644 (file)
@@ -2,39 +2,42 @@
 #ifndef __PARISC_LDCW_H
 #define __PARISC_LDCW_H
 
-#ifndef CONFIG_PA20
 /* Because kmalloc only guarantees 8-byte alignment for kmalloc'd data,
    and GCC only guarantees 8-byte alignment for stack locals, we can't
    be assured of 16-byte alignment for atomic lock data even if we
    specify "__attribute ((aligned(16)))" in the type declaration.  So,
    we use a struct containing an array of four ints for the atomic lock
    type and dynamically select the 16-byte aligned int from the array
-   for the semaphore.  */
+   for the semaphore. */
+
+/* From: "Jim Hull" <jim.hull of hp.com>
+   I've attached a summary of the change, but basically, for PA 2.0, as
+   long as the ",CO" (coherent operation) completer is implemented, then the
+   16-byte alignment requirement for ldcw and ldcd is relaxed, and instead
+   they only require "natural" alignment (4-byte for ldcw, 8-byte for
+   ldcd).
+
+   Although the cache control hint is accepted by all PA 2.0 processors,
+   it is only implemented on PA8800/PA8900 CPUs. Prior PA8X00 CPUs still
+   require 16-byte alignment. If the address is unaligned, the operation
+   of the instruction is undefined. The ldcw instruction does not generate
+   unaligned data reference traps so misaligned accesses are not detected.
+   This hid the problem for years. So, restore the 16-byte alignment dropped
+   by Kyle McMartin in "Remove __ldcw_align for PA-RISC 2.0 processors". */
 
 #define __PA_LDCW_ALIGNMENT    16
-#define __PA_LDCW_ALIGN_ORDER  4
 #define __ldcw_align(a) ({                                     \
        unsigned long __ret = (unsigned long) &(a)->lock[0];    \
        __ret = (__ret + __PA_LDCW_ALIGNMENT - 1)               \
                & ~(__PA_LDCW_ALIGNMENT - 1);                   \
        (volatile unsigned int *) __ret;                        \
 })
-#define __LDCW "ldcw"
 
-#else /*CONFIG_PA20*/
-/* From: "Jim Hull" <jim.hull of hp.com>
-   I've attached a summary of the change, but basically, for PA 2.0, as
-   long as the ",CO" (coherent operation) completer is specified, then the
-   16-byte alignment requirement for ldcw and ldcd is relaxed, and instead
-   they only require "natural" alignment (4-byte for ldcw, 8-byte for
-   ldcd). */
-
-#define __PA_LDCW_ALIGNMENT    4
-#define __PA_LDCW_ALIGN_ORDER  2
-#define __ldcw_align(a) (&(a)->slock)
+#ifdef CONFIG_PA20
 #define __LDCW "ldcw,co"
-
-#endif /*!CONFIG_PA20*/
+#else
+#define __LDCW "ldcw"
+#endif
 
 /* LDCW, the only atomic read-write operation PA-RISC has. *sigh*.
    We don't explicitly expose that "*a" may be written as reload
index efd06a8..7b986b0 100644 (file)
@@ -9,15 +9,10 @@
 #ifndef __ASSEMBLY__
 
 typedef struct {
-#ifdef CONFIG_PA20
-       volatile unsigned int slock;
-# define __ARCH_SPIN_LOCK_UNLOCKED { __ARCH_SPIN_LOCK_UNLOCKED_VAL }
-#else
        volatile unsigned int lock[4];
 # define __ARCH_SPIN_LOCK_UNLOCKED     \
        { { __ARCH_SPIN_LOCK_UNLOCKED_VAL, __ARCH_SPIN_LOCK_UNLOCKED_VAL, \
            __ARCH_SPIN_LOCK_UNLOCKED_VAL, __ARCH_SPIN_LOCK_UNLOCKED_VAL } }
-#endif
 } arch_spinlock_t;
 
 
index 4098f9a..2019c1f 100644 (file)
@@ -440,7 +440,9 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
        if (cpu_online(cpu))
                return 0;
 
-       if (num_online_cpus() < setup_max_cpus && smp_boot_one_cpu(cpu, tidle))
+       if (num_online_cpus() < nr_cpu_ids &&
+               num_online_cpus() < setup_max_cpus &&
+               smp_boot_one_cpu(cpu, tidle))
                return -EIO;
 
        return cpu_online(cpu) ? 0 : -EIO;
index de2fb12..2861e33 100644 (file)
@@ -2513,7 +2513,7 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image,
                        return -E2BIG;
        }
 
-       return ret;
+       return tjit.common.prg;
 }
 
 bool bpf_jit_supports_subprog_tailcalls(void)
index 2eabccd..dcf325b 100644 (file)
@@ -256,7 +256,7 @@ static int __sev_cpuid_hv(u32 fn, int reg_idx, u32 *reg)
        return 0;
 }
 
-static int sev_cpuid_hv(struct cpuid_leaf *leaf)
+static int __sev_cpuid_hv_msr(struct cpuid_leaf *leaf)
 {
        int ret;
 
@@ -279,6 +279,45 @@ static int sev_cpuid_hv(struct cpuid_leaf *leaf)
        return ret;
 }
 
+static int __sev_cpuid_hv_ghcb(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf)
+{
+       u32 cr4 = native_read_cr4();
+       int ret;
+
+       ghcb_set_rax(ghcb, leaf->fn);
+       ghcb_set_rcx(ghcb, leaf->subfn);
+
+       if (cr4 & X86_CR4_OSXSAVE)
+               /* Safe to read xcr0 */
+               ghcb_set_xcr0(ghcb, xgetbv(XCR_XFEATURE_ENABLED_MASK));
+       else
+               /* xgetbv will cause #UD - use reset value for xcr0 */
+               ghcb_set_xcr0(ghcb, 1);
+
+       ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_CPUID, 0, 0);
+       if (ret != ES_OK)
+               return ret;
+
+       if (!(ghcb_rax_is_valid(ghcb) &&
+             ghcb_rbx_is_valid(ghcb) &&
+             ghcb_rcx_is_valid(ghcb) &&
+             ghcb_rdx_is_valid(ghcb)))
+               return ES_VMM_ERROR;
+
+       leaf->eax = ghcb->save.rax;
+       leaf->ebx = ghcb->save.rbx;
+       leaf->ecx = ghcb->save.rcx;
+       leaf->edx = ghcb->save.rdx;
+
+       return ES_OK;
+}
+
+static int sev_cpuid_hv(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf)
+{
+       return ghcb ? __sev_cpuid_hv_ghcb(ghcb, ctxt, leaf)
+                   : __sev_cpuid_hv_msr(leaf);
+}
+
 /*
  * This may be called early while still running on the initial identity
  * mapping. Use RIP-relative addressing to obtain the correct address
@@ -388,19 +427,20 @@ snp_cpuid_get_validated_func(struct cpuid_leaf *leaf)
        return false;
 }
 
-static void snp_cpuid_hv(struct cpuid_leaf *leaf)
+static void snp_cpuid_hv(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf)
 {
-       if (sev_cpuid_hv(leaf))
+       if (sev_cpuid_hv(ghcb, ctxt, leaf))
                sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_CPUID_HV);
 }
 
-static int snp_cpuid_postprocess(struct cpuid_leaf *leaf)
+static int snp_cpuid_postprocess(struct ghcb *ghcb, struct es_em_ctxt *ctxt,
+                                struct cpuid_leaf *leaf)
 {
        struct cpuid_leaf leaf_hv = *leaf;
 
        switch (leaf->fn) {
        case 0x1:
-               snp_cpuid_hv(&leaf_hv);
+               snp_cpuid_hv(ghcb, ctxt, &leaf_hv);
 
                /* initial APIC ID */
                leaf->ebx = (leaf_hv.ebx & GENMASK(31, 24)) | (leaf->ebx & GENMASK(23, 0));
@@ -419,7 +459,7 @@ static int snp_cpuid_postprocess(struct cpuid_leaf *leaf)
                break;
        case 0xB:
                leaf_hv.subfn = 0;
-               snp_cpuid_hv(&leaf_hv);
+               snp_cpuid_hv(ghcb, ctxt, &leaf_hv);
 
                /* extended APIC ID */
                leaf->edx = leaf_hv.edx;
@@ -467,7 +507,7 @@ static int snp_cpuid_postprocess(struct cpuid_leaf *leaf)
                }
                break;
        case 0x8000001E:
-               snp_cpuid_hv(&leaf_hv);
+               snp_cpuid_hv(ghcb, ctxt, &leaf_hv);
 
                /* extended APIC ID */
                leaf->eax = leaf_hv.eax;
@@ -488,7 +528,7 @@ static int snp_cpuid_postprocess(struct cpuid_leaf *leaf)
  * Returns -EOPNOTSUPP if feature not enabled. Any other non-zero return value
  * should be treated as fatal by caller.
  */
-static int snp_cpuid(struct cpuid_leaf *leaf)
+static int snp_cpuid(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf)
 {
        const struct snp_cpuid_table *cpuid_table = snp_cpuid_get_table();
 
@@ -522,7 +562,7 @@ static int snp_cpuid(struct cpuid_leaf *leaf)
                        return 0;
        }
 
-       return snp_cpuid_postprocess(leaf);
+       return snp_cpuid_postprocess(ghcb, ctxt, leaf);
 }
 
 /*
@@ -544,14 +584,14 @@ void __init do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code)
        leaf.fn = fn;
        leaf.subfn = subfn;
 
-       ret = snp_cpuid(&leaf);
+       ret = snp_cpuid(NULL, NULL, &leaf);
        if (!ret)
                goto cpuid_done;
 
        if (ret != -EOPNOTSUPP)
                goto fail;
 
-       if (sev_cpuid_hv(&leaf))
+       if (__sev_cpuid_hv_msr(&leaf))
                goto fail;
 
 cpuid_done:
@@ -848,14 +888,15 @@ static enum es_result vc_handle_ioio(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
        return ret;
 }
 
-static int vc_handle_cpuid_snp(struct pt_regs *regs)
+static int vc_handle_cpuid_snp(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
 {
+       struct pt_regs *regs = ctxt->regs;
        struct cpuid_leaf leaf;
        int ret;
 
        leaf.fn = regs->ax;
        leaf.subfn = regs->cx;
-       ret = snp_cpuid(&leaf);
+       ret = snp_cpuid(ghcb, ctxt, &leaf);
        if (!ret) {
                regs->ax = leaf.eax;
                regs->bx = leaf.ebx;
@@ -874,7 +915,7 @@ static enum es_result vc_handle_cpuid(struct ghcb *ghcb,
        enum es_result ret;
        int snp_cpuid_ret;
 
-       snp_cpuid_ret = vc_handle_cpuid_snp(regs);
+       snp_cpuid_ret = vc_handle_cpuid_snp(ghcb, ctxt);
        if (!snp_cpuid_ret)
                return ES_OK;
        if (snp_cpuid_ret != -EOPNOTSUPP)
index 2787826..d8c1e3b 100644 (file)
@@ -868,8 +868,7 @@ void snp_set_memory_private(unsigned long vaddr, unsigned long npages)
 
 void snp_accept_memory(phys_addr_t start, phys_addr_t end)
 {
-       unsigned long vaddr;
-       unsigned int npages;
+       unsigned long vaddr, npages;
 
        if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
                return;
index f0e6738..f96bf32 100644 (file)
@@ -855,7 +855,7 @@ static size_t sizeof_idt(struct acpi_nfit_interleave *idt)
 {
        if (idt->header.length < sizeof(*idt))
                return 0;
-       return sizeof(*idt) + sizeof(u32) * (idt->line_count - 1);
+       return sizeof(*idt) + sizeof(u32) * idt->line_count;
 }
 
 static bool add_idt(struct acpi_nfit_desc *acpi_desc,
index dc615ef..3a34a8c 100644 (file)
@@ -1217,8 +1217,7 @@ static int acpi_processor_setup_lpi_states(struct acpi_processor *pr)
                strscpy(state->desc, lpi->desc, CPUIDLE_DESC_LEN);
                state->exit_latency = lpi->wake_latency;
                state->target_residency = lpi->min_residency;
-               if (lpi->arch_flags)
-                       state->flags |= CPUIDLE_FLAG_TIMER_STOP;
+               state->flags |= arch_get_idle_state_flags(lpi->arch_flags);
                if (i != 0 && lpi->entry_method == ACPI_CSTATE_FFH)
                        state->flags |= CPUIDLE_FLAG_RCU_IDLE;
                state->enter = acpi_idle_lpi_enter;
index db716ff..3db88bb 100644 (file)
@@ -453,7 +453,8 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
                if (!rbnode)
                        return -ENOMEM;
                regcache_rbtree_set_register(map, rbnode,
-                                            reg - rbnode->base_reg, value);
+                                            (reg - rbnode->base_reg) / map->reg_stride,
+                                            value);
                regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode);
                rbtree_ctx->cached_rbnode = rbnode;
        }
index df1cd0f..800f131 100644 (file)
@@ -1436,8 +1436,9 @@ static int nbd_start_device_ioctl(struct nbd_device *nbd)
 
 static void nbd_clear_sock_ioctl(struct nbd_device *nbd)
 {
-       blk_mark_disk_dead(nbd->disk);
        nbd_clear_sock(nbd);
+       disk_force_media_change(nbd->disk);
+       nbd_bdev_reset(nbd);
        if (test_and_clear_bit(NBD_RT_HAS_CONFIG_REF,
                               &nbd->config->runtime_flags))
                nbd_config_put(nbd);
index 82597ab..499f480 100644 (file)
@@ -4419,6 +4419,7 @@ static int btusb_probe(struct usb_interface *intf,
 
        if (id->driver_info & BTUSB_QCA_ROME) {
                data->setup_on_usb = btusb_setup_qca;
+               hdev->shutdown = btusb_shutdown_qca;
                hdev->set_bdaddr = btusb_set_bdaddr_ath3012;
                hdev->cmd_timeout = btusb_qca_cmd_timeout;
                set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
index 789193e..c278d5f 100644 (file)
@@ -558,6 +558,9 @@ int k3_udma_glue_tx_get_irq(struct k3_udma_glue_tx_channel *tx_chn)
                tx_chn->virq = k3_ringacc_get_ring_irq_num(tx_chn->ringtxcq);
        }
 
+       if (!tx_chn->virq)
+               return -ENXIO;
+
        return tx_chn->virq;
 }
 EXPORT_SYMBOL_GPL(k3_udma_glue_tx_get_irq);
index da33bbb..58f1071 100644 (file)
@@ -973,7 +973,7 @@ static int aspeed_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
        else if (param == PIN_CONFIG_BIAS_DISABLE ||
                        param == PIN_CONFIG_BIAS_PULL_DOWN ||
                        param == PIN_CONFIG_DRIVE_STRENGTH)
-               return pinctrl_gpio_set_config(offset, config);
+               return pinctrl_gpio_set_config(chip->base + offset, config);
        else if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN ||
                        param == PIN_CONFIG_DRIVE_OPEN_SOURCE)
                /* Return -ENOTSUPP to trigger emulation, as per datasheet */
index 7e9f7a3..cae9661 100644 (file)
@@ -237,6 +237,7 @@ static bool pxa_gpio_has_pinctrl(void)
        switch (gpio_type) {
        case PXA3XX_GPIO:
        case MMP2_GPIO:
+       case MMP_GPIO:
                return false;
 
        default:
index 30c4f5c..2b83566 100644 (file)
@@ -2093,7 +2093,7 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
                adev->flags |= AMD_IS_PX;
 
        if (!(adev->flags & AMD_IS_APU)) {
-               parent = pci_upstream_bridge(adev->pdev);
+               parent = pcie_find_root_port(adev->pdev);
                adev->has_pr3 = parent ? pci_pr3_present(parent) : false;
        }
 
index 9c66d98..7cd0dfa 100644 (file)
@@ -170,6 +170,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
                csum += pia[size - 1];
        if (csum) {
                DRM_ERROR("Bad Product Info Area checksum: 0x%02x", csum);
+               kfree(pia);
                return -EIO;
        }
 
index c435f76..5ee8796 100644 (file)
@@ -157,7 +157,7 @@ void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr, struct
                        int32_t N;
                        int32_t j;
 
-                       if (!pipe_ctx->stream)
+                       if (!resource_is_pipe_type(pipe_ctx, OTG_MASTER))
                                continue;
                        /* Virtual encoders don't have this function */
                        if (!stream_enc->funcs->get_fifo_cal_average_level)
@@ -188,7 +188,7 @@ void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr, struct
                        int32_t N;
                        int32_t j;
 
-                       if (!pipe_ctx->stream)
+                       if (!resource_is_pipe_type(pipe_ctx, OTG_MASTER))
                                continue;
                        /* Virtual encoders don't have this function */
                        if (!stream_enc->funcs->get_fifo_cal_average_level)
index 984b529..e9345f6 100644 (file)
@@ -355,7 +355,7 @@ static void dcn32_update_clocks_update_dentist(
                        int32_t N;
                        int32_t j;
 
-                       if (!pipe_ctx->stream)
+                       if (!resource_is_pipe_type(pipe_ctx, OTG_MASTER))
                                continue;
                        /* Virtual encoders don't have this function */
                        if (!stream_enc->funcs->get_fifo_cal_average_level)
@@ -401,7 +401,7 @@ static void dcn32_update_clocks_update_dentist(
                        int32_t N;
                        int32_t j;
 
-                       if (!pipe_ctx->stream)
+                       if (!resource_is_pipe_type(pipe_ctx, OTG_MASTER))
                                continue;
                        /* Virtual encoders don't have this function */
                        if (!stream_enc->funcs->get_fifo_cal_average_level)
index 41147da..8bb2da1 100644 (file)
@@ -2040,6 +2040,7 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_
                case IP_VERSION(11, 0, 0):
                case IP_VERSION(11, 0, 1):
                case IP_VERSION(11, 0, 2):
+               case IP_VERSION(11, 0, 3):
                        *states = ATTR_STATE_SUPPORTED;
                        break;
                default:
index 4bb289f..da2860d 100644 (file)
@@ -2082,36 +2082,41 @@ static int sienna_cichlid_display_disable_memory_clock_switch(struct smu_context
        return ret;
 }
 
+#define MAX(a, b)      ((a) > (b) ? (a) : (b))
+
 static int sienna_cichlid_update_pcie_parameters(struct smu_context *smu,
                                         uint32_t pcie_gen_cap,
                                         uint32_t pcie_width_cap)
 {
        struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
        struct smu_11_0_pcie_table *pcie_table = &dpm_context->dpm_tables.pcie_table;
-       u32 smu_pcie_arg;
+       uint8_t *table_member1, *table_member2;
+       uint32_t min_gen_speed, max_gen_speed;
+       uint32_t min_lane_width, max_lane_width;
+       uint32_t smu_pcie_arg;
        int ret, i;
 
-       /* PCIE gen speed and lane width override */
-       if (!amdgpu_device_pcie_dynamic_switching_supported()) {
-               if (pcie_table->pcie_gen[NUM_LINK_LEVELS - 1] < pcie_gen_cap)
-                       pcie_gen_cap = pcie_table->pcie_gen[NUM_LINK_LEVELS - 1];
+       GET_PPTABLE_MEMBER(PcieGenSpeed, &table_member1);
+       GET_PPTABLE_MEMBER(PcieLaneCount, &table_member2);
 
-               if (pcie_table->pcie_lane[NUM_LINK_LEVELS - 1] < pcie_width_cap)
-                       pcie_width_cap = pcie_table->pcie_lane[NUM_LINK_LEVELS - 1];
+       min_gen_speed = MAX(0, table_member1[0]);
+       max_gen_speed = MIN(pcie_gen_cap, table_member1[1]);
+       min_gen_speed = min_gen_speed > max_gen_speed ?
+                       max_gen_speed : min_gen_speed;
+       min_lane_width = MAX(1, table_member2[0]);
+       max_lane_width = MIN(pcie_width_cap, table_member2[1]);
+       min_lane_width = min_lane_width > max_lane_width ?
+                        max_lane_width : min_lane_width;
 
-               /* Force all levels to use the same settings */
-               for (i = 0; i < NUM_LINK_LEVELS; i++) {
-                       pcie_table->pcie_gen[i] = pcie_gen_cap;
-                       pcie_table->pcie_lane[i] = pcie_width_cap;
-               }
+       if (!amdgpu_device_pcie_dynamic_switching_supported()) {
+               pcie_table->pcie_gen[0] = max_gen_speed;
+               pcie_table->pcie_lane[0] = max_lane_width;
        } else {
-               for (i = 0; i < NUM_LINK_LEVELS; i++) {
-                       if (pcie_table->pcie_gen[i] > pcie_gen_cap)
-                               pcie_table->pcie_gen[i] = pcie_gen_cap;
-                       if (pcie_table->pcie_lane[i] > pcie_width_cap)
-                               pcie_table->pcie_lane[i] = pcie_width_cap;
-               }
+               pcie_table->pcie_gen[0] = min_gen_speed;
+               pcie_table->pcie_lane[0] = min_lane_width;
        }
+       pcie_table->pcie_gen[1] = max_gen_speed;
+       pcie_table->pcie_lane[1] = max_lane_width;
 
        for (i = 0; i < NUM_LINK_LEVELS; i++) {
                smu_pcie_arg = (i << 16 |
index 0cb646c..d5c1529 100644 (file)
@@ -38,6 +38,14 @@ static const struct drm_dmi_panel_orientation_data gpd_micropc = {
        .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
 };
 
+static const struct drm_dmi_panel_orientation_data gpd_onemix2s = {
+       .width = 1200,
+       .height = 1920,
+       .bios_dates = (const char * const []){ "05/21/2018", "10/26/2018",
+               "03/04/2019", NULL },
+       .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
+};
+
 static const struct drm_dmi_panel_orientation_data gpd_pocket = {
        .width = 1200,
        .height = 1920,
@@ -401,6 +409,14 @@ static const struct dmi_system_id orientation_data[] = {
                  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LTH17"),
                },
                .driver_data = (void *)&lcd800x1280_rightside_up,
+       }, {    /* One Mix 2S (generic strings, also match on bios date) */
+               .matches = {
+                 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Default string"),
+                 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
+                 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"),
+                 DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
+               },
+               .driver_data = (void *)&gpd_onemix2s,
        },
        {}
 };
index 6b6d22c..0ba9556 100644 (file)
@@ -198,7 +198,7 @@ static void flush_tlb_invalidate(struct drm_i915_gem_object *obj)
 
        for_each_gt(gt, i915, id) {
                if (!obj->mm.tlb[id])
-                       return;
+                       continue;
 
                intel_gt_invalidate_tlb_full(gt, obj->mm.tlb[id]);
                obj->mm.tlb[id] = 0;
index a4ff55a..7ad3619 100644 (file)
@@ -271,8 +271,17 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode)
                if (GRAPHICS_VER_FULL(rq->i915) >= IP_VER(12, 70))
                        bit_group_0 |= PIPE_CONTROL_CCS_FLUSH;
 
+               /*
+                * L3 fabric flush is needed for AUX CCS invalidation
+                * which happens as part of pipe-control so we can
+                * ignore PIPE_CONTROL_FLUSH_L3. Also PIPE_CONTROL_FLUSH_L3
+                * deals with Protected Memory which is not needed for
+                * AUX CCS invalidation and lead to unwanted side effects.
+                */
+               if (mode & EMIT_FLUSH)
+                       bit_group_1 |= PIPE_CONTROL_FLUSH_L3;
+
                bit_group_1 |= PIPE_CONTROL_TILE_CACHE_FLUSH;
-               bit_group_1 |= PIPE_CONTROL_FLUSH_L3;
                bit_group_1 |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
                bit_group_1 |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
                /* Wa_1409600907:tgl,adl-p */
index 1f65bb3..a8551ce 100644 (file)
@@ -1199,6 +1199,13 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
                        goto err_unlock;
        }
 
+       /*
+        * Register engines early to ensure the engine list is in its final
+        * rb-tree form, lowering the amount of code that has to deal with
+        * the intermediate llist state.
+        */
+       intel_engines_driver_register(dev_priv);
+
        return 0;
 
        /*
@@ -1246,8 +1253,6 @@ err_unlock:
 void i915_gem_driver_register(struct drm_i915_private *i915)
 {
        i915_gem_driver_register__shrinker(i915);
-
-       intel_engines_driver_register(i915);
 }
 
 void i915_gem_driver_unregister(struct drm_i915_private *i915)
index 30afbec..2edd7bb 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "nouveau_drv.h"
 #include "nouveau_dma.h"
+#include "nouveau_exec.h"
 #include "nouveau_gem.h"
 #include "nouveau_chan.h"
 #include "nouveau_abi16.h"
@@ -183,6 +184,20 @@ nouveau_abi16_fini(struct nouveau_abi16 *abi16)
        cli->abi16 = NULL;
 }
 
+static inline int
+getparam_dma_ib_max(struct nvif_device *device)
+{
+       const struct nvif_mclass dmas[] = {
+               { NV03_CHANNEL_DMA, 0 },
+               { NV10_CHANNEL_DMA, 0 },
+               { NV17_CHANNEL_DMA, 0 },
+               { NV40_CHANNEL_DMA, 0 },
+               {}
+       };
+
+       return nvif_mclass(&device->object, dmas) < 0 ? NV50_DMA_IB_MAX : 0;
+}
+
 int
 nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS)
 {
@@ -247,6 +262,12 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS)
        case NOUVEAU_GETPARAM_GRAPH_UNITS:
                getparam->value = nvkm_gr_units(gr);
                break;
+       case NOUVEAU_GETPARAM_EXEC_PUSH_MAX: {
+               int ib_max = getparam_dma_ib_max(device);
+
+               getparam->value = nouveau_exec_push_max_from_ib_max(ib_max);
+               break;
+       }
        default:
                NV_PRINTK(dbg, cli, "unknown parameter %lld\n", getparam->param);
                return -EINVAL;
index bb3d6e5..7c97b28 100644 (file)
@@ -257,10 +257,7 @@ static int
 nouveau_channel_ctor(struct nouveau_drm *drm, struct nvif_device *device, bool priv, u64 runm,
                     struct nouveau_channel **pchan)
 {
-       static const struct {
-               s32 oclass;
-               int version;
-       } hosts[] = {
+       const struct nvif_mclass hosts[] = {
                {  AMPERE_CHANNEL_GPFIFO_B, 0 },
                {  AMPERE_CHANNEL_GPFIFO_A, 0 },
                {  TURING_CHANNEL_GPFIFO_A, 0 },
@@ -443,9 +440,11 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
        }
 
        /* initialise dma tracking parameters */
-       switch (chan->user.oclass & 0x00ff) {
-       case 0x006b:
-       case 0x006e:
+       switch (chan->user.oclass) {
+       case NV03_CHANNEL_DMA:
+       case NV10_CHANNEL_DMA:
+       case NV17_CHANNEL_DMA:
+       case NV40_CHANNEL_DMA:
                chan->user_put = 0x40;
                chan->user_get = 0x44;
                chan->dma.max = (0x10000 / 4) - 2;
@@ -455,7 +454,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
                chan->user_get = 0x44;
                chan->user_get_hi = 0x60;
                chan->dma.ib_base =  0x10000 / 4;
-               chan->dma.ib_max  = (0x02000 / 8) - 1;
+               chan->dma.ib_max  = NV50_DMA_IB_MAX;
                chan->dma.ib_put  = 0;
                chan->dma.ib_free = chan->dma.ib_max - chan->dma.ib_put;
                chan->dma.max = chan->dma.ib_base;
index 1744d95..c52cda8 100644 (file)
@@ -49,6 +49,9 @@ void nv50_dma_push(struct nouveau_channel *, u64 addr, u32 length,
 /* Maximum push buffer size. */
 #define NV50_DMA_PUSH_MAX_LENGTH 0x7fffff
 
+/* Maximum IBs per ring. */
+#define NV50_DMA_IB_MAX ((0x02000 / 8) - 1)
+
 /* Object handles - for stuff that's doesn't use handle == oclass. */
 enum {
        NvDmaFB         = 0x80000002,
index 5dda94e..c1837ba 100644 (file)
@@ -379,7 +379,7 @@ nouveau_exec_ioctl_exec(struct drm_device *dev,
        struct nouveau_channel *chan = NULL;
        struct nouveau_exec_job_args args = {};
        struct drm_nouveau_exec *req = data;
-       int ret = 0;
+       int push_max, ret = 0;
 
        if (unlikely(!abi16))
                return -ENOMEM;
@@ -404,9 +404,10 @@ nouveau_exec_ioctl_exec(struct drm_device *dev,
        if (!chan->dma.ib_max)
                return nouveau_abi16_put(abi16, -ENOSYS);
 
-       if (unlikely(req->push_count > NOUVEAU_GEM_MAX_PUSH)) {
+       push_max = nouveau_exec_push_max_from_ib_max(chan->dma.ib_max);
+       if (unlikely(req->push_count > push_max)) {
                NV_PRINTK(err, cli, "pushbuf push count exceeds limit: %d max %d\n",
-                        req->push_count, NOUVEAU_GEM_MAX_PUSH);
+                         req->push_count, push_max);
                return nouveau_abi16_put(abi16, -EINVAL);
        }
 
index 778cacd..5488d33 100644 (file)
@@ -51,4 +51,14 @@ int nouveau_exec_job_init(struct nouveau_exec_job **job,
 int nouveau_exec_ioctl_exec(struct drm_device *dev, void *data,
                            struct drm_file *file_priv);
 
+static inline unsigned int
+nouveau_exec_push_max_from_ib_max(int ib_max)
+{
+       /* Limit the number of IBs per job to half the size of the ring in order
+        * to avoid the ring running dry between submissions and preserve one
+        * more slot for the job's HW fence.
+        */
+       return ib_max > 1 ? ib_max / 2 - 1 : 0;
+}
+
 #endif
index c1dfbfc..bccb33b 100644 (file)
@@ -118,7 +118,7 @@ void drm_kunit_helper_free_device(struct kunit *test, struct device *dev)
 
        kunit_release_action(test,
                             kunit_action_platform_driver_unregister,
-                            pdev);
+                            &fake_platform_driver);
 }
 EXPORT_SYMBOL_GPL(drm_kunit_helper_free_device);
 
index 0cea301..790aa90 100644 (file)
@@ -799,6 +799,8 @@ config HID_NVIDIA_SHIELD
        tristate "NVIDIA SHIELD devices"
        depends on USB_HID
        depends on BT_HIDP
+       depends on LEDS_CLASS
+       select POWER_SUPPLY
        help
          Support for NVIDIA SHIELD accessories.
 
index 403506b..b346d68 100644 (file)
@@ -130,6 +130,10 @@ static int holtek_kbd_input_event(struct input_dev *dev, unsigned int type,
                return -ENODEV;
 
        boot_hid = usb_get_intfdata(boot_interface);
+       if (list_empty(&boot_hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
        boot_hid_input = list_first_entry(&boot_hid->inputs,
                struct hid_input, list);
 
index 7e49999..e4d2dfd 100644 (file)
 #define I2C_DEVICE_ID_HP_SPECTRE_X360_13T_AW100        0x29F5
 #define I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V1     0x2BED
 #define I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V2     0x2BEE
+#define I2C_DEVICE_ID_HP_ENVY_X360_15_EU0556NG         0x2D02
 
 #define USB_VENDOR_ID_ELECOM           0x056e
 #define USB_DEVICE_ID_ELECOM_BM084     0x0061
index 0235cc1..c8b20d4 100644 (file)
@@ -409,6 +409,8 @@ static const struct hid_device_id hid_battery_quirks[] = {
          HID_BATTERY_QUIRK_IGNORE },
        { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V2),
          HID_BATTERY_QUIRK_IGNORE },
+       { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_15_EU0556NG),
+         HID_BATTERY_QUIRK_IGNORE },
        {}
 };
 
index 05f5b5f..ff077df 100644 (file)
@@ -4677,6 +4677,8 @@ static const struct hid_device_id hidpp_devices[] = {
          HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb008) },
        { /* MX Master mouse over Bluetooth */
          HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb012) },
+       { /* M720 Triathlon mouse over Bluetooth */
+         HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb015) },
        { /* MX Ergo trackball over Bluetooth */
          HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb01d) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb01e) },
index 521b2ff..8db4ae0 100644 (file)
@@ -2146,6 +2146,10 @@ static const struct hid_device_id mt_devices[] = {
        /* Synaptics devices */
        { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
                HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
+                       USB_VENDOR_ID_SYNAPTICS, 0xcd7e) },
+
+       { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
+               HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
                        USB_VENDOR_ID_SYNAPTICS, 0xce08) },
 
        { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
index 250f5d2..10468f7 100644 (file)
@@ -2088,7 +2088,9 @@ static int joycon_read_info(struct joycon_ctlr *ctlr)
        struct joycon_input_report *report;
 
        req.subcmd_id = JC_SUBCMD_REQ_DEV_INFO;
+       mutex_lock(&ctlr->output_mutex);
        ret = joycon_send_subcmd(ctlr, &req, 0, HZ);
+       mutex_unlock(&ctlr->output_mutex);
        if (ret) {
                hid_err(ctlr->hdev, "Failed to get joycon info; ret=%d\n", ret);
                return ret;
@@ -2117,6 +2119,85 @@ static int joycon_read_info(struct joycon_ctlr *ctlr)
        return 0;
 }
 
+static int joycon_init(struct hid_device *hdev)
+{
+       struct joycon_ctlr *ctlr = hid_get_drvdata(hdev);
+       int ret = 0;
+
+       mutex_lock(&ctlr->output_mutex);
+       /* if handshake command fails, assume ble pro controller */
+       if ((jc_type_is_procon(ctlr) || jc_type_is_chrggrip(ctlr)) &&
+           !joycon_send_usb(ctlr, JC_USB_CMD_HANDSHAKE, HZ)) {
+               hid_dbg(hdev, "detected USB controller\n");
+               /* set baudrate for improved latency */
+               ret = joycon_send_usb(ctlr, JC_USB_CMD_BAUDRATE_3M, HZ);
+               if (ret) {
+                       hid_err(hdev, "Failed to set baudrate; ret=%d\n", ret);
+                       goto out_unlock;
+               }
+               /* handshake */
+               ret = joycon_send_usb(ctlr, JC_USB_CMD_HANDSHAKE, HZ);
+               if (ret) {
+                       hid_err(hdev, "Failed handshake; ret=%d\n", ret);
+                       goto out_unlock;
+               }
+               /*
+                * Set no timeout (to keep controller in USB mode).
+                * This doesn't send a response, so ignore the timeout.
+                */
+               joycon_send_usb(ctlr, JC_USB_CMD_NO_TIMEOUT, HZ/10);
+       } else if (jc_type_is_chrggrip(ctlr)) {
+               hid_err(hdev, "Failed charging grip handshake\n");
+               ret = -ETIMEDOUT;
+               goto out_unlock;
+       }
+
+       /* get controller calibration data, and parse it */
+       ret = joycon_request_calibration(ctlr);
+       if (ret) {
+               /*
+                * We can function with default calibration, but it may be
+                * inaccurate. Provide a warning, and continue on.
+                */
+               hid_warn(hdev, "Analog stick positions may be inaccurate\n");
+       }
+
+       /* get IMU calibration data, and parse it */
+       ret = joycon_request_imu_calibration(ctlr);
+       if (ret) {
+               /*
+                * We can function with default calibration, but it may be
+                * inaccurate. Provide a warning, and continue on.
+                */
+               hid_warn(hdev, "Unable to read IMU calibration data\n");
+       }
+
+       /* Set the reporting mode to 0x30, which is the full report mode */
+       ret = joycon_set_report_mode(ctlr);
+       if (ret) {
+               hid_err(hdev, "Failed to set report mode; ret=%d\n", ret);
+               goto out_unlock;
+       }
+
+       /* Enable rumble */
+       ret = joycon_enable_rumble(ctlr);
+       if (ret) {
+               hid_err(hdev, "Failed to enable rumble; ret=%d\n", ret);
+               goto out_unlock;
+       }
+
+       /* Enable the IMU */
+       ret = joycon_enable_imu(ctlr);
+       if (ret) {
+               hid_err(hdev, "Failed to enable the IMU; ret=%d\n", ret);
+               goto out_unlock;
+       }
+
+out_unlock:
+       mutex_unlock(&ctlr->output_mutex);
+       return ret;
+}
+
 /* Common handler for parsing inputs */
 static int joycon_ctlr_read_handler(struct joycon_ctlr *ctlr, u8 *data,
                                                              int size)
@@ -2248,85 +2329,19 @@ static int nintendo_hid_probe(struct hid_device *hdev,
 
        hid_device_io_start(hdev);
 
-       /* Initialize the controller */
-       mutex_lock(&ctlr->output_mutex);
-       /* if handshake command fails, assume ble pro controller */
-       if ((jc_type_is_procon(ctlr) || jc_type_is_chrggrip(ctlr)) &&
-           !joycon_send_usb(ctlr, JC_USB_CMD_HANDSHAKE, HZ)) {
-               hid_dbg(hdev, "detected USB controller\n");
-               /* set baudrate for improved latency */
-               ret = joycon_send_usb(ctlr, JC_USB_CMD_BAUDRATE_3M, HZ);
-               if (ret) {
-                       hid_err(hdev, "Failed to set baudrate; ret=%d\n", ret);
-                       goto err_mutex;
-               }
-               /* handshake */
-               ret = joycon_send_usb(ctlr, JC_USB_CMD_HANDSHAKE, HZ);
-               if (ret) {
-                       hid_err(hdev, "Failed handshake; ret=%d\n", ret);
-                       goto err_mutex;
-               }
-               /*
-                * Set no timeout (to keep controller in USB mode).
-                * This doesn't send a response, so ignore the timeout.
-                */
-               joycon_send_usb(ctlr, JC_USB_CMD_NO_TIMEOUT, HZ/10);
-       } else if (jc_type_is_chrggrip(ctlr)) {
-               hid_err(hdev, "Failed charging grip handshake\n");
-               ret = -ETIMEDOUT;
-               goto err_mutex;
-       }
-
-       /* get controller calibration data, and parse it */
-       ret = joycon_request_calibration(ctlr);
+       ret = joycon_init(hdev);
        if (ret) {
-               /*
-                * We can function with default calibration, but it may be
-                * inaccurate. Provide a warning, and continue on.
-                */
-               hid_warn(hdev, "Analog stick positions may be inaccurate\n");
-       }
-
-       /* get IMU calibration data, and parse it */
-       ret = joycon_request_imu_calibration(ctlr);
-       if (ret) {
-               /*
-                * We can function with default calibration, but it may be
-                * inaccurate. Provide a warning, and continue on.
-                */
-               hid_warn(hdev, "Unable to read IMU calibration data\n");
-       }
-
-       /* Set the reporting mode to 0x30, which is the full report mode */
-       ret = joycon_set_report_mode(ctlr);
-       if (ret) {
-               hid_err(hdev, "Failed to set report mode; ret=%d\n", ret);
-               goto err_mutex;
-       }
-
-       /* Enable rumble */
-       ret = joycon_enable_rumble(ctlr);
-       if (ret) {
-               hid_err(hdev, "Failed to enable rumble; ret=%d\n", ret);
-               goto err_mutex;
-       }
-
-       /* Enable the IMU */
-       ret = joycon_enable_imu(ctlr);
-       if (ret) {
-               hid_err(hdev, "Failed to enable the IMU; ret=%d\n", ret);
-               goto err_mutex;
+               hid_err(hdev, "Failed to initialize controller; ret=%d\n", ret);
+               goto err_close;
        }
 
        ret = joycon_read_info(ctlr);
        if (ret) {
                hid_err(hdev, "Failed to retrieve controller info; ret=%d\n",
                        ret);
-               goto err_mutex;
+               goto err_close;
        }
 
-       mutex_unlock(&ctlr->output_mutex);
-
        /* Initialize the leds */
        ret = joycon_leds_create(ctlr);
        if (ret) {
@@ -2352,8 +2367,6 @@ static int nintendo_hid_probe(struct hid_device *hdev,
        hid_dbg(hdev, "probe - success\n");
        return 0;
 
-err_mutex:
-       mutex_unlock(&ctlr->output_mutex);
 err_close:
        hid_hw_close(hdev);
 err_stop:
@@ -2383,6 +2396,20 @@ static void nintendo_hid_remove(struct hid_device *hdev)
        hid_hw_stop(hdev);
 }
 
+#ifdef CONFIG_PM
+
+static int nintendo_hid_resume(struct hid_device *hdev)
+{
+       int ret = joycon_init(hdev);
+
+       if (ret)
+               hid_err(hdev, "Failed to restore controller after resume");
+
+       return ret;
+}
+
+#endif
+
 static const struct hid_device_id nintendo_hid_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_NINTENDO,
                         USB_DEVICE_ID_NINTENDO_PROCON) },
@@ -2404,6 +2431,10 @@ static struct hid_driver nintendo_hid_driver = {
        .probe          = nintendo_hid_probe,
        .remove         = nintendo_hid_remove,
        .raw_event      = nintendo_hid_event,
+
+#ifdef CONFIG_PM
+       .resume         = nintendo_hid_resume,
+#endif
 };
 module_hid_driver(nintendo_hid_driver);
 
index 9a3576d..c463e54 100644 (file)
@@ -801,7 +801,7 @@ static inline int thunderstrike_led_create(struct thunderstrike *ts)
        led->name = devm_kasprintf(&ts->base.hdev->dev, GFP_KERNEL,
                                   "thunderstrike%d:blue:led", ts->id);
        led->max_brightness = 1;
-       led->flags = LED_CORE_SUSPENDRESUME;
+       led->flags = LED_CORE_SUSPENDRESUME | LED_RETAIN_AT_SHUTDOWN;
        led->brightness_get = &thunderstrike_led_get_brightness;
        led->brightness_set = &thunderstrike_led_set_brightness;
 
@@ -1058,7 +1058,7 @@ static int shield_probe(struct hid_device *hdev, const struct hid_device_id *id)
        ret = hid_hw_start(hdev, HID_CONNECT_HIDINPUT);
        if (ret) {
                hid_err(hdev, "Failed to start HID device\n");
-               goto err_haptics;
+               goto err_ts_create;
        }
 
        ret = hid_hw_open(hdev);
@@ -1073,9 +1073,12 @@ static int shield_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
 err_stop:
        hid_hw_stop(hdev);
-err_haptics:
+err_ts_create:
+       power_supply_unregister(ts->base.battery_dev.psy);
        if (ts->haptics_dev)
                input_unregister_device(ts->haptics_dev);
+       led_classdev_unregister(&ts->led_dev);
+       ida_free(&thunderstrike_ida, ts->id);
        return ret;
 }
 
index dd94206..ebc0aa4 100644 (file)
@@ -2155,6 +2155,8 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
        return ret;
 
 err:
+       usb_free_urb(sc->ghl_urb);
+
        hid_hw_stop(hdev);
        return ret;
 }
index 43d2cf7..b3edadf 100644 (file)
@@ -390,7 +390,7 @@ static int steelseries_headset_arctis_1_fetch_battery(struct hid_device *hdev)
        ret = hid_hw_raw_request(hdev, arctis_1_battery_request[0],
                                 write_buf, sizeof(arctis_1_battery_request),
                                 HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
-       if (ret < sizeof(arctis_1_battery_request)) {
+       if (ret < (int)sizeof(arctis_1_battery_request)) {
                hid_err(hdev, "hid_hw_raw_request() failed with %d\n", ret);
                ret = -ENODATA;
        }
index 55cb250..710fda5 100644 (file)
@@ -133,6 +133,14 @@ static int enable_gpe(struct device *dev)
        }
        wakeup = &adev->wakeup;
 
+       /*
+        * Call acpi_disable_gpe(), so that reference count
+        * gpe_event_info->runtime_count doesn't overflow.
+        * When gpe_event_info->runtime_count = 0, the call
+        * to acpi_disable_gpe() simply return.
+        */
+       acpi_disable_gpe(wakeup->gpe_device, wakeup->gpe_number);
+
        acpi_sts = acpi_enable_gpe(wakeup->gpe_device, wakeup->gpe_number);
        if (ACPI_FAILURE(acpi_sts)) {
                dev_err(dev, "enable ose_gpe failed\n");
index c343edf..1e2cd7c 100644 (file)
@@ -4968,7 +4968,7 @@ static int cma_iboe_join_multicast(struct rdma_id_private *id_priv,
        int err = 0;
        struct sockaddr *addr = (struct sockaddr *)&mc->addr;
        struct net_device *ndev = NULL;
-       struct ib_sa_multicast ib;
+       struct ib_sa_multicast ib = {};
        enum ib_gid_type gid_type;
        bool send_only;
 
index 7b68b3e..f2fb2d8 100644 (file)
@@ -217,7 +217,7 @@ static int make_cma_ports(struct cma_dev_group *cma_dev_group,
                return -ENOMEM;
 
        for (i = 0; i < ports_num; i++) {
-               char port_str[10];
+               char port_str[11];
 
                ports[i].port_num = i + 1;
                snprintf(port_str, sizeof(port_str), "%u", i + 1);
index d5d3e4f..6d1dbc9 100644 (file)
@@ -2529,6 +2529,7 @@ static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = {
        },
        [RDMA_NLDEV_CMD_SYS_SET] = {
                .doit = nldev_set_sys_set_doit,
+               .flags = RDMA_NL_ADMIN_PERM,
        },
        [RDMA_NLDEV_CMD_STAT_SET] = {
                .doit = nldev_stat_set_doit,
index bf800f8..495d5a5 100644 (file)
@@ -546,7 +546,7 @@ static ssize_t verify_hdr(struct ib_uverbs_cmd_hdr *hdr,
        if (hdr->in_words * 4 != count)
                return -EINVAL;
 
-       if (count < method_elm->req_size + sizeof(hdr)) {
+       if (count < method_elm->req_size + sizeof(*hdr)) {
                /*
                 * rdma-core v18 and v19 have a bug where they send DESTROY_CQ
                 * with a 16 byte write instead of 24. Old kernels didn't
index 0848c2c..faa88d1 100644 (file)
@@ -910,6 +910,10 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
        list_del(&qp->list);
        mutex_unlock(&rdev->qp_lock);
        atomic_dec(&rdev->stats.res.qp_count);
+       if (qp->qplib_qp.type == CMDQ_CREATE_QP_TYPE_RC)
+               atomic_dec(&rdev->stats.res.rc_qp_count);
+       else if (qp->qplib_qp.type == CMDQ_CREATE_QP_TYPE_UD)
+               atomic_dec(&rdev->stats.res.ud_qp_count);
 
        ib_umem_release(qp->rumem);
        ib_umem_release(qp->sumem);
index c8c4017..e47b4ca 100644 (file)
@@ -665,7 +665,6 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
                blocked = cookie & RCFW_CMD_IS_BLOCKING;
                cookie &= RCFW_MAX_COOKIE_VALUE;
                crsqe = &rcfw->crsqe_tbl[cookie];
-               crsqe->is_in_used = false;
 
                if (WARN_ONCE(test_bit(FIRMWARE_STALL_DETECTED,
                                       &rcfw->cmdq.flags),
@@ -681,8 +680,14 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
                        atomic_dec(&rcfw->timeout_send);
 
                if (crsqe->is_waiter_alive) {
-                       if (crsqe->resp)
+                       if (crsqe->resp) {
                                memcpy(crsqe->resp, qp_event, sizeof(*qp_event));
+                               /* Insert write memory barrier to ensure that
+                                * response data is copied before clearing the
+                                * flags
+                                */
+                               smp_wmb();
+                       }
                        if (!blocked)
                                wait_cmds++;
                }
@@ -694,6 +699,8 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
                if (!is_waiter_alive)
                        crsqe->resp = NULL;
 
+               crsqe->is_in_used = false;
+
                hwq->cons += req_size;
 
                /* This is a case to handle below scenario -
index ced615b..040ba22 100644 (file)
@@ -1965,6 +1965,9 @@ static int send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid)
        int win;
 
        skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
+       if (!skb)
+               return -ENOMEM;
+
        req = __skb_put_zero(skb, sizeof(*req));
        req->op_compl = htonl(WR_OP_V(FW_OFLD_CONNECTION_WR));
        req->len16_pkd = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*req), 16)));
index dcccb60..c317947 100644 (file)
@@ -133,8 +133,8 @@ static int create_qp_cmd(struct erdma_ucontext *uctx, struct erdma_qp *qp)
 static int regmr_cmd(struct erdma_dev *dev, struct erdma_mr *mr)
 {
        struct erdma_pd *pd = to_epd(mr->ibmr.pd);
+       u32 mtt_level = ERDMA_MR_MTT_0LEVEL;
        struct erdma_cmdq_reg_mr_req req;
-       u32 mtt_level;
 
        erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA, CMDQ_OPCODE_REG_MR);
 
@@ -147,10 +147,9 @@ static int regmr_cmd(struct erdma_dev *dev, struct erdma_mr *mr)
                        req.phy_addr[0] = sg_dma_address(mr->mem.mtt->sglist);
                        mtt_level = mr->mem.mtt->level;
                }
-       } else {
+       } else if (mr->type != ERDMA_MR_TYPE_DMA) {
                memcpy(req.phy_addr, mr->mem.mtt->buf,
                       MTT_SIZE(mr->mem.page_cnt));
-               mtt_level = ERDMA_MR_MTT_0LEVEL;
        }
 
        req.cfg0 = FIELD_PREP(ERDMA_CMD_MR_VALID_MASK, mr->valid) |
@@ -655,7 +654,7 @@ static struct erdma_mtt *erdma_create_scatter_mtt(struct erdma_dev *dev,
 
        mtt = kzalloc(sizeof(*mtt), GFP_KERNEL);
        if (!mtt)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        mtt->size = ALIGN(size, PAGE_SIZE);
        mtt->buf = vzalloc(mtt->size);
index 24ee79a..88f534c 100644 (file)
@@ -223,7 +223,7 @@ void del_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num,
 static int add_port_entries(struct mlx4_ib_dev *device, int port_num)
 {
        int i;
-       char buff[11];
+       char buff[12];
        struct mlx4_ib_iov_port *port = NULL;
        int ret = 0 ;
        struct ib_port_attr attr;
index 1e419e0..520034a 100644 (file)
@@ -2470,8 +2470,8 @@ destroy_res:
        mlx5_steering_anchor_destroy_res(ft_prio);
 put_flow_table:
        put_flow_table(dev, ft_prio, true);
-       mutex_unlock(&dev->flow_db->lock);
 free_obj:
+       mutex_unlock(&dev->flow_db->lock);
        kfree(obj);
 
        return err;
index aed5cde..555629b 100644 (file)
@@ -2084,7 +2084,7 @@ static inline char *mmap_cmd2str(enum mlx5_ib_mmap_cmd cmd)
        case MLX5_IB_MMAP_DEVICE_MEM:
                return "Device Memory";
        default:
-               return NULL;
+               return "Unknown";
        }
 }
 
index 3e345ef..8a3762d 100644 (file)
@@ -301,7 +301,8 @@ static int get_mkc_octo_size(unsigned int access_mode, unsigned int ndescs)
 
 static void set_cache_mkc(struct mlx5_cache_ent *ent, void *mkc)
 {
-       set_mkc_access_pd_addr_fields(mkc, 0, 0, ent->dev->umrc.pd);
+       set_mkc_access_pd_addr_fields(mkc, ent->rb_key.access_flags, 0,
+                                     ent->dev->umrc.pd);
        MLX5_SET(mkc, mkc, free, 1);
        MLX5_SET(mkc, mkc, umr_en, 1);
        MLX5_SET(mkc, mkc, access_mode_1_0, ent->rb_key.access_mode & 0x3);
@@ -1024,19 +1025,26 @@ void mlx5_mkey_cache_cleanup(struct mlx5_ib_dev *dev)
        if (!dev->cache.wq)
                return;
 
-       cancel_delayed_work_sync(&dev->cache.remove_ent_dwork);
        mutex_lock(&dev->cache.rb_lock);
        for (node = rb_first(root); node; node = rb_next(node)) {
                ent = rb_entry(node, struct mlx5_cache_ent, node);
                xa_lock_irq(&ent->mkeys);
                ent->disabled = true;
                xa_unlock_irq(&ent->mkeys);
-               cancel_delayed_work_sync(&ent->dwork);
        }
+       mutex_unlock(&dev->cache.rb_lock);
+
+       /*
+        * After all entries are disabled and will not reschedule on WQ,
+        * flush it and all async commands.
+        */
+       flush_workqueue(dev->cache.wq);
 
        mlx5_mkey_cache_debugfs_cleanup(dev);
        mlx5_cmd_cleanup_async_ctx(&dev->async_ctx);
 
+       /* At this point all entries are disabled and have no concurrent work. */
+       mutex_lock(&dev->cache.rb_lock);
        node = rb_first(root);
        while (node) {
                ent = rb_entry(node, struct mlx5_cache_ent, node);
index a260517..43e7760 100644 (file)
@@ -976,6 +976,7 @@ static void siw_accept_newconn(struct siw_cep *cep)
                        siw_cep_put(cep);
                        new_cep->listen_cep = NULL;
                        if (rv) {
+                               siw_cancel_mpatimer(new_cep);
                                siw_cep_set_free(new_cep);
                                goto error;
                        }
@@ -1100,9 +1101,12 @@ static void siw_cm_work_handler(struct work_struct *w)
                                /*
                                 * Socket close before MPA request received.
                                 */
-                               siw_dbg_cep(cep, "no mpareq: drop listener\n");
-                               siw_cep_put(cep->listen_cep);
-                               cep->listen_cep = NULL;
+                               if (cep->listen_cep) {
+                                       siw_dbg_cep(cep,
+                                               "no mpareq: drop listener\n");
+                                       siw_cep_put(cep->listen_cep);
+                                       cep->listen_cep = NULL;
+                               }
                        }
                }
                release_cep = 1;
@@ -1227,7 +1231,11 @@ static void siw_cm_llp_data_ready(struct sock *sk)
        if (!cep)
                goto out;
 
-       siw_dbg_cep(cep, "state: %d\n", cep->state);
+       siw_dbg_cep(cep, "cep state: %d, socket state %d\n",
+                   cep->state, sk->sk_state);
+
+       if (sk->sk_state != TCP_ESTABLISHED)
+               goto out;
 
        switch (cep->state) {
        case SIW_EPSTATE_RDMA_MODE:
index 1574218..2916e77 100644 (file)
@@ -2784,7 +2784,6 @@ static int srp_abort(struct scsi_cmnd *scmnd)
        u32 tag;
        u16 ch_idx;
        struct srp_rdma_ch *ch;
-       int ret;
 
        shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n");
 
@@ -2798,19 +2797,14 @@ static int srp_abort(struct scsi_cmnd *scmnd)
        shost_printk(KERN_ERR, target->scsi_host,
                     "Sending SRP abort for tag %#x\n", tag);
        if (srp_send_tsk_mgmt(ch, tag, scmnd->device->lun,
-                             SRP_TSK_ABORT_TASK, NULL) == 0)
-               ret = SUCCESS;
-       else if (target->rport->state == SRP_RPORT_LOST)
-               ret = FAST_IO_FAIL;
-       else
-               ret = FAILED;
-       if (ret == SUCCESS) {
+                             SRP_TSK_ABORT_TASK, NULL) == 0) {
                srp_free_req(ch, req, scmnd, 0);
-               scmnd->result = DID_ABORT << 16;
-               scsi_done(scmnd);
+               return SUCCESS;
        }
+       if (target->rport->state == SRP_RPORT_LOST)
+               return FAST_IO_FAIL;
 
-       return ret;
+       return FAILED;
 }
 
 static int srp_reset_device(struct scsi_cmnd *scmnd)
index 2082081..0b89275 100644 (file)
@@ -671,8 +671,7 @@ static int apple_dart_attach_dev(struct iommu_domain *domain,
                return ret;
 
        switch (domain->type) {
-       case IOMMU_DOMAIN_DMA:
-       case IOMMU_DOMAIN_UNMANAGED:
+       default:
                ret = apple_dart_domain_add_streams(dart_domain, cfg);
                if (ret)
                        return ret;
index 4d83edc..8a16cd3 100644 (file)
@@ -186,6 +186,15 @@ static void arm_smmu_free_shared_cd(struct arm_smmu_ctx_desc *cd)
        }
 }
 
+/*
+ * Cloned from the MAX_TLBI_OPS in arch/arm64/include/asm/tlbflush.h, this
+ * is used as a threshold to replace per-page TLBI commands to issue in the
+ * command queue with an address-space TLBI command, when SMMU w/o a range
+ * invalidation feature handles too many per-page TLBI commands, which will
+ * otherwise result in a soft lockup.
+ */
+#define CMDQ_MAX_TLBI_OPS              (1 << (PAGE_SHIFT - 3))
+
 static void arm_smmu_mm_arch_invalidate_secondary_tlbs(struct mmu_notifier *mn,
                                                struct mm_struct *mm,
                                                unsigned long start,
@@ -201,8 +210,13 @@ static void arm_smmu_mm_arch_invalidate_secondary_tlbs(struct mmu_notifier *mn,
         * range. So do a simple translation here by calculating size correctly.
         */
        size = end - start;
-       if (size == ULONG_MAX)
-               size = 0;
+       if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_RANGE_INV)) {
+               if (size >= CMDQ_MAX_TLBI_OPS * PAGE_SIZE)
+                       size = 0;
+       } else {
+               if (size == ULONG_MAX)
+                       size = 0;
+       }
 
        if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_BTM)) {
                if (!size)
index e82bf1c..bd0a596 100644 (file)
@@ -1895,18 +1895,23 @@ static void __arm_smmu_tlb_inv_range(struct arm_smmu_cmdq_ent *cmd,
                /* Get the leaf page size */
                tg = __ffs(smmu_domain->domain.pgsize_bitmap);
 
+               num_pages = size >> tg;
+
                /* Convert page size of 12,14,16 (log2) to 1,2,3 */
                cmd->tlbi.tg = (tg - 10) / 2;
 
                /*
-                * Determine what level the granule is at. For non-leaf, io-pgtable
-                * assumes .tlb_flush_walk can invalidate multiple levels at once,
-                * so ignore the nominal last-level granule and leave TTL=0.
+                * Determine what level the granule is at. For non-leaf, both
+                * io-pgtable and SVA pass a nominal last-level granule because
+                * they don't know what level(s) actually apply, so ignore that
+                * and leave TTL=0. However for various errata reasons we still
+                * want to use a range command, so avoid the SVA corner case
+                * where both scale and num could be 0 as well.
                 */
                if (cmd->tlbi.leaf)
                        cmd->tlbi.ttl = 4 - ((ilog2(granule) - 3) / (tg - 3));
-
-               num_pages = size >> tg;
+               else if ((num_pages & CMDQ_TLBI_RANGE_NUM_MAX) == 1)
+                       num_pages++;
        }
 
        cmds.num = 0;
index 5db283c..3685ba9 100644 (file)
@@ -2998,13 +2998,6 @@ static int iommu_suspend(void)
        struct intel_iommu *iommu = NULL;
        unsigned long flag;
 
-       for_each_active_iommu(iommu, drhd) {
-               iommu->iommu_state = kcalloc(MAX_SR_DMAR_REGS, sizeof(u32),
-                                            GFP_KERNEL);
-               if (!iommu->iommu_state)
-                       goto nomem;
-       }
-
        iommu_flush_all();
 
        for_each_active_iommu(iommu, drhd) {
@@ -3024,12 +3017,6 @@ static int iommu_suspend(void)
                raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
        }
        return 0;
-
-nomem:
-       for_each_active_iommu(iommu, drhd)
-               kfree(iommu->iommu_state);
-
-       return -ENOMEM;
 }
 
 static void iommu_resume(void)
@@ -3061,9 +3048,6 @@ static void iommu_resume(void)
 
                raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
        }
-
-       for_each_active_iommu(iommu, drhd)
-               kfree(iommu->iommu_state);
 }
 
 static struct syscore_ops iommu_syscore_ops = {
index c18fb69..7dac94f 100644 (file)
@@ -681,7 +681,7 @@ struct intel_iommu {
        struct iopf_queue *iopf_queue;
        unsigned char iopfq_name[16];
        struct q_inval  *qi;            /* Queued invalidation info */
-       u32 *iommu_state; /* Store iommu states between suspend and resume.*/
+       u32 iommu_state[MAX_SR_DMAR_REGS]; /* Store iommu states between suspend and resume.*/
 
 #ifdef CONFIG_IRQ_REMAP
        struct ir_table *ir_table;      /* Interrupt remapping info */
index 6402758..fab6c34 100644 (file)
@@ -262,7 +262,7 @@ struct mtk_iommu_data {
        struct device                   *smicomm_dev;
 
        struct mtk_iommu_bank_data      *bank;
-       struct mtk_iommu_domain         *share_dom; /* For 2 HWs share pgtable */
+       struct mtk_iommu_domain         *share_dom;
 
        struct regmap                   *pericfg;
        struct mutex                    mutex; /* Protect m4u_group/m4u_dom above */
@@ -643,8 +643,8 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom,
        struct mtk_iommu_domain *share_dom = data->share_dom;
        const struct mtk_iommu_iova_region *region;
 
-       /* Always use share domain in sharing pgtable case */
-       if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE) && share_dom) {
+       /* Share pgtable when 2 MM IOMMU share the pgtable or one IOMMU use multiple iova ranges */
+       if (share_dom) {
                dom->iop = share_dom->iop;
                dom->cfg = share_dom->cfg;
                dom->domain.pgsize_bitmap = share_dom->cfg.pgsize_bitmap;
@@ -677,8 +677,7 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom,
        /* Update our support page sizes bitmap */
        dom->domain.pgsize_bitmap = dom->cfg.pgsize_bitmap;
 
-       if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE))
-               data->share_dom = dom;
+       data->share_dom = dom;
 
 update_iova_region:
        /* Update the iova region for this domain */
index 04f9ea6..214ed81 100644 (file)
@@ -479,10 +479,6 @@ int led_compose_name(struct device *dev, struct led_init_data *init_data,
 
        led_parse_fwnode_props(dev, fwnode, &props);
 
-       /* We want to label LEDs that can produce full range of colors
-        * as RGB, not multicolor */
-       BUG_ON(props.color == LED_COLOR_ID_MULTI);
-
        if (props.label) {
                /*
                 * If init_data.devicename is NULL, then it indicates that
index ad8e670..b487f7a 100644 (file)
@@ -748,17 +748,16 @@ err:
 /*
  * Cleanup zoned device information.
  */
-static void dmz_put_zoned_device(struct dm_target *ti)
+static void dmz_put_zoned_devices(struct dm_target *ti)
 {
        struct dmz_target *dmz = ti->private;
        int i;
 
-       for (i = 0; i < dmz->nr_ddevs; i++) {
-               if (dmz->ddev[i]) {
+       for (i = 0; i < dmz->nr_ddevs; i++)
+               if (dmz->ddev[i])
                        dm_put_device(ti, dmz->ddev[i]);
-                       dmz->ddev[i] = NULL;
-               }
-       }
+
+       kfree(dmz->ddev);
 }
 
 static int dmz_fixup_devices(struct dm_target *ti)
@@ -948,7 +947,7 @@ err_bio:
 err_meta:
        dmz_dtr_metadata(dmz->metadata);
 err_dev:
-       dmz_put_zoned_device(ti);
+       dmz_put_zoned_devices(ti);
 err:
        kfree(dmz->dev);
        kfree(dmz);
@@ -978,7 +977,7 @@ static void dmz_dtr(struct dm_target *ti)
 
        bioset_exit(&dmz->bio_set);
 
-       dmz_put_zoned_device(ti);
+       dmz_put_zoned_devices(ti);
 
        mutex_destroy(&dmz->chunk_lock);
 
index 4cb9c60..284cd71 100644 (file)
@@ -854,6 +854,13 @@ struct stripe_head *raid5_get_active_stripe(struct r5conf *conf,
 
                set_bit(R5_INACTIVE_BLOCKED, &conf->cache_state);
                r5l_wake_reclaim(conf->log, 0);
+
+               /* release batch_last before wait to avoid risk of deadlock */
+               if (ctx && ctx->batch_last) {
+                       raid5_release_stripe(ctx->batch_last);
+                       ctx->batch_last = NULL;
+               }
+
                wait_event_lock_irq(conf->wait_for_stripe,
                                    is_inactive_blocked(conf, hash),
                                    *(conf->hash_locks + hash));
index e113902..ee46841 100644 (file)
@@ -1,11 +1,19 @@
 # SPDX-License-Identifier: GPL-2.0-only
+
+source "drivers/media/pci/intel/ipu3/Kconfig"
+source "drivers/media/pci/intel/ivsc/Kconfig"
+
 config IPU_BRIDGE
-       tristate
+       tristate "Intel IPU Bridge"
        depends on I2C && ACPI
        help
-         This is a helper module for the IPU bridge, which can be
-         used by ipu3 and other drivers. In order to handle module
-         dependencies, this is selected by each driver that needs it.
+         The IPU bridge is a helper library for Intel IPU drivers to
+         function on systems shipped with Windows.
 
-source "drivers/media/pci/intel/ipu3/Kconfig"
-source "drivers/media/pci/intel/ivsc/Kconfig"
+         Currently used by the ipu3-cio2 and atomisp drivers.
+
+         Supported systems include:
+
+         - Microsoft Surface models (except Surface Pro 3)
+         - The Lenovo Miix line (for example the 510, 520, 710 and 720)
+         - Dell 7285
index 0951545..c0a250d 100644 (file)
@@ -2,13 +2,13 @@
 config VIDEO_IPU3_CIO2
        tristate "Intel ipu3-cio2 driver"
        depends on VIDEO_DEV && PCI
+       depends on IPU_BRIDGE || !IPU_BRIDGE
        depends on ACPI || COMPILE_TEST
        depends on X86
        select MEDIA_CONTROLLER
        select VIDEO_V4L2_SUBDEV_API
        select V4L2_FWNODE
        select VIDEOBUF2_DMA_SG
-       select IPU_BRIDGE if CIO2_BRIDGE
 
        help
          This is the Intel IPU3 CIO2 CSI-2 receiver unit, found in Intel
@@ -18,22 +18,3 @@ config VIDEO_IPU3_CIO2
          Say Y or M here if you have a Skylake/Kaby Lake SoC with MIPI CSI-2
          connected camera.
          The module will be called ipu3-cio2.
-
-config CIO2_BRIDGE
-       bool "IPU3 CIO2 Sensors Bridge"
-       depends on VIDEO_IPU3_CIO2 && ACPI
-       depends on I2C
-       help
-         This extension provides an API for the ipu3-cio2 driver to create
-         connections to cameras that are hidden in the SSDB buffer in ACPI.
-         It can be used to enable support for cameras in detachable / hybrid
-         devices that ship with Windows.
-
-         Say Y here if your device is a detachable / hybrid laptop that comes
-         with Windows installed by the OEM, for example:
-
-               - Microsoft Surface models (except Surface Pro 3)
-               - The Lenovo Miix line (for example the 510, 520, 710 and 720)
-               - Dell 7285
-
-         If in doubt, say N here.
index 2127534..a8cb981 100644 (file)
@@ -6,7 +6,7 @@ config INTEL_VSC
        depends on INTEL_MEI && ACPI && VIDEO_DEV
        select MEDIA_CONTROLLER
        select VIDEO_V4L2_SUBDEV_API
-       select V4L2_ASYNC
+       select V4L2_FWNODE
        help
          This adds support for Intel Visual Sensing Controller (IVSC).
 
index 6e6caf5..59b89e4 100644 (file)
@@ -2398,7 +2398,7 @@ static int pxa_camera_probe(struct platform_device *pdev)
                               PXA_CAM_DRV_NAME, pcdev);
        if (err) {
                dev_err(&pdev->dev, "Camera interrupt register failed\n");
-               goto exit_v4l2_device_unregister;
+               goto exit_deactivate;
        }
 
        pcdev->notifier.ops = &pxa_camera_sensor_ops;
index d299cc2..ae6290d 100644 (file)
@@ -138,7 +138,8 @@ int vpu_enc_init(struct venc_vpu_inst *vpu)
        vpu->ctx->vpu_inst = vpu;
 
        status = mtk_vcodec_fw_ipi_register(vpu->ctx->dev->fw_handler, vpu->id,
-                                           vpu_enc_ipi_handler, "venc", NULL);
+                                           vpu_enc_ipi_handler, "venc",
+                                           vpu->ctx->dev);
 
        if (status) {
                mtk_venc_err(vpu->ctx, "vpu_ipi_register fail %d", status);
index aea9574..90ce58f 100644 (file)
@@ -241,6 +241,7 @@ config MFD_CS42L43
        tristate
        select MFD_CORE
        select REGMAP
+       select REGMAP_IRQ
 
 config MFD_CS42L43_I2C
        tristate "Cirrus Logic CS42L43 (I2C)"
index 8b91a55..8ee51e4 100644 (file)
@@ -894,6 +894,13 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
                return -EINVAL;
        }
 
+       /* UBI cannot work on flashes with zero erasesize. */
+       if (!mtd->erasesize) {
+               pr_err("ubi: refuse attaching mtd%d - zero erasesize flash is not supported\n",
+                       mtd->index);
+               return -EINVAL;
+       }
+
        if (ubi_num == UBI_DEV_NUM_AUTO) {
                /* Search for an empty slot in the @ubi_devices array */
                for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++)
index 52a99d8..ab434a7 100644 (file)
@@ -2958,14 +2958,16 @@ static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip)
                 * from the wrong location resulting in the switch booting
                 * to wrong mode and inoperable.
                 */
-               mv88e6xxx_g1_wait_eeprom_done(chip);
+               if (chip->info->ops->get_eeprom)
+                       mv88e6xxx_g2_eeprom_wait(chip);
 
                gpiod_set_value_cansleep(gpiod, 1);
                usleep_range(10000, 20000);
                gpiod_set_value_cansleep(gpiod, 0);
                usleep_range(10000, 20000);
 
-               mv88e6xxx_g1_wait_eeprom_done(chip);
+               if (chip->info->ops->get_eeprom)
+                       mv88e6xxx_g2_eeprom_wait(chip);
        }
 }
 
index 2fa55a6..174c773 100644 (file)
@@ -75,37 +75,6 @@ static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip)
        return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STS, bit, 1);
 }
 
-void mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip)
-{
-       const unsigned long timeout = jiffies + 1 * HZ;
-       u16 val;
-       int err;
-
-       /* Wait up to 1 second for the switch to finish reading the
-        * EEPROM.
-        */
-       while (time_before(jiffies, timeout)) {
-               err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &val);
-               if (err) {
-                       dev_err(chip->dev, "Error reading status");
-                       return;
-               }
-
-               /* If the switch is still resetting, it may not
-                * respond on the bus, and so MDIO read returns
-                * 0xffff. Differentiate between that, and waiting for
-                * the EEPROM to be done by bit 0 being set.
-                */
-               if (val != 0xffff &&
-                   val & BIT(MV88E6XXX_G1_STS_IRQ_EEPROM_DONE))
-                       return;
-
-               usleep_range(1000, 2000);
-       }
-
-       dev_err(chip->dev, "Timeout waiting for EEPROM done");
-}
-
 /* Offset 0x01: Switch MAC Address Register Bytes 0 & 1
  * Offset 0x02: Switch MAC Address Register Bytes 2 & 3
  * Offset 0x03: Switch MAC Address Register Bytes 4 & 5
index c99ddd1..1095261 100644 (file)
@@ -282,7 +282,6 @@ int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr);
 int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip);
 int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip);
 int mv88e6250_g1_reset(struct mv88e6xxx_chip *chip);
-void mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip);
 
 int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip);
 int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip);
index 937a01f..b2b5f6b 100644 (file)
@@ -340,7 +340,7 @@ int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip)
  * Offset 0x15: EEPROM Addr (for 8-bit data access)
  */
 
-static int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip)
+int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip)
 {
        int bit = __bf_shf(MV88E6XXX_G2_EEPROM_CMD_BUSY);
        int err;
index 7e09196..d9434f7 100644 (file)
@@ -365,6 +365,7 @@ int mv88e6xxx_g2_trunk_clear(struct mv88e6xxx_chip *chip);
 
 int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target,
                                      int port);
+int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip);
 
 extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops;
 extern const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops;
index 832a2ae..a8d79ee 100644 (file)
@@ -1303,24 +1303,23 @@ static void ibmveth_rx_csum_helper(struct sk_buff *skb,
         * the user space for finding a flow. During this process, OVS computes
         * checksum on the first packet when CHECKSUM_PARTIAL flag is set.
         *
-        * So, re-compute TCP pseudo header checksum when configured for
-        * trunk mode.
+        * So, re-compute TCP pseudo header checksum.
         */
+
        if (iph_proto == IPPROTO_TCP) {
                struct tcphdr *tcph = (struct tcphdr *)(skb->data + iphlen);
+
                if (tcph->check == 0x0000) {
                        /* Recompute TCP pseudo header checksum  */
-                       if (adapter->is_active_trunk) {
-                               tcphdrlen = skb->len - iphlen;
-                               if (skb_proto == ETH_P_IP)
-                                       tcph->check =
-                                        ~csum_tcpudp_magic(iph->saddr,
-                                       iph->daddr, tcphdrlen, iph_proto, 0);
-                               else if (skb_proto == ETH_P_IPV6)
-                                       tcph->check =
-                                        ~csum_ipv6_magic(&iph6->saddr,
-                                       &iph6->daddr, tcphdrlen, iph_proto, 0);
-                       }
+                       tcphdrlen = skb->len - iphlen;
+                       if (skb_proto == ETH_P_IP)
+                               tcph->check =
+                                ~csum_tcpudp_magic(iph->saddr,
+                               iph->daddr, tcphdrlen, iph_proto, 0);
+                       else if (skb_proto == ETH_P_IPV6)
+                               tcph->check =
+                                ~csum_ipv6_magic(&iph6->saddr,
+                               &iph6->daddr, tcphdrlen, iph_proto, 0);
                        /* Setup SKB fields for checksum offload */
                        skb_partial_csum_set(skb, iphlen,
                                             offsetof(struct tcphdr, check));
index b03426a..db97353 100644 (file)
@@ -2617,12 +2617,14 @@ static int ice_vc_query_rxdid(struct ice_vf *vf)
                goto err;
        }
 
-       /* Read flexiflag registers to determine whether the
-        * corresponding RXDID is configured and supported or not.
-        * Since Legacy 16byte descriptor format is not supported,
-        * start from Legacy 32byte descriptor.
+       /* RXDIDs supported by DDP package can be read from the register
+        * to get the supported RXDID bitmap. But the legacy 32byte RXDID
+        * is not listed in DDP package, add it in the bitmap manually.
+        * Legacy 16byte descriptor is not supported.
         */
-       for (i = ICE_RXDID_LEGACY_1; i < ICE_FLEX_DESC_RXDID_MAX_NUM; i++) {
+       rxdid->supported_rxdids |= BIT(ICE_RXDID_LEGACY_1);
+
+       for (i = ICE_RXDID_FLEX_NIC; i < ICE_FLEX_DESC_RXDID_MAX_NUM; i++) {
                regval = rd32(hw, GLFLXP_RXDID_FLAGS(i, 0));
                if ((regval >> GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_S)
                        & GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_M)
index ddec162..8d0bacf 100644 (file)
@@ -2195,7 +2195,7 @@ struct rx_ring_info {
        struct sk_buff  *skb;
        dma_addr_t      data_addr;
        DEFINE_DMA_UNMAP_LEN(data_size);
-       dma_addr_t      frag_addr[ETH_JUMBO_MTU >> PAGE_SHIFT];
+       dma_addr_t      frag_addr[ETH_JUMBO_MTU >> PAGE_SHIFT ?: 1];
 };
 
 enum flow_control {
index 3cffd1b..20afe79 100644 (file)
@@ -3171,8 +3171,8 @@ static irqreturn_t mtk_handle_irq_rx(int irq, void *_eth)
 
        eth->rx_events++;
        if (likely(napi_schedule_prep(&eth->rx_napi))) {
-               __napi_schedule(&eth->rx_napi);
                mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask);
+               __napi_schedule(&eth->rx_napi);
        }
 
        return IRQ_HANDLED;
@@ -3184,8 +3184,8 @@ static irqreturn_t mtk_handle_irq_tx(int irq, void *_eth)
 
        eth->tx_events++;
        if (likely(napi_schedule_prep(&eth->tx_napi))) {
-               __napi_schedule(&eth->tx_napi);
                mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
+               __napi_schedule(&eth->tx_napi);
        }
 
        return IRQ_HANDLED;
index 329e374..43ba71e 100644 (file)
@@ -46,6 +46,7 @@ config LAN743X
        tristate "LAN743x support"
        depends on PCI
        depends on PTP_1588_CLOCK_OPTIONAL
+       select PHYLIB
        select FIXED_PHY
        select CRC16
        select CRC32
index 4a16ebf..48ea4ae 100644 (file)
@@ -91,63 +91,137 @@ static unsigned int mana_checksum_info(struct sk_buff *skb)
        return 0;
 }
 
+static void mana_add_sge(struct mana_tx_package *tp, struct mana_skb_head *ash,
+                        int sg_i, dma_addr_t da, int sge_len, u32 gpa_mkey)
+{
+       ash->dma_handle[sg_i] = da;
+       ash->size[sg_i] = sge_len;
+
+       tp->wqe_req.sgl[sg_i].address = da;
+       tp->wqe_req.sgl[sg_i].mem_key = gpa_mkey;
+       tp->wqe_req.sgl[sg_i].size = sge_len;
+}
+
 static int mana_map_skb(struct sk_buff *skb, struct mana_port_context *apc,
-                       struct mana_tx_package *tp)
+                       struct mana_tx_package *tp, int gso_hs)
 {
        struct mana_skb_head *ash = (struct mana_skb_head *)skb->head;
+       int hsg = 1; /* num of SGEs of linear part */
        struct gdma_dev *gd = apc->ac->gdma_dev;
+       int skb_hlen = skb_headlen(skb);
+       int sge0_len, sge1_len = 0;
        struct gdma_context *gc;
        struct device *dev;
        skb_frag_t *frag;
        dma_addr_t da;
+       int sg_i;
        int i;
 
        gc = gd->gdma_context;
        dev = gc->dev;
-       da = dma_map_single(dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
 
+       if (gso_hs && gso_hs < skb_hlen) {
+               sge0_len = gso_hs;
+               sge1_len = skb_hlen - gso_hs;
+       } else {
+               sge0_len = skb_hlen;
+       }
+
+       da = dma_map_single(dev, skb->data, sge0_len, DMA_TO_DEVICE);
        if (dma_mapping_error(dev, da))
                return -ENOMEM;
 
-       ash->dma_handle[0] = da;
-       ash->size[0] = skb_headlen(skb);
+       mana_add_sge(tp, ash, 0, da, sge0_len, gd->gpa_mkey);
 
-       tp->wqe_req.sgl[0].address = ash->dma_handle[0];
-       tp->wqe_req.sgl[0].mem_key = gd->gpa_mkey;
-       tp->wqe_req.sgl[0].size = ash->size[0];
+       if (sge1_len) {
+               sg_i = 1;
+               da = dma_map_single(dev, skb->data + sge0_len, sge1_len,
+                                   DMA_TO_DEVICE);
+               if (dma_mapping_error(dev, da))
+                       goto frag_err;
+
+               mana_add_sge(tp, ash, sg_i, da, sge1_len, gd->gpa_mkey);
+               hsg = 2;
+       }
 
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+               sg_i = hsg + i;
+
                frag = &skb_shinfo(skb)->frags[i];
                da = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag),
                                      DMA_TO_DEVICE);
-
                if (dma_mapping_error(dev, da))
                        goto frag_err;
 
-               ash->dma_handle[i + 1] = da;
-               ash->size[i + 1] = skb_frag_size(frag);
-
-               tp->wqe_req.sgl[i + 1].address = ash->dma_handle[i + 1];
-               tp->wqe_req.sgl[i + 1].mem_key = gd->gpa_mkey;
-               tp->wqe_req.sgl[i + 1].size = ash->size[i + 1];
+               mana_add_sge(tp, ash, sg_i, da, skb_frag_size(frag),
+                            gd->gpa_mkey);
        }
 
        return 0;
 
 frag_err:
-       for (i = i - 1; i >= 0; i--)
-               dma_unmap_page(dev, ash->dma_handle[i + 1], ash->size[i + 1],
+       for (i = sg_i - 1; i >= hsg; i--)
+               dma_unmap_page(dev, ash->dma_handle[i], ash->size[i],
                               DMA_TO_DEVICE);
 
-       dma_unmap_single(dev, ash->dma_handle[0], ash->size[0], DMA_TO_DEVICE);
+       for (i = hsg - 1; i >= 0; i--)
+               dma_unmap_single(dev, ash->dma_handle[i], ash->size[i],
+                                DMA_TO_DEVICE);
 
        return -ENOMEM;
 }
 
+/* Handle the case when GSO SKB linear length is too large.
+ * MANA NIC requires GSO packets to put only the packet header to SGE0.
+ * So, we need 2 SGEs for the skb linear part which contains more than the
+ * header.
+ * Return a positive value for the number of SGEs, or a negative value
+ * for an error.
+ */
+static int mana_fix_skb_head(struct net_device *ndev, struct sk_buff *skb,
+                            int gso_hs)
+{
+       int num_sge = 1 + skb_shinfo(skb)->nr_frags;
+       int skb_hlen = skb_headlen(skb);
+
+       if (gso_hs < skb_hlen) {
+               num_sge++;
+       } else if (gso_hs > skb_hlen) {
+               if (net_ratelimit())
+                       netdev_err(ndev,
+                                  "TX nonlinear head: hs:%d, skb_hlen:%d\n",
+                                  gso_hs, skb_hlen);
+
+               return -EINVAL;
+       }
+
+       return num_sge;
+}
+
+/* Get the GSO packet's header size */
+static int mana_get_gso_hs(struct sk_buff *skb)
+{
+       int gso_hs;
+
+       if (skb->encapsulation) {
+               gso_hs = skb_inner_tcp_all_headers(skb);
+       } else {
+               if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) {
+                       gso_hs = skb_transport_offset(skb) +
+                                sizeof(struct udphdr);
+               } else {
+                       gso_hs = skb_tcp_all_headers(skb);
+               }
+       }
+
+       return gso_hs;
+}
+
 netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 {
        enum mana_tx_pkt_format pkt_fmt = MANA_SHORT_PKT_FMT;
        struct mana_port_context *apc = netdev_priv(ndev);
+       int gso_hs = 0; /* zero for non-GSO pkts */
        u16 txq_idx = skb_get_queue_mapping(skb);
        struct gdma_dev *gd = apc->ac->gdma_dev;
        bool ipv4 = false, ipv6 = false;
@@ -159,7 +233,6 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        struct mana_txq *txq;
        struct mana_cq *cq;
        int err, len;
-       u16 ihs;
 
        if (unlikely(!apc->port_is_up))
                goto tx_drop;
@@ -209,19 +282,6 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        pkg.wqe_req.client_data_unit = 0;
 
        pkg.wqe_req.num_sge = 1 + skb_shinfo(skb)->nr_frags;
-       WARN_ON_ONCE(pkg.wqe_req.num_sge > MAX_TX_WQE_SGL_ENTRIES);
-
-       if (pkg.wqe_req.num_sge <= ARRAY_SIZE(pkg.sgl_array)) {
-               pkg.wqe_req.sgl = pkg.sgl_array;
-       } else {
-               pkg.sgl_ptr = kmalloc_array(pkg.wqe_req.num_sge,
-                                           sizeof(struct gdma_sge),
-                                           GFP_ATOMIC);
-               if (!pkg.sgl_ptr)
-                       goto tx_drop_count;
-
-               pkg.wqe_req.sgl = pkg.sgl_ptr;
-       }
 
        if (skb->protocol == htons(ETH_P_IP))
                ipv4 = true;
@@ -229,6 +289,26 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                ipv6 = true;
 
        if (skb_is_gso(skb)) {
+               int num_sge;
+
+               gso_hs = mana_get_gso_hs(skb);
+
+               num_sge = mana_fix_skb_head(ndev, skb, gso_hs);
+               if (num_sge > 0)
+                       pkg.wqe_req.num_sge = num_sge;
+               else
+                       goto tx_drop_count;
+
+               u64_stats_update_begin(&tx_stats->syncp);
+               if (skb->encapsulation) {
+                       tx_stats->tso_inner_packets++;
+                       tx_stats->tso_inner_bytes += skb->len - gso_hs;
+               } else {
+                       tx_stats->tso_packets++;
+                       tx_stats->tso_bytes += skb->len - gso_hs;
+               }
+               u64_stats_update_end(&tx_stats->syncp);
+
                pkg.tx_oob.s_oob.is_outer_ipv4 = ipv4;
                pkg.tx_oob.s_oob.is_outer_ipv6 = ipv6;
 
@@ -252,28 +332,6 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                                                 &ipv6_hdr(skb)->daddr, 0,
                                                 IPPROTO_TCP, 0);
                }
-
-               if (skb->encapsulation) {
-                       ihs = skb_inner_tcp_all_headers(skb);
-                       u64_stats_update_begin(&tx_stats->syncp);
-                       tx_stats->tso_inner_packets++;
-                       tx_stats->tso_inner_bytes += skb->len - ihs;
-                       u64_stats_update_end(&tx_stats->syncp);
-               } else {
-                       if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) {
-                               ihs = skb_transport_offset(skb) + sizeof(struct udphdr);
-                       } else {
-                               ihs = skb_tcp_all_headers(skb);
-                               if (ipv6_has_hopopt_jumbo(skb))
-                                       ihs -= sizeof(struct hop_jumbo_hdr);
-                       }
-
-                       u64_stats_update_begin(&tx_stats->syncp);
-                       tx_stats->tso_packets++;
-                       tx_stats->tso_bytes += skb->len - ihs;
-                       u64_stats_update_end(&tx_stats->syncp);
-               }
-
        } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
                csum_type = mana_checksum_info(skb);
 
@@ -296,11 +354,25 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                } else {
                        /* Can't do offload of this type of checksum */
                        if (skb_checksum_help(skb))
-                               goto free_sgl_ptr;
+                               goto tx_drop_count;
                }
        }
 
-       if (mana_map_skb(skb, apc, &pkg)) {
+       WARN_ON_ONCE(pkg.wqe_req.num_sge > MAX_TX_WQE_SGL_ENTRIES);
+
+       if (pkg.wqe_req.num_sge <= ARRAY_SIZE(pkg.sgl_array)) {
+               pkg.wqe_req.sgl = pkg.sgl_array;
+       } else {
+               pkg.sgl_ptr = kmalloc_array(pkg.wqe_req.num_sge,
+                                           sizeof(struct gdma_sge),
+                                           GFP_ATOMIC);
+               if (!pkg.sgl_ptr)
+                       goto tx_drop_count;
+
+               pkg.wqe_req.sgl = pkg.sgl_ptr;
+       }
+
+       if (mana_map_skb(skb, apc, &pkg, gso_hs)) {
                u64_stats_update_begin(&tx_stats->syncp);
                tx_stats->mana_map_err++;
                u64_stats_update_end(&tx_stats->syncp);
@@ -1258,11 +1330,16 @@ static void mana_unmap_skb(struct sk_buff *skb, struct mana_port_context *apc)
        struct mana_skb_head *ash = (struct mana_skb_head *)skb->head;
        struct gdma_context *gc = apc->ac->gdma_dev->gdma_context;
        struct device *dev = gc->dev;
-       int i;
+       int hsg, i;
 
-       dma_unmap_single(dev, ash->dma_handle[0], ash->size[0], DMA_TO_DEVICE);
+       /* Number of SGEs of linear part */
+       hsg = (skb_is_gso(skb) && skb_headlen(skb) > ash->size[0]) ? 2 : 1;
 
-       for (i = 1; i < skb_shinfo(skb)->nr_frags + 1; i++)
+       for (i = 0; i < hsg; i++)
+               dma_unmap_single(dev, ash->dma_handle[i], ash->size[i],
+                                DMA_TO_DEVICE);
+
+       for (i = hsg; i < skb_shinfo(skb)->nr_frags + hsg; i++)
                dma_unmap_page(dev, ash->dma_handle[i], ash->size[i],
                               DMA_TO_DEVICE);
 }
@@ -1317,19 +1394,23 @@ static void mana_poll_tx_cq(struct mana_cq *cq)
                case CQE_TX_VPORT_IDX_OUT_OF_RANGE:
                case CQE_TX_VPORT_DISABLED:
                case CQE_TX_VLAN_TAGGING_VIOLATION:
-                       WARN_ONCE(1, "TX: CQE error %d: ignored.\n",
-                                 cqe_oob->cqe_hdr.cqe_type);
+                       if (net_ratelimit())
+                               netdev_err(ndev, "TX: CQE error %d\n",
+                                          cqe_oob->cqe_hdr.cqe_type);
+
                        apc->eth_stats.tx_cqe_err++;
                        break;
 
                default:
-                       /* If the CQE type is unexpected, log an error, assert,
-                        * and go through the error path.
+                       /* If the CQE type is unknown, log an error,
+                        * and still free the SKB, update tail, etc.
                         */
-                       WARN_ONCE(1, "TX: Unexpected CQE type %d: HW BUG?\n",
-                                 cqe_oob->cqe_hdr.cqe_type);
+                       if (net_ratelimit())
+                               netdev_err(ndev, "TX: unknown CQE type %d\n",
+                                          cqe_oob->cqe_hdr.cqe_type);
+
                        apc->eth_stats.tx_cqe_unknown_type++;
-                       return;
+                       break;
                }
 
                if (WARN_ON_ONCE(txq->gdma_txq_id != completions[i].wq_num))
index 0bfc375..a174c6f 100644 (file)
@@ -110,9 +110,9 @@ struct qed_ll2_info {
        enum core_tx_dest tx_dest;
        u8 tx_stats_en;
        bool main_func_queue;
+       struct qed_ll2_cbs cbs;
        struct qed_ll2_rx_queue rx_queue;
        struct qed_ll2_tx_queue tx_queue;
-       struct qed_ll2_cbs cbs;
 };
 
 extern const struct qed_ll2_ops qed_ll2_ops_pass;
index ea91861..fc01ad3 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) 2022 Renesas Electronics Corporation
  */
 
+#include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/etherdevice.h>
@@ -1049,7 +1050,7 @@ static void rswitch_rmac_setting(struct rswitch_etha *etha, const u8 *mac)
 static void rswitch_etha_enable_mii(struct rswitch_etha *etha)
 {
        rswitch_modify(etha->addr, MPIC, MPIC_PSMCS_MASK | MPIC_PSMHT_MASK,
-                      MPIC_PSMCS(0x05) | MPIC_PSMHT(0x06));
+                      MPIC_PSMCS(etha->psmcs) | MPIC_PSMHT(0x06));
        rswitch_modify(etha->addr, MPSM, 0, MPSM_MFF_C45);
 }
 
@@ -1693,6 +1694,12 @@ static void rswitch_etha_init(struct rswitch_private *priv, int index)
        etha->index = index;
        etha->addr = priv->addr + RSWITCH_ETHA_OFFSET + index * RSWITCH_ETHA_SIZE;
        etha->coma_addr = priv->addr;
+
+       /* MPIC.PSMCS = (clk [MHz] / (MDC frequency [MHz] * 2) - 1.
+        * Calculating PSMCS value as MDC frequency = 2.5MHz. So, multiply
+        * both the numerator and the denominator by 10.
+        */
+       etha->psmcs = clk_get_rate(priv->clk) / 100000 / (25 * 2) - 1;
 }
 
 static int rswitch_device_alloc(struct rswitch_private *priv, int index)
@@ -1900,6 +1907,10 @@ static int renesas_eth_sw_probe(struct platform_device *pdev)
                return -ENOMEM;
        spin_lock_init(&priv->lock);
 
+       priv->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(priv->clk))
+               return PTR_ERR(priv->clk);
+
        attr = soc_device_match(rswitch_soc_no_speed_change);
        if (attr)
                priv->etha_no_runtime_change = true;
index f0c16a3..04f49a7 100644 (file)
@@ -915,6 +915,7 @@ struct rswitch_etha {
        bool external_phy;
        struct mii_bus *mii;
        phy_interface_t phy_interface;
+       u32 psmcs;
        u8 mac_addr[MAX_ADDR_LEN];
        int link;
        int speed;
@@ -1012,6 +1013,7 @@ struct rswitch_private {
        struct rswitch_mfwd mfwd;
 
        spinlock_t lock;        /* lock interrupt registers' control */
+       struct clk *clk;
 
        bool etha_no_runtime_change;
        bool gwca_halt;
index 26ea8c6..a0e2767 100644 (file)
@@ -104,6 +104,7 @@ struct stm32_ops {
        int (*parse_data)(struct stm32_dwmac *dwmac,
                          struct device *dev);
        u32 syscfg_eth_mask;
+       bool clk_rx_enable_in_suspend;
 };
 
 static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat)
@@ -121,7 +122,8 @@ static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat)
        if (ret)
                return ret;
 
-       if (!dwmac->dev->power.is_suspended) {
+       if (!dwmac->ops->clk_rx_enable_in_suspend ||
+           !dwmac->dev->power.is_suspended) {
                ret = clk_prepare_enable(dwmac->clk_rx);
                if (ret) {
                        clk_disable_unprepare(dwmac->clk_tx);
@@ -513,7 +515,8 @@ static struct stm32_ops stm32mp1_dwmac_data = {
        .suspend = stm32mp1_suspend,
        .resume = stm32mp1_resume,
        .parse_data = stm32mp1_parse_data,
-       .syscfg_eth_mask = SYSCFG_MP1_ETH_MASK
+       .syscfg_eth_mask = SYSCFG_MP1_ETH_MASK,
+       .clk_rx_enable_in_suspend = true
 };
 
 static const struct of_device_id stm32_dwmac_match[] = {
index 83c567a..ed1a5a3 100644 (file)
@@ -6002,33 +6002,6 @@ static irqreturn_t stmmac_msi_intr_rx(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/* Polling receive - used by NETCONSOLE and other diagnostic tools
- * to allow network I/O with interrupts disabled.
- */
-static void stmmac_poll_controller(struct net_device *dev)
-{
-       struct stmmac_priv *priv = netdev_priv(dev);
-       int i;
-
-       /* If adapter is down, do nothing */
-       if (test_bit(STMMAC_DOWN, &priv->state))
-               return;
-
-       if (priv->plat->flags & STMMAC_FLAG_MULTI_MSI_EN) {
-               for (i = 0; i < priv->plat->rx_queues_to_use; i++)
-                       stmmac_msi_intr_rx(0, &priv->dma_conf.rx_queue[i]);
-
-               for (i = 0; i < priv->plat->tx_queues_to_use; i++)
-                       stmmac_msi_intr_tx(0, &priv->dma_conf.tx_queue[i]);
-       } else {
-               disable_irq(dev->irq);
-               stmmac_interrupt(dev->irq, dev);
-               enable_irq(dev->irq);
-       }
-}
-#endif
-
 /**
  *  stmmac_ioctl - Entry point for the Ioctl
  *  @dev: Device pointer.
@@ -6989,9 +6962,6 @@ static const struct net_device_ops stmmac_netdev_ops = {
        .ndo_get_stats64 = stmmac_get_stats64,
        .ndo_setup_tc = stmmac_setup_tc,
        .ndo_select_queue = stmmac_select_queue,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller = stmmac_poll_controller,
-#endif
        .ndo_set_mac_address = stmmac_set_mac_address,
        .ndo_vlan_rx_add_vid = stmmac_vlan_rx_add_vid,
        .ndo_vlan_rx_kill_vid = stmmac_vlan_rx_kill_vid,
index 0f28795..2f0678f 100644 (file)
@@ -901,7 +901,7 @@ static int __maybe_unused stmmac_pltfr_resume(struct device *dev)
        struct platform_device *pdev = to_platform_device(dev);
        int ret;
 
-       ret = stmmac_pltfr_init(pdev, priv->plat->bsp_priv);
+       ret = stmmac_pltfr_init(pdev, priv->plat);
        if (ret)
                return ret;
 
index bea6fc0..2412060 100644 (file)
@@ -1747,9 +1747,10 @@ static int am65_cpsw_nuss_init_tx_chns(struct am65_cpsw_common *common)
                }
 
                tx_chn->irq = k3_udma_glue_tx_get_irq(tx_chn->tx_chn);
-               if (tx_chn->irq <= 0) {
+               if (tx_chn->irq < 0) {
                        dev_err(dev, "Failed to get tx dma irq %d\n",
                                tx_chn->irq);
+                       ret = tx_chn->irq;
                        goto err;
                }
 
index 410612f..4914d0e 100644 (file)
@@ -316,12 +316,12 @@ static int prueth_init_tx_chns(struct prueth_emac *emac)
                        goto fail;
                }
 
-               tx_chn->irq = k3_udma_glue_tx_get_irq(tx_chn->tx_chn);
-               if (tx_chn->irq <= 0) {
-                       ret = -EINVAL;
+               ret = k3_udma_glue_tx_get_irq(tx_chn->tx_chn);
+               if (ret < 0) {
                        netdev_err(ndev, "failed to get tx irq\n");
                        goto fail;
                }
+               tx_chn->irq = ret;
 
                snprintf(tx_chn->name, sizeof(tx_chn->name), "%s-tx%d",
                         dev_name(dev), tx_chn->id);
index 5d6454f..78ad2da 100644 (file)
@@ -90,7 +90,9 @@ static int __must_check __smsc75xx_read_reg(struct usbnet *dev, u32 index,
        ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN
                 | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                 0, index, &buf, 4);
-       if (unlikely(ret < 0)) {
+       if (unlikely(ret < 4)) {
+               ret = ret < 0 ? ret : -ENODATA;
+
                netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n",
                            index, ret);
                return ret;
index 47c2ad7..fd50bb3 100644 (file)
@@ -34,6 +34,8 @@
 #define TDM_PPPOHT_SLIC_MAXIN
 #define RX_BD_ERRORS (R_CD_S | R_OV_S | R_CR_S | R_AB_S | R_NO_S | R_LG_S)
 
+static int uhdlc_close(struct net_device *dev);
+
 static struct ucc_tdm_info utdm_primary_info = {
        .uf_info = {
                .tsa = 0,
@@ -708,6 +710,7 @@ static int uhdlc_open(struct net_device *dev)
        hdlc_device *hdlc = dev_to_hdlc(dev);
        struct ucc_hdlc_private *priv = hdlc->priv;
        struct ucc_tdm *utdm = priv->utdm;
+       int rc = 0;
 
        if (priv->hdlc_busy != 1) {
                if (request_irq(priv->ut_info->uf_info.irq,
@@ -731,10 +734,13 @@ static int uhdlc_open(struct net_device *dev)
                napi_enable(&priv->napi);
                netdev_reset_queue(dev);
                netif_start_queue(dev);
-               hdlc_open(dev);
+
+               rc = hdlc_open(dev);
+               if (rc)
+                       uhdlc_close(dev);
        }
 
-       return 0;
+       return rc;
 }
 
 static void uhdlc_memclean(struct ucc_hdlc_private *priv)
@@ -824,6 +830,8 @@ static int uhdlc_close(struct net_device *dev)
        netdev_reset_queue(dev);
        priv->hdlc_busy = 0;
 
+       hdlc_close(dev);
+
        return 0;
 }
 
index bece267..611d1a6 100644 (file)
@@ -442,7 +442,12 @@ struct brcmf_scan_params_v2_le {
                                 * fixed parameter portion is assumed, otherwise
                                 * ssid in the fixed portion is ignored
                                 */
-       __le16 channel_list[1]; /* list of chanspecs */
+       union {
+               __le16 padding; /* Reserve space for at least 1 entry for abort
+                                * which uses an on stack brcmf_scan_params_v2_le
+                                */
+               DECLARE_FLEX_ARRAY(__le16, channel_list);       /* chanspecs */
+       };
 };
 
 struct brcmf_scan_results {
@@ -702,7 +707,7 @@ struct brcmf_sta_info_le {
 
 struct brcmf_chanspec_list {
        __le32  count;          /* # of entries */
-       __le32  element[1];     /* variable length uint32 list */
+       __le32  element[];      /* variable length uint32 list */
 };
 
 /*
index f5e0898..06d6f7f 100644 (file)
@@ -310,9 +310,9 @@ struct iwl_fw_ini_fifo_hdr {
 struct iwl_fw_ini_error_dump_range {
        __le32 range_data_size;
        union {
-               __le32 internal_base_addr;
-               __le64 dram_base_addr;
-               __le32 page_num;
+               __le32 internal_base_addr __packed;
+               __le64 dram_base_addr __packed;
+               __le32 page_num __packed;
                struct iwl_fw_ini_fifo_hdr fifo_hdr;
                struct iwl_cmd_header fw_pkt_hdr;
        };
index 1f5db65..1d5ee43 100644 (file)
@@ -802,7 +802,7 @@ out:
                mvm->nvm_data->bands[0].n_channels = 1;
                mvm->nvm_data->bands[0].n_bitrates = 1;
                mvm->nvm_data->bands[0].bitrates =
-                       (void *)((u8 *)mvm->nvm_data->channels + 1);
+                       (void *)(mvm->nvm_data->channels + 1);
                mvm->nvm_data->bands[0].bitrates->hw_value = 10;
        }
 
index 8b6c641..b719843 100644 (file)
@@ -731,73 +731,78 @@ static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm *mvm,
 
        mvmvif->associated = vif->cfg.assoc;
 
-       if (!(changes & BSS_CHANGED_ASSOC))
-               return;
-
-       if (vif->cfg.assoc) {
-               /* clear statistics to get clean beacon counter */
-               iwl_mvm_request_statistics(mvm, true);
-               iwl_mvm_sf_update(mvm, vif, false);
-               iwl_mvm_power_vif_assoc(mvm, vif);
-
-               for_each_mvm_vif_valid_link(mvmvif, i) {
-                       memset(&mvmvif->link[i]->beacon_stats, 0,
-                              sizeof(mvmvif->link[i]->beacon_stats));
+       if (changes & BSS_CHANGED_ASSOC) {
+               if (vif->cfg.assoc) {
+                       /* clear statistics to get clean beacon counter */
+                       iwl_mvm_request_statistics(mvm, true);
+                       iwl_mvm_sf_update(mvm, vif, false);
+                       iwl_mvm_power_vif_assoc(mvm, vif);
+
+                       for_each_mvm_vif_valid_link(mvmvif, i) {
+                               memset(&mvmvif->link[i]->beacon_stats, 0,
+                                      sizeof(mvmvif->link[i]->beacon_stats));
+
+                               if (vif->p2p) {
+                                       iwl_mvm_update_smps(mvm, vif,
+                                                           IWL_MVM_SMPS_REQ_PROT,
+                                                           IEEE80211_SMPS_DYNAMIC, i);
+                               }
+
+                               rcu_read_lock();
+                               link_conf = rcu_dereference(vif->link_conf[i]);
+                               if (link_conf && !link_conf->dtim_period)
+                                       protect = true;
+                               rcu_read_unlock();
+                       }
 
-                       if (vif->p2p) {
-                               iwl_mvm_update_smps(mvm, vif,
-                                                   IWL_MVM_SMPS_REQ_PROT,
-                                                   IEEE80211_SMPS_DYNAMIC, i);
+                       if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
+                           protect) {
+                               /* If we're not restarting and still haven't
+                                * heard a beacon (dtim period unknown) then
+                                * make sure we still have enough minimum time
+                                * remaining in the time event, since the auth
+                                * might actually have taken quite a while
+                                * (especially for SAE) and so the remaining
+                                * time could be small without us having heard
+                                * a beacon yet.
+                                */
+                               iwl_mvm_protect_assoc(mvm, vif, 0);
                        }
 
-                       rcu_read_lock();
-                       link_conf = rcu_dereference(vif->link_conf[i]);
-                       if (link_conf && !link_conf->dtim_period)
-                               protect = true;
-                       rcu_read_unlock();
-               }
+                       iwl_mvm_sf_update(mvm, vif, false);
+
+                       /* FIXME: need to decide about misbehaving AP handling */
+                       iwl_mvm_power_vif_assoc(mvm, vif);
+               } else if (iwl_mvm_mld_vif_have_valid_ap_sta(mvmvif)) {
+                       iwl_mvm_mei_host_disassociated(mvm);
 
-               if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
-                   protect) {
-                       /* If we're not restarting and still haven't
-                        * heard a beacon (dtim period unknown) then
-                        * make sure we still have enough minimum time
-                        * remaining in the time event, since the auth
-                        * might actually have taken quite a while
-                        * (especially for SAE) and so the remaining
-                        * time could be small without us having heard
-                        * a beacon yet.
+                       /* If update fails - SF might be running in associated
+                        * mode while disassociated - which is forbidden.
                         */
-                       iwl_mvm_protect_assoc(mvm, vif, 0);
+                       ret = iwl_mvm_sf_update(mvm, vif, false);
+                       WARN_ONCE(ret &&
+                                 !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
+                                           &mvm->status),
+                                 "Failed to update SF upon disassociation\n");
+
+                       /* If we get an assert during the connection (after the
+                        * station has been added, but before the vif is set
+                        * to associated), mac80211 will re-add the station and
+                        * then configure the vif. Since the vif is not
+                        * associated, we would remove the station here and
+                        * this would fail the recovery.
+                        */
+                       iwl_mvm_mld_vif_delete_all_stas(mvm, vif);
                }
 
-               iwl_mvm_sf_update(mvm, vif, false);
-
-               /* FIXME: need to decide about misbehaving AP handling */
-               iwl_mvm_power_vif_assoc(mvm, vif);
-       } else if (iwl_mvm_mld_vif_have_valid_ap_sta(mvmvif)) {
-               iwl_mvm_mei_host_disassociated(mvm);
-
-               /* If update fails - SF might be running in associated
-                * mode while disassociated - which is forbidden.
-                */
-               ret = iwl_mvm_sf_update(mvm, vif, false);
-               WARN_ONCE(ret &&
-                         !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
-                                   &mvm->status),
-                         "Failed to update SF upon disassociation\n");
-
-               /* If we get an assert during the connection (after the
-                * station has been added, but before the vif is set
-                * to associated), mac80211 will re-add the station and
-                * then configure the vif. Since the vif is not
-                * associated, we would remove the station here and
-                * this would fail the recovery.
-                */
-               iwl_mvm_mld_vif_delete_all_stas(mvm, vif);
+               iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes);
        }
 
-       iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes);
+       if (changes & BSS_CHANGED_PS) {
+               ret = iwl_mvm_power_update_mac(mvm);
+               if (ret)
+                       IWL_ERR(mvm, "failed to update power mode\n");
+       }
 }
 
 static void
index c1d9ce7..3cbe2c0 100644 (file)
@@ -2342,7 +2342,7 @@ iwl_mvm_scan_umac_fill_general_p_v12(struct iwl_mvm *mvm,
        if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2)
                gp->num_of_fragments[SCAN_HB_LMAC_IDX] = IWL_SCAN_NUM_OF_FRAGS;
 
-       if (version < 12) {
+       if (version < 16) {
                gp->scan_start_mac_or_link_id = scan_vif->id;
        } else {
                struct iwl_mvm_vif_link_info *link_info;
index 36d70d5..898dca3 100644 (file)
@@ -1612,6 +1612,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
                iwl_trans_free_tx_cmd(mvm->trans, info->driver_data[1]);
 
                memset(&info->status, 0, sizeof(info->status));
+               info->flags &= ~(IEEE80211_TX_STAT_ACK | IEEE80211_TX_STAT_TX_FILTERED);
 
                /* inform mac80211 about what happened with the frame */
                switch (status & TX_STATUS_MSK) {
@@ -1964,6 +1965,8 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
                 */
                if (!is_flush)
                        info->flags |= IEEE80211_TX_STAT_ACK;
+               else
+                       info->flags &= ~IEEE80211_TX_STAT_ACK;
        }
 
        /*
index 391793a..10690e8 100644 (file)
@@ -918,9 +918,17 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv,
 
        mwifiex_dbg_dump(priv->adapter, EVT_D, "RXBA_SYNC event:",
                         event_buf, len);
-       while (tlv_buf_left >= sizeof(*tlv_rxba)) {
+       while (tlv_buf_left > sizeof(*tlv_rxba)) {
                tlv_type = le16_to_cpu(tlv_rxba->header.type);
                tlv_len  = le16_to_cpu(tlv_rxba->header.len);
+               if (size_add(sizeof(tlv_rxba->header), tlv_len) > tlv_buf_left) {
+                       mwifiex_dbg(priv->adapter, WARN,
+                                   "TLV size (%zu) overflows event_buf buf_left=%d\n",
+                                   size_add(sizeof(tlv_rxba->header), tlv_len),
+                                   tlv_buf_left);
+                       return;
+               }
+
                if (tlv_type != TLV_TYPE_RXBA_SYNC) {
                        mwifiex_dbg(priv->adapter, ERROR,
                                    "Wrong TLV id=0x%x\n", tlv_type);
@@ -929,6 +937,14 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv,
 
                tlv_seq_num = le16_to_cpu(tlv_rxba->seq_num);
                tlv_bitmap_len = le16_to_cpu(tlv_rxba->bitmap_len);
+               if (size_add(sizeof(*tlv_rxba), tlv_bitmap_len) > tlv_buf_left) {
+                       mwifiex_dbg(priv->adapter, WARN,
+                                   "TLV size (%zu) overflows event_buf buf_left=%d\n",
+                                   size_add(sizeof(*tlv_rxba), tlv_bitmap_len),
+                                   tlv_buf_left);
+                       return;
+               }
+
                mwifiex_dbg(priv->adapter, INFO,
                            "%pM tid=%d seq_num=%d bitmap_len=%d\n",
                            tlv_rxba->mac, tlv_rxba->tid, tlv_seq_num,
@@ -965,8 +981,8 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv,
                        }
                }
 
-               tlv_buf_left -= (sizeof(*tlv_rxba) + tlv_len);
-               tmp = (u8 *)tlv_rxba + tlv_len + sizeof(*tlv_rxba);
+               tlv_buf_left -= (sizeof(tlv_rxba->header) + tlv_len);
+               tmp = (u8 *)tlv_rxba  + sizeof(tlv_rxba->header) + tlv_len;
                tlv_rxba = (struct mwifiex_ie_types_rxba_sync *)tmp;
        }
 }
index f2168fa..8e6db90 100644 (file)
@@ -779,7 +779,7 @@ struct mwifiex_ie_types_rxba_sync {
        u8 reserved;
        __le16 seq_num;
        __le16 bitmap_len;
-       u8 bitmap[1];
+       u8 bitmap[];
 } __packed;
 
 struct chan_band_param_set {
index 65420ad..2577371 100644 (file)
@@ -86,7 +86,8 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv,
        rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length);
        rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off;
 
-       if (sizeof(*rx_pkt_hdr) + rx_pkt_off > skb->len) {
+       if (sizeof(rx_pkt_hdr->eth803_hdr) + sizeof(rfc1042_header) +
+           rx_pkt_off > skb->len) {
                mwifiex_dbg(priv->adapter, ERROR,
                            "wrong rx packet offset: len=%d, rx_pkt_off=%d\n",
                            skb->len, rx_pkt_off);
@@ -95,12 +96,13 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv,
                return -1;
        }
 
-       if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
-                    sizeof(bridge_tunnel_header))) ||
-           (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header,
-                    sizeof(rfc1042_header)) &&
-            ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP &&
-            ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) {
+       if (sizeof(*rx_pkt_hdr) + rx_pkt_off <= skb->len &&
+           ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
+                     sizeof(bridge_tunnel_header))) ||
+            (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header,
+                     sizeof(rfc1042_header)) &&
+             ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP &&
+             ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX))) {
                /*
                 *  Replace the 803 header and rfc1042 header (llc/snap) with an
                 *    EthernetII header, keep the src/dst and snap_type
index 05d9ab3..dc8f4e1 100644 (file)
@@ -93,13 +93,13 @@ __mt76_get_rxwi(struct mt76_dev *dev)
 {
        struct mt76_txwi_cache *t = NULL;
 
-       spin_lock(&dev->wed_lock);
+       spin_lock_bh(&dev->wed_lock);
        if (!list_empty(&dev->rxwi_cache)) {
                t = list_first_entry(&dev->rxwi_cache, struct mt76_txwi_cache,
                                     list);
                list_del(&t->list);
        }
-       spin_unlock(&dev->wed_lock);
+       spin_unlock_bh(&dev->wed_lock);
 
        return t;
 }
@@ -145,9 +145,9 @@ mt76_put_rxwi(struct mt76_dev *dev, struct mt76_txwi_cache *t)
        if (!t)
                return;
 
-       spin_lock(&dev->wed_lock);
+       spin_lock_bh(&dev->wed_lock);
        list_add(&t->list, &dev->rxwi_cache);
-       spin_unlock(&dev->wed_lock);
+       spin_unlock_bh(&dev->wed_lock);
 }
 EXPORT_SYMBOL_GPL(mt76_put_rxwi);
 
index 0acabba..5d402cf 100644 (file)
@@ -131,15 +131,8 @@ u8 mt76x02_get_lna_gain(struct mt76x02_dev *dev,
                        s8 *lna_2g, s8 *lna_5g,
                        struct ieee80211_channel *chan)
 {
-       u16 val;
        u8 lna;
 
-       val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1);
-       if (val & MT_EE_NIC_CONF_1_LNA_EXT_2G)
-               *lna_2g = 0;
-       if (val & MT_EE_NIC_CONF_1_LNA_EXT_5G)
-               memset(lna_5g, 0, sizeof(s8) * 3);
-
        if (chan->band == NL80211_BAND_2GHZ)
                lna = *lna_2g;
        else if (chan->hw_value <= 64)
index d580940..8c01855 100644 (file)
@@ -256,7 +256,8 @@ void mt76x2_read_rx_gain(struct mt76x02_dev *dev)
        struct ieee80211_channel *chan = dev->mphy.chandef.chan;
        int channel = chan->hw_value;
        s8 lna_5g[3], lna_2g;
-       u8 lna;
+       bool use_lna;
+       u8 lna = 0;
        u16 val;
 
        if (chan->band == NL80211_BAND_2GHZ)
@@ -275,7 +276,15 @@ void mt76x2_read_rx_gain(struct mt76x02_dev *dev)
        dev->cal.rx.mcu_gain |= (lna_5g[1] & 0xff) << 16;
        dev->cal.rx.mcu_gain |= (lna_5g[2] & 0xff) << 24;
 
-       lna = mt76x02_get_lna_gain(dev, &lna_2g, lna_5g, chan);
+       val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1);
+       if (chan->band == NL80211_BAND_2GHZ)
+               use_lna = !(val & MT_EE_NIC_CONF_1_LNA_EXT_2G);
+       else
+               use_lna = !(val & MT_EE_NIC_CONF_1_LNA_EXT_5G);
+
+       if (use_lna)
+               lna = mt76x02_get_lna_gain(dev, &lna_2g, lna_5g, chan);
+
        dev->cal.rx.lna_gain = mt76x02_sign_extend(lna, 8);
 }
 EXPORT_SYMBOL_GPL(mt76x2_read_rx_gain);
index 3642a2c..2434e24 100644 (file)
@@ -46,6 +46,7 @@ struct rtw8723du_efuse {
        u8 vender_id[2];                /* 0x100 */
        u8 product_id[2];               /* 0x102 */
        u8 usb_option;                  /* 0x104 */
+       u8 res5[2];                     /* 0x105 */
        u8 mac_addr[ETH_ALEN];          /* 0x107 */
 };
 
index 0a3483e..f63250c 100644 (file)
@@ -890,13 +890,13 @@ int of_changeset_action(struct of_changeset *ocs, unsigned long action,
 {
        struct of_changeset_entry *ce;
 
+       if (WARN_ON(action >= ARRAY_SIZE(action_names)))
+               return -EINVAL;
+
        ce = kzalloc(sizeof(*ce), GFP_KERNEL);
        if (!ce)
                return -ENOMEM;
 
-       if (WARN_ON(action >= ARRAY_SIZE(action_names)))
-               return -EINVAL;
-
        /* get a reference to the node */
        ce->action = action;
        ce->np = of_node_get(np);
index dfb6fb9..a9a292d 100644 (file)
@@ -45,8 +45,8 @@ struct target {
 
 /**
  * struct fragment - info about fragment nodes in overlay expanded device tree
- * @target:    target of the overlay operation
  * @overlay:   pointer to the __overlay__ node
+ * @target:    target of the overlay operation
  */
 struct fragment {
        struct device_node *overlay;
index e2f2940..64420ec 100644 (file)
@@ -43,7 +43,6 @@
 #define PARF_PHY_REFCLK                                0x4c
 #define PARF_CONFIG_BITS                       0x50
 #define PARF_DBI_BASE_ADDR                     0x168
-#define PARF_SLV_ADDR_SPACE_SIZE_2_3_3         0x16c /* Register offset specific to IP ver 2.3.3 */
 #define PARF_MHI_CLOCK_RESET_CTRL              0x174
 #define PARF_AXI_MSTR_WR_ADDR_HALT             0x178
 #define PARF_AXI_MSTR_WR_ADDR_HALT_V2          0x1a8
@@ -797,8 +796,7 @@ static int qcom_pcie_post_init_2_3_3(struct qcom_pcie *pcie)
        u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
        u32 val;
 
-       writel(SLV_ADDR_SPACE_SZ,
-               pcie->parf + PARF_SLV_ADDR_SPACE_SIZE_2_3_3);
+       writel(SLV_ADDR_SPACE_SZ, pcie->parf + PARF_SLV_ADDR_SPACE_SIZE);
 
        val = readl(pcie->parf + PARF_PHY_CTRL);
        val &= ~PHY_TEST_PWR_DOWN;
index 2af64bc..51e3dd0 100644 (file)
@@ -657,30 +657,33 @@ void of_pci_make_dev_node(struct pci_dev *pdev)
 
        cset = kmalloc(sizeof(*cset), GFP_KERNEL);
        if (!cset)
-               goto failed;
+               goto out_free_name;
        of_changeset_init(cset);
 
        np = of_changeset_create_node(cset, ppnode, name);
        if (!np)
-               goto failed;
-       np->data = cset;
+               goto out_destroy_cset;
 
        ret = of_pci_add_properties(pdev, cset, np);
        if (ret)
-               goto failed;
+               goto out_free_node;
 
        ret = of_changeset_apply(cset);
        if (ret)
-               goto failed;
+               goto out_free_node;
 
+       np->data = cset;
        pdev->dev.of_node = np;
        kfree(name);
 
        return;
 
-failed:
-       if (np)
-               of_node_put(np);
+out_free_node:
+       of_node_put(np);
+out_destroy_cset:
+       of_changeset_destroy(cset);
+       kfree(cset);
+out_free_name:
        kfree(name);
 }
 #endif
index 710ec35..c2c7334 100644 (file)
@@ -186,8 +186,8 @@ static int of_pci_prop_interrupts(struct pci_dev *pdev,
 static int of_pci_prop_intr_map(struct pci_dev *pdev, struct of_changeset *ocs,
                                struct device_node *np)
 {
+       u32 i, addr_sz[OF_PCI_MAX_INT_PIN] = { 0 }, map_sz = 0;
        struct of_phandle_args out_irq[OF_PCI_MAX_INT_PIN];
-       u32 i, addr_sz[OF_PCI_MAX_INT_PIN], map_sz = 0;
        __be32 laddr[OF_PCI_ADDRESS_CELLS] = { 0 };
        u32 int_map_mask[] = { 0xffff00, 0, 0, 7 };
        struct device_node *pnode;
@@ -213,33 +213,44 @@ static int of_pci_prop_intr_map(struct pci_dev *pdev, struct of_changeset *ocs,
                out_irq[i].args[0] = pin;
                ret = of_irq_parse_raw(laddr, &out_irq[i]);
                if (ret) {
-                       pci_err(pdev, "parse irq %d failed, ret %d", pin, ret);
+                       out_irq[i].np = NULL;
+                       pci_dbg(pdev, "parse irq %d failed, ret %d", pin, ret);
                        continue;
                }
-               ret = of_property_read_u32(out_irq[i].np, "#address-cells",
-                                          &addr_sz[i]);
-               if (ret)
-                       addr_sz[i] = 0;
+               of_property_read_u32(out_irq[i].np, "#address-cells",
+                                    &addr_sz[i]);
        }
 
        list_for_each_entry(child, &pdev->subordinate->devices, bus_list) {
                for (pin = 1; pin <= OF_PCI_MAX_INT_PIN; pin++) {
                        i = pci_swizzle_interrupt_pin(child, pin) - 1;
+                       if (!out_irq[i].np)
+                               continue;
                        map_sz += 5 + addr_sz[i] + out_irq[i].args_count;
                }
        }
 
+       /*
+        * Parsing interrupt failed for all pins. In this case, it does not
+        * need to generate interrupt-map property.
+        */
+       if (!map_sz)
+               return 0;
+
        int_map = kcalloc(map_sz, sizeof(u32), GFP_KERNEL);
        mapp = int_map;
 
        list_for_each_entry(child, &pdev->subordinate->devices, bus_list) {
                for (pin = 1; pin <= OF_PCI_MAX_INT_PIN; pin++) {
+                       i = pci_swizzle_interrupt_pin(child, pin) - 1;
+                       if (!out_irq[i].np)
+                               continue;
+
                        *mapp = (child->bus->number << 16) |
                                (child->devfn << 8);
                        mapp += OF_PCI_ADDRESS_CELLS;
                        *mapp = pin;
                        mapp++;
-                       i = pci_swizzle_interrupt_pin(child, pin) - 1;
                        *mapp = out_irq[i].np->phandle;
                        mapp++;
                        if (addr_sz[i]) {
index a79c110..51ec9e7 100644 (file)
@@ -572,7 +572,19 @@ static void pci_pm_default_resume_early(struct pci_dev *pci_dev)
 
 static void pci_pm_bridge_power_up_actions(struct pci_dev *pci_dev)
 {
-       pci_bridge_wait_for_secondary_bus(pci_dev, "resume");
+       int ret;
+
+       ret = pci_bridge_wait_for_secondary_bus(pci_dev, "resume");
+       if (ret) {
+               /*
+                * The downstream link failed to come up, so mark the
+                * devices below as disconnected to make sure we don't
+                * attempt to resume them.
+                */
+               pci_walk_bus(pci_dev->subordinate, pci_dev_set_disconnected,
+                            NULL);
+               return;
+       }
 
        /*
         * When powering on a bridge from D3cold, the whole hierarchy may be
index 913dc04..6b50bc5 100644 (file)
@@ -1972,7 +1972,7 @@ static irqreturn_t arm_cmn_handle_irq(int irq, void *dev_id)
                u64 delta;
                int i;
 
-               for (i = 0; i < CMN_DTM_NUM_COUNTERS; i++) {
+               for (i = 0; i < CMN_DT_NUM_COUNTERS; i++) {
                        if (status & (1U << i)) {
                                ret = IRQ_HANDLED;
                                if (WARN_ON(!dtc->counters[i]))
index f3696a5..fd38d8c 100644 (file)
@@ -53,7 +53,7 @@
 struct mlxbf_tmfifo;
 
 /**
- * mlxbf_tmfifo_vring - Structure of the TmFifo virtual ring
+ * struct mlxbf_tmfifo_vring - Structure of the TmFifo virtual ring
  * @va: virtual address of the ring
  * @dma: dma address of the ring
  * @vq: pointer to the virtio virtqueue
@@ -113,12 +113,13 @@ enum {
 };
 
 /**
- * mlxbf_tmfifo_vdev - Structure of the TmFifo virtual device
+ * struct mlxbf_tmfifo_vdev - Structure of the TmFifo virtual device
  * @vdev: virtio device, in which the vdev.id.device field has the
  *        VIRTIO_ID_xxx id to distinguish the virtual device.
  * @status: status of the device
  * @features: supported features of the device
  * @vrings: array of tmfifo vrings of this device
+ * @config: non-anonymous union for cons and net
  * @config.cons: virtual console config -
  *               select if vdev.id.device is VIRTIO_ID_CONSOLE
  * @config.net: virtual network config -
@@ -138,7 +139,7 @@ struct mlxbf_tmfifo_vdev {
 };
 
 /**
- * mlxbf_tmfifo_irq_info - Structure of the interrupt information
+ * struct mlxbf_tmfifo_irq_info - Structure of the interrupt information
  * @fifo: pointer to the tmfifo structure
  * @irq: interrupt number
  * @index: index into the interrupt array
@@ -150,7 +151,7 @@ struct mlxbf_tmfifo_irq_info {
 };
 
 /**
- * mlxbf_tmfifo_io - Structure of the TmFifo IO resource (for both rx & tx)
+ * struct mlxbf_tmfifo_io - Structure of the TmFifo IO resource (for both rx & tx)
  * @ctl: control register offset (TMFIFO_RX_CTL / TMFIFO_TX_CTL)
  * @sts: status register offset (TMFIFO_RX_STS / TMFIFO_TX_STS)
  * @data: data register offset (TMFIFO_RX_DATA / TMFIFO_TX_DATA)
@@ -162,7 +163,7 @@ struct mlxbf_tmfifo_io {
 };
 
 /**
- * mlxbf_tmfifo - Structure of the TmFifo
+ * struct mlxbf_tmfifo - Structure of the TmFifo
  * @vdev: array of the virtual devices running over the TmFifo
  * @lock: lock to protect the TmFifo access
  * @res0: mapped resource block 0
@@ -198,7 +199,7 @@ struct mlxbf_tmfifo {
 };
 
 /**
- * mlxbf_tmfifo_msg_hdr - Structure of the TmFifo message header
+ * struct mlxbf_tmfifo_msg_hdr - Structure of the TmFifo message header
  * @type: message type
  * @len: payload length in network byte order. Messages sent into the FIFO
  *       will be read by the other side as data stream in the same byte order.
@@ -208,6 +209,7 @@ struct mlxbf_tmfifo {
 struct mlxbf_tmfifo_msg_hdr {
        u8 type;
        __be16 len;
+       /* private: */
        u8 unused[5];
 } __packed __aligned(sizeof(u64));
 
index 8c4f9e1..5798b49 100644 (file)
@@ -659,7 +659,7 @@ static int hp_init_bios_package_attribute(enum hp_wmi_data_type attr_type,
                                          const char *guid, int min_elements,
                                          int instance_id)
 {
-       struct kobject *attr_name_kobj;
+       struct kobject *attr_name_kobj, *duplicate;
        union acpi_object *elements;
        struct kset *temp_kset;
 
@@ -704,8 +704,11 @@ static int hp_init_bios_package_attribute(enum hp_wmi_data_type attr_type,
        }
 
        /* All duplicate attributes found are ignored */
-       if (kset_find_obj(temp_kset, str_value)) {
+       duplicate = kset_find_obj(temp_kset, str_value);
+       if (duplicate) {
                pr_debug("Duplicate attribute name found - %s\n", str_value);
+               /* kset_find_obj() returns a reference */
+               kobject_put(duplicate);
                goto pack_attr_exit;
        }
 
@@ -768,7 +771,7 @@ static int hp_init_bios_buffer_attribute(enum hp_wmi_data_type attr_type,
                                         const char *guid, int min_elements,
                                         int instance_id)
 {
-       struct kobject *attr_name_kobj;
+       struct kobject *attr_name_kobj, *duplicate;
        struct kset *temp_kset;
        char str[MAX_BUFF_SIZE];
 
@@ -794,8 +797,11 @@ static int hp_init_bios_buffer_attribute(enum hp_wmi_data_type attr_type,
                temp_kset = bioscfg_drv.main_dir_kset;
 
        /* All duplicate attributes found are ignored */
-       if (kset_find_obj(temp_kset, str)) {
+       duplicate = kset_find_obj(temp_kset, str);
+       if (duplicate) {
                pr_debug("Duplicate attribute name found - %s\n", str);
+               /* kset_find_obj() returns a reference */
+               kobject_put(duplicate);
                goto buff_attr_exit;
        }
 
index e76e545..8ebb7be 100644 (file)
@@ -1548,7 +1548,13 @@ static const struct dev_pm_ops hp_wmi_pm_ops = {
        .restore  = hp_wmi_resume_handler,
 };
 
-static struct platform_driver hp_wmi_driver = {
+/*
+ * hp_wmi_bios_remove() lives in .exit.text. For drivers registered via
+ * module_platform_driver_probe() this is ok because they cannot get unbound at
+ * runtime. So mark the driver struct with __refdata to prevent modpost
+ * triggering a section mismatch warning.
+ */
+static struct platform_driver hp_wmi_driver __refdata = {
        .driver = {
                .name = "hp-wmi",
                .pm = &hp_wmi_pm_ops,
index 1061eb7..43c864a 100644 (file)
@@ -331,14 +331,15 @@ int do_core_test(int cpu, struct device *dev)
        switch (test->test_num) {
        case IFS_TYPE_SAF:
                if (!ifsd->loaded)
-                       return -EPERM;
-               ifs_test_core(cpu, dev);
+                       ret = -EPERM;
+               else
+                       ifs_test_core(cpu, dev);
                break;
        case IFS_TYPE_ARRAY_BIST:
                ifs_array_test_core(cpu, dev);
                break;
        default:
-               return -EINVAL;
+               ret = -EINVAL;
        }
 out:
        cpus_read_unlock();
index 7934688..aee8697 100644 (file)
@@ -1248,6 +1248,24 @@ static void tlmi_release_attr(void)
        kset_unregister(tlmi_priv.authentication_kset);
 }
 
+static int tlmi_validate_setting_name(struct kset *attribute_kset, char *name)
+{
+       struct kobject *duplicate;
+
+       if (!strcmp(name, "Reserved"))
+               return -EINVAL;
+
+       duplicate = kset_find_obj(attribute_kset, name);
+       if (duplicate) {
+               pr_debug("Duplicate attribute name found - %s\n", name);
+               /* kset_find_obj() returns a reference */
+               kobject_put(duplicate);
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
 static int tlmi_sysfs_init(void)
 {
        int i, ret;
@@ -1276,10 +1294,8 @@ static int tlmi_sysfs_init(void)
                        continue;
 
                /* check for duplicate or reserved values */
-               if (kset_find_obj(tlmi_priv.attribute_kset, tlmi_priv.setting[i]->display_name) ||
-                   !strcmp(tlmi_priv.setting[i]->display_name, "Reserved")) {
-                       pr_debug("duplicate or reserved attribute name found - %s\n",
-                               tlmi_priv.setting[i]->display_name);
+               if (tlmi_validate_setting_name(tlmi_priv.attribute_kset,
+                                              tlmi_priv.setting[i]->display_name) < 0) {
                        kfree(tlmi_priv.setting[i]->possible_values);
                        kfree(tlmi_priv.setting[i]);
                        tlmi_priv.setting[i] = NULL;
index f9301a9..0c67337 100644 (file)
@@ -42,6 +42,21 @@ static const struct ts_dmi_data archos_101_cesium_educ_data = {
        .properties     = archos_101_cesium_educ_props,
 };
 
+static const struct property_entry bush_bush_windows_tablet_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1850),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
+       PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       PROPERTY_ENTRY_BOOL("silead,home-button"),
+       PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-bush-bush-windows-tablet.fw"),
+       { }
+};
+
+static const struct ts_dmi_data bush_bush_windows_tablet_data = {
+       .acpi_name      = "MSSL1680:00",
+       .properties     = bush_bush_windows_tablet_props,
+};
+
 static const struct property_entry chuwi_hi8_props[] = {
        PROPERTY_ENTRY_U32("touchscreen-size-x", 1665),
        PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
@@ -756,6 +771,21 @@ static const struct ts_dmi_data pipo_w11_data = {
        .properties     = pipo_w11_props,
 };
 
+static const struct property_entry positivo_c4128b_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 4),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 13),
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1915),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1269),
+       PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-positivo-c4128b.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       { }
+};
+
+static const struct ts_dmi_data positivo_c4128b_data = {
+       .acpi_name      = "MSSL1680:00",
+       .properties     = positivo_c4128b_props,
+};
+
 static const struct property_entry pov_mobii_wintab_p800w_v20_props[] = {
        PROPERTY_ENTRY_U32("touchscreen-min-x", 32),
        PROPERTY_ENTRY_U32("touchscreen-min-y", 16),
@@ -1071,6 +1101,13 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
                },
        },
        {
+               /* Bush Windows tablet */
+               .driver_data = (void *)&bush_bush_windows_tablet_data,
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Bush Windows tablet"),
+               },
+       },
+       {
                /* Chuwi Hi8 */
                .driver_data = (void *)&chuwi_hi8_data,
                .matches = {
@@ -1481,6 +1518,14 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
                },
        },
        {
+               /* Positivo C4128B */
+               .driver_data = (void *)&positivo_c4128b_data,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Positivo Tecnologia SA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "C4128B-1"),
+               },
+       },
+       {
                /* Point of View mobii wintab p800w (v2.0) */
                .driver_data = (void *)&pov_mobii_wintab_p800w_v20_data,
                .matches = {
index 20a974c..a7a6947 100644 (file)
@@ -3998,7 +3998,6 @@ ptp_ocp_device_init(struct ptp_ocp *bp, struct pci_dev *pdev)
        return 0;
 
 out:
-       ptp_ocp_dev_release(&bp->dev);
        put_device(&bp->dev);
        return err;
 }
index d8e1caa..3137e40 100644 (file)
@@ -5542,6 +5542,8 @@ regulator_register(struct device *dev,
                goto rinse;
        }
        device_initialize(&rdev->dev);
+       dev_set_drvdata(&rdev->dev, rdev);
+       rdev->dev.class = &regulator_class;
        spin_lock_init(&rdev->err_lock);
 
        /*
@@ -5603,11 +5605,9 @@ regulator_register(struct device *dev,
                rdev->supply_name = regulator_desc->supply_name;
 
        /* register with sysfs */
-       rdev->dev.class = &regulator_class;
        rdev->dev.parent = config->dev;
        dev_set_name(&rdev->dev, "regulator.%lu",
                    (unsigned long) atomic_inc_return(&regulator_no));
-       dev_set_drvdata(&rdev->dev, rdev);
 
        /* set regulator constraints */
        if (init_data)
@@ -5724,15 +5724,11 @@ wash:
        mutex_lock(&regulator_list_mutex);
        regulator_ena_gpio_free(rdev);
        mutex_unlock(&regulator_list_mutex);
-       put_device(&rdev->dev);
-       rdev = NULL;
 clean:
        if (dangling_of_gpiod)
                gpiod_put(config->ena_gpiod);
-       if (rdev && rdev->dev.of_node)
-               of_node_put(rdev->dev.of_node);
-       kfree(rdev);
        kfree(config);
+       put_device(&rdev->dev);
 rinse:
        if (dangling_cfg_gpiod)
                gpiod_put(cfg->ena_gpiod);
index b9cda22..65fbd95 100644 (file)
@@ -43,7 +43,7 @@ struct mt6358_regulator_info {
        .desc = {       \
                .name = #vreg,  \
                .of_match = of_match_ptr(match),        \
-               .ops = &mt6358_volt_range_ops,  \
+               .ops = &mt6358_buck_ops,        \
                .type = REGULATOR_VOLTAGE,      \
                .id = MT6358_ID_##vreg,         \
                .owner = THIS_MODULE,           \
@@ -139,7 +139,7 @@ struct mt6358_regulator_info {
        .desc = {       \
                .name = #vreg,  \
                .of_match = of_match_ptr(match),        \
-               .ops = &mt6358_volt_range_ops,  \
+               .ops = &mt6358_buck_ops,        \
                .type = REGULATOR_VOLTAGE,      \
                .id = MT6366_ID_##vreg,         \
                .owner = THIS_MODULE,           \
@@ -450,7 +450,7 @@ static unsigned int mt6358_regulator_get_mode(struct regulator_dev *rdev)
        }
 }
 
-static const struct regulator_ops mt6358_volt_range_ops = {
+static const struct regulator_ops mt6358_buck_ops = {
        .list_voltage = regulator_list_voltage_linear,
        .map_voltage = regulator_map_voltage_linear,
        .set_voltage_sel = regulator_set_voltage_sel_regmap,
@@ -464,6 +464,18 @@ static const struct regulator_ops mt6358_volt_range_ops = {
        .get_mode = mt6358_regulator_get_mode,
 };
 
+static const struct regulator_ops mt6358_volt_range_ops = {
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = mt6358_get_buck_voltage_sel,
+       .set_voltage_time_sel = regulator_set_voltage_time_sel,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+       .get_status = mt6358_get_status,
+};
+
 static const struct regulator_ops mt6358_volt_table_ops = {
        .list_voltage = regulator_list_voltage_table,
        .map_voltage = regulator_map_voltage_iterate,
index df78264..ab2f35b 100644 (file)
@@ -518,12 +518,12 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
        if (port) {
                put_device(&port->dev);
                retval = -EEXIST;
-               goto err_out;
+               goto err_put;
        }
 
        port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL);
        if (!port)
-               goto err_out;
+               goto err_put;
 
        rwlock_init(&port->unit_list_lock);
        INIT_LIST_HEAD(&port->unit_list);
@@ -546,7 +546,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
 
        if (dev_set_name(&port->dev, "0x%016llx", (unsigned long long)wwpn)) {
                kfree(port);
-               goto err_out;
+               goto err_put;
        }
        retval = -EINVAL;
 
@@ -563,7 +563,8 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
 
        return port;
 
-err_out:
+err_put:
        zfcp_ccw_adapter_put(adapter);
+err_out:
        return ERR_PTR(retval);
 }
index 93c6893..22cef28 100644 (file)
@@ -27,7 +27,7 @@
 
 #define DRV_NAME               "fnic"
 #define DRV_DESCRIPTION                "Cisco FCoE HBA Driver"
-#define DRV_VERSION            "1.6.0.56"
+#define DRV_VERSION            "1.6.0.57"
 #define PFX                    DRV_NAME ": "
 #define DFX                     DRV_NAME "%d: "
 
@@ -237,6 +237,8 @@ struct fnic {
        unsigned int cq_count;
 
        struct mutex sgreset_mutex;
+       spinlock_t sgreset_lock; /* lock for sgreset */
+       struct scsi_cmnd *sgreset_sc;
        struct dentry *fnic_stats_debugfs_host;
        struct dentry *fnic_stats_debugfs_file;
        struct dentry *fnic_reset_debugfs_file;
index f4c8769..5895ead 100644 (file)
@@ -52,6 +52,8 @@ struct fnic_io_req {
        unsigned long start_time; /* in jiffies */
        struct completion *abts_done; /* completion for abts */
        struct completion *dr_done; /* completion for device reset */
+       unsigned int tag;
+       struct scsi_cmnd *sc; /* midlayer's cmd pointer */
 };
 
 enum fnic_port_speeds {
index 984bc5f..f27f931 100644 (file)
@@ -754,6 +754,8 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        for (i = 0; i < FNIC_IO_LOCKS; i++)
                spin_lock_init(&fnic->io_req_lock[i]);
 
+       spin_lock_init(&fnic->sgreset_lock);
+
        err = -ENOMEM;
        fnic->io_req_pool = mempool_create_slab_pool(2, fnic_io_req_cache);
        if (!fnic->io_req_pool)
index 9761b2c..416d819 100644 (file)
@@ -1047,9 +1047,9 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
 {
        u8 type;
        u8 hdr_status;
-       struct fcpio_tag tag;
+       struct fcpio_tag ftag;
        u32 id;
-       struct scsi_cmnd *sc;
+       struct scsi_cmnd *sc = NULL;
        struct fnic_io_req *io_req;
        struct fnic_stats *fnic_stats = &fnic->fnic_stats;
        struct abort_stats *abts_stats = &fnic->fnic_stats.abts_stats;
@@ -1058,27 +1058,43 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
        unsigned long flags;
        spinlock_t *io_lock;
        unsigned long start_time;
+       unsigned int tag;
 
-       fcpio_header_dec(&desc->hdr, &type, &hdr_status, &tag);
-       fcpio_tag_id_dec(&tag, &id);
+       fcpio_header_dec(&desc->hdr, &type, &hdr_status, &ftag);
+       fcpio_tag_id_dec(&ftag, &id);
 
-       if ((id & FNIC_TAG_MASK) >= fnic->fnic_max_tag_id) {
+       tag = id & FNIC_TAG_MASK;
+       if (tag == fnic->fnic_max_tag_id) {
+               if (!(id & FNIC_TAG_DEV_RST)) {
+                       shost_printk(KERN_ERR, fnic->lport->host,
+                                               "Tag out of range id 0x%x hdr status = %s\n",
+                                               id, fnic_fcpio_status_to_str(hdr_status));
+                       return;
+               }
+       } else if (tag > fnic->fnic_max_tag_id) {
                shost_printk(KERN_ERR, fnic->lport->host,
-               "Tag out of range tag %x hdr status = %s\n",
-               id, fnic_fcpio_status_to_str(hdr_status));
+                                       "Tag out of range tag 0x%x hdr status = %s\n",
+                                       tag, fnic_fcpio_status_to_str(hdr_status));
                return;
        }
 
-       sc = scsi_host_find_tag(fnic->lport->host, id & FNIC_TAG_MASK);
+       if ((tag == fnic->fnic_max_tag_id) && (id & FNIC_TAG_DEV_RST)) {
+               sc = fnic->sgreset_sc;
+               io_lock = &fnic->sgreset_lock;
+       } else {
+               sc = scsi_host_find_tag(fnic->lport->host, id & FNIC_TAG_MASK);
+               io_lock = fnic_io_lock_hash(fnic, sc);
+       }
+
        WARN_ON_ONCE(!sc);
        if (!sc) {
                atomic64_inc(&fnic_stats->io_stats.sc_null);
                shost_printk(KERN_ERR, fnic->lport->host,
                          "itmf_cmpl sc is null - hdr status = %s tag = 0x%x\n",
-                         fnic_fcpio_status_to_str(hdr_status), id);
+                         fnic_fcpio_status_to_str(hdr_status), tag);
                return;
        }
-       io_lock = fnic_io_lock_hash(fnic, sc);
+
        spin_lock_irqsave(io_lock, flags);
        io_req = fnic_priv(sc)->io_req;
        WARN_ON_ONCE(!io_req);
@@ -1089,7 +1105,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
                shost_printk(KERN_ERR, fnic->lport->host,
                          "itmf_cmpl io_req is null - "
                          "hdr status = %s tag = 0x%x sc 0x%p\n",
-                         fnic_fcpio_status_to_str(hdr_status), id, sc);
+                         fnic_fcpio_status_to_str(hdr_status), tag, sc);
                return;
        }
        start_time = io_req->start_time;
@@ -1938,6 +1954,10 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic,
        struct scsi_lun fc_lun;
        int ret = 0;
        unsigned long intr_flags;
+       unsigned int tag = scsi_cmd_to_rq(sc)->tag;
+
+       if (tag == SCSI_NO_TAG)
+               tag = io_req->tag;
 
        spin_lock_irqsave(host->host_lock, intr_flags);
        if (unlikely(fnic_chk_state_flags_locked(fnic,
@@ -1964,7 +1984,8 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic,
        /* fill in the lun info */
        int_to_scsilun(sc->device->lun, &fc_lun);
 
-       fnic_queue_wq_copy_desc_itmf(wq, scsi_cmd_to_rq(sc)->tag | FNIC_TAG_DEV_RST,
+       tag |= FNIC_TAG_DEV_RST;
+       fnic_queue_wq_copy_desc_itmf(wq, tag,
                                     0, FCPIO_ITMF_LUN_RESET, SCSI_NO_TAG,
                                     fc_lun.scsi_lun, io_req->port_id,
                                     fnic->config.ra_tov, fnic->config.ed_tov);
@@ -2146,8 +2167,7 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
                .ret = SUCCESS,
        };
 
-       if (new_sc)
-               iter_data.lr_sc = lr_sc;
+       iter_data.lr_sc = lr_sc;
 
        scsi_host_busy_iter(fnic->lport->host,
                            fnic_pending_aborts_iter, &iter_data);
@@ -2230,8 +2250,14 @@ int fnic_device_reset(struct scsi_cmnd *sc)
                mutex_lock(&fnic->sgreset_mutex);
                tag = fnic->fnic_max_tag_id;
                new_sc = 1;
-       }
-       io_lock = fnic_io_lock_hash(fnic, sc);
+               fnic->sgreset_sc = sc;
+               io_lock = &fnic->sgreset_lock;
+               FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
+                       "fcid: 0x%x lun: 0x%llx flags: 0x%x tag: 0x%x Issuing sgreset\n",
+                       rport->port_id, sc->device->lun, fnic_priv(sc)->flags, tag);
+       } else
+               io_lock = fnic_io_lock_hash(fnic, sc);
+
        spin_lock_irqsave(io_lock, flags);
        io_req = fnic_priv(sc)->io_req;
 
@@ -2247,6 +2273,8 @@ int fnic_device_reset(struct scsi_cmnd *sc)
                }
                memset(io_req, 0, sizeof(*io_req));
                io_req->port_id = rport->port_id;
+               io_req->tag = tag;
+               io_req->sc = sc;
                fnic_priv(sc)->io_req = io_req;
        }
        io_req->dr_done = &tm_done;
@@ -2400,8 +2428,10 @@ fnic_device_reset_end:
                  (u64)sc->cmnd[4] << 8 | sc->cmnd[5]),
                  fnic_flags_and_state(sc));
 
-       if (new_sc)
+       if (new_sc) {
+               fnic->sgreset_sc = NULL;
                mutex_unlock(&fnic->sgreset_mutex);
+       }
 
        FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
                      "Returning from device reset %s\n",
index 5d89171..75c985d 100644 (file)
@@ -12,12 +12,12 @@ menuconfig INTEL_ATOMISP
 config VIDEO_ATOMISP
        tristate "Intel Atom Image Signal Processor Driver"
        depends on VIDEO_DEV && INTEL_ATOMISP
+       depends on IPU_BRIDGE
        depends on MEDIA_PCI_SUPPORT
        depends on PMIC_OPREGION
        depends on I2C
        select V4L2_FWNODE
        select IOSF_MBI
-       select IPU_BRIDGE
        select VIDEOBUF2_VMALLOC
        select VIDEO_V4L2_SUBDEV_API
        help
index e98b301..94171e6 100644 (file)
@@ -1455,17 +1455,18 @@ static int __maybe_unused vi_runtime_suspend(struct device *dev)
 }
 
 /*
- * Graph Management
+ * Find the entity matching a given fwnode in an v4l2_async_notifier list
  */
 static struct tegra_vi_graph_entity *
-tegra_vi_graph_find_entity(struct tegra_vi_channel *chan,
+tegra_vi_graph_find_entity(struct list_head *list,
                           const struct fwnode_handle *fwnode)
 {
        struct tegra_vi_graph_entity *entity;
        struct v4l2_async_connection *asd;
 
-       list_for_each_entry(asd, &chan->notifier.done_list, asc_entry) {
+       list_for_each_entry(asd, list, asc_entry) {
                entity = to_tegra_vi_graph_entity(asd);
+
                if (entity->asd.match.fwnode == fwnode)
                        return entity;
        }
@@ -1532,7 +1533,8 @@ static int tegra_vi_graph_build(struct tegra_vi_channel *chan,
                }
 
                /* find the remote entity from notifier list */
-               ent = tegra_vi_graph_find_entity(chan, link.remote_node);
+               ent = tegra_vi_graph_find_entity(&chan->notifier.done_list,
+                                                link.remote_node);
                if (!ent) {
                        dev_err(vi->dev, "no entity found for %pOF\n",
                                to_of_node(link.remote_node));
@@ -1664,7 +1666,8 @@ static int tegra_vi_graph_notify_bound(struct v4l2_async_notifier *notifier,
         * Locate the entity corresponding to the bound subdev and store the
         * subdev pointer.
         */
-       entity = tegra_vi_graph_find_entity(chan, subdev->fwnode);
+       entity = tegra_vi_graph_find_entity(&chan->notifier.waiting_list,
+                                           subdev->fwnode);
        if (!entity) {
                dev_err(vi->dev, "no entity for subdev %s\n", subdev->name);
                return -EINVAL;
@@ -1713,7 +1716,8 @@ static int tegra_vi_graph_parse_one(struct tegra_vi_channel *chan,
 
                /* skip entities that are already processed */
                if (device_match_fwnode(vi->dev, remote) ||
-                   tegra_vi_graph_find_entity(chan, remote)) {
+                   tegra_vi_graph_find_entity(&chan->notifier.waiting_list,
+                                              remote)) {
                        fwnode_handle_put(remote);
                        continue;
                }
index b7ac60f..b6523d4 100644 (file)
@@ -843,7 +843,6 @@ sector_t target_to_linux_sector(struct se_device *dev, sector_t lb)
 EXPORT_SYMBOL(target_to_linux_sector);
 
 struct devices_idr_iter {
-       struct config_item *prev_item;
        int (*fn)(struct se_device *dev, void *data);
        void *data;
 };
@@ -853,11 +852,9 @@ static int target_devices_idr_iter(int id, void *p, void *data)
 {
        struct devices_idr_iter *iter = data;
        struct se_device *dev = p;
+       struct config_item *item;
        int ret;
 
-       config_item_put(iter->prev_item);
-       iter->prev_item = NULL;
-
        /*
         * We add the device early to the idr, so it can be used
         * by backend modules during configuration. We do not want
@@ -867,12 +864,13 @@ static int target_devices_idr_iter(int id, void *p, void *data)
        if (!target_dev_configured(dev))
                return 0;
 
-       iter->prev_item = config_item_get_unless_zero(&dev->dev_group.cg_item);
-       if (!iter->prev_item)
+       item = config_item_get_unless_zero(&dev->dev_group.cg_item);
+       if (!item)
                return 0;
        mutex_unlock(&device_mutex);
 
        ret = iter->fn(dev, iter->data);
+       config_item_put(item);
 
        mutex_lock(&device_mutex);
        return ret;
@@ -895,7 +893,6 @@ int target_for_each_device(int (*fn)(struct se_device *dev, void *data),
        mutex_lock(&device_mutex);
        ret = idr_for_each(&devices_idr, target_devices_idr_iter, &iter);
        mutex_unlock(&device_mutex);
-       config_item_put(iter.prev_item);
        return ret;
 }
 
index 955d938..7b8fd97 100644 (file)
@@ -123,8 +123,18 @@ static inline ssize_t vringh_iov_xfer(struct vringh *vrh,
                done += partlen;
                len -= partlen;
                ptr += partlen;
+               iov->consumed += partlen;
+               iov->iov[iov->i].iov_len -= partlen;
+               iov->iov[iov->i].iov_base += partlen;
 
-               vringh_kiov_advance(iov, partlen);
+               if (!iov->iov[iov->i].iov_len) {
+                       /* Fix up old iov element then increment. */
+                       iov->iov[iov->i].iov_len = iov->consumed;
+                       iov->iov[iov->i].iov_base -= iov->consumed;
+
+                       iov->consumed = 0;
+                       iov->i++;
+               }
        }
        return done;
 }
index a4cb4b6..da519c1 100644 (file)
@@ -682,18 +682,30 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans,
        u64 search_start;
        int ret;
 
-       if (test_bit(BTRFS_ROOT_DELETING, &root->state))
-               btrfs_err(fs_info,
-                       "COW'ing blocks on a fs root that's being dropped");
-
-       if (trans->transaction != fs_info->running_transaction)
-               WARN(1, KERN_CRIT "trans %llu running %llu\n",
-                      trans->transid,
-                      fs_info->running_transaction->transid);
+       if (unlikely(test_bit(BTRFS_ROOT_DELETING, &root->state))) {
+               btrfs_abort_transaction(trans, -EUCLEAN);
+               btrfs_crit(fs_info,
+                  "attempt to COW block %llu on root %llu that is being deleted",
+                          buf->start, btrfs_root_id(root));
+               return -EUCLEAN;
+       }
 
-       if (trans->transid != fs_info->generation)
-               WARN(1, KERN_CRIT "trans %llu running %llu\n",
-                      trans->transid, fs_info->generation);
+       /*
+        * COWing must happen through a running transaction, which always
+        * matches the current fs generation (it's a transaction with a state
+        * less than TRANS_STATE_UNBLOCKED). If it doesn't, then turn the fs
+        * into error state to prevent the commit of any transaction.
+        */
+       if (unlikely(trans->transaction != fs_info->running_transaction ||
+                    trans->transid != fs_info->generation)) {
+               btrfs_abort_transaction(trans, -EUCLEAN);
+               btrfs_crit(fs_info,
+"unexpected transaction when attempting to COW block %llu on root %llu, transaction %llu running transaction %llu fs generation %llu",
+                          buf->start, btrfs_root_id(root), trans->transid,
+                          fs_info->running_transaction->transid,
+                          fs_info->generation);
+               return -EUCLEAN;
+       }
 
        if (!should_cow_block(trans, root, buf)) {
                *cow_ret = buf;
@@ -805,8 +817,22 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
        int progress_passed = 0;
        struct btrfs_disk_key disk_key;
 
-       WARN_ON(trans->transaction != fs_info->running_transaction);
-       WARN_ON(trans->transid != fs_info->generation);
+       /*
+        * COWing must happen through a running transaction, which always
+        * matches the current fs generation (it's a transaction with a state
+        * less than TRANS_STATE_UNBLOCKED). If it doesn't, then turn the fs
+        * into error state to prevent the commit of any transaction.
+        */
+       if (unlikely(trans->transaction != fs_info->running_transaction ||
+                    trans->transid != fs_info->generation)) {
+               btrfs_abort_transaction(trans, -EUCLEAN);
+               btrfs_crit(fs_info,
+"unexpected transaction when attempting to reallocate parent %llu for root %llu, transaction %llu running transaction %llu fs generation %llu",
+                          parent->start, btrfs_root_id(root), trans->transid,
+                          fs_info->running_transaction->transid,
+                          fs_info->generation);
+               return -EUCLEAN;
+       }
 
        parent_nritems = btrfs_header_nritems(parent);
        blocksize = fs_info->nodesize;
index 75ab766..8e7d03b 100644 (file)
@@ -2978,7 +2978,7 @@ static void get_block_group_info(struct list_head *groups_list,
 static long btrfs_ioctl_space_info(struct btrfs_fs_info *fs_info,
                                   void __user *arg)
 {
-       struct btrfs_ioctl_space_args space_args;
+       struct btrfs_ioctl_space_args space_args = { 0 };
        struct btrfs_ioctl_space_info space;
        struct btrfs_ioctl_space_info *dest;
        struct btrfs_ioctl_space_info *dest_orig;
@@ -4338,7 +4338,7 @@ static int _btrfs_ioctl_send(struct inode *inode, void __user *argp, bool compat
 
        if (compat) {
 #if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT)
-               struct btrfs_ioctl_send_args_32 args32;
+               struct btrfs_ioctl_send_args_32 args32 = { 0 };
 
                ret = copy_from_user(&args32, argp, sizeof(args32));
                if (ret)
index 1a093ec..f49e597 100644 (file)
@@ -954,6 +954,10 @@ static int btrfs_parse_subvol_options(const char *options, char **subvol_name,
 
                        *subvol_objectid = subvolid;
                        break;
+               case Opt_err:
+                       btrfs_err(NULL, "unrecognized mount option '%s'", p);
+                       error = -EINVAL;
+                       goto out;
                default:
                        break;
                }
index 6b309f8..93869cd 100644 (file)
@@ -219,8 +219,8 @@ do {                                                                \
                        (errno))) {                                     \
                        /* Stack trace printed. */                      \
                } else {                                                \
-                       btrfs_debug((trans)->fs_info,                   \
-                                   "Transaction aborted (error %d)", \
+                       btrfs_err((trans)->fs_info,                     \
+                                 "Transaction aborted (error %d)",     \
                                  (errno));                     \
                }                                               \
        }                                                       \
index 73091fb..dee10d2 100644 (file)
@@ -217,9 +217,12 @@ again:
                        strm->buf.out_size = min_t(u32, outlen,
                                                   PAGE_SIZE - pageofs);
                        outlen -= strm->buf.out_size;
-                       if (!rq->out[no] && rq->fillgaps)       /* deduped */
+                       if (!rq->out[no] && rq->fillgaps) {     /* deduped */
                                rq->out[no] = erofs_allocpage(pagepool,
                                                GFP_KERNEL | __GFP_NOFAIL);
+                               set_page_private(rq->out[no],
+                                                Z_EROFS_SHORTLIVED_PAGE);
+                       }
                        if (rq->out[no])
                                strm->buf.out = kmap(rq->out[no]) + pageofs;
                        pageofs = 0;
index 44a24d5..3700af9 100644 (file)
@@ -235,7 +235,7 @@ static int erofs_init_device(struct erofs_buf *buf, struct super_block *sb,
                return PTR_ERR(ptr);
        dis = ptr + erofs_blkoff(sb, *pos);
 
-       if (!dif->path) {
+       if (!sbi->devs->flatdev && !dif->path) {
                if (!dis->tag[0]) {
                        erofs_err(sb, "empty device tag @ pos %llu", *pos);
                        return -EINVAL;
index 3508d82..7016eaa 100644 (file)
@@ -10622,7 +10622,9 @@ static void nfs4_disable_swap(struct inode *inode)
         */
        struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
 
-       nfs4_schedule_state_manager(clp);
+       set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state);
+       clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
+       wake_up_var(&clp->cl_state);
 }
 
 static const struct inode_operations nfs4_dir_inode_operations = {
index e079987..9a5d911 100644 (file)
@@ -1209,16 +1209,26 @@ void nfs4_schedule_state_manager(struct nfs_client *clp)
 {
        struct task_struct *task;
        char buf[INET6_ADDRSTRLEN + sizeof("-manager") + 1];
+       struct rpc_clnt *clnt = clp->cl_rpcclient;
+       bool swapon = false;
 
-       if (clp->cl_rpcclient->cl_shutdown)
+       if (clnt->cl_shutdown)
                return;
 
        set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state);
-       if (test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state) != 0) {
-               wake_up_var(&clp->cl_state);
-               return;
+
+       if (atomic_read(&clnt->cl_swapper)) {
+               swapon = !test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE,
+                                          &clp->cl_state);
+               if (!swapon) {
+                       wake_up_var(&clp->cl_state);
+                       return;
+               }
        }
-       set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state);
+
+       if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
+               return;
+
        __module_get(THIS_MODULE);
        refcount_inc(&clp->cl_count);
 
@@ -1235,8 +1245,9 @@ void nfs4_schedule_state_manager(struct nfs_client *clp)
                        __func__, PTR_ERR(task));
                if (!nfs_client_init_is_complete(clp))
                        nfs_mark_client_ready(clp, PTR_ERR(task));
+               if (swapon)
+                       clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
                nfs4_clear_state_manager_bit(clp);
-               clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
                nfs_put_client(clp);
                module_put(THIS_MODULE);
        }
@@ -2703,6 +2714,13 @@ static void nfs4_state_manager(struct nfs_client *clp)
                nfs4_end_drain_session(clp);
                nfs4_clear_state_manager_bit(clp);
 
+               if (test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state) &&
+                   !test_and_set_bit(NFS4CLNT_MANAGER_RUNNING,
+                                     &clp->cl_state)) {
+                       memflags = memalloc_nofs_save();
+                       continue;
+               }
+
                if (!test_and_set_bit(NFS4CLNT_RECALL_RUNNING, &clp->cl_state)) {
                        if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) {
                                nfs_client_return_marked_delegations(clp);
@@ -2741,22 +2759,25 @@ static int nfs4_run_state_manager(void *ptr)
 
        allow_signal(SIGKILL);
 again:
-       set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state);
        nfs4_state_manager(clp);
-       if (atomic_read(&cl->cl_swapper)) {
+
+       if (test_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state) &&
+           !test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state)) {
                wait_var_event_interruptible(&clp->cl_state,
                                             test_bit(NFS4CLNT_RUN_MANAGER,
                                                      &clp->cl_state));
-               if (atomic_read(&cl->cl_swapper) &&
-                   test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state))
+               if (!atomic_read(&cl->cl_swapper))
+                       clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
+               if (refcount_read(&clp->cl_count) > 1 && !signalled() &&
+                   !test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state))
                        goto again;
                /* Either no longer a swapper, or were signalled */
+               clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
        }
-       clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
 
        if (refcount_read(&clp->cl_count) > 1 && !signalled() &&
            test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state) &&
-           !test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state))
+           !test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state))
                goto again;
 
        nfs_put_client(clp);
index 8c1ee1a..7720b5e 100644 (file)
@@ -802,8 +802,8 @@ static void nfs_inode_remove_request(struct nfs_page *req)
        }
 
        if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags)) {
-               nfs_release_request(req);
                atomic_long_dec(&NFS_I(nfs_page_to_inode(req))->nrequests);
+               nfs_release_request(req);
        }
 }
 
index c8c8588..26b782c 100644 (file)
@@ -188,7 +188,7 @@ static int ovl_check_encode_origin(struct dentry *dentry)
 
        /* Lower file handle for non-upper non-decodable */
        if (!ovl_dentry_upper(dentry) && !decodable)
-               return 0;
+               return 1;
 
        /* Upper file handle for pure upper */
        if (!ovl_dentry_lower(dentry))
index 693971d..8be4dc0 100644 (file)
@@ -341,7 +341,6 @@ static ssize_t ovl_read_iter(struct kiocb *iocb, struct iov_iter *iter)
                if (!aio_req)
                        goto out;
 
-               real.flags = 0;
                aio_req->orig_iocb = iocb;
                kiocb_clone(&aio_req->iocb, iocb, get_file(real.file));
                aio_req->iocb.ki_complete = ovl_aio_rw_complete;
@@ -413,7 +412,6 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter)
                if (!aio_req)
                        goto out;
 
-               real.flags = 0;
                aio_req->orig_iocb = iocb;
                kiocb_clone(&aio_req->iocb, iocb, get_file(real.file));
                aio_req->iocb.ki_flags = ifl;
index e9539f9..d82d2a0 100644 (file)
@@ -8,6 +8,7 @@
 struct ovl_config {
        char *upperdir;
        char *workdir;
+       char **lowerdirs;
        bool default_permissions;
        int redirect_mode;
        int verity_mode;
@@ -39,17 +40,8 @@ struct ovl_layer {
        int idx;
        /* One fsid per unique underlying sb (upper fsid == 0) */
        int fsid;
-       char *name;
 };
 
-/*
- * ovl_free_fs() relies on @mnt being the first member when unmounting
- * the private mounts created for each layer. Let's check both the
- * offset and type.
- */
-static_assert(offsetof(struct ovl_layer, mnt) == 0);
-static_assert(__same_type(typeof_member(struct ovl_layer, mnt), struct vfsmount *));
-
 struct ovl_path {
        const struct ovl_layer *layer;
        struct dentry *dentry;
index b9355bb..95b7515 100644 (file)
@@ -752,12 +752,12 @@ void ovl_free_fs(struct ovl_fs *ofs)
        if (ofs->upperdir_locked)
                ovl_inuse_unlock(ovl_upper_mnt(ofs)->mnt_root);
 
-       /* Hack!  Reuse ofs->layers as a vfsmount array before freeing it */
-       mounts = (struct vfsmount **) ofs->layers;
+       /* Reuse ofs->config.lowerdirs as a vfsmount array before freeing it */
+       mounts = (struct vfsmount **) ofs->config.lowerdirs;
        for (i = 0; i < ofs->numlayer; i++) {
                iput(ofs->layers[i].trap);
+               kfree(ofs->config.lowerdirs[i]);
                mounts[i] = ofs->layers[i].mnt;
-               kfree(ofs->layers[i].name);
        }
        kern_unmount_array(mounts, ofs->numlayer);
        kfree(ofs->layers);
@@ -765,6 +765,7 @@ void ovl_free_fs(struct ovl_fs *ofs)
                free_anon_bdev(ofs->fs[i].pseudo_dev);
        kfree(ofs->fs);
 
+       kfree(ofs->config.lowerdirs);
        kfree(ofs->config.upperdir);
        kfree(ofs->config.workdir);
        if (ofs->creator_cred)
@@ -949,16 +950,16 @@ int ovl_show_options(struct seq_file *m, struct dentry *dentry)
        struct super_block *sb = dentry->d_sb;
        struct ovl_fs *ofs = OVL_FS(sb);
        size_t nr, nr_merged_lower = ofs->numlayer - ofs->numdatalayer;
-       const struct ovl_layer *data_layers = &ofs->layers[nr_merged_lower];
+       char **lowerdatadirs = &ofs->config.lowerdirs[nr_merged_lower];
 
-       /* ofs->layers[0] is the upper layer */
-       seq_printf(m, ",lowerdir=%s", ofs->layers[1].name);
+       /* lowerdirs[] starts from offset 1 */
+       seq_printf(m, ",lowerdir=%s", ofs->config.lowerdirs[1]);
        /* dump regular lower layers */
        for (nr = 2; nr < nr_merged_lower; nr++)
-               seq_printf(m, ":%s", ofs->layers[nr].name);
+               seq_printf(m, ":%s", ofs->config.lowerdirs[nr]);
        /* dump data lower layers */
        for (nr = 0; nr < ofs->numdatalayer; nr++)
-               seq_printf(m, "::%s", data_layers[nr].name);
+               seq_printf(m, "::%s", lowerdatadirs[nr]);
        if (ofs->config.upperdir) {
                seq_show_option(m, "upperdir", ofs->config.upperdir);
                seq_show_option(m, "workdir", ofs->config.workdir);
index def266b..3fa2416 100644 (file)
@@ -104,8 +104,8 @@ static int ovl_revalidate_real(struct dentry *d, unsigned int flags, bool weak)
 static int ovl_dentry_revalidate_common(struct dentry *dentry,
                                        unsigned int flags, bool weak)
 {
-       struct ovl_entry *oe = OVL_E(dentry);
-       struct ovl_path *lowerstack = ovl_lowerstack(oe);
+       struct ovl_entry *oe;
+       struct ovl_path *lowerstack;
        struct inode *inode = d_inode_rcu(dentry);
        struct dentry *upper;
        unsigned int i;
@@ -115,6 +115,8 @@ static int ovl_dentry_revalidate_common(struct dentry *dentry,
        if (!inode)
                return -ECHILD;
 
+       oe = OVL_I_E(inode);
+       lowerstack = ovl_lowerstack(oe);
        upper = ovl_i_dentry_upper(inode);
        if (upper)
                ret = ovl_revalidate_real(upper, flags, weak);
@@ -167,6 +169,7 @@ static void ovl_free_inode(struct inode *inode)
        struct ovl_inode *oi = OVL_I(inode);
 
        kfree(oi->redirect);
+       kfree(oi->oe);
        mutex_destroy(&oi->lock);
        kmem_cache_free(ovl_inode_cachep, oi);
 }
@@ -176,7 +179,7 @@ static void ovl_destroy_inode(struct inode *inode)
        struct ovl_inode *oi = OVL_I(inode);
 
        dput(oi->__upperdentry);
-       ovl_free_entry(oi->oe);
+       ovl_stack_put(ovl_lowerstack(oi->oe), ovl_numlower(oi->oe));
        if (S_ISDIR(inode->i_mode))
                ovl_dir_cache_free(inode);
        else
@@ -569,11 +572,6 @@ static int ovl_get_upper(struct super_block *sb, struct ovl_fs *ofs,
        upper_layer->idx = 0;
        upper_layer->fsid = 0;
 
-       err = -ENOMEM;
-       upper_layer->name = kstrdup(ofs->config.upperdir, GFP_KERNEL);
-       if (!upper_layer->name)
-               goto out;
-
        /*
         * Inherit SB_NOSEC flag from upperdir.
         *
@@ -1122,7 +1120,8 @@ static int ovl_get_layers(struct super_block *sb, struct ovl_fs *ofs,
                layers[ofs->numlayer].idx = ofs->numlayer;
                layers[ofs->numlayer].fsid = fsid;
                layers[ofs->numlayer].fs = &ofs->fs[fsid];
-               layers[ofs->numlayer].name = l->name;
+               /* Store for printing lowerdir=... in ovl_show_options() */
+               ofs->config.lowerdirs[ofs->numlayer] = l->name;
                l->name = NULL;
                ofs->numlayer++;
                ofs->fs[fsid].is_lower = true;
@@ -1367,8 +1366,16 @@ int ovl_fill_super(struct super_block *sb, struct fs_context *fc)
        if (!layers)
                goto out_err;
 
+       ofs->config.lowerdirs = kcalloc(ctx->nr + 1, sizeof(char *), GFP_KERNEL);
+       if (!ofs->config.lowerdirs) {
+               kfree(layers);
+               goto out_err;
+       }
        ofs->layers = layers;
-       /* Layer 0 is reserved for upper even if there's no upper */
+       /*
+        * Layer 0 is reserved for upper even if there's no upper.
+        * For consistency, config.lowerdirs[0] is NULL.
+        */
        ofs->numlayer = 1;
 
        sb->s_stack_depth = 0;
index 3902e90..7b923e3 100644 (file)
@@ -2474,8 +2474,9 @@ cifs_put_tcon(struct cifs_tcon *tcon)
 static struct cifs_tcon *
 cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
 {
-       int rc, xid;
        struct cifs_tcon *tcon;
+       bool nohandlecache;
+       int rc, xid;
 
        tcon = cifs_find_tcon(ses, ctx);
        if (tcon) {
@@ -2493,14 +2494,17 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
                goto out_fail;
        }
 
-       if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING)
-               tcon = tcon_info_alloc(true);
+       if (ses->server->dialect >= SMB20_PROT_ID &&
+           (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING))
+               nohandlecache = ctx->nohandlecache;
        else
-               tcon = tcon_info_alloc(false);
+               nohandlecache = true;
+       tcon = tcon_info_alloc(!nohandlecache);
        if (tcon == NULL) {
                rc = -ENOMEM;
                goto out_fail;
        }
+       tcon->nohandlecache = nohandlecache;
 
        if (ctx->snapshot_time) {
                if (ses->server->vals->protocol_id == 0) {
@@ -2662,10 +2666,6 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
        tcon->nocase = ctx->nocase;
        tcon->broken_sparse_sup = ctx->no_sparse;
        tcon->max_cached_dirs = ctx->max_cached_dirs;
-       if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING)
-               tcon->nohandlecache = ctx->nohandlecache;
-       else
-               tcon->nohandlecache = true;
        tcon->nodelete = ctx->nodelete;
        tcon->local_lease = ctx->local_lease;
        INIT_LIST_HEAD(&tcon->pending_opens);
@@ -2895,9 +2895,9 @@ bind_socket(struct TCP_Server_Info *server)
        if (server->srcaddr.ss_family != AF_UNSPEC) {
                /* Bind to the specified local IP address */
                struct socket *socket = server->ssocket;
-               rc = socket->ops->bind(socket,
-                                      (struct sockaddr *) &server->srcaddr,
-                                      sizeof(server->srcaddr));
+               rc = kernel_bind(socket,
+                                (struct sockaddr *) &server->srcaddr,
+                                sizeof(server->srcaddr));
                if (rc < 0) {
                        struct sockaddr_in *saddr4;
                        struct sockaddr_in6 *saddr6;
@@ -3046,8 +3046,8 @@ generic_ip_connect(struct TCP_Server_Info *server)
                 socket->sk->sk_sndbuf,
                 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
 
-       rc = socket->ops->connect(socket, saddr, slen,
-                                 server->noblockcnt ? O_NONBLOCK : 0);
+       rc = kernel_connect(socket, saddr, slen,
+                           server->noblockcnt ? O_NONBLOCK : 0);
        /*
         * When mounting SMB root file systems, we do not want to block in
         * connect. Otherwise bail out and then let cifs_reconnect() perform
index afc4c78..d578799 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (C) 2010 Red Hat, Inc.
+ * Copyright (C) 2010, 2023 Red Hat, Inc.
  * All Rights Reserved.
  */
 #include "xfs.h"
 #include "xfs_log.h"
 #include "xfs_ag.h"
 
-STATIC int
-xfs_trim_extents(
+/*
+ * Notes on an efficient, low latency fstrim algorithm
+ *
+ * We need to walk the filesystem free space and issue discards on the free
+ * space that meet the search criteria (size and location). We cannot issue
+ * discards on extents that might be in use, or are so recently in use they are
+ * still marked as busy. To serialise against extent state changes whilst we are
+ * gathering extents to trim, we must hold the AGF lock to lock out other
+ * allocations and extent free operations that might change extent state.
+ *
+ * However, we cannot just hold the AGF for the entire AG free space walk whilst
+ * we issue discards on each free space that is found. Storage devices can have
+ * extremely slow discard implementations (e.g. ceph RBD) and so walking a
+ * couple of million free extents and issuing synchronous discards on each
+ * extent can take a *long* time. Whilst we are doing this walk, nothing else
+ * can access the AGF, and we can stall transactions and hence the log whilst
+ * modifications wait for the AGF lock to be released. This can lead hung tasks
+ * kicking the hung task timer and rebooting the system. This is bad.
+ *
+ * Hence we need to take a leaf from the bulkstat playbook. It takes the AGI
+ * lock, gathers a range of inode cluster buffers that are allocated, drops the
+ * AGI lock and then reads all the inode cluster buffers and processes them. It
+ * loops doing this, using a cursor to keep track of where it is up to in the AG
+ * for each iteration to restart the INOBT lookup from.
+ *
+ * We can't do this exactly with free space - once we drop the AGF lock, the
+ * state of the free extent is out of our control and we cannot run a discard
+ * safely on it in this situation. Unless, of course, we've marked the free
+ * extent as busy and undergoing a discard operation whilst we held the AGF
+ * locked.
+ *
+ * This is exactly how online discard works - free extents are marked busy when
+ * they are freed, and once the extent free has been committed to the journal,
+ * the busy extent record is marked as "undergoing discard" and the discard is
+ * then issued on the free extent. Once the discard completes, the busy extent
+ * record is removed and the extent is able to be allocated again.
+ *
+ * In the context of fstrim, if we find a free extent we need to discard, we
+ * don't have to discard it immediately. All we need to do it record that free
+ * extent as being busy and under discard, and all the allocation routines will
+ * now avoid trying to allocate it. Hence if we mark the extent as busy under
+ * the AGF lock, we can safely discard it without holding the AGF lock because
+ * nothing will attempt to allocate that free space until the discard completes.
+ *
+ * This also allows us to issue discards asynchronously like we do with online
+ * discard, and so for fast devices fstrim will run much faster as we can have
+ * multiple discard operations in flight at once, as well as pipeline the free
+ * extent search so that it overlaps in flight discard IO.
+ */
+
+struct workqueue_struct *xfs_discard_wq;
+
+static void
+xfs_discard_endio_work(
+       struct work_struct      *work)
+{
+       struct xfs_busy_extents *extents =
+               container_of(work, struct xfs_busy_extents, endio_work);
+
+       xfs_extent_busy_clear(extents->mount, &extents->extent_list, false);
+       kmem_free(extents->owner);
+}
+
+/*
+ * Queue up the actual completion to a thread to avoid IRQ-safe locking for
+ * pagb_lock.
+ */
+static void
+xfs_discard_endio(
+       struct bio              *bio)
+{
+       struct xfs_busy_extents *extents = bio->bi_private;
+
+       INIT_WORK(&extents->endio_work, xfs_discard_endio_work);
+       queue_work(xfs_discard_wq, &extents->endio_work);
+       bio_put(bio);
+}
+
+/*
+ * Walk the discard list and issue discards on all the busy extents in the
+ * list. We plug and chain the bios so that we only need a single completion
+ * call to clear all the busy extents once the discards are complete.
+ */
+int
+xfs_discard_extents(
+       struct xfs_mount        *mp,
+       struct xfs_busy_extents *extents)
+{
+       struct xfs_extent_busy  *busyp;
+       struct bio              *bio = NULL;
+       struct blk_plug         plug;
+       int                     error = 0;
+
+       blk_start_plug(&plug);
+       list_for_each_entry(busyp, &extents->extent_list, list) {
+               trace_xfs_discard_extent(mp, busyp->agno, busyp->bno,
+                                        busyp->length);
+
+               error = __blkdev_issue_discard(mp->m_ddev_targp->bt_bdev,
+                               XFS_AGB_TO_DADDR(mp, busyp->agno, busyp->bno),
+                               XFS_FSB_TO_BB(mp, busyp->length),
+                               GFP_NOFS, &bio);
+               if (error && error != -EOPNOTSUPP) {
+                       xfs_info(mp,
+        "discard failed for extent [0x%llx,%u], error %d",
+                                (unsigned long long)busyp->bno,
+                                busyp->length,
+                                error);
+                       break;
+               }
+       }
+
+       if (bio) {
+               bio->bi_private = extents;
+               bio->bi_end_io = xfs_discard_endio;
+               submit_bio(bio);
+       } else {
+               xfs_discard_endio_work(&extents->endio_work);
+       }
+       blk_finish_plug(&plug);
+
+       return error;
+}
+
+
+static int
+xfs_trim_gather_extents(
        struct xfs_perag        *pag,
        xfs_daddr_t             start,
        xfs_daddr_t             end,
        xfs_daddr_t             minlen,
+       struct xfs_alloc_rec_incore *tcur,
+       struct xfs_busy_extents *extents,
        uint64_t                *blocks_trimmed)
 {
        struct xfs_mount        *mp = pag->pag_mount;
-       struct block_device     *bdev = mp->m_ddev_targp->bt_bdev;
        struct xfs_btree_cur    *cur;
        struct xfs_buf          *agbp;
-       struct xfs_agf          *agf;
        int                     error;
        int                     i;
+       int                     batch = 100;
 
        /*
         * Force out the log.  This means any transactions that might have freed
@@ -45,20 +171,28 @@ xfs_trim_extents(
        error = xfs_alloc_read_agf(pag, NULL, 0, &agbp);
        if (error)
                return error;
-       agf = agbp->b_addr;
 
        cur = xfs_allocbt_init_cursor(mp, NULL, agbp, pag, XFS_BTNUM_CNT);
 
        /*
-        * Look up the longest btree in the AGF and start with it.
+        * Look up the extent length requested in the AGF and start with it.
         */
-       error = xfs_alloc_lookup_ge(cur, 0, be32_to_cpu(agf->agf_longest), &i);
+       if (tcur->ar_startblock == NULLAGBLOCK)
+               error = xfs_alloc_lookup_ge(cur, 0, tcur->ar_blockcount, &i);
+       else
+               error = xfs_alloc_lookup_le(cur, tcur->ar_startblock,
+                               tcur->ar_blockcount, &i);
        if (error)
                goto out_del_cursor;
+       if (i == 0) {
+               /* nothing of that length left in the AG, we are done */
+               tcur->ar_blockcount = 0;
+               goto out_del_cursor;
+       }
 
        /*
         * Loop until we are done with all extents that are large
-        * enough to be worth discarding.
+        * enough to be worth discarding or we hit batch limits.
         */
        while (i) {
                xfs_agblock_t   fbno;
@@ -73,7 +207,16 @@ xfs_trim_extents(
                        error = -EFSCORRUPTED;
                        break;
                }
-               ASSERT(flen <= be32_to_cpu(agf->agf_longest));
+
+               if (--batch <= 0) {
+                       /*
+                        * Update the cursor to point at this extent so we
+                        * restart the next batch from this extent.
+                        */
+                       tcur->ar_startblock = fbno;
+                       tcur->ar_blockcount = flen;
+                       break;
+               }
 
                /*
                 * use daddr format for all range/len calculations as that is
@@ -88,6 +231,7 @@ xfs_trim_extents(
                 */
                if (dlen < minlen) {
                        trace_xfs_discard_toosmall(mp, pag->pag_agno, fbno, flen);
+                       tcur->ar_blockcount = 0;
                        break;
                }
 
@@ -110,29 +254,103 @@ xfs_trim_extents(
                        goto next_extent;
                }
 
-               trace_xfs_discard_extent(mp, pag->pag_agno, fbno, flen);
-               error = blkdev_issue_discard(bdev, dbno, dlen, GFP_NOFS);
-               if (error)
-                       break;
+               xfs_extent_busy_insert_discard(pag, fbno, flen,
+                               &extents->extent_list);
                *blocks_trimmed += flen;
-
 next_extent:
                error = xfs_btree_decrement(cur, 0, &i);
                if (error)
                        break;
 
-               if (fatal_signal_pending(current)) {
-                       error = -ERESTARTSYS;
-                       break;
-               }
+               /*
+                * If there's no more records in the tree, we are done. Set the
+                * cursor block count to 0 to indicate to the caller that there
+                * is no more extents to search.
+                */
+               if (i == 0)
+                       tcur->ar_blockcount = 0;
        }
 
+       /*
+        * If there was an error, release all the gathered busy extents because
+        * we aren't going to issue a discard on them any more.
+        */
+       if (error)
+               xfs_extent_busy_clear(mp, &extents->extent_list, false);
 out_del_cursor:
        xfs_btree_del_cursor(cur, error);
        xfs_buf_relse(agbp);
        return error;
 }
 
+static bool
+xfs_trim_should_stop(void)
+{
+       return fatal_signal_pending(current) || freezing(current);
+}
+
+/*
+ * Iterate the free list gathering extents and discarding them. We need a cursor
+ * for the repeated iteration of gather/discard loop, so use the longest extent
+ * we found in the last batch as the key to start the next.
+ */
+static int
+xfs_trim_extents(
+       struct xfs_perag        *pag,
+       xfs_daddr_t             start,
+       xfs_daddr_t             end,
+       xfs_daddr_t             minlen,
+       uint64_t                *blocks_trimmed)
+{
+       struct xfs_alloc_rec_incore tcur = {
+               .ar_blockcount = pag->pagf_longest,
+               .ar_startblock = NULLAGBLOCK,
+       };
+       int                     error = 0;
+
+       do {
+               struct xfs_busy_extents *extents;
+
+               extents = kzalloc(sizeof(*extents), GFP_KERNEL);
+               if (!extents) {
+                       error = -ENOMEM;
+                       break;
+               }
+
+               extents->mount = pag->pag_mount;
+               extents->owner = extents;
+               INIT_LIST_HEAD(&extents->extent_list);
+
+               error = xfs_trim_gather_extents(pag, start, end, minlen,
+                               &tcur, extents, blocks_trimmed);
+               if (error) {
+                       kfree(extents);
+                       break;
+               }
+
+               /*
+                * We hand the extent list to the discard function here so the
+                * discarded extents can be removed from the busy extent list.
+                * This allows the discards to run asynchronously with gathering
+                * the next round of extents to discard.
+                *
+                * However, we must ensure that we do not reference the extent
+                * list  after this function call, as it may have been freed by
+                * the time control returns to us.
+                */
+               error = xfs_discard_extents(pag->pag_mount, extents);
+               if (error)
+                       break;
+
+               if (xfs_trim_should_stop())
+                       break;
+
+       } while (tcur.ar_blockcount != 0);
+
+       return error;
+
+}
+
 /*
  * trim a range of the filesystem.
  *
@@ -195,12 +413,12 @@ xfs_ioc_trim(
        for_each_perag_range(mp, agno, xfs_daddr_to_agno(mp, end), pag) {
                error = xfs_trim_extents(pag, start, end, minlen,
                                          &blocks_trimmed);
-               if (error) {
+               if (error)
                        last_error = error;
-                       if (error == -ERESTARTSYS) {
-                               xfs_perag_rele(pag);
-                               break;
-                       }
+
+               if (xfs_trim_should_stop()) {
+                       xfs_perag_rele(pag);
+                       break;
                }
        }
 
index de92d9c..2b1a852 100644 (file)
@@ -3,8 +3,10 @@
 #define XFS_DISCARD_H 1
 
 struct fstrim_range;
-struct list_head;
+struct xfs_mount;
+struct xfs_busy_extents;
 
-extern int     xfs_ioc_trim(struct xfs_mount *, struct fstrim_range __user *);
+int xfs_discard_extents(struct xfs_mount *mp, struct xfs_busy_extents *busy);
+int xfs_ioc_trim(struct xfs_mount *mp, struct fstrim_range __user *fstrim);
 
 #endif /* XFS_DISCARD_H */
index 7c2fdc7..7468148 100644 (file)
 #include "xfs_log.h"
 #include "xfs_ag.h"
 
-void
-xfs_extent_busy_insert(
-       struct xfs_trans        *tp,
+static void
+xfs_extent_busy_insert_list(
        struct xfs_perag        *pag,
        xfs_agblock_t           bno,
        xfs_extlen_t            len,
-       unsigned int            flags)
+       unsigned int            flags,
+       struct list_head        *busy_list)
 {
        struct xfs_extent_busy  *new;
        struct xfs_extent_busy  *busyp;
@@ -40,7 +40,7 @@ xfs_extent_busy_insert(
        new->flags = flags;
 
        /* trace before insert to be able to see failed inserts */
-       trace_xfs_extent_busy(tp->t_mountp, pag->pag_agno, bno, len);
+       trace_xfs_extent_busy(pag->pag_mount, pag->pag_agno, bno, len);
 
        spin_lock(&pag->pagb_lock);
        rbp = &pag->pagb_tree.rb_node;
@@ -62,10 +62,32 @@ xfs_extent_busy_insert(
        rb_link_node(&new->rb_node, parent, rbp);
        rb_insert_color(&new->rb_node, &pag->pagb_tree);
 
-       list_add(&new->list, &tp->t_busy);
+       list_add(&new->list, busy_list);
        spin_unlock(&pag->pagb_lock);
 }
 
+void
+xfs_extent_busy_insert(
+       struct xfs_trans        *tp,
+       struct xfs_perag        *pag,
+       xfs_agblock_t           bno,
+       xfs_extlen_t            len,
+       unsigned int            flags)
+{
+       xfs_extent_busy_insert_list(pag, bno, len, flags, &tp->t_busy);
+}
+
+void
+xfs_extent_busy_insert_discard(
+       struct xfs_perag        *pag,
+       xfs_agblock_t           bno,
+       xfs_extlen_t            len,
+       struct list_head        *busy_list)
+{
+       xfs_extent_busy_insert_list(pag, bno, len, XFS_EXTENT_BUSY_DISCARDED,
+                       busy_list);
+}
+
 /*
  * Search for a busy extent within the range of the extent we are about to
  * allocate.  You need to be holding the busy extent tree lock when calling
index c37bf87..0639aab 100644 (file)
@@ -16,9 +16,6 @@ struct xfs_alloc_arg;
 /*
  * Busy block/extent entry.  Indexed by a rbtree in perag to mark blocks that
  * have been freed but whose transactions aren't committed to disk yet.
- *
- * Note that we use the transaction ID to record the transaction, not the
- * transaction structure itself. See xfs_extent_busy_insert() for details.
  */
 struct xfs_extent_busy {
        struct rb_node  rb_node;        /* ag by-bno indexed search tree */
@@ -31,11 +28,32 @@ struct xfs_extent_busy {
 #define XFS_EXTENT_BUSY_SKIP_DISCARD   0x02    /* do not discard */
 };
 
+/*
+ * List used to track groups of related busy extents all the way through
+ * to discard completion.
+ */
+struct xfs_busy_extents {
+       struct xfs_mount        *mount;
+       struct list_head        extent_list;
+       struct work_struct      endio_work;
+
+       /*
+        * Owner is the object containing the struct xfs_busy_extents to free
+        * once the busy extents have been processed. If only the
+        * xfs_busy_extents object needs freeing, then point this at itself.
+        */
+       void                    *owner;
+};
+
 void
 xfs_extent_busy_insert(struct xfs_trans *tp, struct xfs_perag *pag,
        xfs_agblock_t bno, xfs_extlen_t len, unsigned int flags);
 
 void
+xfs_extent_busy_insert_discard(struct xfs_perag *pag, xfs_agblock_t bno,
+       xfs_extlen_t len, struct list_head *busy_list);
+
+void
 xfs_extent_busy_clear(struct xfs_mount *mp, struct list_head *list,
        bool do_discard);
 
index ebc70aa..67a99d9 100644 (file)
@@ -16,8 +16,7 @@
 #include "xfs_log.h"
 #include "xfs_log_priv.h"
 #include "xfs_trace.h"
-
-struct workqueue_struct *xfs_discard_wq;
+#include "xfs_discard.h"
 
 /*
  * Allocate a new ticket. Failing to get a new ticket makes it really hard to
@@ -103,7 +102,7 @@ xlog_cil_ctx_alloc(void)
 
        ctx = kmem_zalloc(sizeof(*ctx), KM_NOFS);
        INIT_LIST_HEAD(&ctx->committing);
-       INIT_LIST_HEAD(&ctx->busy_extents);
+       INIT_LIST_HEAD(&ctx->busy_extents.extent_list);
        INIT_LIST_HEAD(&ctx->log_items);
        INIT_LIST_HEAD(&ctx->lv_chain);
        INIT_WORK(&ctx->push_work, xlog_cil_push_work);
@@ -132,7 +131,7 @@ xlog_cil_push_pcp_aggregate(
 
                if (!list_empty(&cilpcp->busy_extents)) {
                        list_splice_init(&cilpcp->busy_extents,
-                                       &ctx->busy_extents);
+                                       &ctx->busy_extents.extent_list);
                }
                if (!list_empty(&cilpcp->log_items))
                        list_splice_init(&cilpcp->log_items, &ctx->log_items);
@@ -708,76 +707,6 @@ xlog_cil_free_logvec(
        }
 }
 
-static void
-xlog_discard_endio_work(
-       struct work_struct      *work)
-{
-       struct xfs_cil_ctx      *ctx =
-               container_of(work, struct xfs_cil_ctx, discard_endio_work);
-       struct xfs_mount        *mp = ctx->cil->xc_log->l_mp;
-
-       xfs_extent_busy_clear(mp, &ctx->busy_extents, false);
-       kmem_free(ctx);
-}
-
-/*
- * Queue up the actual completion to a thread to avoid IRQ-safe locking for
- * pagb_lock.  Note that we need a unbounded workqueue, otherwise we might
- * get the execution delayed up to 30 seconds for weird reasons.
- */
-static void
-xlog_discard_endio(
-       struct bio              *bio)
-{
-       struct xfs_cil_ctx      *ctx = bio->bi_private;
-
-       INIT_WORK(&ctx->discard_endio_work, xlog_discard_endio_work);
-       queue_work(xfs_discard_wq, &ctx->discard_endio_work);
-       bio_put(bio);
-}
-
-static void
-xlog_discard_busy_extents(
-       struct xfs_mount        *mp,
-       struct xfs_cil_ctx      *ctx)
-{
-       struct list_head        *list = &ctx->busy_extents;
-       struct xfs_extent_busy  *busyp;
-       struct bio              *bio = NULL;
-       struct blk_plug         plug;
-       int                     error = 0;
-
-       ASSERT(xfs_has_discard(mp));
-
-       blk_start_plug(&plug);
-       list_for_each_entry(busyp, list, list) {
-               trace_xfs_discard_extent(mp, busyp->agno, busyp->bno,
-                                        busyp->length);
-
-               error = __blkdev_issue_discard(mp->m_ddev_targp->bt_bdev,
-                               XFS_AGB_TO_DADDR(mp, busyp->agno, busyp->bno),
-                               XFS_FSB_TO_BB(mp, busyp->length),
-                               GFP_NOFS, &bio);
-               if (error && error != -EOPNOTSUPP) {
-                       xfs_info(mp,
-        "discard failed for extent [0x%llx,%u], error %d",
-                                (unsigned long long)busyp->bno,
-                                busyp->length,
-                                error);
-                       break;
-               }
-       }
-
-       if (bio) {
-               bio->bi_private = ctx;
-               bio->bi_end_io = xlog_discard_endio;
-               submit_bio(bio);
-       } else {
-               xlog_discard_endio_work(&ctx->discard_endio_work);
-       }
-       blk_finish_plug(&plug);
-}
-
 /*
  * Mark all items committed and clear busy extents. We free the log vector
  * chains in a separate pass so that we unpin the log items as quickly as
@@ -807,8 +736,8 @@ xlog_cil_committed(
        xfs_trans_committed_bulk(ctx->cil->xc_log->l_ailp, &ctx->lv_chain,
                                        ctx->start_lsn, abort);
 
-       xfs_extent_busy_sort(&ctx->busy_extents);
-       xfs_extent_busy_clear(mp, &ctx->busy_extents,
+       xfs_extent_busy_sort(&ctx->busy_extents.extent_list);
+       xfs_extent_busy_clear(mp, &ctx->busy_extents.extent_list,
                              xfs_has_discard(mp) && !abort);
 
        spin_lock(&ctx->cil->xc_push_lock);
@@ -817,10 +746,14 @@ xlog_cil_committed(
 
        xlog_cil_free_logvec(&ctx->lv_chain);
 
-       if (!list_empty(&ctx->busy_extents))
-               xlog_discard_busy_extents(mp, ctx);
-       else
-               kmem_free(ctx);
+       if (!list_empty(&ctx->busy_extents.extent_list)) {
+               ctx->busy_extents.mount = mp;
+               ctx->busy_extents.owner = ctx;
+               xfs_discard_extents(mp, &ctx->busy_extents);
+               return;
+       }
+
+       kmem_free(ctx);
 }
 
 void
index af87648..fa3ad1d 100644 (file)
@@ -6,6 +6,8 @@
 #ifndef        __XFS_LOG_PRIV_H__
 #define __XFS_LOG_PRIV_H__
 
+#include "xfs_extent_busy.h"   /* for struct xfs_busy_extents */
+
 struct xfs_buf;
 struct xlog;
 struct xlog_ticket;
@@ -223,12 +225,11 @@ struct xfs_cil_ctx {
        struct xlog_in_core     *commit_iclog;
        struct xlog_ticket      *ticket;        /* chkpt ticket */
        atomic_t                space_used;     /* aggregate size of regions */
-       struct list_head        busy_extents;   /* busy extents in chkpt */
+       struct xfs_busy_extents busy_extents;
        struct list_head        log_items;      /* log items in chkpt */
        struct list_head        lv_chain;       /* logvecs being pushed */
        struct list_head        iclog_entry;
        struct list_head        committing;     /* ctx committing list */
-       struct work_struct      discard_endio_work;
        struct work_struct      push_work;
        atomic_t                order_id;
 
index a73246c..afd94c9 100644 (file)
@@ -1480,6 +1480,15 @@ static inline int lpit_read_residency_count_address(u64 *address)
 }
 #endif
 
+#ifdef CONFIG_ACPI_PROCESSOR_IDLE
+#ifndef arch_get_idle_state_flags
+static inline unsigned int arch_get_idle_state_flags(u32 arch_flags)
+{
+       return 0;
+}
+#endif
+#endif /* CONFIG_ACPI_PROCESSOR_IDLE */
+
 #ifdef CONFIG_ACPI_PPTT
 int acpi_pptt_cpu_is_thread(unsigned int cpu);
 int find_acpi_cpu_topology(unsigned int cpu, int level);
index 024e8b2..49f8b69 100644 (file)
@@ -1307,7 +1307,7 @@ static inline int bpf_trampoline_unlink_prog(struct bpf_tramp_link *link,
 static inline struct bpf_trampoline *bpf_trampoline_get(u64 key,
                                                        struct bpf_attach_target_info *tgt_info)
 {
-       return ERR_PTR(-EOPNOTSUPP);
+       return NULL;
 }
 static inline void bpf_trampoline_put(struct bpf_trampoline *tr) {}
 #define DEFINE_BPF_DISPATCHER(name)
index 625f491..fb31312 100644 (file)
@@ -9,6 +9,7 @@ struct ip_ct_sctp {
        enum sctp_conntrack state;
 
        __be32 vtag[IP_CT_DIR_MAX];
+       u8 init[IP_CT_DIR_MAX];
        u8 last_dir;
        u8 flags;
 };
index e6359f7..c33348b 100644 (file)
@@ -350,7 +350,7 @@ struct hci_dev {
        struct list_head list;
        struct mutex    lock;
 
-       char            name[8];
+       const char      *name;
        unsigned long   flags;
        __u16           id;
        __u8            bus;
index 3a4b684..7192346 100644 (file)
@@ -5941,6 +5941,7 @@ void wiphy_delayed_work_cancel(struct wiphy *wiphy,
  * @event_lock: (private) lock for event list
  * @owner_nlportid: (private) owner socket port ID
  * @nl_owner_dead: (private) owner socket went away
+ * @cqm_rssi_work: (private) CQM RSSI reporting work
  * @cqm_config: (private) nl80211 RSSI monitor state
  * @pmsr_list: (private) peer measurement requests
  * @pmsr_lock: (private) peer measurements requests/results lock
@@ -6013,7 +6014,8 @@ struct wireless_dev {
        } wext;
 #endif
 
-       struct cfg80211_cqm_config *cqm_config;
+       struct wiphy_work cqm_rssi_work;
+       struct cfg80211_cqm_config __rcu *cqm_config;
 
        struct list_head pmsr_list;
        spinlock_t pmsr_lock;
@@ -7231,7 +7233,7 @@ struct cfg80211_rx_assoc_resp {
        int uapsd_queues;
        const u8 *ap_mld_addr;
        struct {
-               const u8 *addr;
+               u8 addr[ETH_ALEN] __aligned(2);
                struct cfg80211_bss *bss;
                u16 status;
        } links[IEEE80211_MLD_MAX_NUM_LINKS];
index f0c1386..15de07d 100644 (file)
@@ -154,6 +154,7 @@ struct fib_info {
        int                     fib_nhs;
        bool                    fib_nh_is_v6;
        bool                    nh_updated;
+       bool                    pfsrc_removed;
        struct nexthop          *nh;
        struct rcu_head         rcu;
        struct fib_nh           fib_nh[];
index 9f70b43..4d43adf 100644 (file)
@@ -103,9 +103,10 @@ struct mana_txq {
 
 /* skb data and frags dma mappings */
 struct mana_skb_head {
-       dma_addr_t dma_handle[MAX_SKB_FRAGS + 1];
+       /* GSO pkts may have 2 SGEs for the linear part*/
+       dma_addr_t dma_handle[MAX_SKB_FRAGS + 2];
 
-       u32 size[MAX_SKB_FRAGS + 1];
+       u32 size[MAX_SKB_FRAGS + 2];
 };
 
 #define MANA_HEADROOM sizeof(struct mana_skb_head)
index 6da6888..07022bb 100644 (file)
@@ -539,7 +539,7 @@ static inline int neigh_output(struct neighbour *n, struct sk_buff *skb,
            READ_ONCE(hh->hh_len))
                return neigh_hh_output(hh, skb);
 
-       return n->output(n, skb);
+       return READ_ONCE(n->output)(n, skb);
 }
 
 static inline struct neighbour *
index 9423153..8e77514 100644 (file)
  * page_pool_alloc_pages() call.  Drivers should use
  * page_pool_dev_alloc_pages() replacing dev_alloc_pages().
  *
- * API keeps track of in-flight pages, in order to let API user know
+ * The API keeps track of in-flight pages, in order to let API users know
  * when it is safe to free a page_pool object.  Thus, API users
  * must call page_pool_put_page() to free the page, or attach
- * the page to a page_pool-aware objects like skbs marked with
+ * the page to a page_pool-aware object like skbs marked with
  * skb_mark_for_recycle().
  *
- * API user must call page_pool_put_page() once on a page, as it
+ * API users must call page_pool_put_page() once on a page, as it
  * will either recycle the page, or in case of refcnt > 1, it will
  * release the DMA mapping and in-flight state accounting.
  */
index 91688d0..7b1a720 100644 (file)
@@ -348,12 +348,14 @@ ssize_t tcp_splice_read(struct socket *sk, loff_t *ppos,
 struct sk_buff *tcp_stream_alloc_skb(struct sock *sk, gfp_t gfp,
                                     bool force_schedule);
 
-static inline void tcp_dec_quickack_mode(struct sock *sk,
-                                        const unsigned int pkts)
+static inline void tcp_dec_quickack_mode(struct sock *sk)
 {
        struct inet_connection_sock *icsk = inet_csk(sk);
 
        if (icsk->icsk_ack.quick) {
+               /* How many ACKs S/ACKing new data have we sent? */
+               const unsigned int pkts = inet_csk_ack_scheduled(sk) ? 1 : 0;
+
                if (pkts >= icsk->icsk_ack.quick) {
                        icsk->icsk_ack.quick = 0;
                        /* Leaving quickack mode we deflate ATO. */
index 8d7402c..eaf9f24 100644 (file)
@@ -44,6 +44,16 @@ extern "C" {
 #define NOUVEAU_GETPARAM_PTIMER_TIME     14
 #define NOUVEAU_GETPARAM_HAS_BO_USAGE    15
 #define NOUVEAU_GETPARAM_HAS_PAGEFLIP    16
+
+/**
+ * @NOUVEAU_GETPARAM_EXEC_PUSH_MAX
+ *
+ * Query the maximum amount of IBs that can be pushed through a single
+ * &drm_nouveau_exec structure and hence a single &DRM_IOCTL_NOUVEAU_EXEC
+ * ioctl().
+ */
+#define NOUVEAU_GETPARAM_EXEC_PUSH_MAX   17
+
 struct drm_nouveau_getparam {
        __u64 param;
        __u64 value;
index 1ecc8c7..522196d 100644 (file)
@@ -1151,9 +1151,6 @@ struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data)
        wq = kzalloc(sizeof(struct io_wq), GFP_KERNEL);
        if (!wq)
                return ERR_PTR(-ENOMEM);
-       ret = cpuhp_state_add_instance_nocalls(io_wq_online, &wq->cpuhp_node);
-       if (ret)
-               goto err_wq;
 
        refcount_inc(&data->hash->refs);
        wq->hash = data->hash;
@@ -1186,13 +1183,14 @@ struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data)
        wq->task = get_task_struct(data->task);
        atomic_set(&wq->worker_refs, 1);
        init_completion(&wq->worker_done);
+       ret = cpuhp_state_add_instance_nocalls(io_wq_online, &wq->cpuhp_node);
+       if (ret)
+               goto err;
+
        return wq;
 err:
        io_wq_put_hash(data->hash);
-       cpuhp_state_remove_instance_nocalls(io_wq_online, &wq->cpuhp_node);
-
        free_cpumask_var(wq->cpu_mask);
-err_wq:
        kfree(wq);
        return ERR_PTR(ret);
 }
index 783ed0f..d839a80 100644 (file)
@@ -2686,7 +2686,7 @@ static void *__io_uaddr_map(struct page ***pages, unsigned short *npages,
 {
        struct page **page_array;
        unsigned int nr_pages;
-       int ret;
+       int ret, i;
 
        *npages = 0;
 
@@ -2716,6 +2716,20 @@ err:
         */
        if (page_array[0] != page_array[ret - 1])
                goto err;
+
+       /*
+        * Can't support mapping user allocated ring memory on 32-bit archs
+        * where it could potentially reside in highmem. Just fail those with
+        * -EINVAL, just like we did on kernels that didn't support this
+        * feature.
+        */
+       for (i = 0; i < nr_pages; i++) {
+               if (PageHighMem(page_array[i])) {
+                       ret = -EINVAL;
+                       goto err;
+               }
+       }
+
        *pages = page_array;
        *npages = nr_pages;
        return page_to_virt(page_array[0]);
index 547c305..0bc1456 100644 (file)
@@ -86,20 +86,33 @@ bool __io_alloc_req_refill(struct io_ring_ctx *ctx);
 bool io_match_task_safe(struct io_kiocb *head, struct task_struct *task,
                        bool cancel_all);
 
-#define io_lockdep_assert_cq_locked(ctx)                               \
-       do {                                                            \
-               lockdep_assert(in_task());                              \
-                                                                       \
-               if (ctx->flags & IORING_SETUP_IOPOLL) {                 \
-                       lockdep_assert_held(&ctx->uring_lock);          \
-               } else if (!ctx->task_complete) {                       \
-                       lockdep_assert_held(&ctx->completion_lock);     \
-               } else if (ctx->submitter_task->flags & PF_EXITING) {   \
-                       lockdep_assert(current_work());                 \
-               } else {                                                \
-                       lockdep_assert(current == ctx->submitter_task); \
-               }                                                       \
-       } while (0)
+#if defined(CONFIG_PROVE_LOCKING)
+static inline void io_lockdep_assert_cq_locked(struct io_ring_ctx *ctx)
+{
+       lockdep_assert(in_task());
+
+       if (ctx->flags & IORING_SETUP_IOPOLL) {
+               lockdep_assert_held(&ctx->uring_lock);
+       } else if (!ctx->task_complete) {
+               lockdep_assert_held(&ctx->completion_lock);
+       } else if (ctx->submitter_task) {
+               /*
+                * ->submitter_task may be NULL and we can still post a CQE,
+                * if the ring has been setup with IORING_SETUP_R_DISABLED.
+                * Not from an SQE, as those cannot be submitted, but via
+                * updating tagged resources.
+                */
+               if (ctx->submitter_task->flags & PF_EXITING)
+                       lockdep_assert(current_work());
+               else
+                       lockdep_assert(current == ctx->submitter_task);
+       }
+}
+#else
+static inline void io_lockdep_assert_cq_locked(struct io_ring_ctx *ctx)
+{
+}
+#endif
 
 static inline void io_req_task_work_add(struct io_kiocb *req)
 {
index 556f4df..9123138 100644 (file)
@@ -477,7 +477,7 @@ static int io_pin_pbuf_ring(struct io_uring_buf_reg *reg,
 {
        struct io_uring_buf_ring *br;
        struct page **pages;
-       int nr_pages;
+       int i, nr_pages;
 
        pages = io_pin_pages(reg->ring_addr,
                             flex_array_size(br, bufs, reg->ring_entries),
@@ -485,6 +485,17 @@ static int io_pin_pbuf_ring(struct io_uring_buf_reg *reg,
        if (IS_ERR(pages))
                return PTR_ERR(pages);
 
+       /*
+        * Apparently some 32-bit boxes (ARM) will return highmem pages,
+        * which then need to be mapped. We could support that, but it'd
+        * complicate the code and slowdown the common cases quite a bit.
+        * So just error out, returning -EINVAL just like we did on kernels
+        * that didn't support mapped buffer rings.
+        */
+       for (i = 0; i < nr_pages; i++)
+               if (PageHighMem(pages[i]))
+                       goto error_unpin;
+
        br = page_address(pages[0]);
 #ifdef SHM_COLOUR
        /*
@@ -496,13 +507,8 @@ static int io_pin_pbuf_ring(struct io_uring_buf_reg *reg,
         * should use IOU_PBUF_RING_MMAP instead, and liburing will handle
         * this transparently.
         */
-       if ((reg->ring_addr | (unsigned long) br) & (SHM_COLOUR - 1)) {
-               int i;
-
-               for (i = 0; i < nr_pages; i++)
-                       unpin_user_page(pages[i]);
-               return -EINVAL;
-       }
+       if ((reg->ring_addr | (unsigned long) br) & (SHM_COLOUR - 1))
+               goto error_unpin;
 #endif
        bl->buf_pages = pages;
        bl->buf_nr_pages = nr_pages;
@@ -510,6 +516,11 @@ static int io_pin_pbuf_ring(struct io_uring_buf_reg *reg,
        bl->is_mapped = 1;
        bl->is_mmap = 0;
        return 0;
+error_unpin:
+       for (i = 0; i < nr_pages; i++)
+               unpin_user_page(pages[i]);
+       kvfree(pages);
+       return -EINVAL;
 }
 
 static int io_alloc_pbuf_ring(struct io_uring_buf_reg *reg,
index cf19415..d93ddac 100644 (file)
@@ -965,37 +965,31 @@ void notrace *bpf_mem_cache_alloc_flags(struct bpf_mem_alloc *ma, gfp_t flags)
        return !ret ? NULL : ret + LLIST_NODE_SZ;
 }
 
-/* Most of the logic is taken from setup_kmalloc_cache_index_table() */
 static __init int bpf_mem_cache_adjust_size(void)
 {
-       unsigned int size, index;
+       unsigned int size;
 
-       /* Normally KMALLOC_MIN_SIZE is 8-bytes, but it can be
-        * up-to 256-bytes.
+       /* Adjusting the indexes in size_index() according to the object_size
+        * of underlying slab cache, so bpf_mem_alloc() will select a
+        * bpf_mem_cache with unit_size equal to the object_size of
+        * the underlying slab cache.
+        *
+        * The maximal value of KMALLOC_MIN_SIZE and __kmalloc_minalign() is
+        * 256-bytes, so only do adjustment for [8-bytes, 192-bytes].
         */
-       size = KMALLOC_MIN_SIZE;
-       if (size <= 192)
-               index = size_index[(size - 1) / 8];
-       else
-               index = fls(size - 1) - 1;
-       for (size = 8; size < KMALLOC_MIN_SIZE && size <= 192; size += 8)
-               size_index[(size - 1) / 8] = index;
+       for (size = 192; size >= 8; size -= 8) {
+               unsigned int kmalloc_size, index;
 
-       /* The minimal alignment is 64-bytes, so disable 96-bytes cache and
-        * use 128-bytes cache instead.
-        */
-       if (KMALLOC_MIN_SIZE >= 64) {
-               index = size_index[(128 - 1) / 8];
-               for (size = 64 + 8; size <= 96; size += 8)
-                       size_index[(size - 1) / 8] = index;
-       }
+               kmalloc_size = kmalloc_size_roundup(size);
+               if (kmalloc_size == size)
+                       continue;
 
-       /* The minimal alignment is 128-bytes, so disable 192-bytes cache and
-        * use 256-bytes cache instead.
-        */
-       if (KMALLOC_MIN_SIZE >= 128) {
-               index = fls(256 - 1) - 1;
-               for (size = 128 + 8; size <= 192; size += 8)
+               if (kmalloc_size <= 192)
+                       index = size_index[(kmalloc_size - 1) / 8];
+               else
+                       index = fls(kmalloc_size - 1) - 1;
+               /* Only overwrite if necessary */
+               if (size_index[(size - 1) / 8] != index)
                        size_index[(size - 1) / 8] = index;
        }
 
index 32d2c48..007d98c 100644 (file)
@@ -253,6 +253,9 @@ int bpf_mprog_attach(struct bpf_mprog_entry *entry,
                        goto out;
                }
                idx = tidx;
+       } else if (bpf_mprog_total(entry) == bpf_mprog_max()) {
+               ret = -ERANGE;
+               goto out;
        }
        if (flags & BPF_F_BEFORE) {
                tidx = bpf_mprog_pos_before(entry, &rtuple);
index bb78212..c0c7d13 100644 (file)
@@ -4047,11 +4047,9 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno)
                                bitmap_from_u64(mask, bt_reg_mask(bt));
                                for_each_set_bit(i, mask, 32) {
                                        reg = &st->frame[0]->regs[i];
-                                       if (reg->type != SCALAR_VALUE) {
-                                               bt_clear_reg(bt, i);
-                                               continue;
-                                       }
-                                       reg->precise = true;
+                                       bt_clear_reg(bt, i);
+                                       if (reg->type == SCALAR_VALUE)
+                                               reg->precise = true;
                                }
                                return 0;
                        }
index 87e9f7e..0f12e0a 100644 (file)
@@ -2647,7 +2647,7 @@ static int prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm,
        memory_bm_free(bm, PG_UNSAFE_KEEP);
 
        /* Make a copy of zero_bm so it can be created in safe pages */
-       error = memory_bm_create(&tmp, GFP_ATOMIC, PG_ANY);
+       error = memory_bm_create(&tmp, GFP_ATOMIC, PG_SAFE);
        if (error)
                goto Free;
 
@@ -2660,7 +2660,7 @@ static int prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm,
                goto Free;
 
        duplicate_memory_bitmap(zero_bm, &tmp);
-       memory_bm_free(&tmp, PG_UNSAFE_KEEP);
+       memory_bm_free(&tmp, PG_UNSAFE_CLEAR);
        /* At this point zero_bm is in safe pages and it can be used for restoring. */
 
        if (nr_highmem > 0) {
index 4492608..458d359 100644 (file)
@@ -350,7 +350,8 @@ static void sugov_update_single_freq(struct update_util_data *hook, u64 time,
         * Except when the rq is capped by uclamp_max.
         */
        if (!uclamp_rq_is_capped(cpu_rq(sg_cpu->cpu)) &&
-           sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq) {
+           sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq &&
+           !sg_policy->need_freq_update) {
                next_f = sg_policy->next_freq;
 
                /* Restore cached freq as next_freq has changed */
index cb22592..ef7490c 100644 (file)
@@ -664,6 +664,10 @@ void avg_vruntime_update(struct cfs_rq *cfs_rq, s64 delta)
        cfs_rq->avg_vruntime -= cfs_rq->avg_load * delta;
 }
 
+/*
+ * Specifically: avg_runtime() + 0 must result in entity_eligible() := true
+ * For this to be so, the result of this function must have a left bias.
+ */
 u64 avg_vruntime(struct cfs_rq *cfs_rq)
 {
        struct sched_entity *curr = cfs_rq->curr;
@@ -677,8 +681,12 @@ u64 avg_vruntime(struct cfs_rq *cfs_rq)
                load += weight;
        }
 
-       if (load)
+       if (load) {
+               /* sign flips effective floor / ceil */
+               if (avg < 0)
+                       avg -= (load - 1);
                avg = div_s64(avg, load);
+       }
 
        return cfs_rq->min_vruntime + avg;
 }
@@ -4919,10 +4927,12 @@ static inline void update_misfit_status(struct task_struct *p, struct rq *rq) {}
 static void
 place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
 {
-       u64 vslice = calc_delta_fair(se->slice, se);
-       u64 vruntime = avg_vruntime(cfs_rq);
+       u64 vslice, vruntime = avg_vruntime(cfs_rq);
        s64 lag = 0;
 
+       se->slice = sysctl_sched_base_slice;
+       vslice = calc_delta_fair(se->slice, se);
+
        /*
         * Due to how V is constructed as the weighted average of entities,
         * adding tasks with positive lag, or removing tasks with negative lag
index 9d5057c..7a6f203 100644 (file)
@@ -2413,34 +2413,41 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type,
        if (!test_bit(HCI_CONN_AUTH, &conn->flags))
                goto auth;
 
-       /* An authenticated FIPS approved combination key has sufficient
-        * security for security level 4. */
-       if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256 &&
-           sec_level == BT_SECURITY_FIPS)
-               goto encrypt;
-
-       /* An authenticated combination key has sufficient security for
-          security level 3. */
-       if ((conn->key_type == HCI_LK_AUTH_COMBINATION_P192 ||
-            conn->key_type == HCI_LK_AUTH_COMBINATION_P256) &&
-           sec_level == BT_SECURITY_HIGH)
-               goto encrypt;
-
-       /* An unauthenticated combination key has sufficient security for
-          security level 1 and 2. */
-       if ((conn->key_type == HCI_LK_UNAUTH_COMBINATION_P192 ||
-            conn->key_type == HCI_LK_UNAUTH_COMBINATION_P256) &&
-           (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW))
-               goto encrypt;
-
-       /* A combination key has always sufficient security for the security
-          levels 1 or 2. High security level requires the combination key
-          is generated using maximum PIN code length (16).
-          For pre 2.1 units. */
-       if (conn->key_type == HCI_LK_COMBINATION &&
-           (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW ||
-            conn->pin_length == 16))
-               goto encrypt;
+       switch (conn->key_type) {
+       case HCI_LK_AUTH_COMBINATION_P256:
+               /* An authenticated FIPS approved combination key has
+                * sufficient security for security level 4 or lower.
+                */
+               if (sec_level <= BT_SECURITY_FIPS)
+                       goto encrypt;
+               break;
+       case HCI_LK_AUTH_COMBINATION_P192:
+               /* An authenticated combination key has sufficient security for
+                * security level 3 or lower.
+                */
+               if (sec_level <= BT_SECURITY_HIGH)
+                       goto encrypt;
+               break;
+       case HCI_LK_UNAUTH_COMBINATION_P192:
+       case HCI_LK_UNAUTH_COMBINATION_P256:
+               /* An unauthenticated combination key has sufficient security
+                * for security level 2 or lower.
+                */
+               if (sec_level <= BT_SECURITY_MEDIUM)
+                       goto encrypt;
+               break;
+       case HCI_LK_COMBINATION:
+               /* A combination key has always sufficient security for the
+                * security levels 2 or lower. High security level requires the
+                * combination key is generated using maximum PIN code length
+                * (16). For pre 2.1 units.
+                */
+               if (sec_level <= BT_SECURITY_MEDIUM || conn->pin_length == 16)
+                       goto encrypt;
+               break;
+       default:
+               break;
+       }
 
 auth:
        if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
index a5992f1..195aea2 100644 (file)
@@ -2617,7 +2617,11 @@ int hci_register_dev(struct hci_dev *hdev)
        if (id < 0)
                return id;
 
-       snprintf(hdev->name, sizeof(hdev->name), "hci%d", id);
+       error = dev_set_name(&hdev->dev, "hci%u", id);
+       if (error)
+               return error;
+
+       hdev->name = dev_name(&hdev->dev);
        hdev->id = id;
 
        BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
@@ -2639,8 +2643,6 @@ int hci_register_dev(struct hci_dev *hdev)
        if (!IS_ERR_OR_NULL(bt_debugfs))
                hdev->debugfs = debugfs_create_dir(hdev->name, bt_debugfs);
 
-       dev_set_name(&hdev->dev, "%s", hdev->name);
-
        error = device_add(&hdev->dev);
        if (error < 0)
                goto err_wqueue;
@@ -2784,6 +2786,7 @@ void hci_release_dev(struct hci_dev *hdev)
        hci_conn_params_clear_all(hdev);
        hci_discovery_filter_clear(hdev);
        hci_blocked_keys_clear(hdev);
+       hci_codec_list_clear(&hdev->local_codecs);
        hci_dev_unlock(hdev);
 
        ida_simple_remove(&hci_index_ida, hdev->id);
@@ -3418,7 +3421,12 @@ static void hci_link_tx_to(struct hci_dev *hdev, __u8 type)
                if (c->type == type && c->sent) {
                        bt_dev_err(hdev, "killing stalled connection %pMR",
                                   &c->dst);
+                       /* hci_disconnect might sleep, so, we have to release
+                        * the RCU read lock before calling it.
+                        */
+                       rcu_read_unlock();
                        hci_disconnect(c, HCI_ERROR_REMOTE_USER_TERM);
+                       rcu_read_lock();
                }
        }
 
index 35f2510..31d02b5 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "hci_request.h"
 #include "hci_debugfs.h"
+#include "hci_codec.h"
 #include "a2mp.h"
 #include "amp.h"
 #include "smp.h"
index b9c5a98..0be75cf 100644 (file)
@@ -71,7 +71,5 @@ struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen,
 void hci_req_add_le_scan_disable(struct hci_request *req, bool rpa_le_conn);
 void hci_req_add_le_passive_scan(struct hci_request *req);
 
-void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next);
-
 void hci_request_setup(struct hci_dev *hdev);
 void hci_request_cancel_all(struct hci_dev *hdev);
index 9b93653..d06e07a 100644 (file)
@@ -413,11 +413,6 @@ static int hci_le_scan_restart_sync(struct hci_dev *hdev)
                                           LE_SCAN_FILTER_DUP_ENABLE);
 }
 
-static int le_scan_restart_sync(struct hci_dev *hdev, void *data)
-{
-       return hci_le_scan_restart_sync(hdev);
-}
-
 static void le_scan_restart(struct work_struct *work)
 {
        struct hci_dev *hdev = container_of(work, struct hci_dev,
@@ -427,15 +422,15 @@ static void le_scan_restart(struct work_struct *work)
 
        bt_dev_dbg(hdev, "");
 
-       hci_dev_lock(hdev);
-
-       status = hci_cmd_sync_queue(hdev, le_scan_restart_sync, NULL, NULL);
+       status = hci_le_scan_restart_sync(hdev);
        if (status) {
                bt_dev_err(hdev, "failed to restart LE scan: status %d",
                           status);
-               goto unlock;
+               return;
        }
 
+       hci_dev_lock(hdev);
+
        if (!test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks) ||
            !hdev->discovery.scan_start)
                goto unlock;
@@ -5079,6 +5074,7 @@ int hci_dev_close_sync(struct hci_dev *hdev)
        memset(hdev->eir, 0, sizeof(hdev->eir));
        memset(hdev->dev_class, 0, sizeof(hdev->dev_class));
        bacpy(&hdev->random_addr, BDADDR_ANY);
+       hci_codec_list_clear(&hdev->local_codecs);
 
        hci_dev_put(hdev);
        return err;
index 16da946..7124816 100644 (file)
@@ -502,7 +502,7 @@ drop:
 }
 
 /* -------- Socket interface ---------- */
-static struct sock *__iso_get_sock_listen_by_addr(bdaddr_t *ba)
+static struct sock *__iso_get_sock_listen_by_addr(bdaddr_t *src, bdaddr_t *dst)
 {
        struct sock *sk;
 
@@ -510,7 +510,10 @@ static struct sock *__iso_get_sock_listen_by_addr(bdaddr_t *ba)
                if (sk->sk_state != BT_LISTEN)
                        continue;
 
-               if (!bacmp(&iso_pi(sk)->src, ba))
+               if (bacmp(&iso_pi(sk)->dst, dst))
+                       continue;
+
+               if (!bacmp(&iso_pi(sk)->src, src))
                        return sk;
        }
 
@@ -952,7 +955,7 @@ static int iso_listen_cis(struct sock *sk)
 
        write_lock(&iso_sk_list.lock);
 
-       if (__iso_get_sock_listen_by_addr(&iso_pi(sk)->src))
+       if (__iso_get_sock_listen_by_addr(&iso_pi(sk)->src, &iso_pi(sk)->dst))
                err = -EADDRINUSE;
 
        write_unlock(&iso_sk_list.lock);
index 1518624..033034d 100644 (file)
@@ -294,7 +294,7 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_
                        /* tell br_dev_xmit to continue with forwarding */
                        nf_bridge->bridged_dnat = 1;
                        /* FIXME Need to refragment */
-                       ret = neigh->output(neigh, skb);
+                       ret = READ_ONCE(neigh->output)(neigh, skb);
                }
                neigh_release(neigh);
                return ret;
index 6b76cd1..9c09f09 100644 (file)
@@ -410,7 +410,7 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev,
                                 */
                                __skb_queue_purge(&n->arp_queue);
                                n->arp_queue_len_bytes = 0;
-                               n->output = neigh_blackhole;
+                               WRITE_ONCE(n->output, neigh_blackhole);
                                if (n->nud_state & NUD_VALID)
                                        n->nud_state = NUD_NOARP;
                                else
@@ -920,7 +920,7 @@ static void neigh_suspect(struct neighbour *neigh)
 {
        neigh_dbg(2, "neigh %p is suspected\n", neigh);
 
-       neigh->output = neigh->ops->output;
+       WRITE_ONCE(neigh->output, neigh->ops->output);
 }
 
 /* Neighbour state is OK;
@@ -932,7 +932,7 @@ static void neigh_connect(struct neighbour *neigh)
 {
        neigh_dbg(2, "neigh %p is connected\n", neigh);
 
-       neigh->output = neigh->ops->connected_output;
+       WRITE_ONCE(neigh->output, neigh->ops->connected_output);
 }
 
 static void neigh_periodic_work(struct work_struct *work)
@@ -988,7 +988,9 @@ static void neigh_periodic_work(struct work_struct *work)
                            (state == NUD_FAILED ||
                             !time_in_range_open(jiffies, n->used,
                                                 n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
-                               *np = n->next;
+                               rcu_assign_pointer(*np,
+                                       rcu_dereference_protected(n->next,
+                                               lockdep_is_held(&tbl->lock)));
                                neigh_mark_dead(n);
                                write_unlock(&n->lock);
                                neigh_cleanup_and_release(n);
@@ -1447,7 +1449,7 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr,
                                if (n2)
                                        n1 = n2;
                        }
-                       n1->output(n1, skb);
+                       READ_ONCE(n1->output)(n1, skb);
                        if (n2)
                                neigh_release(n2);
                        rcu_read_unlock();
@@ -3153,7 +3155,7 @@ int neigh_xmit(int index, struct net_device *dev,
                        rcu_read_unlock();
                        goto out_kfree_skb;
                }
-               err = neigh->output(neigh, skb);
+               err = READ_ONCE(neigh->output)(neigh, skb);
                rcu_read_unlock();
        }
        else if (index == NEIGH_LINK_TABLE) {
index cb11750..4292c2e 100644 (file)
@@ -668,6 +668,8 @@ BPF_CALL_4(bpf_msg_redirect_map, struct sk_msg *, msg,
        sk = __sock_map_lookup_elem(map, key);
        if (unlikely(!sk || !sock_map_redirect_allowed(sk)))
                return SK_DROP;
+       if (!(flags & BPF_F_INGRESS) && !sk_is_tcp(sk))
+               return SK_DROP;
 
        msg->flags = flags;
        msg->sk_redir = sk;
@@ -1267,6 +1269,8 @@ BPF_CALL_4(bpf_msg_redirect_hash, struct sk_msg *, msg,
        sk = __sock_hash_lookup_elem(map, key);
        if (unlikely(!sk || !sock_map_redirect_allowed(sk)))
                return SK_DROP;
+       if (!(flags & BPF_F_INGRESS) && !sk_is_tcp(sk))
+               return SK_DROP;
 
        msg->flags = flags;
        msg->sk_redir = sk;
index b238a1a..b1e2e3b 100644 (file)
@@ -21,16 +21,6 @@ struct plca_reply_data {
 #define PLCA_REPDATA(__reply_base) \
        container_of(__reply_base, struct plca_reply_data, base)
 
-static void plca_update_sint(int *dst, const struct nlattr *attr,
-                            bool *mod)
-{
-       if (!attr)
-               return;
-
-       *dst = nla_get_u32(attr);
-       *mod = true;
-}
-
 // PLCA get configuration message ------------------------------------------- //
 
 const struct nla_policy ethnl_plca_get_cfg_policy[] = {
@@ -38,6 +28,29 @@ const struct nla_policy ethnl_plca_get_cfg_policy[] = {
                NLA_POLICY_NESTED(ethnl_header_policy),
 };
 
+static void plca_update_sint(int *dst, struct nlattr **tb, u32 attrid,
+                            bool *mod)
+{
+       const struct nlattr *attr = tb[attrid];
+
+       if (!attr ||
+           WARN_ON_ONCE(attrid >= ARRAY_SIZE(ethnl_plca_set_cfg_policy)))
+               return;
+
+       switch (ethnl_plca_set_cfg_policy[attrid].type) {
+       case NLA_U8:
+               *dst = nla_get_u8(attr);
+               break;
+       case NLA_U32:
+               *dst = nla_get_u32(attr);
+               break;
+       default:
+               WARN_ON_ONCE(1);
+       }
+
+       *mod = true;
+}
+
 static int plca_get_cfg_prepare_data(const struct ethnl_req_info *req_base,
                                     struct ethnl_reply_data *reply_base,
                                     const struct genl_info *info)
@@ -144,13 +157,13 @@ ethnl_set_plca(struct ethnl_req_info *req_info, struct genl_info *info)
                return -EOPNOTSUPP;
 
        memset(&plca_cfg, 0xff, sizeof(plca_cfg));
-       plca_update_sint(&plca_cfg.enabled, tb[ETHTOOL_A_PLCA_ENABLED], &mod);
-       plca_update_sint(&plca_cfg.node_id, tb[ETHTOOL_A_PLCA_NODE_ID], &mod);
-       plca_update_sint(&plca_cfg.node_cnt, tb[ETHTOOL_A_PLCA_NODE_CNT], &mod);
-       plca_update_sint(&plca_cfg.to_tmr, tb[ETHTOOL_A_PLCA_TO_TMR], &mod);
-       plca_update_sint(&plca_cfg.burst_cnt, tb[ETHTOOL_A_PLCA_BURST_CNT],
+       plca_update_sint(&plca_cfg.enabled, tb, ETHTOOL_A_PLCA_ENABLED, &mod);
+       plca_update_sint(&plca_cfg.node_id, tb, ETHTOOL_A_PLCA_NODE_ID, &mod);
+       plca_update_sint(&plca_cfg.node_cnt, tb, ETHTOOL_A_PLCA_NODE_CNT, &mod);
+       plca_update_sint(&plca_cfg.to_tmr, tb, ETHTOOL_A_PLCA_TO_TMR, &mod);
+       plca_update_sint(&plca_cfg.burst_cnt, tb, ETHTOOL_A_PLCA_BURST_CNT,
                         &mod);
-       plca_update_sint(&plca_cfg.burst_tmr, tb[ETHTOOL_A_PLCA_BURST_TMR],
+       plca_update_sint(&plca_cfg.burst_tmr, tb, ETHTOOL_A_PLCA_BURST_TMR,
                         &mod);
        if (!mod)
                return 0;
index eafa4a0..1ea82bc 100644 (file)
@@ -1887,6 +1887,7 @@ int fib_sync_down_addr(struct net_device *dev, __be32 local)
                        continue;
                if (fi->fib_prefsrc == local) {
                        fi->fib_flags |= RTNH_F_DEAD;
+                       fi->pfsrc_removed = true;
                        ret++;
                }
        }
index d13fb9e..9bdfdab 100644 (file)
@@ -2027,6 +2027,7 @@ void fib_table_flush_external(struct fib_table *tb)
 int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all)
 {
        struct trie *t = (struct trie *)tb->tb_data;
+       struct nl_info info = { .nl_net = net };
        struct key_vector *pn = t->kv;
        unsigned long cindex = 1;
        struct hlist_node *tmp;
@@ -2089,6 +2090,9 @@ int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all)
 
                        fib_notify_alias_delete(net, n->key, &n->leaf, fa,
                                                NULL);
+                       if (fi->pfsrc_removed)
+                               rtmsg_fib(RTM_DELROUTE, htonl(n->key), fa,
+                                         KEYLENGTH - fa->fa_slen, tb->tb_id, &info, 0);
                        hlist_del_rcu(&fa->fa_list);
                        fib_release_info(fa->fa_info);
                        alias_free_mem_rcu(fa);
index a570622..b214b5a 100644 (file)
@@ -3417,6 +3417,8 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
                                    fa->fa_type == fri.type) {
                                        fri.offload = READ_ONCE(fa->offload);
                                        fri.trap = READ_ONCE(fa->trap);
+                                       fri.offload_failed =
+                                               READ_ONCE(fa->offload_failed);
                                        break;
                                }
                        }
index 0c3040a..3f66cde 100644 (file)
@@ -1621,16 +1621,13 @@ EXPORT_SYMBOL(tcp_read_sock);
 
 int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
 {
-       struct tcp_sock *tp = tcp_sk(sk);
-       u32 seq = tp->copied_seq;
        struct sk_buff *skb;
        int copied = 0;
-       u32 offset;
 
        if (sk->sk_state == TCP_LISTEN)
                return -ENOTCONN;
 
-       while ((skb = tcp_recv_skb(sk, seq, &offset)) != NULL) {
+       while ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) {
                u8 tcp_flags;
                int used;
 
@@ -1643,13 +1640,10 @@ int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
                                copied = used;
                        break;
                }
-               seq += used;
                copied += used;
 
-               if (tcp_flags & TCPHDR_FIN) {
-                       ++seq;
+               if (tcp_flags & TCPHDR_FIN)
                        break;
-               }
        }
        return copied;
 }
index 81f0dff..3272682 100644 (file)
@@ -222,6 +222,7 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,
                                  int *addr_len)
 {
        struct tcp_sock *tcp = tcp_sk(sk);
+       int peek = flags & MSG_PEEK;
        u32 seq = tcp->copied_seq;
        struct sk_psock *psock;
        int copied = 0;
@@ -311,7 +312,8 @@ msg_bytes_ready:
                copied = -EAGAIN;
        }
 out:
-       WRITE_ONCE(tcp->copied_seq, seq);
+       if (!peek)
+               WRITE_ONCE(tcp->copied_seq, seq);
        tcp_rcv_space_adjust(sk);
        if (copied > 0)
                __tcp_cleanup_rbuf(sk, copied);
index 06fe1cf..8afb095 100644 (file)
@@ -253,6 +253,19 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb)
                if (unlikely(len > icsk->icsk_ack.rcv_mss +
                                   MAX_TCP_OPTION_SPACE))
                        tcp_gro_dev_warn(sk, skb, len);
+               /* If the skb has a len of exactly 1*MSS and has the PSH bit
+                * set then it is likely the end of an application write. So
+                * more data may not be arriving soon, and yet the data sender
+                * may be waiting for an ACK if cwnd-bound or using TX zero
+                * copy. So we set ICSK_ACK_PUSHED here so that
+                * tcp_cleanup_rbuf() will send an ACK immediately if the app
+                * reads all of the data and is not ping-pong. If len > MSS
+                * then this logic does not matter (and does not hurt) because
+                * tcp_cleanup_rbuf() will always ACK immediately if the app
+                * reads data and there is more than an MSS of unACKed data.
+                */
+               if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_PSH)
+                       icsk->icsk_ack.pending |= ICSK_ACK_PUSHED;
        } else {
                /* Otherwise, we make more careful check taking into account,
                 * that SACKs block is variable.
index ccfc8bb..aa0fc8c 100644 (file)
@@ -177,8 +177,7 @@ static void tcp_event_data_sent(struct tcp_sock *tp,
 }
 
 /* Account for an ACK we sent. */
-static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts,
-                                     u32 rcv_nxt)
+static inline void tcp_event_ack_sent(struct sock *sk, u32 rcv_nxt)
 {
        struct tcp_sock *tp = tcp_sk(sk);
 
@@ -192,7 +191,7 @@ static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts,
 
        if (unlikely(rcv_nxt != tp->rcv_nxt))
                return;  /* Special ACK sent by DCTCP to reflect ECN */
-       tcp_dec_quickack_mode(sk, pkts);
+       tcp_dec_quickack_mode(sk);
        inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);
 }
 
@@ -1387,7 +1386,7 @@ static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb,
                           sk, skb);
 
        if (likely(tcb->tcp_flags & TCPHDR_ACK))
-               tcp_event_ack_sent(sk, tcp_skb_pcount(skb), rcv_nxt);
+               tcp_event_ack_sent(sk, rcv_nxt);
 
        if (skb->len != tcp_header_size) {
                tcp_event_data_sent(tp, sk);
index 3a88545..44b6949 100644 (file)
@@ -1640,9 +1640,12 @@ process:
                struct sock *nsk;
 
                sk = req->rsk_listener;
-               drop_reason = tcp_inbound_md5_hash(sk, skb,
-                                                  &hdr->saddr, &hdr->daddr,
-                                                  AF_INET6, dif, sdif);
+               if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
+                       drop_reason = SKB_DROP_REASON_XFRM_POLICY;
+               else
+                       drop_reason = tcp_inbound_md5_hash(sk, skb,
+                                                          &hdr->saddr, &hdr->daddr,
+                                                          AF_INET6, dif, sdif);
                if (drop_reason) {
                        sk_drops_add(sk, skb);
                        reqsk_put(req);
@@ -1689,6 +1692,7 @@ process:
                        }
                        goto discard_and_relse;
                }
+               nf_reset_ct(skb);
                if (nsk == sk) {
                        reqsk_put(req);
                        tcp_v6_restore_cb(skb);
index ed8ebb6..11f3d37 100644 (file)
@@ -507,7 +507,6 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
         */
        if (len > INT_MAX - transhdrlen)
                return -EMSGSIZE;
-       ulen = len + transhdrlen;
 
        /* Mirror BSD error message compatibility */
        if (msg->msg_flags & MSG_OOB)
@@ -628,6 +627,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 
 back_from_confirm:
        lock_sock(sk);
+       ulen = len + skb_queue_empty(&sk->sk_write_queue) ? transhdrlen : 0;
        err = ip6_append_data(sk, ip_generic_getfrag, msg,
                              ulen, transhdrlen, &ipc6,
                              &fl6, (struct rt6_info *)dst,
index 45e7a5d..0e3a175 100644 (file)
@@ -566,6 +566,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
        }
 
        err = ieee80211_key_link(key, link, sta);
+       /* KRACK protection, shouldn't happen but just silently accept key */
+       if (err == -EALREADY)
+               err = 0;
 
  out_unlock:
        mutex_unlock(&local->sta_mtx);
@@ -1857,7 +1860,8 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
        /* VHT can override some HT caps such as the A-MSDU max length */
        if (params->vht_capa)
                ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
-                                                   params->vht_capa, link_sta);
+                                                   params->vht_capa, NULL,
+                                                   link_sta);
 
        if (params->he_capa)
                ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband,
index e190007..5542c93 100644 (file)
@@ -1072,7 +1072,7 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata,
                                                   &chandef);
                        memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie));
                        ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
-                                                           &cap_ie,
+                                                           &cap_ie, NULL,
                                                            &sta->deflink);
                        if (memcmp(&cap, &sta->sta.deflink.vht_cap, sizeof(cap)))
                                rates_updated |= true;
index 06bd406..98ef1fe 100644 (file)
@@ -676,7 +676,7 @@ struct ieee80211_if_mesh {
        struct timer_list mesh_path_root_timer;
 
        unsigned long wrkq_flags;
-       unsigned long mbss_changed;
+       unsigned long mbss_changed[64 / BITS_PER_LONG];
 
        bool userspace_handles_dfs;
 
@@ -2141,6 +2141,7 @@ void
 ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
                                    struct ieee80211_supported_band *sband,
                                    const struct ieee80211_vht_cap *vht_cap_ie,
+                                   const struct ieee80211_vht_cap *vht_cap_ie2,
                                    struct link_sta_info *link_sta);
 enum ieee80211_sta_rx_bandwidth
 ieee80211_sta_cap_rx_bw(struct link_sta_info *link_sta);
index 13050dc..0665ff5 100644 (file)
@@ -802,6 +802,9 @@ static void ieee80211_key_destroy(struct ieee80211_key *key,
 
 void ieee80211_key_free_unused(struct ieee80211_key *key)
 {
+       if (!key)
+               return;
+
        WARN_ON(key->sdata || key->local);
        ieee80211_key_free_common(key);
 }
@@ -854,7 +857,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
         * can cause warnings to appear.
         */
        bool delay_tailroom = sdata->vif.type == NL80211_IFTYPE_STATION;
-       int ret = -EOPNOTSUPP;
+       int ret;
 
        mutex_lock(&sdata->local->key_mtx);
 
@@ -868,8 +871,10 @@ int ieee80211_key_link(struct ieee80211_key *key,
                 * the same cipher. Enforce the assumption for pairwise keys.
                 */
                if ((alt_key && alt_key->conf.cipher != key->conf.cipher) ||
-                   (old_key && old_key->conf.cipher != key->conf.cipher))
+                   (old_key && old_key->conf.cipher != key->conf.cipher)) {
+                       ret = -EOPNOTSUPP;
                        goto out;
+               }
        } else if (sta) {
                struct link_sta_info *link_sta = &sta->deflink;
                int link_id = key->conf.link_id;
@@ -895,8 +900,10 @@ int ieee80211_key_link(struct ieee80211_key *key,
 
        /* Non-pairwise keys must also not switch the cipher on rekey */
        if (!pairwise) {
-               if (old_key && old_key->conf.cipher != key->conf.cipher)
+               if (old_key && old_key->conf.cipher != key->conf.cipher) {
+                       ret = -EOPNOTSUPP;
                        goto out;
+               }
        }
 
        /*
@@ -904,9 +911,8 @@ int ieee80211_key_link(struct ieee80211_key *key,
         * new version of the key to avoid nonce reuse or replay issues.
         */
        if (ieee80211_key_identical(sdata, old_key, key)) {
-               ieee80211_key_free_unused(key);
-               ret = 0;
-               goto out;
+               ret = -EALREADY;
+               goto unlock;
        }
 
        key->local = sdata->local;
@@ -930,7 +936,11 @@ int ieee80211_key_link(struct ieee80211_key *key,
                ieee80211_key_free(key, delay_tailroom);
        }
 
+       key = NULL;
+
  out:
+       ieee80211_key_free_unused(key);
+ unlock:
        mutex_unlock(&sdata->local->key_mtx);
 
        return ret;
index af8c5fc..e31c312 100644 (file)
@@ -1175,7 +1175,7 @@ void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata,
 
        /* if we race with running work, worst case this work becomes a noop */
        for_each_set_bit(bit, &bits, sizeof(changed) * BITS_PER_BYTE)
-               set_bit(bit, &ifmsh->mbss_changed);
+               set_bit(bit, ifmsh->mbss_changed);
        set_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags);
        wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work);
 }
@@ -1257,7 +1257,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
 
        /* clear any mesh work (for next join) we may have accrued */
        ifmsh->wrkq_flags = 0;
-       ifmsh->mbss_changed = 0;
+       memset(ifmsh->mbss_changed, 0, sizeof(ifmsh->mbss_changed));
 
        local->fif_other_bss--;
        atomic_dec(&local->iff_allmultis);
@@ -1724,9 +1724,9 @@ static void mesh_bss_info_changed(struct ieee80211_sub_if_data *sdata)
        u32 bit;
        u64 changed = 0;
 
-       for_each_set_bit(bit, &ifmsh->mbss_changed,
+       for_each_set_bit(bit, ifmsh->mbss_changed,
                         sizeof(changed) * BITS_PER_BYTE) {
-               clear_bit(bit, &ifmsh->mbss_changed);
+               clear_bit(bit, ifmsh->mbss_changed);
                changed |= BIT(bit);
        }
 
index f3d5bb0..a1e5264 100644 (file)
@@ -451,7 +451,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
                changed |= IEEE80211_RC_BW_CHANGED;
 
        ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
-                                           elems->vht_cap_elem,
+                                           elems->vht_cap_elem, NULL,
                                            &sta->deflink);
 
        ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, elems->he_cap,
index f93eb38..0c91989 100644 (file)
@@ -4202,10 +4202,33 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link,
                                                  elems->ht_cap_elem,
                                                  link_sta);
 
-       if (elems->vht_cap_elem && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT))
+       if (elems->vht_cap_elem &&
+           !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) {
+               const struct ieee80211_vht_cap *bss_vht_cap = NULL;
+               const struct cfg80211_bss_ies *ies;
+
+               /*
+                * Cisco AP module 9115 with FW 17.3 has a bug and sends a
+                * too large maximum MPDU length in the association response
+                * (indicating 12k) that it cannot actually process ...
+                * Work around that.
+                */
+               rcu_read_lock();
+               ies = rcu_dereference(cbss->ies);
+               if (ies) {
+                       const struct element *elem;
+
+                       elem = cfg80211_find_elem(WLAN_EID_VHT_CAPABILITY,
+                                                 ies->data, ies->len);
+                       if (elem && elem->datalen >= sizeof(*bss_vht_cap))
+                               bss_vht_cap = (const void *)elem->data;
+               }
+
                ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
                                                    elems->vht_cap_elem,
-                                                   link_sta);
+                                                   bss_vht_cap, link_sta);
+               rcu_read_unlock();
+       }
 
        if (elems->he_operation && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) &&
            elems->he_cap) {
@@ -5107,9 +5130,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
                                continue;
 
                        valid_links |= BIT(link_id);
-                       if (assoc_data->link[link_id].disabled) {
+                       if (assoc_data->link[link_id].disabled)
                                dormant_links |= BIT(link_id);
-                       } else if (link_id != assoc_data->assoc_link_id) {
+
+                       if (link_id != assoc_data->assoc_link_id) {
                                err = ieee80211_sta_allocate_link(sta, link_id);
                                if (err)
                                        goto out_err;
@@ -5124,7 +5148,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
                struct ieee80211_link_data *link;
                struct link_sta_info *link_sta;
 
-               if (!cbss || assoc_data->link[link_id].disabled)
+               if (!cbss)
                        continue;
 
                link = sdata_dereference(sdata->link[link_id], sdata);
@@ -5429,17 +5453,18 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
        for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
                struct ieee80211_link_data *link;
 
-               link = sdata_dereference(sdata->link[link_id], sdata);
-               if (!link)
-                       continue;
-
                if (!assoc_data->link[link_id].bss)
                        continue;
 
                resp.links[link_id].bss = assoc_data->link[link_id].bss;
-               resp.links[link_id].addr = link->conf->addr;
+               ether_addr_copy(resp.links[link_id].addr,
+                               assoc_data->link[link_id].addr);
                resp.links[link_id].status = assoc_data->link[link_id].status;
 
+               link = sdata_dereference(sdata->link[link_id], sdata);
+               if (!link)
+                       continue;
+
                /* get uapsd queues configuration - same for all links */
                resp.uapsd_queues = 0;
                for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
index 7fe7280..d45d4be 100644 (file)
@@ -665,7 +665,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
                }
 
                if (unlikely(tx->key && tx->key->flags & KEY_FLAG_TAINTED &&
-                            !ieee80211_is_deauth(hdr->frame_control)))
+                            !ieee80211_is_deauth(hdr->frame_control)) &&
+                            tx->skb->protocol != tx->sdata->control_port_protocol)
                        return TX_DROP;
 
                if (!skip_hw && tx->key &&
index c1250aa..b3a5c3e 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Portions of this file
  * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
- * Copyright (C) 2018 - 2022 Intel Corporation
+ * Copyright (C) 2018 - 2023 Intel Corporation
  */
 
 #include <linux/ieee80211.h>
@@ -116,12 +116,14 @@ void
 ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
                                    struct ieee80211_supported_band *sband,
                                    const struct ieee80211_vht_cap *vht_cap_ie,
+                                   const struct ieee80211_vht_cap *vht_cap_ie2,
                                    struct link_sta_info *link_sta)
 {
        struct ieee80211_sta_vht_cap *vht_cap = &link_sta->pub->vht_cap;
        struct ieee80211_sta_vht_cap own_cap;
        u32 cap_info, i;
        bool have_80mhz;
+       u32 mpdu_len;
 
        memset(vht_cap, 0, sizeof(*vht_cap));
 
@@ -318,10 +320,20 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
        link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta);
 
        /*
+        * Work around the Cisco 9115 FW 17.3 bug by taking the min of
+        * both reported MPDU lengths.
+        */
+       mpdu_len = vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK;
+       if (vht_cap_ie2)
+               mpdu_len = min_t(u32, mpdu_len,
+                                le32_get_bits(vht_cap_ie2->vht_cap_info,
+                                              IEEE80211_VHT_CAP_MAX_MPDU_MASK));
+
+       /*
         * FIXME - should the amsdu len be per link? store per link
         * and maintain a minimum?
         */
-       switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
+       switch (mpdu_len) {
        case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
                link_sta->pub->agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454;
                break;
index b5a8aa4..d042d32 100644 (file)
@@ -307,12 +307,6 @@ int mptcp_nl_cmd_sf_create(struct sk_buff *skb, struct genl_info *info)
                goto create_err;
        }
 
-       if (addr_l.id == 0) {
-               NL_SET_ERR_MSG_ATTR(info->extack, laddr, "missing local addr id");
-               err = -EINVAL;
-               goto create_err;
-       }
-
        err = mptcp_pm_parse_addr(raddr, info, &addr_r);
        if (err < 0) {
                NL_SET_ERR_MSG_ATTR(info->extack, raddr, "error parsing remote addr");
index e252539..c3b83cb 100644 (file)
@@ -3425,24 +3425,21 @@ static void schedule_3rdack_retransmission(struct sock *ssk)
        sk_reset_timer(ssk, &icsk->icsk_delack_timer, timeout);
 }
 
-void mptcp_subflow_process_delegated(struct sock *ssk)
+void mptcp_subflow_process_delegated(struct sock *ssk, long status)
 {
        struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
        struct sock *sk = subflow->conn;
 
-       if (test_bit(MPTCP_DELEGATE_SEND, &subflow->delegated_status)) {
+       if (status & BIT(MPTCP_DELEGATE_SEND)) {
                mptcp_data_lock(sk);
                if (!sock_owned_by_user(sk))
                        __mptcp_subflow_push_pending(sk, ssk, true);
                else
                        __set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->cb_flags);
                mptcp_data_unlock(sk);
-               mptcp_subflow_delegated_done(subflow, MPTCP_DELEGATE_SEND);
        }
-       if (test_bit(MPTCP_DELEGATE_ACK, &subflow->delegated_status)) {
+       if (status & BIT(MPTCP_DELEGATE_ACK))
                schedule_3rdack_retransmission(ssk);
-               mptcp_subflow_delegated_done(subflow, MPTCP_DELEGATE_ACK);
-       }
 }
 
 static int mptcp_hash(struct sock *sk)
@@ -3968,14 +3965,17 @@ static int mptcp_napi_poll(struct napi_struct *napi, int budget)
                struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
 
                bh_lock_sock_nested(ssk);
-               if (!sock_owned_by_user(ssk) &&
-                   mptcp_subflow_has_delegated_action(subflow))
-                       mptcp_subflow_process_delegated(ssk);
-               /* ... elsewhere tcp_release_cb_override already processed
-                * the action or will do at next release_sock().
-                * In both case must dequeue the subflow here - on the same
-                * CPU that scheduled it.
-                */
+               if (!sock_owned_by_user(ssk)) {
+                       mptcp_subflow_process_delegated(ssk, xchg(&subflow->delegated_status, 0));
+               } else {
+                       /* tcp_release_cb_override already processed
+                        * the action or will do at next release_sock().
+                        * In both case must dequeue the subflow here - on the same
+                        * CPU that scheduled it.
+                        */
+                       smp_wmb();
+                       clear_bit(MPTCP_DELEGATE_SCHEDULED, &subflow->delegated_status);
+               }
                bh_unlock_sock(ssk);
                sock_put(ssk);
 
index ed61d68..3612545 100644 (file)
@@ -444,9 +444,11 @@ struct mptcp_delegated_action {
 
 DECLARE_PER_CPU(struct mptcp_delegated_action, mptcp_delegated_actions);
 
-#define MPTCP_DELEGATE_SEND            0
-#define MPTCP_DELEGATE_ACK             1
+#define MPTCP_DELEGATE_SCHEDULED       0
+#define MPTCP_DELEGATE_SEND            1
+#define MPTCP_DELEGATE_ACK             2
 
+#define MPTCP_DELEGATE_ACTIONS_MASK    (~BIT(MPTCP_DELEGATE_SCHEDULED))
 /* MPTCP subflow context */
 struct mptcp_subflow_context {
        struct  list_head node;/* conn_list of subflows */
@@ -564,23 +566,24 @@ mptcp_subflow_get_mapped_dsn(const struct mptcp_subflow_context *subflow)
        return subflow->map_seq + mptcp_subflow_get_map_offset(subflow);
 }
 
-void mptcp_subflow_process_delegated(struct sock *ssk);
+void mptcp_subflow_process_delegated(struct sock *ssk, long actions);
 
 static inline void mptcp_subflow_delegate(struct mptcp_subflow_context *subflow, int action)
 {
+       long old, set_bits = BIT(MPTCP_DELEGATE_SCHEDULED) | BIT(action);
        struct mptcp_delegated_action *delegated;
        bool schedule;
 
        /* the caller held the subflow bh socket lock */
        lockdep_assert_in_softirq();
 
-       /* The implied barrier pairs with mptcp_subflow_delegated_done(), and
-        * ensures the below list check sees list updates done prior to status
-        * bit changes
+       /* The implied barrier pairs with tcp_release_cb_override()
+        * mptcp_napi_poll(), and ensures the below list check sees list
+        * updates done prior to delegated status bits changes
         */
-       if (!test_and_set_bit(action, &subflow->delegated_status)) {
-               /* still on delegated list from previous scheduling */
-               if (!list_empty(&subflow->delegated_node))
+       old = set_mask_bits(&subflow->delegated_status, 0, set_bits);
+       if (!(old & BIT(MPTCP_DELEGATE_SCHEDULED))) {
+               if (WARN_ON_ONCE(!list_empty(&subflow->delegated_node)))
                        return;
 
                delegated = this_cpu_ptr(&mptcp_delegated_actions);
@@ -605,20 +608,6 @@ mptcp_subflow_delegated_next(struct mptcp_delegated_action *delegated)
        return ret;
 }
 
-static inline bool mptcp_subflow_has_delegated_action(const struct mptcp_subflow_context *subflow)
-{
-       return !!READ_ONCE(subflow->delegated_status);
-}
-
-static inline void mptcp_subflow_delegated_done(struct mptcp_subflow_context *subflow, int action)
-{
-       /* pairs with mptcp_subflow_delegate, ensures delegate_node is updated before
-        * touching the status bit
-        */
-       smp_wmb();
-       clear_bit(action, &subflow->delegated_status);
-}
-
 int mptcp_is_enabled(const struct net *net);
 unsigned int mptcp_get_add_addr_timeout(const struct net *net);
 int mptcp_is_checksum_enabled(const struct net *net);
index 918c1a2..9c1f8d1 100644 (file)
@@ -1956,9 +1956,15 @@ static void subflow_ulp_clone(const struct request_sock *req,
 static void tcp_release_cb_override(struct sock *ssk)
 {
        struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
+       long status;
 
-       if (mptcp_subflow_has_delegated_action(subflow))
-               mptcp_subflow_process_delegated(ssk);
+       /* process and clear all the pending actions, but leave the subflow into
+        * the napi queue. To respect locking, only the same CPU that originated
+        * the action can touch the list. mptcp_napi_poll will take care of it.
+        */
+       status = set_mask_bits(&subflow->delegated_status, MPTCP_DELEGATE_ACTIONS_MASK, 0);
+       if (status)
+               mptcp_subflow_process_delegated(ssk, status);
 
        tcp_release_cb(ssk);
 }
index da5af28..4174076 100644 (file)
@@ -1439,7 +1439,7 @@ static int bind_mcastif_addr(struct socket *sock, struct net_device *dev)
        sin.sin_addr.s_addr  = addr;
        sin.sin_port         = 0;
 
-       return sock->ops->bind(sock, (struct sockaddr*)&sin, sizeof(sin));
+       return kernel_bind(sock, (struct sockaddr *)&sin, sizeof(sin));
 }
 
 static void get_mcast_sockaddr(union ipvs_sockaddr *sa, int *salen,
@@ -1505,8 +1505,8 @@ static int make_send_sock(struct netns_ipvs *ipvs, int id,
        }
 
        get_mcast_sockaddr(&mcast_addr, &salen, &ipvs->mcfg, id);
-       result = sock->ops->connect(sock, (struct sockaddr *) &mcast_addr,
-                                   salen, 0);
+       result = kernel_connect(sock, (struct sockaddr *)&mcast_addr,
+                               salen, 0);
        if (result < 0) {
                pr_err("Error connecting to the multicast addr\n");
                goto error;
@@ -1546,7 +1546,7 @@ static int make_receive_sock(struct netns_ipvs *ipvs, int id,
 
        get_mcast_sockaddr(&mcast_addr, &salen, &ipvs->bcfg, id);
        sock->sk->sk_bound_dev_if = dev->ifindex;
-       result = sock->ops->bind(sock, (struct sockaddr *)&mcast_addr, salen);
+       result = kernel_bind(sock, (struct sockaddr *)&mcast_addr, salen);
        if (result < 0) {
                pr_err("Error binding to the multicast addr\n");
                goto error;
index b6bcc8f..c6bd533 100644 (file)
@@ -112,7 +112,7 @@ static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = {
 /* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA, sSA},
 /* error        */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL},/* Can't have Stale cookie*/
 /* cookie_echo  */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA, sCL},/* 5.2.4 - Big TODO */
-/* cookie_ack   */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL},/* Can't come in orig dir */
+/* cookie_ack   */ {sCL, sCL, sCW, sES, sES, sSS, sSR, sSA, sCL},/* Can't come in orig dir */
 /* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL, sCL},
 /* heartbeat    */ {sHS, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS},
 /* heartbeat_ack*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS},
@@ -126,7 +126,7 @@ static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = {
 /* shutdown     */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA, sIV},
 /* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA, sIV},
 /* error        */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA, sIV},
-/* cookie_echo  */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sIV},/* Can't come in reply dir */
+/* cookie_echo  */ {sIV, sCL, sCE, sCE, sES, sSS, sSR, sSA, sIV},/* Can't come in reply dir */
 /* cookie_ack   */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA, sIV},
 /* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL, sIV},
 /* heartbeat    */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS},
@@ -412,6 +412,9 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct,
                        /* (D) vtag must be same as init_vtag as found in INIT_ACK */
                        if (sh->vtag != ct->proto.sctp.vtag[dir])
                                goto out_unlock;
+               } else if (sch->type == SCTP_CID_COOKIE_ACK) {
+                       ct->proto.sctp.init[dir] = 0;
+                       ct->proto.sctp.init[!dir] = 0;
                } else if (sch->type == SCTP_CID_HEARTBEAT) {
                        if (ct->proto.sctp.vtag[dir] == 0) {
                                pr_debug("Setting %d vtag %x for dir %d\n", sch->type, sh->vtag, dir);
@@ -461,16 +464,18 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct,
                }
 
                /* If it is an INIT or an INIT ACK note down the vtag */
-               if (sch->type == SCTP_CID_INIT ||
-                   sch->type == SCTP_CID_INIT_ACK) {
-                       struct sctp_inithdr _inithdr, *ih;
+               if (sch->type == SCTP_CID_INIT) {
+                       struct sctp_inithdr _ih, *ih;
 
-                       ih = skb_header_pointer(skb, offset + sizeof(_sch),
-                                               sizeof(_inithdr), &_inithdr);
-                       if (ih == NULL)
+                       ih = skb_header_pointer(skb, offset + sizeof(_sch), sizeof(*ih), &_ih);
+                       if (!ih)
                                goto out_unlock;
-                       pr_debug("Setting vtag %x for dir %d\n",
-                                ih->init_tag, !dir);
+
+                       if (ct->proto.sctp.init[dir] && ct->proto.sctp.init[!dir])
+                               ct->proto.sctp.init[!dir] = 0;
+                       ct->proto.sctp.init[dir] = 1;
+
+                       pr_debug("Setting vtag %x for dir %d\n", ih->init_tag, !dir);
                        ct->proto.sctp.vtag[!dir] = ih->init_tag;
 
                        /* don't renew timeout on init retransmit so
@@ -481,6 +486,24 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct,
                            old_state == SCTP_CONNTRACK_CLOSED &&
                            nf_ct_is_confirmed(ct))
                                ignore = true;
+               } else if (sch->type == SCTP_CID_INIT_ACK) {
+                       struct sctp_inithdr _ih, *ih;
+                       __be32 vtag;
+
+                       ih = skb_header_pointer(skb, offset + sizeof(_sch), sizeof(*ih), &_ih);
+                       if (!ih)
+                               goto out_unlock;
+
+                       vtag = ct->proto.sctp.vtag[!dir];
+                       if (!ct->proto.sctp.init[!dir] && vtag && vtag != ih->init_tag)
+                               goto out_unlock;
+                       /* collision */
+                       if (ct->proto.sctp.init[dir] && ct->proto.sctp.init[!dir] &&
+                           vtag != ih->init_tag)
+                               goto out_unlock;
+
+                       pr_debug("Setting vtag %x for dir %d\n", ih->init_tag, !dir);
+                       ct->proto.sctp.vtag[!dir] = ih->init_tag;
                }
 
                ct->proto.sctp.state = new_state;
index 4356189..a72b6ae 100644 (file)
@@ -7871,24 +7871,14 @@ static int nf_tables_delobj(struct sk_buff *skb, const struct nfnl_info *info,
        return nft_delobj(&ctx, obj);
 }
 
-void nft_obj_notify(struct net *net, const struct nft_table *table,
-                   struct nft_object *obj, u32 portid, u32 seq, int event,
-                   u16 flags, int family, int report, gfp_t gfp)
+static void
+__nft_obj_notify(struct net *net, const struct nft_table *table,
+                struct nft_object *obj, u32 portid, u32 seq, int event,
+                u16 flags, int family, int report, gfp_t gfp)
 {
        struct nftables_pernet *nft_net = nft_pernet(net);
        struct sk_buff *skb;
        int err;
-       char *buf = kasprintf(gfp, "%s:%u",
-                             table->name, nft_net->base_seq);
-
-       audit_log_nfcfg(buf,
-                       family,
-                       obj->handle,
-                       event == NFT_MSG_NEWOBJ ?
-                                AUDIT_NFT_OP_OBJ_REGISTER :
-                                AUDIT_NFT_OP_OBJ_UNREGISTER,
-                       gfp);
-       kfree(buf);
 
        if (!report &&
            !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
@@ -7911,13 +7901,35 @@ void nft_obj_notify(struct net *net, const struct nft_table *table,
 err:
        nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, -ENOBUFS);
 }
+
+void nft_obj_notify(struct net *net, const struct nft_table *table,
+                   struct nft_object *obj, u32 portid, u32 seq, int event,
+                   u16 flags, int family, int report, gfp_t gfp)
+{
+       struct nftables_pernet *nft_net = nft_pernet(net);
+       char *buf = kasprintf(gfp, "%s:%u",
+                             table->name, nft_net->base_seq);
+
+       audit_log_nfcfg(buf,
+                       family,
+                       obj->handle,
+                       event == NFT_MSG_NEWOBJ ?
+                                AUDIT_NFT_OP_OBJ_REGISTER :
+                                AUDIT_NFT_OP_OBJ_UNREGISTER,
+                       gfp);
+       kfree(buf);
+
+       __nft_obj_notify(net, table, obj, portid, seq, event,
+                        flags, family, report, gfp);
+}
 EXPORT_SYMBOL_GPL(nft_obj_notify);
 
 static void nf_tables_obj_notify(const struct nft_ctx *ctx,
                                 struct nft_object *obj, int event)
 {
-       nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, ctx->seq, event,
-                      ctx->flags, ctx->family, ctx->report, GFP_KERNEL);
+       __nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid,
+                        ctx->seq, event, ctx->flags, ctx->family,
+                        ctx->report, GFP_KERNEL);
 }
 
 /*
index 8cb8009..120f6d3 100644 (file)
@@ -154,6 +154,17 @@ int nft_payload_inner_offset(const struct nft_pktinfo *pkt)
        return pkt->inneroff;
 }
 
+static bool nft_payload_need_vlan_copy(const struct nft_payload *priv)
+{
+       unsigned int len = priv->offset + priv->len;
+
+       /* data past ether src/dst requested, copy needed */
+       if (len > offsetof(struct ethhdr, h_proto))
+               return true;
+
+       return false;
+}
+
 void nft_payload_eval(const struct nft_expr *expr,
                      struct nft_regs *regs,
                      const struct nft_pktinfo *pkt)
@@ -172,7 +183,7 @@ void nft_payload_eval(const struct nft_expr *expr,
                        goto err;
 
                if (skb_vlan_tag_present(skb) &&
-                   priv->offset >= offsetof(struct ethhdr, h_proto)) {
+                   nft_payload_need_vlan_copy(priv)) {
                        if (!nft_payload_copy_vlan(dest, skb,
                                                   priv->offset, priv->len))
                                goto err;
index 487572d..2660cea 100644 (file)
@@ -233,10 +233,9 @@ static void nft_rbtree_gc_remove(struct net *net, struct nft_set *set,
        rb_erase(&rbe->node, &priv->root);
 }
 
-static int nft_rbtree_gc_elem(const struct nft_set *__set,
-                             struct nft_rbtree *priv,
-                             struct nft_rbtree_elem *rbe,
-                             u8 genmask)
+static const struct nft_rbtree_elem *
+nft_rbtree_gc_elem(const struct nft_set *__set, struct nft_rbtree *priv,
+                  struct nft_rbtree_elem *rbe, u8 genmask)
 {
        struct nft_set *set = (struct nft_set *)__set;
        struct rb_node *prev = rb_prev(&rbe->node);
@@ -246,7 +245,7 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set,
 
        gc = nft_trans_gc_alloc(set, 0, GFP_ATOMIC);
        if (!gc)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        /* search for end interval coming before this element.
         * end intervals don't carry a timeout extension, they
@@ -261,6 +260,7 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set,
                prev = rb_prev(prev);
        }
 
+       rbe_prev = NULL;
        if (prev) {
                rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node);
                nft_rbtree_gc_remove(net, set, priv, rbe_prev);
@@ -272,7 +272,7 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set,
                 */
                gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
                if (WARN_ON_ONCE(!gc))
-                       return -ENOMEM;
+                       return ERR_PTR(-ENOMEM);
 
                nft_trans_gc_elem_add(gc, rbe_prev);
        }
@@ -280,13 +280,13 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set,
        nft_rbtree_gc_remove(net, set, priv, rbe);
        gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
        if (WARN_ON_ONCE(!gc))
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        nft_trans_gc_elem_add(gc, rbe);
 
        nft_trans_gc_queue_sync_done(gc);
 
-       return 0;
+       return rbe_prev;
 }
 
 static bool nft_rbtree_update_first(const struct nft_set *set,
@@ -314,7 +314,7 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
        struct nft_rbtree *priv = nft_set_priv(set);
        u8 cur_genmask = nft_genmask_cur(net);
        u8 genmask = nft_genmask_next(net);
-       int d, err;
+       int d;
 
        /* Descend the tree to search for an existing element greater than the
         * key value to insert that is greater than the new element. This is the
@@ -363,9 +363,14 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
                 */
                if (nft_set_elem_expired(&rbe->ext) &&
                    nft_set_elem_active(&rbe->ext, cur_genmask)) {
-                       err = nft_rbtree_gc_elem(set, priv, rbe, genmask);
-                       if (err < 0)
-                               return err;
+                       const struct nft_rbtree_elem *removed_end;
+
+                       removed_end = nft_rbtree_gc_elem(set, priv, rbe, genmask);
+                       if (IS_ERR(removed_end))
+                               return PTR_ERR(removed_end);
+
+                       if (removed_end == rbe_le || removed_end == rbe_ge)
+                               return -EAGAIN;
 
                        continue;
                }
@@ -486,11 +491,18 @@ static int nft_rbtree_insert(const struct net *net, const struct nft_set *set,
        struct nft_rbtree_elem *rbe = elem->priv;
        int err;
 
-       write_lock_bh(&priv->lock);
-       write_seqcount_begin(&priv->count);
-       err = __nft_rbtree_insert(net, set, rbe, ext);
-       write_seqcount_end(&priv->count);
-       write_unlock_bh(&priv->lock);
+       do {
+               if (fatal_signal_pending(current))
+                       return -EINTR;
+
+               cond_resched();
+
+               write_lock_bh(&priv->lock);
+               write_seqcount_begin(&priv->count);
+               err = __nft_rbtree_insert(net, set, rbe, ext);
+               write_seqcount_end(&priv->count);
+               write_unlock_bh(&priv->lock);
+       } while (err == -EAGAIN);
 
        return err;
 }
index 642b9d3..eb086b0 100644 (file)
@@ -352,7 +352,7 @@ static void netlink_overrun(struct sock *sk)
        if (!nlk_test_bit(RECV_NO_ENOBUFS, sk)) {
                if (!test_and_set_bit(NETLINK_S_CONGESTED,
                                      &nlk_sk(sk)->state)) {
-                       sk->sk_err = ENOBUFS;
+                       WRITE_ONCE(sk->sk_err, ENOBUFS);
                        sk_error_report(sk);
                }
        }
@@ -1605,7 +1605,7 @@ static int do_one_set_err(struct sock *sk, struct netlink_set_err_data *p)
                goto out;
        }
 
-       sk->sk_err = p->code;
+       WRITE_ONCE(sk->sk_err, p->code);
        sk_error_report(sk);
 out:
        return ret;
@@ -1991,7 +1991,7 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
            atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2) {
                ret = netlink_dump(sk);
                if (ret) {
-                       sk->sk_err = -ret;
+                       WRITE_ONCE(sk->sk_err, -ret);
                        sk_error_report(sk);
                }
        }
@@ -2511,7 +2511,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
 err_bad_put:
        nlmsg_free(skb);
 err_skb:
-       NETLINK_CB(in_skb).sk->sk_err = ENOBUFS;
+       WRITE_ONCE(NETLINK_CB(in_skb).sk->sk_err, ENOBUFS);
        sk_error_report(NETLINK_CB(in_skb).sk);
 }
 EXPORT_SYMBOL(netlink_ack);
index f60e424..6705bb8 100644 (file)
@@ -1636,7 +1636,9 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
        timer_setup(&local->sdreq_timer, nfc_llcp_sdreq_timer, 0);
        INIT_WORK(&local->sdreq_timeout_work, nfc_llcp_sdreq_timeout_work);
 
+       spin_lock(&llcp_devices_lock);
        list_add(&local->list, &llcp_devices);
+       spin_unlock(&llcp_devices_lock);
 
        return 0;
 }
index f0c477c..a0046e9 100644 (file)
@@ -145,7 +145,7 @@ int rds_tcp_conn_path_connect(struct rds_conn_path *cp)
                addrlen = sizeof(sin);
        }
 
-       ret = sock->ops->bind(sock, addr, addrlen);
+       ret = kernel_bind(sock, addr, addrlen);
        if (ret) {
                rdsdebug("bind failed with %d at address %pI6c\n",
                         ret, &conn->c_laddr);
@@ -173,7 +173,7 @@ int rds_tcp_conn_path_connect(struct rds_conn_path *cp)
         * own the socket
         */
        rds_tcp_set_callbacks(sock, cp);
-       ret = sock->ops->connect(sock, addr, addrlen, O_NONBLOCK);
+       ret = kernel_connect(sock, addr, addrlen, O_NONBLOCK);
 
        rdsdebug("connect to address %pI6c returned %d\n", &conn->c_faddr, ret);
        if (ret == -EINPROGRESS)
index 014fa24..53b3535 100644 (file)
@@ -306,7 +306,7 @@ struct socket *rds_tcp_listen_init(struct net *net, bool isv6)
                addr_len = sizeof(*sin);
        }
 
-       ret = sock->ops->bind(sock, (struct sockaddr *)&ss, addr_len);
+       ret = kernel_bind(sock, (struct sockaddr *)&ss, addr_len);
        if (ret < 0) {
                rdsdebug("could not bind %s listener socket: %d\n",
                         isv6 ? "IPv6" : "IPv4", ret);
index 01fca7a..0863089 100644 (file)
@@ -48,6 +48,7 @@ struct rfkill {
        bool                    persistent;
        bool                    polling_paused;
        bool                    suspended;
+       bool                    need_sync;
 
        const struct rfkill_ops *ops;
        void                    *data;
@@ -368,6 +369,17 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked)
                rfkill_event(rfkill);
 }
 
+static void rfkill_sync(struct rfkill *rfkill)
+{
+       lockdep_assert_held(&rfkill_global_mutex);
+
+       if (!rfkill->need_sync)
+               return;
+
+       rfkill_set_block(rfkill, rfkill_global_states[rfkill->type].cur);
+       rfkill->need_sync = false;
+}
+
 static void rfkill_update_global_state(enum rfkill_type type, bool blocked)
 {
        int i;
@@ -730,6 +742,10 @@ static ssize_t soft_show(struct device *dev, struct device_attribute *attr,
 {
        struct rfkill *rfkill = to_rfkill(dev);
 
+       mutex_lock(&rfkill_global_mutex);
+       rfkill_sync(rfkill);
+       mutex_unlock(&rfkill_global_mutex);
+
        return sysfs_emit(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_SW) ? 1 : 0);
 }
 
@@ -751,6 +767,7 @@ static ssize_t soft_store(struct device *dev, struct device_attribute *attr,
                return -EINVAL;
 
        mutex_lock(&rfkill_global_mutex);
+       rfkill_sync(rfkill);
        rfkill_set_block(rfkill, state);
        mutex_unlock(&rfkill_global_mutex);
 
@@ -783,6 +800,10 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr,
 {
        struct rfkill *rfkill = to_rfkill(dev);
 
+       mutex_lock(&rfkill_global_mutex);
+       rfkill_sync(rfkill);
+       mutex_unlock(&rfkill_global_mutex);
+
        return sysfs_emit(buf, "%d\n", user_state_from_blocked(rfkill->state));
 }
 
@@ -805,6 +826,7 @@ static ssize_t state_store(struct device *dev, struct device_attribute *attr,
                return -EINVAL;
 
        mutex_lock(&rfkill_global_mutex);
+       rfkill_sync(rfkill);
        rfkill_set_block(rfkill, state == RFKILL_USER_STATE_SOFT_BLOCKED);
        mutex_unlock(&rfkill_global_mutex);
 
@@ -1032,14 +1054,10 @@ static void rfkill_uevent_work(struct work_struct *work)
 
 static void rfkill_sync_work(struct work_struct *work)
 {
-       struct rfkill *rfkill;
-       bool cur;
-
-       rfkill = container_of(work, struct rfkill, sync_work);
+       struct rfkill *rfkill = container_of(work, struct rfkill, sync_work);
 
        mutex_lock(&rfkill_global_mutex);
-       cur = rfkill_global_states[rfkill->type].cur;
-       rfkill_set_block(rfkill, cur);
+       rfkill_sync(rfkill);
        mutex_unlock(&rfkill_global_mutex);
 }
 
@@ -1087,6 +1105,7 @@ int __must_check rfkill_register(struct rfkill *rfkill)
                        round_jiffies_relative(POLL_INTERVAL));
 
        if (!rfkill->persistent || rfkill_epo_lock_active) {
+               rfkill->need_sync = true;
                schedule_work(&rfkill->sync_work);
        } else {
 #ifdef CONFIG_RFKILL_INPUT
@@ -1171,6 +1190,7 @@ static int rfkill_fop_open(struct inode *inode, struct file *file)
                ev = kzalloc(sizeof(*ev), GFP_KERNEL);
                if (!ev)
                        goto free;
+               rfkill_sync(rfkill);
                rfkill_fill_event(&ev->ev, rfkill, RFKILL_OP_ADD);
                list_add_tail(&ev->list, &data->events);
        }
index 7965291..c45c192 100644 (file)
@@ -1159,8 +1159,7 @@ int sctp_assoc_update(struct sctp_association *asoc,
                /* Add any peer addresses from the new association. */
                list_for_each_entry(trans, &new->peer.transport_addr_list,
                                    transports)
-                       if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr) &&
-                           !sctp_assoc_add_peer(asoc, &trans->ipaddr,
+                       if (!sctp_assoc_add_peer(asoc, &trans->ipaddr,
                                                 GFP_ATOMIC, trans->state))
                                return -ENOMEM;
 
index ab943e8..7f89e43 100644 (file)
@@ -2450,6 +2450,7 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params,
                        if (trans) {
                                trans->hbinterval =
                                    msecs_to_jiffies(params->spp_hbinterval);
+                               sctp_transport_reset_hb_timer(trans);
                        } else if (asoc) {
                                asoc->hbinterval =
                                    msecs_to_jiffies(params->spp_hbinterval);
index c8b08b3..c4a6f55 100644 (file)
@@ -737,6 +737,14 @@ static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg)
        return ret;
 }
 
+static int __sock_sendmsg(struct socket *sock, struct msghdr *msg)
+{
+       int err = security_socket_sendmsg(sock, msg,
+                                         msg_data_left(msg));
+
+       return err ?: sock_sendmsg_nosec(sock, msg);
+}
+
 /**
  *     sock_sendmsg - send a message through @sock
  *     @sock: socket
@@ -747,10 +755,19 @@ static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg)
  */
 int sock_sendmsg(struct socket *sock, struct msghdr *msg)
 {
-       int err = security_socket_sendmsg(sock, msg,
-                                         msg_data_left(msg));
+       struct sockaddr_storage *save_addr = (struct sockaddr_storage *)msg->msg_name;
+       struct sockaddr_storage address;
+       int ret;
 
-       return err ?: sock_sendmsg_nosec(sock, msg);
+       if (msg->msg_name) {
+               memcpy(&address, msg->msg_name, msg->msg_namelen);
+               msg->msg_name = &address;
+       }
+
+       ret = __sock_sendmsg(sock, msg);
+       msg->msg_name = save_addr;
+
+       return ret;
 }
 EXPORT_SYMBOL(sock_sendmsg);
 
@@ -1138,7 +1155,7 @@ static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
        if (sock->type == SOCK_SEQPACKET)
                msg.msg_flags |= MSG_EOR;
 
-       res = sock_sendmsg(sock, &msg);
+       res = __sock_sendmsg(sock, &msg);
        *from = msg.msg_iter;
        return res;
 }
@@ -2174,7 +2191,7 @@ int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags,
        if (sock->file->f_flags & O_NONBLOCK)
                flags |= MSG_DONTWAIT;
        msg.msg_flags = flags;
-       err = sock_sendmsg(sock, &msg);
+       err = __sock_sendmsg(sock, &msg);
 
 out_put:
        fput_light(sock->file, fput_needed);
@@ -2538,7 +2555,7 @@ static int ____sys_sendmsg(struct socket *sock, struct msghdr *msg_sys,
                err = sock_sendmsg_nosec(sock, msg_sys);
                goto out_freectl;
        }
-       err = sock_sendmsg(sock, msg_sys);
+       err = __sock_sendmsg(sock, msg_sys);
        /*
         * If this is sendmmsg() and sending to current destination address was
         * successful, remember it.
@@ -3499,7 +3516,12 @@ static long compat_sock_ioctl(struct file *file, unsigned int cmd,
 
 int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
 {
-       return READ_ONCE(sock->ops)->bind(sock, addr, addrlen);
+       struct sockaddr_storage address;
+
+       memcpy(&address, addr, addrlen);
+
+       return READ_ONCE(sock->ops)->bind(sock, (struct sockaddr *)&address,
+                                         addrlen);
 }
 EXPORT_SYMBOL(kernel_bind);
 
index 2f16f9d..814b016 100644 (file)
@@ -769,9 +769,14 @@ int rpcauth_wrap_req(struct rpc_task *task, struct xdr_stream *xdr)
  * @task: controlling RPC task
  * @xdr: xdr_stream containing RPC Reply header
  *
- * On success, @xdr is updated to point past the verifier and
- * zero is returned. Otherwise, @xdr is in an undefined state
- * and a negative errno is returned.
+ * Return values:
+ *   %0: Verifier is valid. @xdr now points past the verifier.
+ *   %-EIO: Verifier is corrupted or message ended early.
+ *   %-EACCES: Verifier is intact but not valid.
+ *   %-EPROTONOSUPPORT: Server does not support the requested auth type.
+ *
+ * When a negative errno is returned, @xdr is left in an undefined
+ * state.
  */
 int
 rpcauth_checkverf(struct rpc_task *task, struct xdr_stream *xdr)
index de7678f..87f570f 100644 (file)
@@ -129,9 +129,9 @@ static int tls_validate(struct rpc_task *task, struct xdr_stream *xdr)
        if (*p != rpc_auth_null)
                return -EIO;
        if (xdr_stream_decode_opaque_inline(xdr, &str, starttls_len) != starttls_len)
-               return -EIO;
+               return -EPROTONOSUPPORT;
        if (memcmp(str, starttls_token, starttls_len))
-               return -EIO;
+               return -EPROTONOSUPPORT;
        return 0;
 }
 
index 37b0b21..9c21027 100644 (file)
@@ -2476,8 +2476,7 @@ call_status(struct rpc_task *task)
                goto out_exit;
        }
        task->tk_action = call_encode;
-       if (status != -ECONNRESET && status != -ECONNABORTED)
-               rpc_check_timeout(task);
+       rpc_check_timeout(task);
        return;
 out_exit:
        rpc_call_rpcerror(task, status);
@@ -2725,7 +2724,15 @@ out_unparsable:
 
 out_verifier:
        trace_rpc_bad_verifier(task);
-       goto out_garbage;
+       switch (error) {
+       case -EPROTONOSUPPORT:
+               goto out_err;
+       case -EACCES:
+               /* Re-encode with a fresh cred */
+               fallthrough;
+       default:
+               goto out_garbage;
+       }
 
 out_msg_denied:
        error = -EACCES;
index 71cd916..a15bf2e 100644 (file)
@@ -2672,6 +2672,10 @@ static void xs_tcp_tls_setup_socket(struct work_struct *work)
        rcu_read_lock();
        lower_xprt = rcu_dereference(lower_clnt->cl_xprt);
        rcu_read_unlock();
+
+       if (wait_on_bit_lock(&lower_xprt->state, XPRT_LOCKED, TASK_KILLABLE))
+               goto out_unlock;
+
        status = xs_tls_handshake_sync(lower_xprt, &upper_xprt->xprtsec);
        if (status) {
                trace_rpc_tls_not_started(upper_clnt, upper_xprt);
@@ -2681,6 +2685,7 @@ static void xs_tcp_tls_setup_socket(struct work_struct *work)
        status = xs_tcp_tls_finish_connecting(lower_xprt, upper_transport);
        if (status)
                goto out_close;
+       xprt_release_write(lower_xprt, NULL);
 
        trace_rpc_socket_connect(upper_xprt, upper_transport->sock, 0);
        if (!xprt_test_and_set_connected(upper_xprt)) {
@@ -2702,6 +2707,7 @@ out_unlock:
        return;
 
 out_close:
+       xprt_release_write(lower_xprt, NULL);
        rpc_shutdown_client(lower_clnt);
 
        /* xprt_force_disconnect() wakes tasks with a fixed tk_status code.
index 302fd74..43c3f1c 100644 (file)
@@ -1441,14 +1441,14 @@ static int tipc_crypto_key_revoke(struct net *net, u8 tx_key)
        struct tipc_crypto *tx = tipc_net(net)->crypto_tx;
        struct tipc_key key;
 
-       spin_lock(&tx->lock);
+       spin_lock_bh(&tx->lock);
        key = tx->key;
        WARN_ON(!key.active || tx_key != key.active);
 
        /* Free the active key */
        tipc_crypto_key_set_state(tx, key.passive, 0, key.pending);
        tipc_crypto_key_detach(tx->aead[key.active], &tx->lock);
-       spin_unlock(&tx->lock);
+       spin_unlock_bh(&tx->lock);
 
        pr_warn("%s: key is revoked\n", tx->name);
        return -EKEYREVOKED;
index 25bc2e5..64e8616 100644 (file)
@@ -1181,16 +1181,11 @@ void wiphy_rfkill_set_hw_state_reason(struct wiphy *wiphy, bool blocked,
 }
 EXPORT_SYMBOL(wiphy_rfkill_set_hw_state_reason);
 
-void cfg80211_cqm_config_free(struct wireless_dev *wdev)
-{
-       kfree(wdev->cqm_config);
-       wdev->cqm_config = NULL;
-}
-
 static void _cfg80211_unregister_wdev(struct wireless_dev *wdev,
                                      bool unregister_netdev)
 {
        struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+       struct cfg80211_cqm_config *cqm_config;
        unsigned int link_id;
 
        ASSERT_RTNL();
@@ -1227,7 +1222,10 @@ static void _cfg80211_unregister_wdev(struct wireless_dev *wdev,
        kfree_sensitive(wdev->wext.keys);
        wdev->wext.keys = NULL;
 #endif
-       cfg80211_cqm_config_free(wdev);
+       wiphy_work_cancel(wdev->wiphy, &wdev->cqm_rssi_work);
+       /* deleted from the list, so can't be found from nl80211 any more */
+       cqm_config = rcu_access_pointer(wdev->cqm_config);
+       kfree_rcu(cqm_config, rcu_head);
 
        /*
         * Ensure that all events have been processed and
@@ -1379,6 +1377,8 @@ void cfg80211_init_wdev(struct wireless_dev *wdev)
        wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
 #endif
 
+       wiphy_work_init(&wdev->cqm_rssi_work, cfg80211_cqm_rssi_notify_work);
+
        if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT)
                wdev->ps = true;
        else
index 507d184..ba9c717 100644 (file)
@@ -295,12 +295,17 @@ struct cfg80211_beacon_registration {
 };
 
 struct cfg80211_cqm_config {
+       struct rcu_head rcu_head;
        u32 rssi_hyst;
        s32 last_rssi_event_value;
+       enum nl80211_cqm_rssi_threshold_event last_rssi_event_type;
        int n_rssi_thresholds;
        s32 rssi_thresholds[] __counted_by(n_rssi_thresholds);
 };
 
+void cfg80211_cqm_rssi_notify_work(struct wiphy *wiphy,
+                                  struct wiphy_work *work);
+
 void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev);
 
 /* free object */
@@ -566,8 +571,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
 #define CFG80211_DEV_WARN_ON(cond)     ({bool __r = (cond); __r; })
 #endif
 
-void cfg80211_cqm_config_free(struct wireless_dev *wdev);
-
 void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid);
 void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev);
 void cfg80211_pmsr_free_wk(struct work_struct *work);
index 775cac4..3e2c398 100644 (file)
@@ -52,7 +52,8 @@ void cfg80211_rx_assoc_resp(struct net_device *dev,
                cr.links[link_id].bssid = data->links[link_id].bss->bssid;
                cr.links[link_id].addr = data->links[link_id].addr;
                /* need to have local link addresses for MLO connections */
-               WARN_ON(cr.ap_mld_addr && !cr.links[link_id].addr);
+               WARN_ON(cr.ap_mld_addr &&
+                       !is_valid_ether_addr(cr.links[link_id].addr));
 
                BUG_ON(!cr.links[link_id].bss->channel);
 
index de47838..931a03f 100644 (file)
@@ -5909,6 +5909,21 @@ out:
        nlmsg_free(msg);
 }
 
+static int nl80211_validate_ap_phy_operation(struct cfg80211_ap_settings *params)
+{
+       struct ieee80211_channel *channel = params->chandef.chan;
+
+       if ((params->he_cap ||  params->he_oper) &&
+           (channel->flags & IEEE80211_CHAN_NO_HE))
+               return -EOPNOTSUPP;
+
+       if ((params->eht_cap || params->eht_oper) &&
+           (channel->flags & IEEE80211_CHAN_NO_EHT))
+               return -EOPNOTSUPP;
+
+       return 0;
+}
+
 static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -6178,6 +6193,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
        if (err)
                goto out_unlock;
 
+       err = nl80211_validate_ap_phy_operation(params);
+       if (err)
+               goto out_unlock;
+
        if (info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS])
                params->flags = nla_get_u32(
                        info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS]);
@@ -8482,7 +8501,7 @@ static int nl80211_update_mesh_config(struct sk_buff *skb,
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
        struct net_device *dev = info->user_ptr[1];
        struct wireless_dev *wdev = dev->ieee80211_ptr;
-       struct mesh_config cfg;
+       struct mesh_config cfg = {};
        u32 mask;
        int err;
 
@@ -12796,7 +12815,8 @@ static int nl80211_set_cqm_txe(struct genl_info *info,
 }
 
 static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
-                                   struct net_device *dev)
+                                   struct net_device *dev,
+                                   struct cfg80211_cqm_config *cqm_config)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        s32 last, low, high;
@@ -12805,7 +12825,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
        int err;
 
        /* RSSI reporting disabled? */
-       if (!wdev->cqm_config)
+       if (!cqm_config)
                return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
 
        /*
@@ -12814,7 +12834,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
         * connection is established and enough beacons received to calculate
         * the average.
         */
-       if (!wdev->cqm_config->last_rssi_event_value &&
+       if (!cqm_config->last_rssi_event_value &&
            wdev->links[0].client.current_bss &&
            rdev->ops->get_station) {
                struct station_info sinfo = {};
@@ -12828,30 +12848,30 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
 
                cfg80211_sinfo_release_content(&sinfo);
                if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG))
-                       wdev->cqm_config->last_rssi_event_value =
+                       cqm_config->last_rssi_event_value =
                                (s8) sinfo.rx_beacon_signal_avg;
        }
 
-       last = wdev->cqm_config->last_rssi_event_value;
-       hyst = wdev->cqm_config->rssi_hyst;
-       n = wdev->cqm_config->n_rssi_thresholds;
+       last = cqm_config->last_rssi_event_value;
+       hyst = cqm_config->rssi_hyst;
+       n = cqm_config->n_rssi_thresholds;
 
        for (i = 0; i < n; i++) {
                i = array_index_nospec(i, n);
-               if (last < wdev->cqm_config->rssi_thresholds[i])
+               if (last < cqm_config->rssi_thresholds[i])
                        break;
        }
 
        low_index = i - 1;
        if (low_index >= 0) {
                low_index = array_index_nospec(low_index, n);
-               low = wdev->cqm_config->rssi_thresholds[low_index] - hyst;
+               low = cqm_config->rssi_thresholds[low_index] - hyst;
        } else {
                low = S32_MIN;
        }
        if (i < n) {
                i = array_index_nospec(i, n);
-               high = wdev->cqm_config->rssi_thresholds[i] + hyst - 1;
+               high = cqm_config->rssi_thresholds[i] + hyst - 1;
        } else {
                high = S32_MAX;
        }
@@ -12864,6 +12884,7 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
                                u32 hysteresis)
 {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
+       struct cfg80211_cqm_config *cqm_config = NULL, *old;
        struct net_device *dev = info->user_ptr[1];
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        int i, err;
@@ -12881,10 +12902,6 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
            wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
                return -EOPNOTSUPP;
 
-       wdev_lock(wdev);
-       cfg80211_cqm_config_free(wdev);
-       wdev_unlock(wdev);
-
        if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) {
                if (n_thresholds == 0 || thresholds[0] == 0) /* Disabling */
                        return rdev_set_cqm_rssi_config(rdev, dev, 0, 0);
@@ -12901,9 +12918,10 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
                n_thresholds = 0;
 
        wdev_lock(wdev);
-       if (n_thresholds) {
-               struct cfg80211_cqm_config *cqm_config;
+       old = rcu_dereference_protected(wdev->cqm_config,
+                                       lockdep_is_held(&wdev->mtx));
 
+       if (n_thresholds) {
                cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds,
                                                 n_thresholds),
                                     GFP_KERNEL);
@@ -12918,11 +12936,18 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
                       flex_array_size(cqm_config, rssi_thresholds,
                                       n_thresholds));
 
-               wdev->cqm_config = cqm_config;
+               rcu_assign_pointer(wdev->cqm_config, cqm_config);
+       } else {
+               RCU_INIT_POINTER(wdev->cqm_config, NULL);
        }
 
-       err = cfg80211_cqm_rssi_update(rdev, dev);
-
+       err = cfg80211_cqm_rssi_update(rdev, dev, cqm_config);
+       if (err) {
+               rcu_assign_pointer(wdev->cqm_config, old);
+               kfree_rcu(cqm_config, rcu_head);
+       } else {
+               kfree_rcu(old, rcu_head);
+       }
 unlock:
        wdev_unlock(wdev);
 
@@ -19073,9 +19098,8 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
                              enum nl80211_cqm_rssi_threshold_event rssi_event,
                              s32 rssi_level, gfp_t gfp)
 {
-       struct sk_buff *msg;
        struct wireless_dev *wdev = dev->ieee80211_ptr;
-       struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+       struct cfg80211_cqm_config *cqm_config;
 
        trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level);
 
@@ -19083,18 +19107,41 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
                    rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH))
                return;
 
-       if (wdev->cqm_config) {
-               wdev->cqm_config->last_rssi_event_value = rssi_level;
+       rcu_read_lock();
+       cqm_config = rcu_dereference(wdev->cqm_config);
+       if (cqm_config) {
+               cqm_config->last_rssi_event_value = rssi_level;
+               cqm_config->last_rssi_event_type = rssi_event;
+               wiphy_work_queue(wdev->wiphy, &wdev->cqm_rssi_work);
+       }
+       rcu_read_unlock();
+}
+EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
 
-               cfg80211_cqm_rssi_update(rdev, dev);
+void cfg80211_cqm_rssi_notify_work(struct wiphy *wiphy, struct wiphy_work *work)
+{
+       struct wireless_dev *wdev = container_of(work, struct wireless_dev,
+                                                cqm_rssi_work);
+       struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+       enum nl80211_cqm_rssi_threshold_event rssi_event;
+       struct cfg80211_cqm_config *cqm_config;
+       struct sk_buff *msg;
+       s32 rssi_level;
 
-               if (rssi_level == 0)
-                       rssi_level = wdev->cqm_config->last_rssi_event_value;
-       }
+       wdev_lock(wdev);
+       cqm_config = rcu_dereference_protected(wdev->cqm_config,
+                                              lockdep_is_held(&wdev->mtx));
+       if (!wdev->cqm_config)
+               goto unlock;
 
-       msg = cfg80211_prepare_cqm(dev, NULL, gfp);
+       cfg80211_cqm_rssi_update(rdev, wdev->netdev, cqm_config);
+
+       rssi_level = cqm_config->last_rssi_event_value;
+       rssi_event = cqm_config->last_rssi_event_type;
+
+       msg = cfg80211_prepare_cqm(wdev->netdev, NULL, GFP_KERNEL);
        if (!msg)
-               return;
+               goto unlock;
 
        if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT,
                        rssi_event))
@@ -19104,14 +19151,15 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
                                      rssi_level))
                goto nla_put_failure;
 
-       cfg80211_send_cqm(msg, gfp);
+       cfg80211_send_cqm(msg, GFP_KERNEL);
 
-       return;
+       goto unlock;
 
  nla_put_failure:
        nlmsg_free(msg);
+ unlock:
+       wdev_unlock(wdev);
 }
-EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
 
 void cfg80211_cqm_txe_notify(struct net_device *dev,
                             const u8 *peer, u32 num_packets,
index 0cf1ce7..939deec 100644 (file)
@@ -908,6 +908,10 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev)
                    !cfg80211_find_ssid_match(ap, request))
                        continue;
 
+               if (!is_broadcast_ether_addr(request->bssid) &&
+                   !ether_addr_equal(request->bssid, ap->bssid))
+                       continue;
+
                if (!request->n_ssids && ap->multi_bss && !ap->transmitted_bssid)
                        continue;
 
index ecddc80..a6bd817 100644 (file)
@@ -29,9 +29,11 @@ config IMA
          to learn more about IMA.
          If unsure, say N.
 
+if IMA
+
 config IMA_KEXEC
        bool "Enable carrying the IMA measurement list across a soft boot"
-       depends on IMA && TCG_TPM && HAVE_IMA_KEXEC
+       depends on TCG_TPM && HAVE_IMA_KEXEC
        default n
        help
           TPM PCRs are only reset on a hard reboot.  In order to validate
@@ -43,7 +45,6 @@ config IMA_KEXEC
 
 config IMA_MEASURE_PCR_IDX
        int
-       depends on IMA
        range 8 14
        default 10
        help
@@ -53,7 +54,7 @@ config IMA_MEASURE_PCR_IDX
 
 config IMA_LSM_RULES
        bool
-       depends on IMA && AUDIT && (SECURITY_SELINUX || SECURITY_SMACK || SECURITY_APPARMOR)
+       depends on AUDIT && (SECURITY_SELINUX || SECURITY_SMACK || SECURITY_APPARMOR)
        default y
        help
          Disabling this option will disregard LSM based policy rules.
@@ -61,7 +62,6 @@ config IMA_LSM_RULES
 choice
        prompt "Default template"
        default IMA_NG_TEMPLATE
-       depends on IMA
        help
          Select the default IMA measurement template.
 
@@ -80,14 +80,12 @@ endchoice
 
 config IMA_DEFAULT_TEMPLATE
        string
-       depends on IMA
        default "ima-ng" if IMA_NG_TEMPLATE
        default "ima-sig" if IMA_SIG_TEMPLATE
 
 choice
        prompt "Default integrity hash algorithm"
        default IMA_DEFAULT_HASH_SHA1
-       depends on IMA
        help
           Select the default hash algorithm used for the measurement
           list, integrity appraisal and audit log.  The compiled default
@@ -117,7 +115,6 @@ endchoice
 
 config IMA_DEFAULT_HASH
        string
-       depends on IMA
        default "sha1" if IMA_DEFAULT_HASH_SHA1
        default "sha256" if IMA_DEFAULT_HASH_SHA256
        default "sha512" if IMA_DEFAULT_HASH_SHA512
@@ -126,7 +123,6 @@ config IMA_DEFAULT_HASH
 
 config IMA_WRITE_POLICY
        bool "Enable multiple writes to the IMA policy"
-       depends on IMA
        default n
        help
          IMA policy can now be updated multiple times.  The new rules get
@@ -137,7 +133,6 @@ config IMA_WRITE_POLICY
 
 config IMA_READ_POLICY
        bool "Enable reading back the current IMA policy"
-       depends on IMA
        default y if IMA_WRITE_POLICY
        default n if !IMA_WRITE_POLICY
        help
@@ -147,7 +142,6 @@ config IMA_READ_POLICY
 
 config IMA_APPRAISE
        bool "Appraise integrity measurements"
-       depends on IMA
        default n
        help
          This option enables local measurement integrity appraisal.
@@ -269,7 +263,7 @@ config IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY
 config IMA_BLACKLIST_KEYRING
        bool "Create IMA machine owner blacklist keyrings (EXPERIMENTAL)"
        depends on SYSTEM_TRUSTED_KEYRING
-       depends on IMA_TRUSTED_KEYRING
+       depends on INTEGRITY_TRUSTED_KEYRING
        default n
        help
           This option creates an IMA blacklist keyring, which contains all
@@ -279,7 +273,7 @@ config IMA_BLACKLIST_KEYRING
 
 config IMA_LOAD_X509
        bool "Load X509 certificate onto the '.ima' trusted keyring"
-       depends on IMA_TRUSTED_KEYRING
+       depends on INTEGRITY_TRUSTED_KEYRING
        default n
        help
           File signature verification is based on the public keys
@@ -304,7 +298,6 @@ config IMA_APPRAISE_SIGNED_INIT
 
 config IMA_MEASURE_ASYMMETRIC_KEYS
        bool
-       depends on IMA
        depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
        default y
 
@@ -323,7 +316,8 @@ config IMA_SECURE_AND_OR_TRUSTED_BOOT
 
 config IMA_DISABLE_HTABLE
        bool "Disable htable to allow measurement of duplicate records"
-       depends on IMA
        default n
        help
           This option disables htable to allow measurement of duplicate records.
+
+endif
index 42806ad..1a21d6b 100644 (file)
@@ -92,7 +92,7 @@ endif
 TARGETS += tmpfs
 TARGETS += tpm2
 TARGETS += tty
-TARGETS += uevents
+TARGETS += uevent
 TARGETS += user
 TARGETS += user_events
 TARGETS += vDSO
index a53c254..4aabeaa 100644 (file)
@@ -185,6 +185,8 @@ static void test_cubic(void)
 
        do_test("bpf_cubic", NULL);
 
+       ASSERT_EQ(cubic_skel->bss->bpf_cubic_acked_called, 1, "pkts_acked called");
+
        bpf_link__destroy(link);
        bpf_cubic__destroy(cubic_skel);
 }
index 064cc5e..dda7060 100644 (file)
@@ -475,6 +475,55 @@ out:
                test_sockmap_drop_prog__destroy(drop);
 }
 
+static void test_sockmap_skb_verdict_peek(void)
+{
+       int err, map, verdict, s, c1, p1, zero = 0, sent, recvd, avail;
+       struct test_sockmap_pass_prog *pass;
+       char snd[256] = "0123456789";
+       char rcv[256] = "0";
+
+       pass = test_sockmap_pass_prog__open_and_load();
+       if (!ASSERT_OK_PTR(pass, "open_and_load"))
+               return;
+       verdict = bpf_program__fd(pass->progs.prog_skb_verdict);
+       map = bpf_map__fd(pass->maps.sock_map_rx);
+
+       err = bpf_prog_attach(verdict, map, BPF_SK_SKB_STREAM_VERDICT, 0);
+       if (!ASSERT_OK(err, "bpf_prog_attach"))
+               goto out;
+
+       s = socket_loopback(AF_INET, SOCK_STREAM);
+       if (!ASSERT_GT(s, -1, "socket_loopback(s)"))
+               goto out;
+
+       err = create_pair(s, AF_INET, SOCK_STREAM, &c1, &p1);
+       if (!ASSERT_OK(err, "create_pairs(s)"))
+               goto out;
+
+       err = bpf_map_update_elem(map, &zero, &c1, BPF_NOEXIST);
+       if (!ASSERT_OK(err, "bpf_map_update_elem(c1)"))
+               goto out_close;
+
+       sent = xsend(p1, snd, sizeof(snd), 0);
+       ASSERT_EQ(sent, sizeof(snd), "xsend(p1)");
+       recvd = recv(c1, rcv, sizeof(rcv), MSG_PEEK);
+       ASSERT_EQ(recvd, sizeof(rcv), "recv(c1)");
+       err = ioctl(c1, FIONREAD, &avail);
+       ASSERT_OK(err, "ioctl(FIONREAD) error");
+       ASSERT_EQ(avail, sizeof(snd), "after peek ioctl(FIONREAD)");
+       recvd = recv(c1, rcv, sizeof(rcv), 0);
+       ASSERT_EQ(recvd, sizeof(rcv), "recv(p0)");
+       err = ioctl(c1, FIONREAD, &avail);
+       ASSERT_OK(err, "ioctl(FIONREAD) error");
+       ASSERT_EQ(avail, 0, "after read ioctl(FIONREAD)");
+
+out_close:
+       close(c1);
+       close(p1);
+out:
+       test_sockmap_pass_prog__destroy(pass);
+}
+
 void test_sockmap_basic(void)
 {
        if (test__start_subtest("sockmap create_update_free"))
@@ -515,4 +564,6 @@ void test_sockmap_basic(void)
                test_sockmap_skb_verdict_fionread(true);
        if (test__start_subtest("sockmap skb_verdict fionread on drop"))
                test_sockmap_skb_verdict_fionread(false);
+       if (test__start_subtest("sockmap skb_verdict msg_f_peek"))
+               test_sockmap_skb_verdict_peek();
 }
index 7a2ecd4..99af79e 100644 (file)
@@ -2378,3 +2378,87 @@ void serial_test_tc_opts_chain_mixed(void)
        test_tc_chain_mixed(BPF_TCX_INGRESS);
        test_tc_chain_mixed(BPF_TCX_EGRESS);
 }
+
+static int generate_dummy_prog(void)
+{
+       const struct bpf_insn prog_insns[] = {
+               BPF_MOV64_IMM(BPF_REG_0, 0),
+               BPF_EXIT_INSN(),
+       };
+       const size_t prog_insn_cnt = sizeof(prog_insns) / sizeof(struct bpf_insn);
+       LIBBPF_OPTS(bpf_prog_load_opts, opts);
+       const size_t log_buf_sz = 256;
+       char *log_buf;
+       int fd = -1;
+
+       log_buf = malloc(log_buf_sz);
+       if (!ASSERT_OK_PTR(log_buf, "log_buf_alloc"))
+               return fd;
+       opts.log_buf = log_buf;
+       opts.log_size = log_buf_sz;
+
+       log_buf[0] = '\0';
+       opts.log_level = 0;
+       fd = bpf_prog_load(BPF_PROG_TYPE_SCHED_CLS, "tcx_prog", "GPL",
+                          prog_insns, prog_insn_cnt, &opts);
+       ASSERT_STREQ(log_buf, "", "log_0");
+       ASSERT_GE(fd, 0, "prog_fd");
+       free(log_buf);
+       return fd;
+}
+
+static void test_tc_opts_max_target(int target, int flags, bool relative)
+{
+       int err, ifindex, i, prog_fd, last_fd = -1;
+       LIBBPF_OPTS(bpf_prog_attach_opts, opta);
+       const int max_progs = 63;
+
+       ASSERT_OK(system("ip link add dev tcx_opts1 type veth peer name tcx_opts2"), "add veth");
+       ifindex = if_nametoindex("tcx_opts1");
+       ASSERT_NEQ(ifindex, 0, "non_zero_ifindex");
+
+       assert_mprog_count_ifindex(ifindex, target, 0);
+
+       for (i = 0; i < max_progs; i++) {
+               prog_fd = generate_dummy_prog();
+               if (!ASSERT_GE(prog_fd, 0, "dummy_prog"))
+                       goto cleanup;
+               err = bpf_prog_attach_opts(prog_fd, ifindex, target, &opta);
+               if (!ASSERT_EQ(err, 0, "prog_attach"))
+                       goto cleanup;
+               assert_mprog_count_ifindex(ifindex, target, i + 1);
+               if (i == max_progs - 1 && relative)
+                       last_fd = prog_fd;
+               else
+                       close(prog_fd);
+       }
+
+       prog_fd = generate_dummy_prog();
+       if (!ASSERT_GE(prog_fd, 0, "dummy_prog"))
+               goto cleanup;
+       opta.flags = flags;
+       if (last_fd > 0)
+               opta.relative_fd = last_fd;
+       err = bpf_prog_attach_opts(prog_fd, ifindex, target, &opta);
+       ASSERT_EQ(err, -ERANGE, "prog_64_attach");
+       assert_mprog_count_ifindex(ifindex, target, max_progs);
+       close(prog_fd);
+cleanup:
+       if (last_fd > 0)
+               close(last_fd);
+       ASSERT_OK(system("ip link del dev tcx_opts1"), "del veth");
+       ASSERT_EQ(if_nametoindex("tcx_opts1"), 0, "dev1_removed");
+       ASSERT_EQ(if_nametoindex("tcx_opts2"), 0, "dev2_removed");
+}
+
+void serial_test_tc_opts_max(void)
+{
+       test_tc_opts_max_target(BPF_TCX_INGRESS, 0, false);
+       test_tc_opts_max_target(BPF_TCX_EGRESS, 0, false);
+
+       test_tc_opts_max_target(BPF_TCX_INGRESS, BPF_F_BEFORE, false);
+       test_tc_opts_max_target(BPF_TCX_EGRESS, BPF_F_BEFORE, true);
+
+       test_tc_opts_max_target(BPF_TCX_INGRESS, BPF_F_AFTER, true);
+       test_tc_opts_max_target(BPF_TCX_EGRESS, BPF_F_AFTER, false);
+}
index d9660e7..c997e3e 100644 (file)
@@ -490,6 +490,8 @@ static __always_inline void hystart_update(struct sock *sk, __u32 delay)
        }
 }
 
+int bpf_cubic_acked_called = 0;
+
 void BPF_STRUCT_OPS(bpf_cubic_acked, struct sock *sk,
                    const struct ack_sample *sample)
 {
@@ -497,6 +499,7 @@ void BPF_STRUCT_OPS(bpf_cubic_acked, struct sock *sk,
        struct bictcp *ca = inet_csk_ca(sk);
        __u32 delay;
 
+       bpf_cubic_acked_called = 1;
        /* Some calls are for duplicates without timetamps */
        if (sample->rtt_us < 0)
                return;
index 321db88..ef90aca 100644 (file)
@@ -6,13 +6,14 @@ TEST_PROGS := nft_trans_stress.sh nft_fib.sh nft_nat.sh bridge_brouter.sh \
        nft_concat_range.sh nft_conntrack_helper.sh \
        nft_queue.sh nft_meta.sh nf_nat_edemux.sh \
        ipip-conntrack-mtu.sh conntrack_tcp_unreplied.sh \
-       conntrack_vrf.sh nft_synproxy.sh rpath.sh nft_audit.sh
+       conntrack_vrf.sh nft_synproxy.sh rpath.sh nft_audit.sh \
+       conntrack_sctp_collision.sh
 
 HOSTPKG_CONFIG := pkg-config
 
 CFLAGS += $(shell $(HOSTPKG_CONFIG) --cflags libmnl 2>/dev/null)
 LDLIBS += $(shell $(HOSTPKG_CONFIG) --libs libmnl 2>/dev/null || echo -lmnl)
 
-TEST_GEN_FILES =  nf-queue connect_close audit_logread
+TEST_GEN_FILES =  nf-queue connect_close audit_logread sctp_collision
 
 include ../lib.mk
diff --git a/tools/testing/selftests/netfilter/conntrack_sctp_collision.sh b/tools/testing/selftests/netfilter/conntrack_sctp_collision.sh
new file mode 100755 (executable)
index 0000000..a924e59
--- /dev/null
@@ -0,0 +1,89 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Testing For SCTP COLLISION SCENARIO as Below:
+#
+#   14:35:47.655279 IP CLIENT_IP.PORT > SERVER_IP.PORT: sctp (1) [INIT] [init tag: 2017837359]
+#   14:35:48.353250 IP SERVER_IP.PORT > CLIENT_IP.PORT: sctp (1) [INIT] [init tag: 1187206187]
+#   14:35:48.353275 IP CLIENT_IP.PORT > SERVER_IP.PORT: sctp (1) [INIT ACK] [init tag: 2017837359]
+#   14:35:48.353283 IP SERVER_IP.PORT > CLIENT_IP.PORT: sctp (1) [COOKIE ECHO]
+#   14:35:48.353977 IP CLIENT_IP.PORT > SERVER_IP.PORT: sctp (1) [COOKIE ACK]
+#   14:35:48.855335 IP SERVER_IP.PORT > CLIENT_IP.PORT: sctp (1) [INIT ACK] [init tag: 164579970]
+#
+# TOPO: SERVER_NS (link0)<--->(link1) ROUTER_NS (link2)<--->(link3) CLIENT_NS
+
+CLIENT_NS=$(mktemp -u client-XXXXXXXX)
+CLIENT_IP="198.51.200.1"
+CLIENT_PORT=1234
+
+SERVER_NS=$(mktemp -u server-XXXXXXXX)
+SERVER_IP="198.51.100.1"
+SERVER_PORT=1234
+
+ROUTER_NS=$(mktemp -u router-XXXXXXXX)
+CLIENT_GW="198.51.200.2"
+SERVER_GW="198.51.100.2"
+
+# setup the topo
+setup() {
+       ip net add $CLIENT_NS
+       ip net add $SERVER_NS
+       ip net add $ROUTER_NS
+       ip -n $SERVER_NS link add link0 type veth peer name link1 netns $ROUTER_NS
+       ip -n $CLIENT_NS link add link3 type veth peer name link2 netns $ROUTER_NS
+
+       ip -n $SERVER_NS link set link0 up
+       ip -n $SERVER_NS addr add $SERVER_IP/24 dev link0
+       ip -n $SERVER_NS route add $CLIENT_IP dev link0 via $SERVER_GW
+
+       ip -n $ROUTER_NS link set link1 up
+       ip -n $ROUTER_NS link set link2 up
+       ip -n $ROUTER_NS addr add $SERVER_GW/24 dev link1
+       ip -n $ROUTER_NS addr add $CLIENT_GW/24 dev link2
+       ip net exec $ROUTER_NS sysctl -wq net.ipv4.ip_forward=1
+
+       ip -n $CLIENT_NS link set link3 up
+       ip -n $CLIENT_NS addr add $CLIENT_IP/24 dev link3
+       ip -n $CLIENT_NS route add $SERVER_IP dev link3 via $CLIENT_GW
+
+       # simulate the delay on OVS upcall by setting up a delay for INIT_ACK with
+       # tc on $SERVER_NS side
+       tc -n $SERVER_NS qdisc add dev link0 root handle 1: htb
+       tc -n $SERVER_NS class add dev link0 parent 1: classid 1:1 htb rate 100mbit
+       tc -n $SERVER_NS filter add dev link0 parent 1: protocol ip u32 match ip protocol 132 \
+               0xff match u8 2 0xff at 32 flowid 1:1
+       tc -n $SERVER_NS qdisc add dev link0 parent 1:1 handle 10: netem delay 1200ms
+
+       # simulate the ctstate check on OVS nf_conntrack
+       ip net exec $ROUTER_NS iptables -A FORWARD -m state --state INVALID,UNTRACKED -j DROP
+       ip net exec $ROUTER_NS iptables -A INPUT -p sctp -j DROP
+
+       # use a smaller number for assoc's max_retrans to reproduce the issue
+       modprobe sctp
+       ip net exec $CLIENT_NS sysctl -wq net.sctp.association_max_retrans=3
+}
+
+cleanup() {
+       ip net exec $CLIENT_NS pkill sctp_collision 2>&1 >/dev/null
+       ip net exec $SERVER_NS pkill sctp_collision 2>&1 >/dev/null
+       ip net del "$CLIENT_NS"
+       ip net del "$SERVER_NS"
+       ip net del "$ROUTER_NS"
+}
+
+do_test() {
+       ip net exec $SERVER_NS ./sctp_collision server \
+               $SERVER_IP $SERVER_PORT $CLIENT_IP $CLIENT_PORT &
+       ip net exec $CLIENT_NS ./sctp_collision client \
+               $CLIENT_IP $CLIENT_PORT $SERVER_IP $SERVER_PORT
+}
+
+# NOTE: one way to work around the issue is set a smaller hb_interval
+# ip net exec $CLIENT_NS sysctl -wq net.sctp.hb_interval=3500
+
+# run the test case
+trap cleanup EXIT
+setup && \
+echo "Test for SCTP Collision in nf_conntrack:" && \
+do_test && echo "PASS!"
+exit $?
index 83c271b..bb34329 100755 (executable)
@@ -12,10 +12,11 @@ nft --version >/dev/null 2>&1 || {
 }
 
 logfile=$(mktemp)
+rulefile=$(mktemp)
 echo "logging into $logfile"
 ./audit_logread >"$logfile" &
 logread_pid=$!
-trap 'kill $logread_pid; rm -f $logfile' EXIT
+trap 'kill $logread_pid; rm -f $logfile $rulefile' EXIT
 exec 3<"$logfile"
 
 do_test() { # (cmd, log)
@@ -26,12 +27,14 @@ do_test() { # (cmd, log)
        res=$(diff -a -u <(echo "$2") - <&3)
        [ $? -eq 0 ] && { echo "OK"; return; }
        echo "FAIL"
-       echo "$res"
-       ((RC++))
+       grep -v '^\(---\|+++\|@@\)' <<< "$res"
+       ((RC--))
 }
 
 nft flush ruleset
 
+# adding tables, chains and rules
+
 for table in t1 t2; do
        do_test "nft add table $table" \
        "table=$table family=2 entries=1 op=nft_register_table"
@@ -62,6 +65,48 @@ for table in t1 t2; do
        "table=$table family=2 entries=6 op=nft_register_rule"
 done
 
+for ((i = 0; i < 500; i++)); do
+       echo "add rule t2 c3 counter accept comment \"rule $i\""
+done >$rulefile
+do_test "nft -f $rulefile" \
+'table=t2 family=2 entries=500 op=nft_register_rule'
+
+# adding sets and elements
+
+settype='type inet_service; counter'
+setelem='{ 22, 80, 443 }'
+setblock="{ $settype; elements = $setelem; }"
+do_test "nft add set t1 s $setblock" \
+"table=t1 family=2 entries=4 op=nft_register_set"
+
+do_test "nft add set t1 s2 $setblock; add set t1 s3 { $settype; }" \
+"table=t1 family=2 entries=5 op=nft_register_set"
+
+do_test "nft add element t1 s3 $setelem" \
+"table=t1 family=2 entries=3 op=nft_register_setelem"
+
+# adding counters
+
+do_test 'nft add counter t1 c1' \
+'table=t1 family=2 entries=1 op=nft_register_obj'
+
+do_test 'nft add counter t2 c1; add counter t2 c2' \
+'table=t2 family=2 entries=2 op=nft_register_obj'
+
+# adding/updating quotas
+
+do_test 'nft add quota t1 q1 { 10 bytes }' \
+'table=t1 family=2 entries=1 op=nft_register_obj'
+
+do_test 'nft add quota t2 q1 { 10 bytes }; add quota t2 q2 { 10 bytes }' \
+'table=t2 family=2 entries=2 op=nft_register_obj'
+
+# changing the quota value triggers obj update path
+do_test 'nft add quota t1 q1 { 20 bytes }' \
+'table=t1 family=2 entries=1 op=nft_register_obj'
+
+# resetting rules
+
 do_test 'nft reset rules t1 c2' \
 'table=t1 family=2 entries=3 op=nft_reset_rule'
 
@@ -70,19 +115,6 @@ do_test 'nft reset rules table t1' \
 table=t1 family=2 entries=3 op=nft_reset_rule
 table=t1 family=2 entries=3 op=nft_reset_rule'
 
-do_test 'nft reset rules' \
-'table=t1 family=2 entries=3 op=nft_reset_rule
-table=t1 family=2 entries=3 op=nft_reset_rule
-table=t1 family=2 entries=3 op=nft_reset_rule
-table=t2 family=2 entries=3 op=nft_reset_rule
-table=t2 family=2 entries=3 op=nft_reset_rule
-table=t2 family=2 entries=3 op=nft_reset_rule'
-
-for ((i = 0; i < 500; i++)); do
-       echo "add rule t2 c3 counter accept comment \"rule $i\""
-done | do_test 'nft -f -' \
-'table=t2 family=2 entries=500 op=nft_register_rule'
-
 do_test 'nft reset rules t2 c3' \
 'table=t2 family=2 entries=189 op=nft_reset_rule
 table=t2 family=2 entries=188 op=nft_reset_rule
@@ -105,4 +137,57 @@ table=t2 family=2 entries=180 op=nft_reset_rule
 table=t2 family=2 entries=188 op=nft_reset_rule
 table=t2 family=2 entries=135 op=nft_reset_rule'
 
+# resetting sets and elements
+
+elem=(22 ,80 ,443)
+relem=""
+for i in {1..3}; do
+       relem+="${elem[((i - 1))]}"
+       do_test "nft reset element t1 s { $relem }" \
+       "table=t1 family=2 entries=$i op=nft_reset_setelem"
+done
+
+do_test 'nft reset set t1 s' \
+'table=t1 family=2 entries=3 op=nft_reset_setelem'
+
+# deleting rules
+
+readarray -t handles < <(nft -a list chain t1 c1 | \
+                        sed -n 's/.*counter.* handle \(.*\)$/\1/p')
+
+do_test "nft delete rule t1 c1 handle ${handles[0]}" \
+'table=t1 family=2 entries=1 op=nft_unregister_rule'
+
+cmd='delete rule t1 c1 handle'
+do_test "nft $cmd ${handles[1]}; $cmd ${handles[2]}" \
+'table=t1 family=2 entries=2 op=nft_unregister_rule'
+
+do_test 'nft flush chain t1 c2' \
+'table=t1 family=2 entries=3 op=nft_unregister_rule'
+
+do_test 'nft flush table t2' \
+'table=t2 family=2 entries=509 op=nft_unregister_rule'
+
+# deleting chains
+
+do_test 'nft delete chain t2 c2' \
+'table=t2 family=2 entries=1 op=nft_unregister_chain'
+
+# deleting sets and elements
+
+do_test 'nft delete element t1 s { 22 }' \
+'table=t1 family=2 entries=1 op=nft_unregister_setelem'
+
+do_test 'nft delete element t1 s { 80, 443 }' \
+'table=t1 family=2 entries=2 op=nft_unregister_setelem'
+
+do_test 'nft flush set t1 s2' \
+'table=t1 family=2 entries=3 op=nft_unregister_setelem'
+
+do_test 'nft delete set t1 s2' \
+'table=t1 family=2 entries=1 op=nft_unregister_set'
+
+do_test 'nft delete set t1 s3' \
+'table=t1 family=2 entries=1 op=nft_unregister_set'
+
 exit $RC
diff --git a/tools/testing/selftests/netfilter/sctp_collision.c b/tools/testing/selftests/netfilter/sctp_collision.c
new file mode 100644 (file)
index 0000000..21bb1cf
--- /dev/null
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+
+int main(int argc, char *argv[])
+{
+       struct sockaddr_in saddr = {}, daddr = {};
+       int sd, ret, len = sizeof(daddr);
+       struct timeval tv = {25, 0};
+       char buf[] = "hello";
+
+       if (argc != 6 || (strcmp(argv[1], "server") && strcmp(argv[1], "client"))) {
+               printf("%s <server|client> <LOCAL_IP> <LOCAL_PORT> <REMOTE_IP> <REMOTE_PORT>\n",
+                      argv[0]);
+               return -1;
+       }
+
+       sd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
+       if (sd < 0) {
+               printf("Failed to create sd\n");
+               return -1;
+       }
+
+       saddr.sin_family = AF_INET;
+       saddr.sin_addr.s_addr = inet_addr(argv[2]);
+       saddr.sin_port = htons(atoi(argv[3]));
+
+       ret = bind(sd, (struct sockaddr *)&saddr, sizeof(saddr));
+       if (ret < 0) {
+               printf("Failed to bind to address\n");
+               goto out;
+       }
+
+       ret = listen(sd, 5);
+       if (ret < 0) {
+               printf("Failed to listen on port\n");
+               goto out;
+       }
+
+       daddr.sin_family = AF_INET;
+       daddr.sin_addr.s_addr = inet_addr(argv[4]);
+       daddr.sin_port = htons(atoi(argv[5]));
+
+       /* make test shorter than 25s */
+       ret = setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+       if (ret < 0) {
+               printf("Failed to setsockopt SO_RCVTIMEO\n");
+               goto out;
+       }
+
+       if (!strcmp(argv[1], "server")) {
+               sleep(1); /* wait a bit for client's INIT */
+               ret = connect(sd, (struct sockaddr *)&daddr, len);
+               if (ret < 0) {
+                       printf("Failed to connect to peer\n");
+                       goto out;
+               }
+               ret = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr *)&daddr, &len);
+               if (ret < 0) {
+                       printf("Failed to recv msg %d\n", ret);
+                       goto out;
+               }
+               ret = sendto(sd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&daddr, len);
+               if (ret < 0) {
+                       printf("Failed to send msg %d\n", ret);
+                       goto out;
+               }
+               printf("Server: sent! %d\n", ret);
+       }
+
+       if (!strcmp(argv[1], "client")) {
+               usleep(300000); /* wait a bit for server's listening */
+               ret = connect(sd, (struct sockaddr *)&daddr, len);
+               if (ret < 0) {
+                       printf("Failed to connect to peer\n");
+                       goto out;
+               }
+               sleep(1); /* wait a bit for server's delayed INIT_ACK to reproduce the issue */
+               ret = sendto(sd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&daddr, len);
+               if (ret < 0) {
+                       printf("Failed to send msg %d\n", ret);
+                       goto out;
+               }
+               ret = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr *)&daddr, &len);
+               if (ret < 0) {
+                       printf("Failed to recv msg %d\n", ret);
+                       goto out;
+               }
+               printf("Client: rcvd! %d\n", ret);
+       }
+       ret = 0;
+out:
+       close(sd);
+       return ret;
+}
index e0ffe69..7093fd5 100644 (file)
@@ -159,6 +159,7 @@ static int timerlat_aa_irq_latency(struct timerlat_aa_data *taa_data,
        taa_data->thread_nmi_sum = 0;
        taa_data->thread_irq_sum = 0;
        taa_data->thread_softirq_sum = 0;
+       taa_data->thread_thread_sum = 0;
        taa_data->thread_blocking_duration = 0;
        taa_data->timer_irq_start_time = 0;
        taa_data->timer_irq_duration = 0;
@@ -337,7 +338,23 @@ static int timerlat_aa_irq_handler(struct trace_seq *s, struct tep_record *recor
                taa_data->timer_irq_start_time = start;
                taa_data->timer_irq_duration = duration;
 
-               taa_data->timer_irq_start_delay = taa_data->timer_irq_start_time - expected_start;
+               /*
+                * We are dealing with two different clock sources: the
+                * external clock source that timerlat uses as a reference
+                * and the clock used by the tracer. There are also two
+                * moments: the time reading the clock and the timer in
+                * which the event is placed in the buffer (the trace
+                * event timestamp). If the processor is slow or there
+                * is some hardware noise, the difference between the
+                * timestamp and the external clock read can be longer
+                * than the IRQ handler delay, resulting in a negative
+                * time. If so, set IRQ start delay as 0. In the end,
+                * it is less relevant than the noise.
+                */
+               if (expected_start < taa_data->timer_irq_start_time)
+                       taa_data->timer_irq_start_delay = taa_data->timer_irq_start_time - expected_start;
+               else
+                       taa_data->timer_irq_start_delay = 0;
 
                /*
                 * not exit from idle.
@@ -528,7 +545,7 @@ static int timerlat_aa_kworker_start_handler(struct trace_seq *s, struct tep_rec
 static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu,
                                     int irq_thresh, int thread_thresh)
 {
-       unsigned long long exp_irq_ts;
+       long long exp_irq_ts;
        int total;
        int irq;
 
@@ -545,12 +562,15 @@ static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu,
 
        /*
         * Expected IRQ arrival time using the trace clock as the base.
+        *
+        * TODO: Add a list of previous IRQ, and then run the list backwards.
         */
        exp_irq_ts = taa_data->timer_irq_start_time - taa_data->timer_irq_start_delay;
-
-       if (exp_irq_ts < taa_data->prev_irq_timstamp + taa_data->prev_irq_duration)
-               printf("  Previous IRQ interference:    \t\t up to  %9.2f us\n",
-                       ns_to_usf(taa_data->prev_irq_duration));
+       if (exp_irq_ts < taa_data->prev_irq_timstamp + taa_data->prev_irq_duration) {
+               if (taa_data->prev_irq_timstamp < taa_data->timer_irq_start_time)
+                       printf("  Previous IRQ interference:    \t\t up to  %9.2f us\n",
+                               ns_to_usf(taa_data->prev_irq_duration));
+       }
 
        /*
         * The delay that the IRQ suffered before starting.
index 05e3106..01dbf9a 100644 (file)
@@ -45,7 +45,7 @@ static int timerlat_u_main(int cpu, struct timerlat_u_params *params)
 
        retval = sched_setaffinity(gettid(), sizeof(set), &set);
        if (retval == -1) {
-               err_msg("Error setting user thread affinity\n");
+               debug_msg("Error setting user thread affinity %d, is the CPU online?\n", cpu);
                exit(1);
        }
 
@@ -193,7 +193,9 @@ void *timerlat_u_dispatcher(void *data)
                                        procs_count--;
                                }
                        }
-                       break;
+
+                       if (!procs_count)
+                               break;
                }
 
                sleep(1);