Merge tag 'perf-urgent-2023-11-26' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 26 Nov 2023 16:34:12 +0000 (08:34 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 26 Nov 2023 16:34:12 +0000 (08:34 -0800)
Pull x86 perf event fix from Ingo Molnar:
 "Fix a bug in the Intel hybrid CPUs hardware-capabilities enumeration
  code resulting in non-working events on those platforms"

* tag 'perf-urgent-2023-11-26' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  perf/x86/intel: Correct incorrect 'or' operation for PMU capabilities

229 files changed:
Documentation/arch/loongarch/introduction.rst
Documentation/devicetree/bindings/usb/microchip,usb5744.yaml
Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
Documentation/devicetree/bindings/usb/usb-hcd.yaml
Documentation/filesystems/erofs.rst
Documentation/process/maintainer-netdev.rst
Documentation/translations/zh_CN/arch/loongarch/introduction.rst
MAINTAINERS
arch/arm/xen/enlighten.c
arch/arm64/Makefile
arch/arm64/include/asm/setup.h
arch/arm64/mm/pageattr.c
arch/loongarch/Makefile
arch/loongarch/include/asm/asmmacro.h
arch/loongarch/include/asm/percpu.h
arch/loongarch/include/asm/setup.h
arch/loongarch/kernel/relocate.c
arch/loongarch/kernel/time.c
arch/loongarch/mm/pgtable.c
arch/s390/include/asm/processor.h
arch/s390/kernel/ipl.c
arch/s390/kernel/perf_pai_crypto.c
arch/s390/kernel/perf_pai_ext.c
arch/x86/hyperv/hv_init.c
arch/x86/kernel/cpu/mshyperv.c
block/bdev.c
block/blk-cgroup.c
block/blk-cgroup.h
block/blk-pm.c
block/blk-throttle.c
drivers/accel/ivpu/ivpu_hw_37xx.c
drivers/acpi/acpi_video.c
drivers/acpi/device_pm.c
drivers/acpi/processor_idle.c
drivers/acpi/resource.c
drivers/ata/pata_isapnp.c
drivers/block/nbd.c
drivers/block/null_blk/main.c
drivers/dpll/dpll_netlink.c
drivers/gpu/drm/ast/ast_drv.h
drivers/gpu/drm/ast/ast_mode.c
drivers/gpu/drm/i915/display/intel_dp_mst.c
drivers/gpu/drm/i915/gt/intel_gt.c
drivers/gpu/drm/i915/i915_driver.c
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h
drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
drivers/gpu/drm/msm/dp/dp_display.c
drivers/gpu/drm/msm/dp/dp_drm.c
drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/r535.c
drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
drivers/gpu/drm/panel/panel-simple.c
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
drivers/hid/hid-apple.c
drivers/hid/hid-asus.c
drivers/hid/hid-core.c
drivers/hid/hid-debug.c
drivers/hid/hid-glorious.c
drivers/hid/hid-ids.h
drivers/hid/hid-logitech-dj.c
drivers/hid/hid-mcp2221.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-quirks.c
drivers/md/bcache/bcache.h
drivers/md/bcache/btree.c
drivers/md/bcache/super.c
drivers/md/bcache/sysfs.c
drivers/md/bcache/writeback.c
drivers/md/md.c
drivers/net/ethernet/amd/xgbe/xgbe-drv.c
drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/ice/ice_ptp.c
drivers/net/ethernet/intel/ice/ice_ptp.h
drivers/net/ethernet/intel/ice/ice_txrx.c
drivers/net/ethernet/intel/ice/ice_txrx.h
drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
drivers/net/ethernet/realtek/r8169_main.c
drivers/net/ethernet/stmicro/stmmac/Kconfig
drivers/net/ethernet/wangxun/libwx/wx_hw.c
drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
drivers/net/ethernet/xilinx/xilinx_axienet_main.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/ipa/reg/gsi_reg-v5.0.c
drivers/net/netkit.c
drivers/net/usb/aqc111.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/qmi_wwan.c
drivers/net/veth.c
drivers/net/vrf.c
drivers/net/wireguard/device.c
drivers/net/wireguard/receive.c
drivers/net/wireguard/send.c
drivers/nfc/virtual_ncidev.c
drivers/nvme/host/auth.c
drivers/nvme/host/core.c
drivers/nvme/host/fabrics.c
drivers/nvme/host/fc.c
drivers/nvme/host/rdma.c
drivers/nvme/host/tcp.c
drivers/nvme/target/Kconfig
drivers/nvme/target/configfs.c
drivers/nvme/target/fabrics-cmd.c
drivers/nvme/target/tcp.c
drivers/phy/Kconfig
drivers/phy/Makefile
drivers/phy/realtek/Kconfig [deleted file]
drivers/phy/realtek/Makefile [deleted file]
drivers/phy/realtek/phy-rtk-usb2.c [deleted file]
drivers/phy/realtek/phy-rtk-usb3.c [deleted file]
drivers/platform/x86/amd/pmc/pmc.c
drivers/platform/x86/hp/hp-bioscfg/bioscfg.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel/telemetry/core.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_int.h
drivers/s390/net/Kconfig
drivers/s390/net/ism_drv.c
drivers/thunderbolt/switch.c
drivers/thunderbolt/tb.c
drivers/usb/cdns3/cdnsp-ring.c
drivers/usb/core/config.c
drivers/usb/core/hub.c
drivers/usb/dwc2/hcd_intr.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/drd.c
drivers/usb/dwc3/dwc3-qcom.c
drivers/usb/dwc3/dwc3-rtk.c
drivers/usb/host/xhci-mtk-sch.c
drivers/usb/host/xhci-mtk.h
drivers/usb/host/xhci-plat.c
drivers/usb/misc/onboard_usb_hub.c
drivers/usb/misc/onboard_usb_hub.h
drivers/usb/misc/usb-ljca.c
drivers/usb/serial/option.c
drivers/usb/typec/tcpm/tcpm.c
drivers/usb/typec/tipd/core.c
drivers/xen/privcmd.c
drivers/xen/swiotlb-xen.c
fs/afs/dynroot.c
fs/afs/internal.h
fs/afs/server_list.c
fs/afs/super.c
fs/afs/vl_rotate.c
fs/autofs/inode.c
fs/ecryptfs/inode.c
fs/erofs/Kconfig
fs/erofs/data.c
fs/erofs/inode.c
fs/inode.c
fs/libfs.c
fs/overlayfs/inode.c
fs/overlayfs/overlayfs.h
fs/smb/client/cifsglob.h
fs/smb/client/cifspdu.h
fs/smb/client/cifsproto.h
fs/smb/client/cifssmb.c
fs/smb/client/inode.c
fs/smb/client/readdir.c
fs/smb/client/sess.c
fs/smb/client/smb1ops.c
fs/smb/client/smb2inode.c
fs/smb/client/smb2ops.c
fs/stat.c
fs/xfs/xfs_dquot.c
fs/xfs/xfs_dquot_item_recover.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_ioctl.c
fs/xfs/xfs_iops.c
include/acpi/acpi_bus.h
include/asm-generic/qspinlock.h
include/linux/blk-pm.h
include/linux/bpf_verifier.h
include/linux/hid.h
include/linux/netdevice.h
include/linux/pagemap.h
include/linux/usb/phy.h
include/net/netkit.h
include/trace/events/rxrpc.h
include/uapi/linux/fcntl.h
io_uring/fs.c
io_uring/rsrc.c
kernel/bpf/verifier.c
kernel/locking/lockdep.c
lib/iov_iter.c
mm/page-writeback.c
net/core/dev.c
net/core/filter.c
net/ipv4/inet_diag.c
net/ipv4/raw_diag.c
net/ipv4/route.c
net/ipv4/tcp_diag.c
net/ipv4/udp_diag.c
net/mptcp/mptcp_diag.c
net/packet/diag.c
net/rxrpc/conn_client.c
net/rxrpc/input.c
net/sctp/diag.c
net/smc/af_smc.c
net/smc/smc_diag.c
net/tipc/diag.c
net/tls/tls_sw.c
net/unix/diag.c
net/vmw_vsock/diag.c
net/xdp/xsk_diag.c
scripts/checkstack.pl
tools/hv/hv_kvp_daemon.c
tools/hv/hv_set_ifconfig.sh
tools/net/ynl/Makefile.deps
tools/net/ynl/generated/devlink-user.c
tools/net/ynl/ynl-gen-c.py
tools/power/pm-graph/sleepgraph.py
tools/testing/selftests/arm64/fp/za-fork.c
tools/testing/selftests/bpf/prog_tests/tc_redirect.c
tools/testing/selftests/bpf/prog_tests/verifier.c
tools/testing/selftests/bpf/progs/bpf_loop_bench.c
tools/testing/selftests/bpf/progs/cb_refs.c
tools/testing/selftests/bpf/progs/exceptions_fail.c
tools/testing/selftests/bpf/progs/strobemeta.h
tools/testing/selftests/bpf/progs/verifier_iterating_callbacks.c [new file with mode: 0644]
tools/testing/selftests/bpf/progs/verifier_subprog_precision.c
tools/testing/selftests/bpf/progs/xdp_synproxy_kern.c
tools/testing/selftests/net/rtnetlink.sh
tools/testing/vsock/vsock_test.c

index 8c568cfc2107984092f4d82c2076a3bed0c05c4f..5e6db78abeaf50fd48a9e8e67fa4d61f49c64905 100644 (file)
@@ -375,9 +375,9 @@ Developer web site of Loongson and LoongArch (Software and Documentation):
 
 Documentation of LoongArch ISA:
 
-  https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-CN.pdf (in Chinese)
+  https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.10-CN.pdf (in Chinese)
 
-  https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-EN.pdf (in English)
+  https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.10-EN.pdf (in English)
 
 Documentation of LoongArch ELF psABI:
 
index ff3a1707ef570f50871ca6bd630381c6d130fbb7..6d4cfd943f5847ff43cbccd13e5f210a95448c1c 100644 (file)
@@ -36,7 +36,11 @@ properties:
 
   vdd-supply:
     description:
-      VDD power supply to the hub
+      3V3 power supply to the hub
+
+  vdd2-supply:
+    description:
+      1V2 power supply to the hub
 
   peer-hub:
     $ref: /schemas/types.yaml#/definitions/phandle
@@ -62,6 +66,7 @@ allOf:
       properties:
         reset-gpios: false
         vdd-supply: false
+        vdd2-supply: false
         peer-hub: false
         i2c-bus: false
     else:
index e889158ca20578893ef0c7072ce1fbf64f70a41c..915c8205623b3abf98a43c9ab851e2bdb32c36f7 100644 (file)
@@ -521,8 +521,8 @@ examples:
 
             interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
                          <GIC_SPI 486 IRQ_TYPE_LEVEL_HIGH>,
-                         <GIC_SPI 488 IRQ_TYPE_LEVEL_HIGH>,
-                         <GIC_SPI 489 IRQ_TYPE_LEVEL_HIGH>;
+                         <GIC_SPI 488 IRQ_TYPE_EDGE_BOTH>,
+                         <GIC_SPI 489 IRQ_TYPE_EDGE_BOTH>;
             interrupt-names = "hs_phy_irq", "ss_phy_irq",
                           "dm_hs_phy_irq", "dp_hs_phy_irq";
 
index 692dd60e3f73f321a20761f81e54d512953f9dba..45a19d4928afa6eeb521556e603004bd6d6a5ed8 100644 (file)
@@ -41,7 +41,7 @@ examples:
   - |
     usb {
         phys = <&usb2_phy1>, <&usb3_phy1>;
-        phy-names = "usb";
+        phy-names = "usb2", "usb3";
         #address-cells = <1>;
         #size-cells = <0>;
 
index 57c6ae23b3fcf97ce4f875cfd34d4bd08e7bbae1..cc4626d6ee4f836b50dcb8b3e85de56d01da968f 100644 (file)
@@ -91,6 +91,10 @@ compatibility checking tool (fsck.erofs), and a debugging tool (dump.erofs):
 
 - git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs-utils.git
 
+For more information, please also refer to the documentation site:
+
+- https://erofs.docs.kernel.org
+
 Bugs and patches are welcome, please kindly help us and send to the following
 linux-erofs mailing list:
 
index 7feacc20835e424b584927ce0db990e4a9657c8c..84ee60fceef24cbf1ba9e090ac91c94abd4064b5 100644 (file)
@@ -193,9 +193,23 @@ Review timelines
 Generally speaking, the patches get triaged quickly (in less than
 48h). But be patient, if your patch is active in patchwork (i.e. it's
 listed on the project's patch list) the chances it was missed are close to zero.
-Asking the maintainer for status updates on your
-patch is a good way to ensure your patch is ignored or pushed to the
-bottom of the priority list.
+
+The high volume of development on netdev makes reviewers move on
+from discussions relatively quickly. New comments and replies
+are very unlikely to arrive after a week of silence. If a patch
+is no longer active in patchwork and the thread went idle for more
+than a week - clarify the next steps and/or post the next version.
+
+For RFC postings specifically, if nobody responded in a week - reviewers
+either missed the posting or have no strong opinions. If the code is ready,
+repost as a PATCH.
+
+Emails saying just "ping" or "bump" are considered rude. If you can't figure
+out the status of the patch from patchwork or where the discussion has
+landed - describe your best guess and ask if it's correct. For example::
+
+  I don't understand what the next steps are. Person X seems to be unhappy
+  with A, should I do B and repost the patches?
 
 .. _Changes requested:
 
index 59d6bf33050cb831236321d91eab7bbf313655ea..bf463c5a4c5144c6d2520449472553ae9da88ed8 100644 (file)
@@ -338,9 +338,9 @@ Loongson与LoongArch的开发者网站(软件与文档资源):
 
 LoongArch指令集架构的文档:
 
-  https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-CN.pdf (中文版)
+  https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.10-CN.pdf (中文版)
 
-  https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-EN.pdf (英文版)
+  https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.10-EN.pdf (英文版)
 
 LoongArch的ELF psABI文档:
 
index ea790149af795155003eaacca87289e05d55454b..509281e9e1695a5a7b7d81e091f7835d1514cc59 100644 (file)
@@ -7855,6 +7855,7 @@ R:        Yue Hu <huyue2@coolpad.com>
 R:     Jeffle Xu <jefflexu@linux.alibaba.com>
 L:     linux-erofs@lists.ozlabs.org
 S:     Maintained
+W:     https://erofs.docs.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs.git
 F:     Documentation/ABI/testing/sysfs-fs-erofs
 F:     Documentation/filesystems/erofs.rst
@@ -11024,7 +11025,6 @@ F:      drivers/net/wireless/intel/iwlwifi/
 
 INTEL WMI SLIM BOOTLOADER (SBL) FIRMWARE UPDATE DRIVER
 M:     Jithu Joseph <jithu.joseph@intel.com>
-R:     Maurice Ma <maurice.ma@intel.com>
 S:     Maintained
 W:     https://slimbootloader.github.io/security/firmware-update.html
 F:     drivers/platform/x86/intel/wmi/sbl-fw-update.c
@@ -13778,7 +13778,6 @@ F:      drivers/net/ethernet/mellanox/mlxfw/
 MELLANOX HARDWARE PLATFORM SUPPORT
 M:     Hans de Goede <hdegoede@redhat.com>
 M:     Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
-M:     Mark Gross <markgross@kernel.org>
 M:     Vadim Pasternak <vadimp@nvidia.com>
 L:     platform-driver-x86@vger.kernel.org
 S:     Supported
@@ -14387,7 +14386,6 @@ F:      drivers/platform/surface/surface_gpe.c
 MICROSOFT SURFACE HARDWARE PLATFORM SUPPORT
 M:     Hans de Goede <hdegoede@redhat.com>
 M:     Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
-M:     Mark Gross <markgross@kernel.org>
 M:     Maximilian Luz <luzmaximilian@gmail.com>
 L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
@@ -14994,6 +14992,7 @@ M:      Jakub Kicinski <kuba@kernel.org>
 M:     Paolo Abeni <pabeni@redhat.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
+P:     Documentation/process/maintainer-netdev.rst
 Q:     https://patchwork.kernel.org/project/netdevbpf/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
@@ -15045,6 +15044,7 @@ M:      Jakub Kicinski <kuba@kernel.org>
 M:     Paolo Abeni <pabeni@redhat.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
+P:     Documentation/process/maintainer-netdev.rst
 Q:     https://patchwork.kernel.org/project/netdevbpf/list/
 B:     mailto:netdev@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
@@ -15055,6 +15055,7 @@ F:      Documentation/networking/
 F:     Documentation/process/maintainer-netdev.rst
 F:     Documentation/userspace-api/netlink/
 F:     include/linux/in.h
+F:     include/linux/indirect_call_wrapper.h
 F:     include/linux/net.h
 F:     include/linux/netdevice.h
 F:     include/net/
@@ -23664,7 +23665,6 @@ F:      drivers/platform/x86/x86-android-tablets/
 X86 PLATFORM DRIVERS
 M:     Hans de Goede <hdegoede@redhat.com>
 M:     Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
-M:     Mark Gross <markgross@kernel.org>
 L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
 Q:     https://patchwork.kernel.org/project/platform-driver-x86/list/
index 9afdc4c4a5dc15f9bf4a1972894e2b046f5489d6..a395b6c0aae2a92e40b88dc37faa2829df9f95f0 100644 (file)
@@ -484,7 +484,8 @@ static int __init xen_guest_init(void)
         * for secondary CPUs as they are brought up.
         * For uniformity we use VCPUOP_register_vcpu_info even on cpu0.
         */
-       xen_vcpu_info = alloc_percpu(struct vcpu_info);
+       xen_vcpu_info = __alloc_percpu(sizeof(struct vcpu_info),
+                                      1 << fls(sizeof(struct vcpu_info) - 1));
        if (xen_vcpu_info == NULL)
                return -ENOMEM;
 
index 4bd85cc0d32bfac906b039cab192f36a5d77a813..9a2d3723cd0fa9563647d8aaa9d6602f2546f823 100644 (file)
@@ -158,7 +158,7 @@ endif
 
 all:   $(notdir $(KBUILD_IMAGE))
 
-
+vmlinuz.efi: Image
 Image vmlinuz.efi: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
index f4af547ef54caa70a521387d442ffeb6d04a230b..2e4d7da74fb87a8444c516e343108f88f611336e 100644 (file)
@@ -21,9 +21,22 @@ static inline bool arch_parse_debug_rodata(char *arg)
        extern bool rodata_enabled;
        extern bool rodata_full;
 
-       if (arg && !strcmp(arg, "full")) {
+       if (!arg)
+               return false;
+
+       if (!strcmp(arg, "full")) {
+               rodata_enabled = rodata_full = true;
+               return true;
+       }
+
+       if (!strcmp(arg, "off")) {
+               rodata_enabled = rodata_full = false;
+               return true;
+       }
+
+       if (!strcmp(arg, "on")) {
                rodata_enabled = true;
-               rodata_full = true;
+               rodata_full = false;
                return true;
        }
 
index 8e2017ba5f1b114640544e1f01e0ebb399d074c7..924843f1f661bfe1ff5c6b8f9eff753872416040 100644 (file)
@@ -29,8 +29,8 @@ bool can_set_direct_map(void)
         *
         * KFENCE pool requires page-granular mapping if initialized late.
         */
-       return (rodata_enabled && rodata_full) || debug_pagealloc_enabled() ||
-               arm64_kfence_can_set_direct_map();
+       return rodata_full || debug_pagealloc_enabled() ||
+              arm64_kfence_can_set_direct_map();
 }
 
 static int change_page_range(pte_t *ptep, unsigned long addr, void *data)
@@ -105,8 +105,7 @@ static int change_memory_common(unsigned long addr, int numpages,
         * If we are manipulating read-only permissions, apply the same
         * change to the linear mapping of the pages that back this VM area.
         */
-       if (rodata_enabled &&
-           rodata_full && (pgprot_val(set_mask) == PTE_RDONLY ||
+       if (rodata_full && (pgprot_val(set_mask) == PTE_RDONLY ||
                            pgprot_val(clear_mask) == PTE_RDONLY)) {
                for (i = 0; i < area->nr_pages; i++) {
                        __change_memory_common((u64)page_address(area->pages[i]),
index 9eeb0c05f3f4d2a48ab743c15e42ac6cb2c88fe8..204b94b2e6aaa6e3afc71b292004fb3b329256b2 100644 (file)
@@ -68,6 +68,7 @@ LDFLAGS_vmlinux                       += -static -n -nostdlib
 ifdef CONFIG_AS_HAS_EXPLICIT_RELOCS
 cflags-y                       += $(call cc-option,-mexplicit-relocs)
 KBUILD_CFLAGS_KERNEL           += $(call cc-option,-mdirect-extern-access)
+KBUILD_CFLAGS_KERNEL           += $(call cc-option,-fdirect-access-external-data)
 KBUILD_AFLAGS_MODULE           += $(call cc-option,-fno-direct-access-external-data)
 KBUILD_CFLAGS_MODULE           += $(call cc-option,-fno-direct-access-external-data)
 KBUILD_AFLAGS_MODULE           += $(call cc-option,-mno-relax) $(call cc-option,-Wa$(comma)-mno-relax)
@@ -142,6 +143,8 @@ vdso-install-y += arch/loongarch/vdso/vdso.so.dbg
 
 all:   $(notdir $(KBUILD_IMAGE))
 
+vmlinuz.efi: vmlinux.efi
+
 vmlinux.elf vmlinux.efi vmlinuz.efi: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $(bootvars-y) $(boot)/$@
 
index c9544f358c33991b46b67edec578af1df44939b7..655db7d7a42796d947e857b6c546023d82c13fba 100644 (file)
        lu32i.d \reg, 0
        lu52i.d \reg, \reg, 0
        .pushsection ".la_abs", "aw", %progbits
-       768:
-       .dword  768b-766b
+       .dword  766b
        .dword  \sym
        .popsection
 #endif
index ed5da02b1cf6f1611ac4b83e560d1f544ed6e270..9b36ac003f8907ed06a279c94bb49ede82b213b2 100644 (file)
@@ -40,13 +40,13 @@ static __always_inline unsigned long __percpu_##op(void *ptr,               \
        switch (size) {                                                 \
        case 4:                                                         \
                __asm__ __volatile__(                                   \
-               "am"#asm_op".w" " %[ret], %[val], %[ptr]        \n"             \
+               "am"#asm_op".w" " %[ret], %[val], %[ptr]        \n"     \
                : [ret] "=&r" (ret), [ptr] "+ZB"(*(u32 *)ptr)           \
                : [val] "r" (val));                                     \
                break;                                                  \
        case 8:                                                         \
                __asm__ __volatile__(                                   \
-               "am"#asm_op".d" " %[ret], %[val], %[ptr]        \n"             \
+               "am"#asm_op".d" " %[ret], %[val], %[ptr]        \n"     \
                : [ret] "=&r" (ret), [ptr] "+ZB"(*(u64 *)ptr)           \
                : [val] "r" (val));                                     \
                break;                                                  \
@@ -63,7 +63,7 @@ PERCPU_OP(and, and, &)
 PERCPU_OP(or, or, |)
 #undef PERCPU_OP
 
-static __always_inline unsigned long __percpu_read(void *ptr, int size)
+static __always_inline unsigned long __percpu_read(void __percpu *ptr, int size)
 {
        unsigned long ret;
 
@@ -100,7 +100,7 @@ static __always_inline unsigned long __percpu_read(void *ptr, int size)
        return ret;
 }
 
-static __always_inline void __percpu_write(void *ptr, unsigned long val, int size)
+static __always_inline void __percpu_write(void __percpu *ptr, unsigned long val, int size)
 {
        switch (size) {
        case 1:
@@ -132,8 +132,7 @@ static __always_inline void __percpu_write(void *ptr, unsigned long val, int siz
        }
 }
 
-static __always_inline unsigned long __percpu_xchg(void *ptr, unsigned long val,
-                                                  int size)
+static __always_inline unsigned long __percpu_xchg(void *ptr, unsigned long val, int size)
 {
        switch (size) {
        case 1:
index a0bc159ce8bdc0348defe27953c07d973dd58b5f..ee52fb1e99631653e3e40d6998afd159a7e5986d 100644 (file)
@@ -25,7 +25,7 @@ extern void set_merr_handler(unsigned long offset, void *addr, unsigned long len
 #ifdef CONFIG_RELOCATABLE
 
 struct rela_la_abs {
-       long offset;
+       long pc;
        long symvalue;
 };
 
index 6c3eff9af9fb1ed4cc4af8ffa9b9ea5490591ee3..1acfa704c8d09b95b625da9fd047833b181d35f7 100644 (file)
@@ -52,7 +52,7 @@ static inline void __init relocate_absolute(long random_offset)
        for (p = begin; (void *)p < end; p++) {
                long v = p->symvalue;
                uint32_t lu12iw, ori, lu32id, lu52id;
-               union loongarch_instruction *insn = (void *)p - p->offset;
+               union loongarch_instruction *insn = (void *)p->pc;
 
                lu12iw = (v >> 12) & 0xfffff;
                ori    = v & 0xfff;
@@ -102,6 +102,14 @@ static inline __init unsigned long get_random_boot(void)
        return hash;
 }
 
+static int __init nokaslr(char *p)
+{
+       pr_info("KASLR is disabled.\n");
+
+       return 0; /* Print a notice and silence the boot warning */
+}
+early_param("nokaslr", nokaslr);
+
 static inline __init bool kaslr_disabled(void)
 {
        char *str;
index 3064af94db9c2e14e953a4aad68c2a8d28588447..e7015f7b70e37c4cabf736512c50a998455bbdf9 100644 (file)
@@ -58,14 +58,16 @@ static int constant_set_state_oneshot(struct clock_event_device *evt)
        return 0;
 }
 
-static int constant_set_state_oneshot_stopped(struct clock_event_device *evt)
+static int constant_set_state_periodic(struct clock_event_device *evt)
 {
+       unsigned long period;
        unsigned long timer_config;
 
        raw_spin_lock(&state_lock);
 
-       timer_config = csr_read64(LOONGARCH_CSR_TCFG);
-       timer_config &= ~CSR_TCFG_EN;
+       period = const_clock_freq / HZ;
+       timer_config = period & CSR_TCFG_VAL;
+       timer_config |= (CSR_TCFG_PERIOD | CSR_TCFG_EN);
        csr_write64(timer_config, LOONGARCH_CSR_TCFG);
 
        raw_spin_unlock(&state_lock);
@@ -73,16 +75,14 @@ static int constant_set_state_oneshot_stopped(struct clock_event_device *evt)
        return 0;
 }
 
-static int constant_set_state_periodic(struct clock_event_device *evt)
+static int constant_set_state_shutdown(struct clock_event_device *evt)
 {
-       unsigned long period;
        unsigned long timer_config;
 
        raw_spin_lock(&state_lock);
 
-       period = const_clock_freq / HZ;
-       timer_config = period & CSR_TCFG_VAL;
-       timer_config |= (CSR_TCFG_PERIOD | CSR_TCFG_EN);
+       timer_config = csr_read64(LOONGARCH_CSR_TCFG);
+       timer_config &= ~CSR_TCFG_EN;
        csr_write64(timer_config, LOONGARCH_CSR_TCFG);
 
        raw_spin_unlock(&state_lock);
@@ -90,11 +90,6 @@ static int constant_set_state_periodic(struct clock_event_device *evt)
        return 0;
 }
 
-static int constant_set_state_shutdown(struct clock_event_device *evt)
-{
-       return 0;
-}
-
 static int constant_timer_next_event(unsigned long delta, struct clock_event_device *evt)
 {
        unsigned long timer_config;
@@ -161,7 +156,7 @@ int constant_clockevent_init(void)
        cd->rating = 320;
        cd->cpumask = cpumask_of(cpu);
        cd->set_state_oneshot = constant_set_state_oneshot;
-       cd->set_state_oneshot_stopped = constant_set_state_oneshot_stopped;
+       cd->set_state_oneshot_stopped = constant_set_state_shutdown;
        cd->set_state_periodic = constant_set_state_periodic;
        cd->set_state_shutdown = constant_set_state_shutdown;
        cd->set_next_event = constant_timer_next_event;
index 71d0539e2d0b0207f901e3ef75679bc4e6bc2fa3..2aae72e638713a658475e6fb82fc73eae0fc3469 100644 (file)
@@ -13,13 +13,13 @@ struct page *dmw_virt_to_page(unsigned long kaddr)
 {
        return pfn_to_page(virt_to_pfn(kaddr));
 }
-EXPORT_SYMBOL_GPL(dmw_virt_to_page);
+EXPORT_SYMBOL(dmw_virt_to_page);
 
 struct page *tlb_virt_to_page(unsigned long kaddr)
 {
        return pfn_to_page(pte_pfn(*virt_to_kpte(kaddr)));
 }
-EXPORT_SYMBOL_GPL(tlb_virt_to_page);
+EXPORT_SYMBOL(tlb_virt_to_page);
 
 pgd_t *pgd_alloc(struct mm_struct *mm)
 {
index dc17896a001a9235d8cf21374f323917e46d1e97..c15eadbb998343cb74aad00c48145e6d602302ee 100644 (file)
@@ -228,7 +228,6 @@ typedef struct thread_struct thread_struct;
        execve_tail();                                                  \
 } while (0)
 
-/* Forward declaration, a strange C thing */
 struct task_struct;
 struct mm_struct;
 struct seq_file;
index cc364fce6aa96bb7deea8eed54694bb93419ecc2..ba75f6bee77423be0f9a54e0afdaa88cbb342728 100644 (file)
@@ -666,6 +666,7 @@ static int __init ipl_init(void)
                                                &ipl_ccw_attr_group_lpar);
                break;
        case IPL_TYPE_ECKD:
+       case IPL_TYPE_ECKD_DUMP:
                rc = sysfs_create_group(&ipl_kset->kobj, &ipl_eckd_attr_group);
                break;
        case IPL_TYPE_FCP:
index 77fd24e6cbb643bccb79777da90481c748f4feaf..39a91b00438a7f6ba48fb541d8f24b51070391d2 100644 (file)
@@ -279,12 +279,6 @@ static int paicrypt_event_init(struct perf_event *event)
        if (IS_ERR(cpump))
                return PTR_ERR(cpump);
 
-       /* Event initialization sets last_tag to 0. When later on the events
-        * are deleted and re-added, do not reset the event count value to zero.
-        * Events are added, deleted and re-added when 2 or more events
-        * are active at the same time.
-        */
-       event->hw.last_tag = 0;
        event->destroy = paicrypt_event_destroy;
 
        if (a->sample_period) {
@@ -318,6 +312,11 @@ static void paicrypt_start(struct perf_event *event, int flags)
 {
        u64 sum;
 
+       /* Event initialization sets last_tag to 0. When later on the events
+        * are deleted and re-added, do not reset the event count value to zero.
+        * Events are added, deleted and re-added when 2 or more events
+        * are active at the same time.
+        */
        if (!event->hw.last_tag) {
                event->hw.last_tag = 1;
                sum = paicrypt_getall(event);           /* Get current value */
index 8ba0f1a3a39dc0b7b4a2a2e300604a1b7968208c..e7013a2e8960508566083cfa9344e6daa60638fb 100644 (file)
@@ -260,7 +260,6 @@ static int paiext_event_init(struct perf_event *event)
        rc = paiext_alloc(a, event);
        if (rc)
                return rc;
-       event->hw.last_tag = 0;
        event->destroy = paiext_event_destroy;
 
        if (a->sample_period) {
index 21556ad87f4ba86a076c828b2a88daf76a02c038..8f3a4d16bb791f37ac924858668d37eb49446f91 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/io.h>
 #include <asm/apic.h>
 #include <asm/desc.h>
+#include <asm/e820/api.h>
 #include <asm/sev.h>
 #include <asm/ibt.h>
 #include <asm/hypervisor.h>
@@ -286,15 +287,31 @@ static int hv_cpu_die(unsigned int cpu)
 
 static int __init hv_pci_init(void)
 {
-       int gen2vm = efi_enabled(EFI_BOOT);
+       bool gen2vm = efi_enabled(EFI_BOOT);
 
        /*
-        * For Generation-2 VM, we exit from pci_arch_init() by returning 0.
-        * The purpose is to suppress the harmless warning:
+        * A Generation-2 VM doesn't support legacy PCI/PCIe, so both
+        * raw_pci_ops and raw_pci_ext_ops are NULL, and pci_subsys_init() ->
+        * pcibios_init() doesn't call pcibios_resource_survey() ->
+        * e820__reserve_resources_late(); as a result, any emulated persistent
+        * memory of E820_TYPE_PRAM (12) via the kernel parameter
+        * memmap=nn[KMG]!ss is not added into iomem_resource and hence can't be
+        * detected by register_e820_pmem(). Fix this by directly calling
+        * e820__reserve_resources_late() here: e820__reserve_resources_late()
+        * depends on e820__reserve_resources(), which has been called earlier
+        * from setup_arch(). Note: e820__reserve_resources_late() also adds
+        * any memory of E820_TYPE_PMEM (7) into iomem_resource, and
+        * acpi_nfit_register_region() -> acpi_nfit_insert_resource() ->
+        * region_intersects() returns REGION_INTERSECTS, so the memory of
+        * E820_TYPE_PMEM won't get added twice.
+        *
+        * We return 0 here so that pci_arch_init() won't print the warning:
         * "PCI: Fatal: No config space access function found"
         */
-       if (gen2vm)
+       if (gen2vm) {
+               e820__reserve_resources_late();
                return 0;
+       }
 
        /* For Generation-1 VM, we'll proceed in pci_arch_init().  */
        return 1;
index e6bba12c759cb793a2a3eb0ff367bb51a6b502f0..01fa06dd06b66c9324c670e4847c0d503dbd5691 100644 (file)
@@ -262,11 +262,14 @@ static uint32_t  __init ms_hyperv_platform(void)
 static int hv_nmi_unknown(unsigned int val, struct pt_regs *regs)
 {
        static atomic_t nmi_cpu = ATOMIC_INIT(-1);
+       unsigned int old_cpu, this_cpu;
 
        if (!unknown_nmi_panic)
                return NMI_DONE;
 
-       if (atomic_cmpxchg(&nmi_cpu, -1, raw_smp_processor_id()) != -1)
+       old_cpu = -1;
+       this_cpu = raw_smp_processor_id();
+       if (!atomic_try_cmpxchg(&nmi_cpu, &old_cpu, this_cpu))
                return NMI_HANDLED;
 
        return NMI_DONE;
index e4cfb7adb64581d0630d61dc0f5a287245da7d38..750aec178b6abfb08472e68bf8558c786d8ab64b 100644 (file)
@@ -425,6 +425,8 @@ void bdev_set_nr_sectors(struct block_device *bdev, sector_t sectors)
 
 void bdev_add(struct block_device *bdev, dev_t dev)
 {
+       if (bdev_stable_writes(bdev))
+               mapping_set_stable_writes(bdev->bd_inode->i_mapping);
        bdev->bd_dev = dev;
        bdev->bd_inode->i_rdev = dev;
        bdev->bd_inode->i_ino = dev;
index 4a42ea2972ad85693480c5e9c0e9599923c73ccf..4b48c2c44098131328447f80172269657e64c2d0 100644 (file)
@@ -577,6 +577,7 @@ static void blkg_destroy_all(struct gendisk *disk)
        struct request_queue *q = disk->queue;
        struct blkcg_gq *blkg, *n;
        int count = BLKG_DESTROY_BATCH_SIZE;
+       int i;
 
 restart:
        spin_lock_irq(&q->queue_lock);
@@ -602,6 +603,18 @@ restart:
                }
        }
 
+       /*
+        * Mark policy deactivated since policy offline has been done, and
+        * the free is scheduled, so future blkcg_deactivate_policy() can
+        * be bypassed
+        */
+       for (i = 0; i < BLKCG_MAX_POLS; i++) {
+               struct blkcg_policy *pol = blkcg_policy[i];
+
+               if (pol)
+                       __clear_bit(pol->plid, q->blkcg_pols);
+       }
+
        q->root_blkg = NULL;
        spin_unlock_irq(&q->queue_lock);
 }
index 624c03c8fe64e37f4ff742b27a1d1fa2d2588c39..fd482439afbc9aa810471db434217dcb5e06c296 100644 (file)
@@ -249,8 +249,6 @@ static inline struct blkcg_gq *blkg_lookup(struct blkcg *blkcg,
 {
        struct blkcg_gq *blkg;
 
-       WARN_ON_ONCE(!rcu_read_lock_held());
-
        if (blkcg == &blkcg_root)
                return q->root_blkg;
 
index 6b72b2e03fc8a877fcf7dc412762cf6db42a382f..42e8420747153b840317ec01c6020384449d3c3f 100644 (file)
@@ -163,38 +163,15 @@ EXPORT_SYMBOL(blk_pre_runtime_resume);
  * @q: the queue of the device
  *
  * Description:
- *    For historical reasons, this routine merely calls blk_set_runtime_active()
- *    to do the real work of restarting the queue.  It does this regardless of
- *    whether the device's runtime-resume succeeded; even if it failed the
+ *    Restart the queue of a runtime suspended device. It does this regardless
+ *    of whether the device's runtime-resume succeeded; even if it failed the
  *    driver or error handler will need to communicate with the device.
  *
  *    This function should be called near the end of the device's
- *    runtime_resume callback.
+ *    runtime_resume callback to correct queue runtime PM status and re-enable
+ *    peeking requests from the queue.
  */
 void blk_post_runtime_resume(struct request_queue *q)
-{
-       blk_set_runtime_active(q);
-}
-EXPORT_SYMBOL(blk_post_runtime_resume);
-
-/**
- * blk_set_runtime_active - Force runtime status of the queue to be active
- * @q: the queue of the device
- *
- * If the device is left runtime suspended during system suspend the resume
- * hook typically resumes the device and corrects runtime status
- * accordingly. However, that does not affect the queue runtime PM status
- * which is still "suspended". This prevents processing requests from the
- * queue.
- *
- * This function can be used in driver's resume hook to correct queue
- * runtime PM status and re-enable peeking requests from the queue. It
- * should be called before first request is added to the queue.
- *
- * This function is also called by blk_post_runtime_resume() for
- * runtime resumes.  It does everything necessary to restart the queue.
- */
-void blk_set_runtime_active(struct request_queue *q)
 {
        int old_status;
 
@@ -211,4 +188,4 @@ void blk_set_runtime_active(struct request_queue *q)
        if (old_status != RPM_ACTIVE)
                blk_clear_pm_only(q);
 }
-EXPORT_SYMBOL(blk_set_runtime_active);
+EXPORT_SYMBOL(blk_post_runtime_resume);
index 13e4377a8b2865f527019830074e0febbd7a766e..16f5766620a41043645756c51d441f4488af9edf 100644 (file)
@@ -1320,6 +1320,7 @@ static void tg_conf_updated(struct throtl_grp *tg, bool global)
                   tg_bps_limit(tg, READ), tg_bps_limit(tg, WRITE),
                   tg_iops_limit(tg, READ), tg_iops_limit(tg, WRITE));
 
+       rcu_read_lock();
        /*
         * Update has_rules[] flags for the updated tg's subtree.  A tg is
         * considered to have rules if either the tg itself or any of its
@@ -1347,6 +1348,7 @@ static void tg_conf_updated(struct throtl_grp *tg, bool global)
                this_tg->latency_target = max(this_tg->latency_target,
                                parent_tg->latency_target);
        }
+       rcu_read_unlock();
 
        /*
         * We're already holding queue_lock and know @tg is valid.  Let's
index 5c0246b9e52287ff9aae57efe93480d774d49b49..4ccf1994b97adbf8e8f9add7e3ff67d3bb5b3567 100644 (file)
@@ -502,6 +502,16 @@ static int ivpu_boot_pwr_domain_enable(struct ivpu_device *vdev)
        return ret;
 }
 
+static int ivpu_boot_pwr_domain_disable(struct ivpu_device *vdev)
+{
+       ivpu_boot_dpu_active_drive(vdev, false);
+       ivpu_boot_pwr_island_isolation_drive(vdev, true);
+       ivpu_boot_pwr_island_trickle_drive(vdev, false);
+       ivpu_boot_pwr_island_drive(vdev, false);
+
+       return ivpu_boot_wait_for_pwr_island_status(vdev, 0x0);
+}
+
 static void ivpu_boot_no_snoop_enable(struct ivpu_device *vdev)
 {
        u32 val = REGV_RD32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES);
@@ -600,25 +610,17 @@ static int ivpu_hw_37xx_info_init(struct ivpu_device *vdev)
 
 static int ivpu_hw_37xx_reset(struct ivpu_device *vdev)
 {
-       int ret;
-       u32 val;
-
-       if (IVPU_WA(punit_disabled))
-               return 0;
+       int ret = 0;
 
-       ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US);
-       if (ret) {
-               ivpu_err(vdev, "Timed out waiting for TRIGGER bit\n");
-               return ret;
+       if (ivpu_boot_pwr_domain_disable(vdev)) {
+               ivpu_err(vdev, "Failed to disable power domain\n");
+               ret = -EIO;
        }
 
-       val = REGB_RD32(VPU_37XX_BUTTRESS_VPU_IP_RESET);
-       val = REG_SET_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, val);
-       REGB_WR32(VPU_37XX_BUTTRESS_VPU_IP_RESET, val);
-
-       ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US);
-       if (ret)
-               ivpu_err(vdev, "Timed out waiting for RESET completion\n");
+       if (ivpu_pll_disable(vdev)) {
+               ivpu_err(vdev, "Failed to disable PLL\n");
+               ret = -EIO;
+       }
 
        return ret;
 }
@@ -651,10 +653,6 @@ static int ivpu_hw_37xx_power_up(struct ivpu_device *vdev)
 {
        int ret;
 
-       ret = ivpu_hw_37xx_reset(vdev);
-       if (ret)
-               ivpu_warn(vdev, "Failed to reset HW: %d\n", ret);
-
        ret = ivpu_hw_37xx_d0i3_disable(vdev);
        if (ret)
                ivpu_warn(vdev, "Failed to disable D0I3: %d\n", ret);
@@ -722,11 +720,11 @@ static int ivpu_hw_37xx_power_down(struct ivpu_device *vdev)
 {
        int ret = 0;
 
-       if (!ivpu_hw_37xx_is_idle(vdev) && ivpu_hw_37xx_reset(vdev))
-               ivpu_err(vdev, "Failed to reset the VPU\n");
+       if (!ivpu_hw_37xx_is_idle(vdev))
+               ivpu_warn(vdev, "VPU not idle during power down\n");
 
-       if (ivpu_pll_disable(vdev)) {
-               ivpu_err(vdev, "Failed to disable PLL\n");
+       if (ivpu_hw_37xx_reset(vdev)) {
+               ivpu_err(vdev, "Failed to reset VPU\n");
                ret = -EIO;
        }
 
index 0b7a01f38b65cc15bd2f60535286f362564ba4fd..d321ca7160d978c68ce8ea337b838ccf2b281b76 100644 (file)
@@ -2031,7 +2031,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
         * HP ZBook Fury 16 G10 requires ACPI video's child devices have _PS0
         * evaluated to have functional panel brightness control.
         */
-       acpi_device_fix_up_power_extended(device);
+       acpi_device_fix_up_power_children(device);
 
        pr_info("%s [%s] (multi-head: %s  rom: %s  post: %s)\n",
               ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
index f007116a8427628526ea001f5ee5fd4ec73e09fb..3b4d048c49417303bf5c4451e94e6d9f3dd77e56 100644 (file)
@@ -397,6 +397,19 @@ void acpi_device_fix_up_power_extended(struct acpi_device *adev)
 }
 EXPORT_SYMBOL_GPL(acpi_device_fix_up_power_extended);
 
+/**
+ * acpi_device_fix_up_power_children - Force a device's children into D0.
+ * @adev: Parent device object whose children's power state is to be fixed up.
+ *
+ * Call acpi_device_fix_up_power() for @adev's children so long as they
+ * are reported as present and enabled.
+ */
+void acpi_device_fix_up_power_children(struct acpi_device *adev)
+{
+       acpi_dev_for_each_child(adev, fix_up_power_if_applicable, NULL);
+}
+EXPORT_SYMBOL_GPL(acpi_device_fix_up_power_children);
+
 int acpi_device_update_power(struct acpi_device *device, int *state_p)
 {
        int state;
index 3a34a8c425fe4a673119d5ac7d9fef87ed145f38..55437f5e0c3aee4bf8e404b2e3b0977238401eb0 100644 (file)
@@ -592,7 +592,7 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
        while (1) {
 
                if (cx->entry_method == ACPI_CSTATE_HALT)
-                       safe_halt();
+                       raw_safe_halt();
                else if (cx->entry_method == ACPI_CSTATE_SYSTEMIO) {
                        io_idle(cx->address);
                } else
index 15a3bdbd0755d45045d4224fcbbe9ab15dae2fa0..9bd9f79cd40990fee75134397500d123816062bd 100644 (file)
@@ -447,6 +447,13 @@ static const struct dmi_system_id irq1_level_low_skip_override[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "B1402CBA"),
                },
        },
+       {
+               /* Asus ExpertBook B1402CVA */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_BOARD_NAME, "B1402CVA"),
+               },
+       },
        {
                /* Asus ExpertBook B1502CBA */
                .matches = {
index 25a63d043c8e1f442001304b5aef2606f0c7ac17..0f77e042406619577335ffbfbf6d7075988234ea 100644 (file)
@@ -82,6 +82,9 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
        if (pnp_port_valid(idev, 1)) {
                ctl_addr = devm_ioport_map(&idev->dev,
                                           pnp_port_start(idev, 1), 1);
+               if (!ctl_addr)
+                       return -ENOMEM;
+
                ap->ioaddr.altstatus_addr = ctl_addr;
                ap->ioaddr.ctl_addr = ctl_addr;
                ap->ops = &isapnp_port_ops;
index 855fdf5c3b4eaae1b8b462fc4ebfb8a4cbb2e7c3..b6414e1e645b763f619dfcf976aefcf3851d03c8 100644 (file)
@@ -67,6 +67,7 @@ struct nbd_sock {
 struct recv_thread_args {
        struct work_struct work;
        struct nbd_device *nbd;
+       struct nbd_sock *nsock;
        int index;
 };
 
@@ -395,6 +396,22 @@ static u32 req_to_nbd_cmd_type(struct request *req)
        }
 }
 
+static struct nbd_config *nbd_get_config_unlocked(struct nbd_device *nbd)
+{
+       if (refcount_inc_not_zero(&nbd->config_refs)) {
+               /*
+                * Add smp_mb__after_atomic to ensure that reading nbd->config_refs
+                * and reading nbd->config is ordered. The pair is the barrier in
+                * nbd_alloc_and_init_config(), avoid nbd->config_refs is set
+                * before nbd->config.
+                */
+               smp_mb__after_atomic();
+               return nbd->config;
+       }
+
+       return NULL;
+}
+
 static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req)
 {
        struct nbd_cmd *cmd = blk_mq_rq_to_pdu(req);
@@ -409,13 +426,13 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req)
                return BLK_EH_DONE;
        }
 
-       if (!refcount_inc_not_zero(&nbd->config_refs)) {
+       config = nbd_get_config_unlocked(nbd);
+       if (!config) {
                cmd->status = BLK_STS_TIMEOUT;
                __clear_bit(NBD_CMD_INFLIGHT, &cmd->flags);
                mutex_unlock(&cmd->lock);
                goto done;
        }
-       config = nbd->config;
 
        if (config->num_connections > 1 ||
            (config->num_connections == 1 && nbd->tag_set.timeout)) {
@@ -489,15 +506,9 @@ done:
        return BLK_EH_DONE;
 }
 
-/*
- *  Send or receive packet. Return a positive value on success and
- *  negtive value on failue, and never return 0.
- */
-static int sock_xmit(struct nbd_device *nbd, int index, int send,
-                    struct iov_iter *iter, int msg_flags, int *sent)
+static int __sock_xmit(struct nbd_device *nbd, struct socket *sock, int send,
+                      struct iov_iter *iter, int msg_flags, int *sent)
 {
-       struct nbd_config *config = nbd->config;
-       struct socket *sock = config->socks[index]->sock;
        int result;
        struct msghdr msg;
        unsigned int noreclaim_flag;
@@ -540,6 +551,19 @@ static int sock_xmit(struct nbd_device *nbd, int index, int send,
        return result;
 }
 
+/*
+ *  Send or receive packet. Return a positive value on success and
+ *  negtive value on failure, and never return 0.
+ */
+static int sock_xmit(struct nbd_device *nbd, int index, int send,
+                    struct iov_iter *iter, int msg_flags, int *sent)
+{
+       struct nbd_config *config = nbd->config;
+       struct socket *sock = config->socks[index]->sock;
+
+       return __sock_xmit(nbd, sock, send, iter, msg_flags, sent);
+}
+
 /*
  * Different settings for sk->sk_sndtimeo can result in different return values
  * if there is a signal pending when we enter sendmsg, because reasons?
@@ -696,7 +720,7 @@ out:
        return 0;
 }
 
-static int nbd_read_reply(struct nbd_device *nbd, int index,
+static int nbd_read_reply(struct nbd_device *nbd, struct socket *sock,
                          struct nbd_reply *reply)
 {
        struct kvec iov = {.iov_base = reply, .iov_len = sizeof(*reply)};
@@ -705,7 +729,7 @@ static int nbd_read_reply(struct nbd_device *nbd, int index,
 
        reply->magic = 0;
        iov_iter_kvec(&to, ITER_DEST, &iov, 1, sizeof(*reply));
-       result = sock_xmit(nbd, index, 0, &to, MSG_WAITALL, NULL);
+       result = __sock_xmit(nbd, sock, 0, &to, MSG_WAITALL, NULL);
        if (result < 0) {
                if (!nbd_disconnected(nbd->config))
                        dev_err(disk_to_dev(nbd->disk),
@@ -829,14 +853,14 @@ static void recv_work(struct work_struct *work)
        struct nbd_device *nbd = args->nbd;
        struct nbd_config *config = nbd->config;
        struct request_queue *q = nbd->disk->queue;
-       struct nbd_sock *nsock;
+       struct nbd_sock *nsock = args->nsock;
        struct nbd_cmd *cmd;
        struct request *rq;
 
        while (1) {
                struct nbd_reply reply;
 
-               if (nbd_read_reply(nbd, args->index, &reply))
+               if (nbd_read_reply(nbd, nsock->sock, &reply))
                        break;
 
                /*
@@ -871,7 +895,6 @@ static void recv_work(struct work_struct *work)
                percpu_ref_put(&q->q_usage_counter);
        }
 
-       nsock = config->socks[args->index];
        mutex_lock(&nsock->tx_lock);
        nbd_mark_nsock_dead(nbd, nsock, 1);
        mutex_unlock(&nsock->tx_lock);
@@ -977,12 +1000,12 @@ static int nbd_handle_cmd(struct nbd_cmd *cmd, int index)
        struct nbd_sock *nsock;
        int ret;
 
-       if (!refcount_inc_not_zero(&nbd->config_refs)) {
+       config = nbd_get_config_unlocked(nbd);
+       if (!config) {
                dev_err_ratelimited(disk_to_dev(nbd->disk),
                                    "Socks array is empty\n");
                return -EINVAL;
        }
-       config = nbd->config;
 
        if (index >= config->num_connections) {
                dev_err_ratelimited(disk_to_dev(nbd->disk),
@@ -1215,6 +1238,7 @@ static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg)
                INIT_WORK(&args->work, recv_work);
                args->index = i;
                args->nbd = nbd;
+               args->nsock = nsock;
                nsock->cookie++;
                mutex_unlock(&nsock->tx_lock);
                sockfd_put(old);
@@ -1397,6 +1421,7 @@ static int nbd_start_device(struct nbd_device *nbd)
                refcount_inc(&nbd->config_refs);
                INIT_WORK(&args->work, recv_work);
                args->nbd = nbd;
+               args->nsock = config->socks[i];
                args->index = i;
                queue_work(nbd->recv_workq, &args->work);
        }
@@ -1530,17 +1555,20 @@ static int nbd_ioctl(struct block_device *bdev, blk_mode_t mode,
        return error;
 }
 
-static struct nbd_config *nbd_alloc_config(void)
+static int nbd_alloc_and_init_config(struct nbd_device *nbd)
 {
        struct nbd_config *config;
 
+       if (WARN_ON(nbd->config))
+               return -EINVAL;
+
        if (!try_module_get(THIS_MODULE))
-               return ERR_PTR(-ENODEV);
+               return -ENODEV;
 
        config = kzalloc(sizeof(struct nbd_config), GFP_NOFS);
        if (!config) {
                module_put(THIS_MODULE);
-               return ERR_PTR(-ENOMEM);
+               return -ENOMEM;
        }
 
        atomic_set(&config->recv_threads, 0);
@@ -1548,12 +1576,24 @@ static struct nbd_config *nbd_alloc_config(void)
        init_waitqueue_head(&config->conn_wait);
        config->blksize_bits = NBD_DEF_BLKSIZE_BITS;
        atomic_set(&config->live_connections, 0);
-       return config;
+
+       nbd->config = config;
+       /*
+        * Order refcount_set(&nbd->config_refs, 1) and nbd->config assignment,
+        * its pair is the barrier in nbd_get_config_unlocked().
+        * So nbd_get_config_unlocked() won't see nbd->config as null after
+        * refcount_inc_not_zero() succeed.
+        */
+       smp_mb__before_atomic();
+       refcount_set(&nbd->config_refs, 1);
+
+       return 0;
 }
 
 static int nbd_open(struct gendisk *disk, blk_mode_t mode)
 {
        struct nbd_device *nbd;
+       struct nbd_config *config;
        int ret = 0;
 
        mutex_lock(&nbd_index_mutex);
@@ -1566,27 +1606,25 @@ static int nbd_open(struct gendisk *disk, blk_mode_t mode)
                ret = -ENXIO;
                goto out;
        }
-       if (!refcount_inc_not_zero(&nbd->config_refs)) {
-               struct nbd_config *config;
 
+       config = nbd_get_config_unlocked(nbd);
+       if (!config) {
                mutex_lock(&nbd->config_lock);
                if (refcount_inc_not_zero(&nbd->config_refs)) {
                        mutex_unlock(&nbd->config_lock);
                        goto out;
                }
-               config = nbd_alloc_config();
-               if (IS_ERR(config)) {
-                       ret = PTR_ERR(config);
+               ret = nbd_alloc_and_init_config(nbd);
+               if (ret) {
                        mutex_unlock(&nbd->config_lock);
                        goto out;
                }
-               nbd->config = config;
-               refcount_set(&nbd->config_refs, 1);
+
                refcount_inc(&nbd->refs);
                mutex_unlock(&nbd->config_lock);
                if (max_part)
                        set_bit(GD_NEED_PART_SCAN, &disk->state);
-       } else if (nbd_disconnected(nbd->config)) {
+       } else if (nbd_disconnected(config)) {
                if (max_part)
                        set_bit(GD_NEED_PART_SCAN, &disk->state);
        }
@@ -1990,22 +2028,17 @@ again:
                pr_err("nbd%d already in use\n", index);
                return -EBUSY;
        }
-       if (WARN_ON(nbd->config)) {
-               mutex_unlock(&nbd->config_lock);
-               nbd_put(nbd);
-               return -EINVAL;
-       }
-       config = nbd_alloc_config();
-       if (IS_ERR(config)) {
+
+       ret = nbd_alloc_and_init_config(nbd);
+       if (ret) {
                mutex_unlock(&nbd->config_lock);
                nbd_put(nbd);
                pr_err("couldn't allocate config\n");
-               return PTR_ERR(config);
+               return ret;
        }
-       nbd->config = config;
-       refcount_set(&nbd->config_refs, 1);
-       set_bit(NBD_RT_BOUND, &config->runtime_flags);
 
+       config = nbd->config;
+       set_bit(NBD_RT_BOUND, &config->runtime_flags);
        ret = nbd_genl_size_set(info, nbd);
        if (ret)
                goto out;
@@ -2208,7 +2241,8 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
        }
        mutex_unlock(&nbd_index_mutex);
 
-       if (!refcount_inc_not_zero(&nbd->config_refs)) {
+       config = nbd_get_config_unlocked(nbd);
+       if (!config) {
                dev_err(nbd_to_dev(nbd),
                        "not configured, cannot reconfigure\n");
                nbd_put(nbd);
@@ -2216,7 +2250,6 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
        }
 
        mutex_lock(&nbd->config_lock);
-       config = nbd->config;
        if (!test_bit(NBD_RT_BOUND, &config->runtime_flags) ||
            !nbd->pid) {
                dev_err(nbd_to_dev(nbd),
index 22a3cf7f32e2335d87710dfa32f0c286ae1768aa..3021d58ca51c1ff4dc223446b3bd9a3fb0b685f9 100644 (file)
@@ -1464,19 +1464,13 @@ blk_status_t null_process_cmd(struct nullb_cmd *cmd, enum req_op op,
        return BLK_STS_OK;
 }
 
-static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector,
-                                   sector_t nr_sectors, enum req_op op)
+static void null_handle_cmd(struct nullb_cmd *cmd, sector_t sector,
+                           sector_t nr_sectors, enum req_op op)
 {
        struct nullb_device *dev = cmd->nq->dev;
        struct nullb *nullb = dev->nullb;
        blk_status_t sts;
 
-       if (test_bit(NULLB_DEV_FL_THROTTLED, &dev->flags)) {
-               sts = null_handle_throttled(cmd);
-               if (sts != BLK_STS_OK)
-                       return sts;
-       }
-
        if (op == REQ_OP_FLUSH) {
                cmd->error = errno_to_blk_status(null_handle_flush(nullb));
                goto out;
@@ -1493,7 +1487,6 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector,
 
 out:
        nullb_complete_cmd(cmd);
-       return BLK_STS_OK;
 }
 
 static enum hrtimer_restart nullb_bwtimer_fn(struct hrtimer *timer)
@@ -1724,8 +1717,6 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx,
        cmd->fake_timeout = should_timeout_request(rq) ||
                blk_should_fake_timeout(rq->q);
 
-       blk_mq_start_request(rq);
-
        if (should_requeue_request(rq)) {
                /*
                 * Alternate between hitting the core BUSY path, and the
@@ -1738,6 +1729,15 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx,
                return BLK_STS_OK;
        }
 
+       if (test_bit(NULLB_DEV_FL_THROTTLED, &nq->dev->flags)) {
+               blk_status_t sts = null_handle_throttled(cmd);
+
+               if (sts != BLK_STS_OK)
+                       return sts;
+       }
+
+       blk_mq_start_request(rq);
+
        if (is_poll) {
                spin_lock(&nq->poll_lock);
                list_add_tail(&rq->queuelist, &nq->poll_list);
@@ -1747,7 +1747,8 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx,
        if (cmd->fake_timeout)
                return BLK_STS_OK;
 
-       return null_handle_cmd(cmd, sector, nr_sectors, req_op(rq));
+       null_handle_cmd(cmd, sector, nr_sectors, req_op(rq));
+       return BLK_STS_OK;
 }
 
 static void null_queue_rqs(struct request **rqlist)
index a6dc3997bf5c50cfbe4dd23d0836ed0f29b00fbd..442a0ebeb953e983d053d4c70d919e3a8aee213e 100644 (file)
@@ -1093,9 +1093,10 @@ int dpll_nl_pin_id_get_doit(struct sk_buff *skb, struct genl_info *info)
                return -ENOMEM;
        hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
                                DPLL_CMD_PIN_ID_GET);
-       if (!hdr)
+       if (!hdr) {
+               nlmsg_free(msg);
                return -EMSGSIZE;
-
+       }
        pin = dpll_pin_find_from_nlattr(info);
        if (!IS_ERR(pin)) {
                ret = dpll_msg_add_pin_handle(msg, pin);
@@ -1123,8 +1124,10 @@ int dpll_nl_pin_get_doit(struct sk_buff *skb, struct genl_info *info)
                return -ENOMEM;
        hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
                                DPLL_CMD_PIN_GET);
-       if (!hdr)
+       if (!hdr) {
+               nlmsg_free(msg);
                return -EMSGSIZE;
+       }
        ret = dpll_cmd_pin_get_one(msg, pin, info->extack);
        if (ret) {
                nlmsg_free(msg);
@@ -1256,8 +1259,10 @@ int dpll_nl_device_id_get_doit(struct sk_buff *skb, struct genl_info *info)
                return -ENOMEM;
        hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
                                DPLL_CMD_DEVICE_ID_GET);
-       if (!hdr)
+       if (!hdr) {
+               nlmsg_free(msg);
                return -EMSGSIZE;
+       }
 
        dpll = dpll_device_find_from_nlattr(info);
        if (!IS_ERR(dpll)) {
@@ -1284,8 +1289,10 @@ int dpll_nl_device_get_doit(struct sk_buff *skb, struct genl_info *info)
                return -ENOMEM;
        hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
                                DPLL_CMD_DEVICE_GET);
-       if (!hdr)
+       if (!hdr) {
+               nlmsg_free(msg);
                return -EMSGSIZE;
+       }
 
        ret = dpll_device_get_one(dpll, msg, info->extack);
        if (ret) {
index 2aee32344f4a2554fb8ba491f0734656ccfc187d..772f3b049c1694408d7acc89f4235a1c8c657ea9 100644 (file)
@@ -174,6 +174,17 @@ to_ast_sil164_connector(struct drm_connector *connector)
        return container_of(connector, struct ast_sil164_connector, base);
 }
 
+struct ast_bmc_connector {
+       struct drm_connector base;
+       struct drm_connector *physical_connector;
+};
+
+static inline struct ast_bmc_connector *
+to_ast_bmc_connector(struct drm_connector *connector)
+{
+       return container_of(connector, struct ast_bmc_connector, base);
+}
+
 /*
  * Device
  */
@@ -218,7 +229,7 @@ struct ast_device {
                } astdp;
                struct {
                        struct drm_encoder encoder;
-                       struct drm_connector connector;
+                       struct ast_bmc_connector bmc_connector;
                } bmc;
        } output;
 
index cb96149842851aa6fa66506e542a34f85c64d638..c20534d0ef7c8af580e4e6a3eb2c4c2bd49842eb 100644 (file)
@@ -1767,6 +1767,30 @@ static const struct drm_encoder_funcs ast_bmc_encoder_funcs = {
        .destroy = drm_encoder_cleanup,
 };
 
+static int ast_bmc_connector_helper_detect_ctx(struct drm_connector *connector,
+                                              struct drm_modeset_acquire_ctx *ctx,
+                                              bool force)
+{
+       struct ast_bmc_connector *bmc_connector = to_ast_bmc_connector(connector);
+       struct drm_connector *physical_connector = bmc_connector->physical_connector;
+
+       /*
+        * Most user-space compositors cannot handle more than one connected
+        * connector per CRTC. Hence, we only mark the BMC as connected if the
+        * physical connector is disconnected. If the physical connector's status
+        * is connected or unknown, the BMC remains disconnected. This has no
+        * effect on the output of the BMC.
+        *
+        * FIXME: Remove this logic once user-space compositors can handle more
+        *        than one connector per CRTC. The BMC should always be connected.
+        */
+
+       if (physical_connector && physical_connector->status == connector_status_disconnected)
+               return connector_status_connected;
+
+       return connector_status_disconnected;
+}
+
 static int ast_bmc_connector_helper_get_modes(struct drm_connector *connector)
 {
        return drm_add_modes_noedid(connector, 4096, 4096);
@@ -1774,6 +1798,7 @@ static int ast_bmc_connector_helper_get_modes(struct drm_connector *connector)
 
 static const struct drm_connector_helper_funcs ast_bmc_connector_helper_funcs = {
        .get_modes = ast_bmc_connector_helper_get_modes,
+       .detect_ctx = ast_bmc_connector_helper_detect_ctx,
 };
 
 static const struct drm_connector_funcs ast_bmc_connector_funcs = {
@@ -1784,12 +1809,33 @@ static const struct drm_connector_funcs ast_bmc_connector_funcs = {
        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
-static int ast_bmc_output_init(struct ast_device *ast)
+static int ast_bmc_connector_init(struct drm_device *dev,
+                                 struct ast_bmc_connector *bmc_connector,
+                                 struct drm_connector *physical_connector)
+{
+       struct drm_connector *connector = &bmc_connector->base;
+       int ret;
+
+       ret = drm_connector_init(dev, connector, &ast_bmc_connector_funcs,
+                                DRM_MODE_CONNECTOR_VIRTUAL);
+       if (ret)
+               return ret;
+
+       drm_connector_helper_add(connector, &ast_bmc_connector_helper_funcs);
+
+       bmc_connector->physical_connector = physical_connector;
+
+       return 0;
+}
+
+static int ast_bmc_output_init(struct ast_device *ast,
+                              struct drm_connector *physical_connector)
 {
        struct drm_device *dev = &ast->base;
        struct drm_crtc *crtc = &ast->crtc;
        struct drm_encoder *encoder = &ast->output.bmc.encoder;
-       struct drm_connector *connector = &ast->output.bmc.connector;
+       struct ast_bmc_connector *bmc_connector = &ast->output.bmc.bmc_connector;
+       struct drm_connector *connector = &bmc_connector->base;
        int ret;
 
        ret = drm_encoder_init(dev, encoder,
@@ -1799,13 +1845,10 @@ static int ast_bmc_output_init(struct ast_device *ast)
                return ret;
        encoder->possible_crtcs = drm_crtc_mask(crtc);
 
-       ret = drm_connector_init(dev, connector, &ast_bmc_connector_funcs,
-                                DRM_MODE_CONNECTOR_VIRTUAL);
+       ret = ast_bmc_connector_init(dev, bmc_connector, physical_connector);
        if (ret)
                return ret;
 
-       drm_connector_helper_add(connector, &ast_bmc_connector_helper_funcs);
-
        ret = drm_connector_attach_encoder(connector, encoder);
        if (ret)
                return ret;
@@ -1864,6 +1907,7 @@ static const struct drm_mode_config_funcs ast_mode_config_funcs = {
 int ast_mode_config_init(struct ast_device *ast)
 {
        struct drm_device *dev = &ast->base;
+       struct drm_connector *physical_connector = NULL;
        int ret;
 
        ret = drmm_mode_config_init(dev);
@@ -1904,23 +1948,27 @@ int ast_mode_config_init(struct ast_device *ast)
                ret = ast_vga_output_init(ast);
                if (ret)
                        return ret;
+               physical_connector = &ast->output.vga.vga_connector.base;
        }
        if (ast->tx_chip_types & AST_TX_SIL164_BIT) {
                ret = ast_sil164_output_init(ast);
                if (ret)
                        return ret;
+               physical_connector = &ast->output.sil164.sil164_connector.base;
        }
        if (ast->tx_chip_types & AST_TX_DP501_BIT) {
                ret = ast_dp501_output_init(ast);
                if (ret)
                        return ret;
+               physical_connector = &ast->output.dp501.connector;
        }
        if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
                ret = ast_astdp_output_init(ast);
                if (ret)
                        return ret;
+               physical_connector = &ast->output.astdp.connector;
        }
-       ret = ast_bmc_output_init(ast);
+       ret = ast_bmc_output_init(ast, physical_connector);
        if (ret)
                return ret;
 
index 7b4628f4f124040eae309b7367d2f26c59933e53..851b312bd84494cca9e074bb5f3fb2dcf49472bf 100644 (file)
@@ -1161,6 +1161,14 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
        intel_connector->port = port;
        drm_dp_mst_get_port_malloc(port);
 
+       /*
+        * TODO: set the AUX for the actual MST port decompressing the stream.
+        * At the moment the driver only supports enabling this globally in the
+        * first downstream MST branch, via intel_dp's (root port) AUX.
+        */
+       intel_connector->dp.dsc_decompression_aux = &intel_dp->aux;
+       intel_dp_mst_read_decompression_port_dsc_caps(intel_dp, intel_connector);
+
        connector = &intel_connector->base;
        ret = drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs,
                                 DRM_MODE_CONNECTOR_DisplayPort);
@@ -1172,14 +1180,6 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
 
        drm_connector_helper_add(connector, &intel_dp_mst_connector_helper_funcs);
 
-       /*
-        * TODO: set the AUX for the actual MST port decompressing the stream.
-        * At the moment the driver only supports enabling this globally in the
-        * first downstream MST branch, via intel_dp's (root port) AUX.
-        */
-       intel_connector->dp.dsc_decompression_aux = &intel_dp->aux;
-       intel_dp_mst_read_decompression_port_dsc_caps(intel_dp, intel_connector);
-
        for_each_pipe(dev_priv, pipe) {
                struct drm_encoder *enc =
                        &intel_dp->mst_encoders[pipe]->base.base;
index ed32bf5b15464e63efceedc7752e851dea8ad212..ba1186fc524f84c9d5d0c8a1481b6d0bf301607c 100644 (file)
@@ -982,8 +982,6 @@ int intel_gt_probe_all(struct drm_i915_private *i915)
 
 err:
        i915_probe_error(i915, "Failed to initialize %s! (%d)\n", gtdef->name, ret);
-       intel_gt_release_all(i915);
-
        return ret;
 }
 
@@ -1002,15 +1000,6 @@ int intel_gt_tiles_init(struct drm_i915_private *i915)
        return 0;
 }
 
-void intel_gt_release_all(struct drm_i915_private *i915)
-{
-       struct intel_gt *gt;
-       unsigned int id;
-
-       for_each_gt(gt, i915, id)
-               i915->gt[id] = NULL;
-}
-
 void intel_gt_info_print(const struct intel_gt_info *info,
                         struct drm_printer *p)
 {
index 8a0e2c745e1f9e40051cf0313134f5aa58a78f07..802de2c6decb7b0e78f206ac4edb20c7e6c58941 100644 (file)
@@ -782,7 +782,7 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        ret = i915_driver_mmio_probe(i915);
        if (ret < 0)
-               goto out_tiles_cleanup;
+               goto out_runtime_pm_put;
 
        ret = i915_driver_hw_probe(i915);
        if (ret < 0)
@@ -842,8 +842,6 @@ out_cleanup_hw:
        i915_ggtt_driver_late_release(i915);
 out_cleanup_mmio:
        i915_driver_mmio_release(i915);
-out_tiles_cleanup:
-       intel_gt_release_all(i915);
 out_runtime_pm_put:
        enable_rpm_wakeref_asserts(&i915->runtime_pm);
        i915_driver_late_release(i915);
index 1ccd1edd693c54748a6c474fedbe064e8e33907a..4c0528794e7a7ef7eb05f69ebce8a94db64ce863 100644 (file)
@@ -406,6 +406,7 @@ static const struct dpu_perf_cfg sc8280xp_perf_data = {
        .min_llcc_ib = 0,
        .min_dram_ib = 800000,
        .danger_lut_tbl = {0xf, 0xffff, 0x0},
+       .safe_lut_tbl = {0xfe00, 0xfe00, 0xffff},
        .qos_lut_tbl = {
                {.nentry = ARRAY_SIZE(sc8180x_qos_linear),
                .entries = sc8180x_qos_linear
index 11d9fc2c6bf5e07845a43e40035d0b39f9810350..ec933d597e20cfc1eed66439f69a2297f46f1b9a 100644 (file)
@@ -844,8 +844,7 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev)
 
        return 0;
 fail:
-       if (mdp5_kms)
-               mdp5_destroy(mdp5_kms);
+       mdp5_destroy(mdp5_kms);
        return ret;
 }
 
index e329e03e068d527339fb31ca3cc8dbcd4e2bd83a..1b88fb52726f244b28a95c6c8133bb0a864cc3a9 100644 (file)
@@ -365,9 +365,11 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp,
        /* reset video pattern flag on disconnect */
        if (!hpd) {
                dp->panel->video_test = false;
-               drm_dp_set_subconnector_property(dp->dp_display.connector,
-                                                connector_status_disconnected,
-                                                dp->panel->dpcd, dp->panel->downstream_ports);
+               if (!dp->dp_display.is_edp)
+                       drm_dp_set_subconnector_property(dp->dp_display.connector,
+                                                        connector_status_disconnected,
+                                                        dp->panel->dpcd,
+                                                        dp->panel->downstream_ports);
        }
 
        dp->dp_display.is_connected = hpd;
@@ -396,8 +398,11 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp)
 
        dp_link_process_request(dp->link);
 
-       drm_dp_set_subconnector_property(dp->dp_display.connector, connector_status_connected,
-                                        dp->panel->dpcd, dp->panel->downstream_ports);
+       if (!dp->dp_display.is_edp)
+               drm_dp_set_subconnector_property(dp->dp_display.connector,
+                                                connector_status_connected,
+                                                dp->panel->dpcd,
+                                                dp->panel->downstream_ports);
 
        edid = dp->panel->edid;
 
index 40e7344180e3e0e8d4f99804835d5ab51a12a842..e3bdd7dd4cdc7de80b1ca1e2cd1f60386c31594c 100644 (file)
@@ -345,6 +345,9 @@ struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display, struct dr
        if (IS_ERR(connector))
                return connector;
 
+       if (!dp_display->is_edp)
+               drm_connector_attach_dp_subconnector_property(connector);
+
        drm_connector_attach_encoder(connector, encoder);
 
        return connector;
index 3b1ed02f644d2821221f54f4a46f611692a4c413..89a6344bc8653d61a3dea4860cb3320f1bcf7a15 100644 (file)
@@ -918,7 +918,7 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
        if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) {
                if (phy->cphy_mode) {
                        vreg_ctrl_0 = 0x45;
-                       vreg_ctrl_1 = 0x45;
+                       vreg_ctrl_1 = 0x41;
                        glbl_rescode_top_ctrl = 0x00;
                        glbl_rescode_bot_ctrl = 0x00;
                } else {
index 2aae7d107f3356e08b55b6b05bf7cf96205318a0..3f217b57829347413a5e570ba3441fc758e915ae 100644 (file)
@@ -288,8 +288,6 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
        if (ret)
                goto err_msm_uninit;
 
-       drm_kms_helper_poll_init(ddev);
-
        if (priv->kms_init) {
                drm_kms_helper_poll_init(ddev);
                msm_fbdev_setup(ddev);
index 3adbb05ff587ba93ca6c618679aba7af9261ae29..d088e636edc31c407582bdbe8ab0ee28653956bf 100644 (file)
@@ -539,7 +539,7 @@ r535_fifo_runl_ctor(struct nvkm_fifo *fifo)
        struct nvkm_runl *runl;
        struct nvkm_engn *engn;
        u32 cgids = 2048;
-       u32 chids = 2048 / CHID_PER_USERD;
+       u32 chids = 2048;
        int ret;
        NV2080_CTRL_FIFO_GET_DEVICE_INFO_TABLE_PARAMS *ctrl;
 
index 9323e7b9e38493461e716561bfd73673ef2bd332..be8f48e3c1db87832de479e720efef2b6999360c 100644 (file)
@@ -1709,6 +1709,7 @@ static const struct panel_desc auo_b101uan08_3_desc = {
        .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
                      MIPI_DSI_MODE_LPM,
        .init_cmds = auo_b101uan08_3_init_cmd,
+       .lp11_before_reset = true,
 };
 
 static const struct drm_display_mode boe_tv105wum_nw0_default_mode = {
@@ -1766,11 +1767,11 @@ static const struct panel_desc starry_qfh032011_53g_desc = {
 };
 
 static const struct drm_display_mode starry_himax83102_j02_default_mode = {
-       .clock = 161600,
+       .clock = 162850,
        .hdisplay = 1200,
-       .hsync_start = 1200 + 40,
-       .hsync_end = 1200 + 40 + 20,
-       .htotal = 1200 + 40 + 20 + 40,
+       .hsync_start = 1200 + 50,
+       .hsync_end = 1200 + 50 + 20,
+       .htotal = 1200 + 50 + 20 + 50,
        .vdisplay = 1920,
        .vsync_start = 1920 + 116,
        .vsync_end = 1920 + 116 + 8,
index 6cd32b9090876585c7e7610813a37d2c3c1647c5..9367a4572dcf645037803cb629ae0e1c5ff692ab 100644 (file)
@@ -2379,13 +2379,13 @@ static const struct panel_desc innolux_g070y2_t02 = {
 static const struct display_timing innolux_g101ice_l01_timing = {
        .pixelclock = { 60400000, 71100000, 74700000 },
        .hactive = { 1280, 1280, 1280 },
-       .hfront_porch = { 41, 80, 100 },
-       .hback_porch = { 40, 79, 99 },
-       .hsync_len = { 1, 1, 1 },
+       .hfront_porch = { 30, 60, 70 },
+       .hback_porch = { 30, 60, 70 },
+       .hsync_len = { 22, 40, 60 },
        .vactive = { 800, 800, 800 },
-       .vfront_porch = { 5, 11, 14 },
-       .vback_porch = { 4, 11, 14 },
-       .vsync_len = { 1, 1, 1 },
+       .vfront_porch = { 3, 8, 14 },
+       .vback_porch = { 3, 8, 14 },
+       .vsync_len = { 4, 7, 12 },
        .flags = DISPLAY_FLAGS_DE_HIGH,
 };
 
@@ -2402,6 +2402,7 @@ static const struct panel_desc innolux_g101ice_l01 = {
                .disable = 200,
        },
        .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+       .bus_flags = DRM_BUS_FLAG_DE_HIGH,
        .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
index 066299894d0480bc4ec7c6aac371c3d3e9bd1c9c..a13473b2d54c40a8a3ba62a547d39166613865df 100644 (file)
@@ -247,14 +247,22 @@ static inline void vop_cfg_done(struct vop *vop)
        VOP_REG_SET(vop, common, cfg_done, 1);
 }
 
-static bool has_rb_swapped(uint32_t format)
+static bool has_rb_swapped(uint32_t version, uint32_t format)
 {
        switch (format) {
        case DRM_FORMAT_XBGR8888:
        case DRM_FORMAT_ABGR8888:
-       case DRM_FORMAT_BGR888:
        case DRM_FORMAT_BGR565:
                return true;
+       /*
+        * full framework (IP version 3.x) only need rb swapped for RGB888 and
+        * little framework (IP version 2.x) only need rb swapped for BGR888,
+        * check for 3.x to also only rb swap BGR888 for unknown vop version
+        */
+       case DRM_FORMAT_RGB888:
+               return VOP_MAJOR(version) == 3;
+       case DRM_FORMAT_BGR888:
+               return VOP_MAJOR(version) != 3;
        default:
                return false;
        }
@@ -1030,7 +1038,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
        VOP_WIN_SET(vop, win, dsp_info, dsp_info);
        VOP_WIN_SET(vop, win, dsp_st, dsp_st);
 
-       rb_swap = has_rb_swapped(fb->format->format);
+       rb_swap = has_rb_swapped(vop->data->version, fb->format->format);
        VOP_WIN_SET(vop, win, rb_swap, rb_swap);
 
        /*
index 3ca45975c686eee3563dabb287caf4c1c21a10ac..d9e9829b22001aa468c1fd837fc692ce807d313f 100644 (file)
@@ -345,6 +345,8 @@ static const struct apple_non_apple_keyboard non_apple_keyboards[] = {
        { "AONE" },
        { "GANSS" },
        { "Hailuck" },
+       { "Jamesdonkey" },
+       { "A3R" },
 };
 
 static bool apple_is_non_apple_keyboard(struct hid_device *hdev)
index fd61dba882338e022685fca453e2d70a0e093106..78cdfb8b9a7aeb6f03b6dc58157cb0b925b4ac76 100644 (file)
@@ -381,7 +381,7 @@ static int asus_raw_event(struct hid_device *hdev,
        return 0;
 }
 
-static int asus_kbd_set_report(struct hid_device *hdev, u8 *buf, size_t buf_size)
+static int asus_kbd_set_report(struct hid_device *hdev, const u8 *buf, size_t buf_size)
 {
        unsigned char *dmabuf;
        int ret;
@@ -404,7 +404,7 @@ static int asus_kbd_set_report(struct hid_device *hdev, u8 *buf, size_t buf_size
 
 static int asus_kbd_init(struct hid_device *hdev)
 {
-       u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x41, 0x53, 0x55, 0x53, 0x20, 0x54,
+       const u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x41, 0x53, 0x55, 0x53, 0x20, 0x54,
                     0x65, 0x63, 0x68, 0x2e, 0x49, 0x6e, 0x63, 0x2e, 0x00 };
        int ret;
 
@@ -418,7 +418,7 @@ static int asus_kbd_init(struct hid_device *hdev)
 static int asus_kbd_get_functions(struct hid_device *hdev,
                                  unsigned char *kbd_func)
 {
-       u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x05, 0x20, 0x31, 0x00, 0x08 };
+       const u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x05, 0x20, 0x31, 0x00, 0x08 };
        u8 *readbuf;
        int ret;
 
@@ -449,7 +449,7 @@ static int asus_kbd_get_functions(struct hid_device *hdev,
 
 static int rog_nkey_led_init(struct hid_device *hdev)
 {
-       u8 buf_init_start[] = { FEATURE_KBD_LED_REPORT_ID1, 0xB9 };
+       const u8 buf_init_start[] = { FEATURE_KBD_LED_REPORT_ID1, 0xB9 };
        u8 buf_init2[] = { FEATURE_KBD_LED_REPORT_ID1, 0x41, 0x53, 0x55, 0x53, 0x20,
                                0x54, 0x65, 0x63, 0x68, 0x2e, 0x49, 0x6e, 0x63, 0x2e, 0x00 };
        u8 buf_init3[] = { FEATURE_KBD_LED_REPORT_ID1,
@@ -1000,6 +1000,24 @@ static int asus_start_multitouch(struct hid_device *hdev)
        return 0;
 }
 
+static int __maybe_unused asus_resume(struct hid_device *hdev) {
+       struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
+       int ret = 0;
+
+       if (drvdata->kbd_backlight) {
+               const u8 buf[] = { FEATURE_KBD_REPORT_ID, 0xba, 0xc5, 0xc4,
+                               drvdata->kbd_backlight->cdev.brightness };
+               ret = asus_kbd_set_report(hdev, buf, sizeof(buf));
+               if (ret < 0) {
+                       hid_err(hdev, "Asus failed to set keyboard backlight: %d\n", ret);
+                       goto asus_resume_err;
+               }
+       }
+
+asus_resume_err:
+       return ret;
+}
+
 static int __maybe_unused asus_reset_resume(struct hid_device *hdev)
 {
        struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
@@ -1294,6 +1312,7 @@ static struct hid_driver asus_driver = {
        .input_configured       = asus_input_configured,
 #ifdef CONFIG_PM
        .reset_resume           = asus_reset_resume,
+       .resume                                 = asus_resume,
 #endif
        .event                  = asus_event,
        .raw_event              = asus_raw_event
index 8992e3c1e7698eeaeeb7711876d66022ef5ec9d0..e0181218ad857862aba07f6ff0ffe30df42bfb16 100644 (file)
@@ -702,15 +702,22 @@ static void hid_close_report(struct hid_device *device)
  * Free a device structure, all reports, and all fields.
  */
 
-static void hid_device_release(struct device *dev)
+void hiddev_free(struct kref *ref)
 {
-       struct hid_device *hid = to_hid_device(dev);
+       struct hid_device *hid = container_of(ref, struct hid_device, ref);
 
        hid_close_report(hid);
        kfree(hid->dev_rdesc);
        kfree(hid);
 }
 
+static void hid_device_release(struct device *dev)
+{
+       struct hid_device *hid = to_hid_device(dev);
+
+       kref_put(&hid->ref, hiddev_free);
+}
+
 /*
  * Fetch a report description item from the data stream. We support long
  * items, though they are not used yet.
@@ -2846,6 +2853,7 @@ struct hid_device *hid_allocate_device(void)
        spin_lock_init(&hdev->debug_list_lock);
        sema_init(&hdev->driver_input_lock, 1);
        mutex_init(&hdev->ll_open_lock);
+       kref_init(&hdev->ref);
 
        hid_bpf_device_init(hdev);
 
index e7ef1ea107c9e618b035552ebf45154ff43a30df..7dd83ec74f8a9df75c6e966b3876f8481166a22f 100644 (file)
@@ -1135,6 +1135,7 @@ static int hid_debug_events_open(struct inode *inode, struct file *file)
                goto out;
        }
        list->hdev = (struct hid_device *) inode->i_private;
+       kref_get(&list->hdev->ref);
        file->private_data = list;
        mutex_init(&list->read_mutex);
 
@@ -1227,6 +1228,8 @@ static int hid_debug_events_release(struct inode *inode, struct file *file)
        list_del(&list->node);
        spin_unlock_irqrestore(&list->hdev->debug_list_lock, flags);
        kfifo_free(&list->hid_debug_fifo);
+
+       kref_put(&list->hdev->ref, hiddev_free);
        kfree(list);
 
        return 0;
index 558eb08c19ef9da28b233e4418353a32b0172260..281b3a7187cec2ff355aae17a4cec2b59d2102ca 100644 (file)
@@ -21,6 +21,10 @@ MODULE_DESCRIPTION("HID driver for Glorious PC Gaming Race mice");
  * Glorious Model O and O- specify the const flag in the consumer input
  * report descriptor, which leads to inputs being ignored. Fix this
  * by patching the descriptor.
+ *
+ * Glorious Model I incorrectly specifes the Usage Minimum for its
+ * keyboard HID report, causing keycodes to be misinterpreted.
+ * Fix this by setting Usage Minimum to 0 in that report.
  */
 static __u8 *glorious_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                unsigned int *rsize)
@@ -32,6 +36,10 @@ static __u8 *glorious_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                rdesc[85] = rdesc[113] = rdesc[141] = \
                        HID_MAIN_ITEM_VARIABLE | HID_MAIN_ITEM_RELATIVE;
        }
+       if (*rsize == 156 && rdesc[41] == 1) {
+               hid_info(hdev, "patching Glorious Model I keyboard report descriptor\n");
+               rdesc[41] = 0;
+       }
        return rdesc;
 }
 
@@ -44,6 +52,8 @@ static void glorious_update_name(struct hid_device *hdev)
                model = "Model O"; break;
        case USB_DEVICE_ID_GLORIOUS_MODEL_D:
                model = "Model D"; break;
+       case USB_DEVICE_ID_GLORIOUS_MODEL_I:
+               model = "Model I"; break;
        }
 
        snprintf(hdev->name, sizeof(hdev->name), "%s %s", "Glorious", model);
@@ -66,10 +76,12 @@ static int glorious_probe(struct hid_device *hdev,
 }
 
 static const struct hid_device_id glorious_devices[] = {
-       { HID_USB_DEVICE(USB_VENDOR_ID_GLORIOUS,
+       { HID_USB_DEVICE(USB_VENDOR_ID_SINOWEALTH,
                USB_DEVICE_ID_GLORIOUS_MODEL_O) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_GLORIOUS,
+       { HID_USB_DEVICE(USB_VENDOR_ID_SINOWEALTH,
                USB_DEVICE_ID_GLORIOUS_MODEL_D) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LAVIEW,
+               USB_DEVICE_ID_GLORIOUS_MODEL_I) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, glorious_devices);
index f7973ccd84a287017db736ca4dcb9baf150b1b2b..c6e4e0d1f2147e6221c10e607859354d2c1a32be 100644 (file)
 #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_010A 0x010a
 #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100 0xe100
 
-#define USB_VENDOR_ID_GLORIOUS  0x258a
-#define USB_DEVICE_ID_GLORIOUS_MODEL_D 0x0033
-#define USB_DEVICE_ID_GLORIOUS_MODEL_O 0x0036
-
 #define I2C_VENDOR_ID_GOODIX           0x27c6
 #define I2C_DEVICE_ID_GOODIX_01F0      0x01f0
 
 #define USB_VENDOR_ID_LABTEC           0x1020
 #define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD 0x0006
 
+#define USB_VENDOR_ID_LAVIEW           0x22D4
+#define USB_DEVICE_ID_GLORIOUS_MODEL_I 0x1503
+
 #define USB_VENDOR_ID_LCPOWER          0x1241
 #define USB_DEVICE_ID_LCPOWER_LC1000   0xf767
 
 #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2         0xc534
 #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1      0xc539
 #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1    0xc53f
-#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_2    0xc547
 #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_POWERPLAY 0xc53a
 #define USB_DEVICE_ID_SPACETRAVELLER   0xc623
 #define USB_DEVICE_ID_SPACENAVIGATOR   0xc626
 #define USB_VENDOR_ID_SIGMATEL         0x066F
 #define USB_DEVICE_ID_SIGMATEL_STMP3780        0x3780
 
+#define USB_VENDOR_ID_SINOWEALTH  0x258a
+#define USB_DEVICE_ID_GLORIOUS_MODEL_D 0x0033
+#define USB_DEVICE_ID_GLORIOUS_MODEL_O 0x0036
+
 #define USB_VENDOR_ID_SIS_TOUCH                0x0457
 #define USB_DEVICE_ID_SIS9200_TOUCH    0x9200
 #define USB_DEVICE_ID_SIS817_TOUCH     0x0817
index 8afe3be683ba251617e5b5f2b9477738ce2f13d7..e6a8b6d8eab707da539cbc209f205d0ef02bba67 100644 (file)
@@ -1695,12 +1695,11 @@ static int logi_dj_raw_event(struct hid_device *hdev,
                }
                /*
                 * Mouse-only receivers send unnumbered mouse data. The 27 MHz
-                * receiver uses 6 byte packets, the nano receiver 8 bytes,
-                * the lightspeed receiver (Pro X Superlight) 13 bytes.
+                * receiver uses 6 byte packets, the nano receiver 8 bytes.
                 */
                if (djrcv_dev->unnumbered_application == HID_GD_MOUSE &&
-                   size <= 13){
-                       u8 mouse_report[14];
+                   size <= 8) {
+                       u8 mouse_report[9];
 
                        /* Prepend report id */
                        mouse_report[0] = REPORT_TYPE_MOUSE;
@@ -1984,10 +1983,6 @@ static const struct hid_device_id logi_dj_receivers[] = {
          HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
                USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1),
         .driver_data = recvr_type_gaming_hidpp},
-       { /* Logitech lightspeed receiver (0xc547) */
-         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
-               USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_2),
-        .driver_data = recvr_type_gaming_hidpp},
 
        { /* Logitech 27 MHz HID++ 1.0 receiver (0xc513) */
          HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
index 72883e0ce75758c948683b0cee7377ecfd5c19fa..aef0785c91cc2d19385b54c8689be4e875aa85c9 100644 (file)
@@ -1142,6 +1142,8 @@ static int mcp2221_probe(struct hid_device *hdev,
        if (ret)
                return ret;
 
+       hid_device_io_start(hdev);
+
        /* Set I2C bus clock diviser */
        if (i2c_clk_freq > 400)
                i2c_clk_freq = 400;
@@ -1157,12 +1159,12 @@ static int mcp2221_probe(struct hid_device *hdev,
        snprintf(mcp->adapter.name, sizeof(mcp->adapter.name),
                        "MCP2221 usb-i2c bridge");
 
+       i2c_set_adapdata(&mcp->adapter, mcp);
        ret = devm_i2c_add_adapter(&hdev->dev, &mcp->adapter);
        if (ret) {
                hid_err(hdev, "can't add usb-i2c adapter: %d\n", ret);
                return ret;
        }
-       i2c_set_adapdata(&mcp->adapter, mcp);
 
 #if IS_REACHABLE(CONFIG_GPIOLIB)
        /* Setup GPIO chip */
index e098cc7b3944375387bb8003ca6ab4807bfb3eb9..fd5b0637dad683e7b20c929974c958e79936880c 100644 (file)
@@ -2046,6 +2046,11 @@ static const struct hid_device_id mt_devices[] = {
                MT_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT,
                        USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) },
 
+       /* HONOR GLO-GXXX panel */
+       { .driver_data = MT_CLS_VTL,
+               HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
+                       0x347d, 0x7853) },
+
        /* Ilitek dual touch panel */
        {  .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_ILITEK,
index 5a48fcaa32f007cddda7f18bf1b79261553f675a..ea472923fab07841ba6ee136da95a4a060690c4d 100644 (file)
@@ -33,6 +33,7 @@ static const struct hid_device_id hid_quirks[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_AKAI, USB_DEVICE_ID_AKAI_MPKMINI2), HID_QUIRK_NO_INIT_REPORTS },
        { HID_USB_DEVICE(USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD), HID_QUIRK_BADPAD },
        { HID_USB_DEVICE(USB_VENDOR_ID_AMI, USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE), HID_QUIRK_ALWAYS_POLL },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI), HID_QUIRK_ALWAYS_POLL },
        { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM), HID_QUIRK_NOGET },
        { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC), HID_QUIRK_NOGET },
        { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM), HID_QUIRK_NOGET },
index 05be59ae21b29d7de20c7ca32cae293f7ea195e4..6ae2329052c92c3c2724694c11f586bed8c5c15a 100644 (file)
@@ -265,6 +265,7 @@ struct bcache_device {
 #define BCACHE_DEV_WB_RUNNING          3
 #define BCACHE_DEV_RATE_DW_RUNNING     4
        int                     nr_stripes;
+#define BCH_MIN_STRIPE_SZ              ((4 << 20) >> SECTOR_SHIFT)
        unsigned int            stripe_size;
        atomic_t                *stripe_sectors_dirty;
        unsigned long           *full_dirty_stripes;
index ae5cbb55861fdb7967ad9ad686161b377de345b4..de3019972b355121fdf836af3f56fd9a949aeff9 100644 (file)
@@ -1000,6 +1000,9 @@ err:
  *
  * The btree node will have either a read or a write lock held, depending on
  * level and op->lock.
+ *
+ * Note: Only error code or btree pointer will be returned, it is unncessary
+ *       for callers to check NULL pointer.
  */
 struct btree *bch_btree_node_get(struct cache_set *c, struct btree_op *op,
                                 struct bkey *k, int level, bool write,
@@ -1111,6 +1114,10 @@ retry:
        mutex_unlock(&b->c->bucket_lock);
 }
 
+/*
+ * Only error code or btree pointer will be returned, it is unncessary for
+ * callers to check NULL pointer.
+ */
 struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op,
                                     int level, bool wait,
                                     struct btree *parent)
@@ -1368,7 +1375,7 @@ static int btree_gc_coalesce(struct btree *b, struct btree_op *op,
        memset(new_nodes, 0, sizeof(new_nodes));
        closure_init_stack(&cl);
 
-       while (nodes < GC_MERGE_NODES && !IS_ERR(r[nodes].b))
+       while (nodes < GC_MERGE_NODES && !IS_ERR_OR_NULL(r[nodes].b))
                keys += r[nodes++].keys;
 
        blocks = btree_default_blocks(b->c) * 2 / 3;
@@ -1532,6 +1539,8 @@ static int btree_gc_rewrite_node(struct btree *b, struct btree_op *op,
                return 0;
 
        n = btree_node_alloc_replacement(replace, NULL);
+       if (IS_ERR(n))
+               return 0;
 
        /* recheck reserve after allocating replacement node */
        if (btree_check_reserve(b, NULL)) {
index 8bd899766372afe253eae981870c20dea9dfedc7..bfe1685dbae5748feafceb1ea7d98572a11e7c76 100644 (file)
@@ -905,6 +905,8 @@ static int bcache_device_init(struct bcache_device *d, unsigned int block_size,
 
        if (!d->stripe_size)
                d->stripe_size = 1 << 31;
+       else if (d->stripe_size < BCH_MIN_STRIPE_SZ)
+               d->stripe_size = roundup(BCH_MIN_STRIPE_SZ, d->stripe_size);
 
        n = DIV_ROUND_UP_ULL(sectors, d->stripe_size);
        if (!n || n > max_stripes) {
@@ -2016,7 +2018,7 @@ static int run_cache_set(struct cache_set *c)
                c->root = bch_btree_node_get(c, NULL, k,
                                             j->btree_level,
                                             true, NULL);
-               if (IS_ERR_OR_NULL(c->root))
+               if (IS_ERR(c->root))
                        goto err;
 
                list_del_init(&c->root->list);
index 45d8af755de6d17ceb9988604a3596fd99f7fbb9..a438efb660699b1f1a9dbb162310bfd1fa8e7258 100644 (file)
@@ -1104,7 +1104,7 @@ SHOW(__bch_cache)
                        sum += INITIAL_PRIO - cached[i];
 
                if (n)
-                       do_div(sum, n);
+                       sum = div64_u64(sum, n);
 
                for (i = 0; i < ARRAY_SIZE(q); i++)
                        q[i] = INITIAL_PRIO - cached[n * (i + 1) /
index 24c049067f61ae6ec9e9c0280e948becb2943f88..3accfdaee6b192956fa760bf2ec38a8039d0b88d 100644 (file)
@@ -913,7 +913,7 @@ static int bch_dirty_init_thread(void *arg)
        int cur_idx, prev_idx, skip_nr;
 
        k = p = NULL;
-       cur_idx = prev_idx = 0;
+       prev_idx = 0;
 
        bch_btree_iter_init(&c->root->keys, &iter, NULL);
        k = bch_btree_iter_next_filter(&iter, &c->root->keys, bch_ptr_bad);
@@ -977,24 +977,35 @@ static int bch_btre_dirty_init_thread_nr(void)
 void bch_sectors_dirty_init(struct bcache_device *d)
 {
        int i;
+       struct btree *b = NULL;
        struct bkey *k = NULL;
        struct btree_iter iter;
        struct sectors_dirty_init op;
        struct cache_set *c = d->c;
        struct bch_dirty_init_state state;
 
+retry_lock:
+       b = c->root;
+       rw_lock(0, b, b->level);
+       if (b != c->root) {
+               rw_unlock(0, b);
+               goto retry_lock;
+       }
+
        /* Just count root keys if no leaf node */
-       rw_lock(0, c->root, c->root->level);
        if (c->root->level == 0) {
                bch_btree_op_init(&op.op, -1);
                op.inode = d->id;
                op.count = 0;
 
                for_each_key_filter(&c->root->keys,
-                                   k, &iter, bch_ptr_invalid)
+                                   k, &iter, bch_ptr_invalid) {
+                       if (KEY_INODE(k) != op.inode)
+                               continue;
                        sectors_dirty_init_fn(&op.op, c->root, k);
+               }
 
-               rw_unlock(0, c->root);
+               rw_unlock(0, b);
                return;
        }
 
@@ -1014,23 +1025,24 @@ void bch_sectors_dirty_init(struct bcache_device *d)
                if (atomic_read(&state.enough))
                        break;
 
+               atomic_inc(&state.started);
                state.infos[i].state = &state;
                state.infos[i].thread =
                        kthread_run(bch_dirty_init_thread, &state.infos[i],
                                    "bch_dirtcnt[%d]", i);
                if (IS_ERR(state.infos[i].thread)) {
                        pr_err("fails to run thread bch_dirty_init[%d]\n", i);
+                       atomic_dec(&state.started);
                        for (--i; i >= 0; i--)
                                kthread_stop(state.infos[i].thread);
                        goto out;
                }
-               atomic_inc(&state.started);
        }
 
 out:
        /* Must wait for all threads to stop. */
        wait_event(state.wait, atomic_read(&state.started) == 0);
-       rw_unlock(0, c->root);
+       rw_unlock(0, b);
 }
 
 void bch_cached_dev_writeback_init(struct cached_dev *dc)
index 4ee4593c874a769b96b36696aa50cbc806cb8385..c94373d64f2cd4cbbdb8d49591d23b8f129aa46c 100644 (file)
@@ -8666,7 +8666,8 @@ static void md_end_clone_io(struct bio *bio)
        struct bio *orig_bio = md_io_clone->orig_bio;
        struct mddev *mddev = md_io_clone->mddev;
 
-       orig_bio->bi_status = bio->bi_status;
+       if (bio->bi_status && !orig_bio->bi_status)
+               orig_bio->bi_status = bio->bi_status;
 
        if (md_io_clone->start_time)
                bio_end_io_acct(orig_bio, md_io_clone->start_time);
index 614c0278419bcf31e8be085300b34acd00847df4..6b73648b3779368f8a01cbc95f8afb88bc07786d 100644 (file)
@@ -682,10 +682,24 @@ static void xgbe_service(struct work_struct *work)
 static void xgbe_service_timer(struct timer_list *t)
 {
        struct xgbe_prv_data *pdata = from_timer(pdata, t, service_timer);
+       struct xgbe_channel *channel;
+       unsigned int i;
 
        queue_work(pdata->dev_workqueue, &pdata->service_work);
 
        mod_timer(&pdata->service_timer, jiffies + HZ);
+
+       if (!pdata->tx_usecs)
+               return;
+
+       for (i = 0; i < pdata->channel_count; i++) {
+               channel = pdata->channel[i];
+               if (!channel->tx_ring || channel->tx_timer_active)
+                       break;
+               channel->tx_timer_active = 1;
+               mod_timer(&channel->tx_timer,
+                         jiffies + usecs_to_jiffies(pdata->tx_usecs));
+       }
 }
 
 static void xgbe_init_timers(struct xgbe_prv_data *pdata)
index 6e83ff59172a36b66d1442dc32b338edfe3d5773..32fab5e7724626f856da6c17ae9df2c92241b0c1 100644 (file)
@@ -314,10 +314,15 @@ static int xgbe_get_link_ksettings(struct net_device *netdev,
 
        cmd->base.phy_address = pdata->phy.address;
 
-       cmd->base.autoneg = pdata->phy.autoneg;
-       cmd->base.speed = pdata->phy.speed;
-       cmd->base.duplex = pdata->phy.duplex;
+       if (netif_carrier_ok(netdev)) {
+               cmd->base.speed = pdata->phy.speed;
+               cmd->base.duplex = pdata->phy.duplex;
+       } else {
+               cmd->base.speed = SPEED_UNKNOWN;
+               cmd->base.duplex = DUPLEX_UNKNOWN;
+       }
 
+       cmd->base.autoneg = pdata->phy.autoneg;
        cmd->base.port = PORT_NONE;
 
        XGBE_LM_COPY(cmd, supported, lks, supported);
index 32d2c6fac65266baee9bc36477f21418b50f67e0..4a2dc705b52801792652c3ba6a9c945b306c3198 100644 (file)
@@ -1193,7 +1193,19 @@ static int xgbe_phy_config_fixed(struct xgbe_prv_data *pdata)
        if (pdata->phy.duplex != DUPLEX_FULL)
                return -EINVAL;
 
-       xgbe_set_mode(pdata, mode);
+       /* Force the mode change for SFI in Fixed PHY config.
+        * Fixed PHY configs needs PLL to be enabled while doing mode set.
+        * When the SFP module isn't connected during boot, driver assumes
+        * AN is ON and attempts autonegotiation. However, if the connected
+        * SFP comes up in Fixed PHY config, the link will not come up as
+        * PLL isn't enabled while the initial mode set command is issued.
+        * So, force the mode change for SFI in Fixed PHY configuration to
+        * fix link issues.
+        */
+       if (mode == XGBE_MODE_SFI)
+               xgbe_change_mode(pdata, mode);
+       else
+               xgbe_set_mode(pdata, mode);
 
        return 0;
 }
index 08d7edccfb8ddbd6385a7ce843bf652d87526b7f..3f99eb1982452725caa0548f01329350300cd8b9 100644 (file)
@@ -3844,7 +3844,7 @@ static int i40e_vc_add_cloud_filter(struct i40e_vf *vf, u8 *msg)
        struct i40e_pf *pf = vf->pf;
        struct i40e_vsi *vsi = NULL;
        int aq_ret = 0;
-       int i, ret;
+       int i;
 
        if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) {
                aq_ret = -EINVAL;
@@ -3868,8 +3868,10 @@ static int i40e_vc_add_cloud_filter(struct i40e_vf *vf, u8 *msg)
        }
 
        cfilter = kzalloc(sizeof(*cfilter), GFP_KERNEL);
-       if (!cfilter)
-               return -ENOMEM;
+       if (!cfilter) {
+               aq_ret = -ENOMEM;
+               goto err_out;
+       }
 
        /* parse destination mac address */
        for (i = 0; i < ETH_ALEN; i++)
@@ -3917,13 +3919,13 @@ static int i40e_vc_add_cloud_filter(struct i40e_vf *vf, u8 *msg)
 
        /* Adding cloud filter programmed as TC filter */
        if (tcf.dst_port)
-               ret = i40e_add_del_cloud_filter_big_buf(vsi, cfilter, true);
+               aq_ret = i40e_add_del_cloud_filter_big_buf(vsi, cfilter, true);
        else
-               ret = i40e_add_del_cloud_filter(vsi, cfilter, true);
-       if (ret) {
+               aq_ret = i40e_add_del_cloud_filter(vsi, cfilter, true);
+       if (aq_ret) {
                dev_err(&pf->pdev->dev,
                        "VF %d: Failed to add cloud filter, err %pe aq_err %s\n",
-                       vf->vf_id, ERR_PTR(ret),
+                       vf->vf_id, ERR_PTR(aq_ret),
                        i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
                goto err_free;
        }
index 6607fa6fe55626b97f0de34b58dcb9dfdb8f815c..fb9c93f37e84f7f0e9e1d960522aaae1601f98ca 100644 (file)
@@ -7401,15 +7401,6 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
                goto err_vsi_rebuild;
        }
 
-       /* configure PTP timestamping after VSI rebuild */
-       if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags)) {
-               if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_SELF)
-                       ice_ptp_cfg_timestamp(pf, false);
-               else if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_ALL)
-                       /* for E82x PHC owner always need to have interrupts */
-                       ice_ptp_cfg_timestamp(pf, true);
-       }
-
        err = ice_vsi_rebuild_by_type(pf, ICE_VSI_SWITCHDEV_CTRL);
        if (err) {
                dev_err(dev, "Switchdev CTRL VSI rebuild failed: %d\n", err);
@@ -7461,6 +7452,9 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
        ice_plug_aux_dev(pf);
        if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG))
                ice_lag_rebuild(pf);
+
+       /* Restore timestamp mode settings after VSI rebuild */
+       ice_ptp_restore_timestamp_mode(pf);
        return;
 
 err_vsi_rebuild:
index 1eddcbe89b0c47c18aaaa288839149f4443a94f7..71f405f8a6fee67663feb4b5ea805dfb75239c9a 100644 (file)
@@ -256,48 +256,42 @@ ice_verify_pin_e810t(struct ptp_clock_info *info, unsigned int pin,
 }
 
 /**
- * ice_ptp_configure_tx_tstamp - Enable or disable Tx timestamp interrupt
- * @pf: The PF pointer to search in
- * @on: bool value for whether timestamp interrupt is enabled or disabled
+ * ice_ptp_cfg_tx_interrupt - Configure Tx timestamp interrupt for the device
+ * @pf: Board private structure
+ *
+ * Program the device to respond appropriately to the Tx timestamp interrupt
+ * cause.
  */
-static void ice_ptp_configure_tx_tstamp(struct ice_pf *pf, bool on)
+static void ice_ptp_cfg_tx_interrupt(struct ice_pf *pf)
 {
+       struct ice_hw *hw = &pf->hw;
+       bool enable;
        u32 val;
 
+       switch (pf->ptp.tx_interrupt_mode) {
+       case ICE_PTP_TX_INTERRUPT_ALL:
+               /* React to interrupts across all quads. */
+               wr32(hw, PFINT_TSYN_MSK + (0x4 * hw->pf_id), (u32)0x1f);
+               enable = true;
+               break;
+       case ICE_PTP_TX_INTERRUPT_NONE:
+               /* Do not react to interrupts on any quad. */
+               wr32(hw, PFINT_TSYN_MSK + (0x4 * hw->pf_id), (u32)0x0);
+               enable = false;
+               break;
+       case ICE_PTP_TX_INTERRUPT_SELF:
+       default:
+               enable = pf->ptp.tstamp_config.tx_type == HWTSTAMP_TX_ON;
+               break;
+       }
+
        /* Configure the Tx timestamp interrupt */
-       val = rd32(&pf->hw, PFINT_OICR_ENA);
-       if (on)
+       val = rd32(hw, PFINT_OICR_ENA);
+       if (enable)
                val |= PFINT_OICR_TSYN_TX_M;
        else
                val &= ~PFINT_OICR_TSYN_TX_M;
-       wr32(&pf->hw, PFINT_OICR_ENA, val);
-}
-
-/**
- * ice_set_tx_tstamp - Enable or disable Tx timestamping
- * @pf: The PF pointer to search in
- * @on: bool value for whether timestamps are enabled or disabled
- */
-static void ice_set_tx_tstamp(struct ice_pf *pf, bool on)
-{
-       struct ice_vsi *vsi;
-       u16 i;
-
-       vsi = ice_get_main_vsi(pf);
-       if (!vsi)
-               return;
-
-       /* Set the timestamp enable flag for all the Tx rings */
-       ice_for_each_txq(vsi, i) {
-               if (!vsi->tx_rings[i])
-                       continue;
-               vsi->tx_rings[i]->ptp_tx = on;
-       }
-
-       if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_SELF)
-               ice_ptp_configure_tx_tstamp(pf, on);
-
-       pf->ptp.tstamp_config.tx_type = on ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
+       wr32(hw, PFINT_OICR_ENA, val);
 }
 
 /**
@@ -311,7 +305,7 @@ static void ice_set_rx_tstamp(struct ice_pf *pf, bool on)
        u16 i;
 
        vsi = ice_get_main_vsi(pf);
-       if (!vsi)
+       if (!vsi || !vsi->rx_rings)
                return;
 
        /* Set the timestamp flag for all the Rx rings */
@@ -320,23 +314,50 @@ static void ice_set_rx_tstamp(struct ice_pf *pf, bool on)
                        continue;
                vsi->rx_rings[i]->ptp_rx = on;
        }
+}
+
+/**
+ * ice_ptp_disable_timestamp_mode - Disable current timestamp mode
+ * @pf: Board private structure
+ *
+ * Called during preparation for reset to temporarily disable timestamping on
+ * the device. Called during remove to disable timestamping while cleaning up
+ * driver resources.
+ */
+static void ice_ptp_disable_timestamp_mode(struct ice_pf *pf)
+{
+       struct ice_hw *hw = &pf->hw;
+       u32 val;
+
+       val = rd32(hw, PFINT_OICR_ENA);
+       val &= ~PFINT_OICR_TSYN_TX_M;
+       wr32(hw, PFINT_OICR_ENA, val);
 
-       pf->ptp.tstamp_config.rx_filter = on ? HWTSTAMP_FILTER_ALL :
-                                              HWTSTAMP_FILTER_NONE;
+       ice_set_rx_tstamp(pf, false);
 }
 
 /**
- * ice_ptp_cfg_timestamp - Configure timestamp for init/deinit
+ * ice_ptp_restore_timestamp_mode - Restore timestamp configuration
  * @pf: Board private structure
- * @ena: bool value to enable or disable time stamp
  *
- * This function will configure timestamping during PTP initialization
- * and deinitialization
+ * Called at the end of rebuild to restore timestamp configuration after
+ * a device reset.
  */
-void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena)
+void ice_ptp_restore_timestamp_mode(struct ice_pf *pf)
 {
-       ice_set_tx_tstamp(pf, ena);
-       ice_set_rx_tstamp(pf, ena);
+       struct ice_hw *hw = &pf->hw;
+       bool enable_rx;
+
+       ice_ptp_cfg_tx_interrupt(pf);
+
+       enable_rx = pf->ptp.tstamp_config.rx_filter == HWTSTAMP_FILTER_ALL;
+       ice_set_rx_tstamp(pf, enable_rx);
+
+       /* Trigger an immediate software interrupt to ensure that timestamps
+        * which occurred during reset are handled now.
+        */
+       wr32(hw, PFINT_OICR, PFINT_OICR_TSYN_TX_M);
+       ice_flush(hw);
 }
 
 /**
@@ -2037,10 +2058,10 @@ ice_ptp_set_timestamp_mode(struct ice_pf *pf, struct hwtstamp_config *config)
 {
        switch (config->tx_type) {
        case HWTSTAMP_TX_OFF:
-               ice_set_tx_tstamp(pf, false);
+               pf->ptp.tstamp_config.tx_type = HWTSTAMP_TX_OFF;
                break;
        case HWTSTAMP_TX_ON:
-               ice_set_tx_tstamp(pf, true);
+               pf->ptp.tstamp_config.tx_type = HWTSTAMP_TX_ON;
                break;
        default:
                return -ERANGE;
@@ -2048,7 +2069,7 @@ ice_ptp_set_timestamp_mode(struct ice_pf *pf, struct hwtstamp_config *config)
 
        switch (config->rx_filter) {
        case HWTSTAMP_FILTER_NONE:
-               ice_set_rx_tstamp(pf, false);
+               pf->ptp.tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
                break;
        case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
        case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
@@ -2064,12 +2085,15 @@ ice_ptp_set_timestamp_mode(struct ice_pf *pf, struct hwtstamp_config *config)
        case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
        case HWTSTAMP_FILTER_NTP_ALL:
        case HWTSTAMP_FILTER_ALL:
-               ice_set_rx_tstamp(pf, true);
+               pf->ptp.tstamp_config.rx_filter = HWTSTAMP_FILTER_ALL;
                break;
        default:
                return -ERANGE;
        }
 
+       /* Immediately update the device timestamping mode */
+       ice_ptp_restore_timestamp_mode(pf);
+
        return 0;
 }
 
@@ -2737,7 +2761,7 @@ void ice_ptp_prepare_for_reset(struct ice_pf *pf)
        clear_bit(ICE_FLAG_PTP, pf->flags);
 
        /* Disable timestamping for both Tx and Rx */
-       ice_ptp_cfg_timestamp(pf, false);
+       ice_ptp_disable_timestamp_mode(pf);
 
        kthread_cancel_delayed_work_sync(&ptp->work);
 
@@ -2803,15 +2827,7 @@ static int ice_ptp_init_owner(struct ice_pf *pf)
        /* Release the global hardware lock */
        ice_ptp_unlock(hw);
 
-       if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_ALL) {
-               /* The clock owner for this device type handles the timestamp
-                * interrupt for all ports.
-                */
-               ice_ptp_configure_tx_tstamp(pf, true);
-
-               /* React on all quads interrupts for E82x */
-               wr32(hw, PFINT_TSYN_MSK + (0x4 * hw->pf_id), (u32)0x1f);
-
+       if (!ice_is_e810(hw)) {
                /* Enable quad interrupts */
                err = ice_ptp_tx_ena_intr(pf, true, itr);
                if (err)
@@ -2881,13 +2897,6 @@ static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port)
        case ICE_PHY_E810:
                return ice_ptp_init_tx_e810(pf, &ptp_port->tx);
        case ICE_PHY_E822:
-               /* Non-owner PFs don't react to any interrupts on E82x,
-                * neither on own quad nor on others
-                */
-               if (!ice_ptp_pf_handles_tx_interrupt(pf)) {
-                       ice_ptp_configure_tx_tstamp(pf, false);
-                       wr32(hw, PFINT_TSYN_MSK + (0x4 * hw->pf_id), (u32)0x0);
-               }
                kthread_init_delayed_work(&ptp_port->ov_work,
                                          ice_ptp_wait_for_offsets);
 
@@ -3032,6 +3041,9 @@ void ice_ptp_init(struct ice_pf *pf)
        /* Start the PHY timestamping block */
        ice_ptp_reset_phy_timestamping(pf);
 
+       /* Configure initial Tx interrupt settings */
+       ice_ptp_cfg_tx_interrupt(pf);
+
        set_bit(ICE_FLAG_PTP, pf->flags);
        err = ice_ptp_init_work(pf, ptp);
        if (err)
@@ -3067,7 +3079,7 @@ void ice_ptp_release(struct ice_pf *pf)
                return;
 
        /* Disable timestamping for both Tx and Rx */
-       ice_ptp_cfg_timestamp(pf, false);
+       ice_ptp_disable_timestamp_mode(pf);
 
        ice_ptp_remove_auxbus_device(pf);
 
index 8f6f943927564337d184168b072e1e656f6abbd9..06a330867fc9be3b5f6653bb6c8c43740cd62b04 100644 (file)
@@ -292,7 +292,7 @@ int ice_ptp_clock_index(struct ice_pf *pf);
 struct ice_pf;
 int ice_ptp_set_ts_config(struct ice_pf *pf, struct ifreq *ifr);
 int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr);
-void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena);
+void ice_ptp_restore_timestamp_mode(struct ice_pf *pf);
 
 void ice_ptp_extts_event(struct ice_pf *pf);
 s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb);
@@ -317,8 +317,7 @@ static inline int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr)
        return -EOPNOTSUPP;
 }
 
-static inline void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena) { }
-
+static inline void ice_ptp_restore_timestamp_mode(struct ice_pf *pf) { }
 static inline void ice_ptp_extts_event(struct ice_pf *pf) { }
 static inline s8
 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb)
index 52d0a126eb6161852bb96457b9025a35e5641578..9e97ea8630686720bca3903cc3f6ae86c6807316 100644 (file)
@@ -2306,9 +2306,6 @@ ice_tstamp(struct ice_tx_ring *tx_ring, struct sk_buff *skb,
        if (likely(!(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)))
                return;
 
-       if (!tx_ring->ptp_tx)
-               return;
-
        /* Tx timestamps cannot be sampled when doing TSO */
        if (first->tx_flags & ICE_TX_FLAGS_TSO)
                return;
index 166413fc33f48f71a459009819a75d000601b03f..daf7b9dbb1435ad45a6c5efd0acfc84563434e02 100644 (file)
@@ -380,7 +380,6 @@ struct ice_tx_ring {
 #define ICE_TX_FLAGS_RING_VLAN_L2TAG2  BIT(2)
        u8 flags;
        u8 dcb_tc;                      /* Traffic class of ring */
-       u8 ptp_tx;
 } ____cacheline_internodealigned_in_smp;
 
 static inline bool ice_ring_uses_build_skb(struct ice_rx_ring *ring)
index 4762dbea64a12bab71b579b822a9c355c2535e30..97a71e9b856372b95edd964e31fdc0b1156b8454 100644 (file)
@@ -1088,6 +1088,7 @@ int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc)
        struct ethhdr *eth_hdr;
        bool new = false;
        int err = 0;
+       u64 vf_num;
        u32 ring;
 
        if (!flow_cfg->max_flows) {
@@ -1100,7 +1101,21 @@ int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc)
        if (!(pfvf->flags & OTX2_FLAG_NTUPLE_SUPPORT))
                return -ENOMEM;
 
-       if (ring >= pfvf->hw.rx_queues && fsp->ring_cookie != RX_CLS_FLOW_DISC)
+       /* Number of queues on a VF can be greater or less than
+        * the PF's queue. Hence no need to check for the
+        * queue count. Hence no need to check queue count if PF
+        * is installing for its VF. Below is the expected vf_num value
+        * based on the ethtool commands.
+        *
+        * e.g.
+        * 1. ethtool -U <netdev> ... action -1  ==> vf_num:255
+        * 2. ethtool -U <netdev> ... action <queue_num>  ==> vf_num:0
+        * 3. ethtool -U <netdev> ... vf <vf_idx> queue <queue_num>  ==>
+        *    vf_num:vf_idx+1
+        */
+       vf_num = ethtool_get_flow_spec_ring_vf(fsp->ring_cookie);
+       if (!is_otx2_vf(pfvf->pcifunc) && !vf_num &&
+           ring >= pfvf->hw.rx_queues && fsp->ring_cookie != RX_CLS_FLOW_DISC)
                return -EINVAL;
 
        if (fsp->location >= otx2_get_maxflows(flow_cfg))
@@ -1182,6 +1197,9 @@ int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc)
                flow_cfg->nr_flows++;
        }
 
+       if (flow->is_vf)
+               netdev_info(pfvf->netdev,
+                           "Make sure that VF's queue number is within its queue limit\n");
        return 0;
 }
 
index 91b99fd703616ae5915758a374a17e458bea8ffc..ba95ac91327467697f81b6c5ad25e6b230188fcd 100644 (file)
@@ -1934,6 +1934,8 @@ int otx2_stop(struct net_device *netdev)
        /* Clear RSS enable flag */
        rss = &pf->hw.rss_info;
        rss->enable = false;
+       if (!netif_is_rxfh_configured(netdev))
+               kfree(rss->rss_ctx[DEFAULT_RSS_CONTEXT_GROUP]);
 
        /* Cleanup Queue IRQ */
        vec = pci_irq_vector(pf->pdev,
index b9bb1d2f0237e986ea258ef2f441564969dd6c0e..295366a85c630c84a0be3544054c0acb4f71546a 100644 (file)
@@ -2599,9 +2599,7 @@ static void rtl_set_rx_mode(struct net_device *dev)
                rx_mode &= ~AcceptMulticast;
        } else if (netdev_mc_count(dev) > MC_FILTER_LIMIT ||
                   dev->flags & IFF_ALLMULTI ||
-                  tp->mac_version == RTL_GIGA_MAC_VER_35 ||
-                  tp->mac_version == RTL_GIGA_MAC_VER_46 ||
-                  tp->mac_version == RTL_GIGA_MAC_VER_48) {
+                  tp->mac_version == RTL_GIGA_MAC_VER_35) {
                /* accept all multicasts */
        } else if (netdev_mc_empty(dev)) {
                rx_mode &= ~AcceptMulticast;
index a2b9e289aa36a9488e536d27665e0829d3688086..85dcda51df0522f0c4048890b484f98c5bf6e3f2 100644 (file)
@@ -280,7 +280,7 @@ config DWMAC_INTEL
 config DWMAC_LOONGSON
        tristate "Loongson PCI DWMAC support"
        default MACH_LOONGSON64
-       depends on STMMAC_ETH && PCI
+       depends on (MACH_LOONGSON64 || COMPILE_TEST) && STMMAC_ETH && PCI
        depends on COMMON_CLK
        help
          This selects the LOONGSON PCI bus support for the stmmac driver,
index a3c5de9d547a4b082cb52e60dc23ff721cf66b27..533e912af0893a0786a7436b88512cb65e9a5d63 100644 (file)
@@ -1769,10 +1769,12 @@ int wx_sw_init(struct wx *wx)
                wx->subsystem_device_id = pdev->subsystem_device;
        } else {
                err = wx_flash_read_dword(wx, 0xfffdc, &ssid);
-               if (!err)
-                       wx->subsystem_device_id = swab16((u16)ssid);
+               if (err < 0) {
+                       wx_err(wx, "read of internal subsystem device id failed\n");
+                       return err;
+               }
 
-               return err;
+               wx->subsystem_device_id = swab16((u16)ssid);
        }
 
        wx->mac_table = kcalloc(wx->mac.num_rar_entries,
index 3d43f808c86b784d60aaa1eb8d90769fcedbafba..8db804543e66da8a39e1246a95d0e0622c1f5d94 100644 (file)
@@ -121,10 +121,8 @@ static int ngbe_sw_init(struct wx *wx)
 
        /* PCI config space info */
        err = wx_sw_init(wx);
-       if (err < 0) {
-               wx_err(wx, "read of internal subsystem device id failed\n");
+       if (err < 0)
                return err;
-       }
 
        /* mac type, phy type , oem type */
        ngbe_init_type_code(wx);
index 70f0b5c01dacf2dbd29c2322551ae146fa07baa4..526250102db27c139c140fac7dfd0117c566426b 100644 (file)
@@ -364,10 +364,8 @@ static int txgbe_sw_init(struct wx *wx)
 
        /* PCI config space info */
        err = wx_sw_init(wx);
-       if (err < 0) {
-               wx_err(wx, "read of internal subsystem device id failed\n");
+       if (err < 0)
                return err;
-       }
 
        txgbe_init_type_code(wx);
 
index 82d0d44b2b02f1b564ce3502a2534f269566959f..bf6e33990490922851d029ffb7f42bad444964f8 100644 (file)
@@ -822,7 +822,7 @@ axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                if (lp->features & XAE_FEATURE_FULL_TX_CSUM) {
                        /* Tx Full Checksum Offload Enabled */
                        cur_p->app0 |= 2;
-               } else if (lp->features & XAE_FEATURE_PARTIAL_RX_CSUM) {
+               } else if (lp->features & XAE_FEATURE_PARTIAL_TX_CSUM) {
                        csum_start_off = skb_transport_offset(skb);
                        csum_index_off = csum_start_off + skb->csum_offset;
                        /* Tx Partial Checksum Offload Enabled */
index 3ba3c8fb28a5d692c268b243a2fcfb893a31c36e..706ea5263e879df8b4bff89cd4408e151f4615cd 100644 (file)
@@ -2206,9 +2206,6 @@ static int netvsc_vf_join(struct net_device *vf_netdev,
                goto upper_link_failed;
        }
 
-       /* set slave flag before open to prevent IPv6 addrconf */
-       vf_netdev->flags |= IFF_SLAVE;
-
        schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT);
 
        call_netdevice_notifiers(NETDEV_JOIN, vf_netdev);
@@ -2315,16 +2312,18 @@ static struct net_device *get_netvsc_byslot(const struct net_device *vf_netdev)
 
        }
 
-       /* Fallback path to check synthetic vf with
-        * help of mac addr
+       /* Fallback path to check synthetic vf with help of mac addr.
+        * Because this function can be called before vf_netdev is
+        * initialized (NETDEV_POST_INIT) when its perm_addr has not been copied
+        * from dev_addr, also try to match to its dev_addr.
+        * Note: On Hyper-V and Azure, it's not possible to set a MAC address
+        * on a VF that matches to the MAC of a unrelated NETVSC device.
         */
        list_for_each_entry(ndev_ctx, &netvsc_dev_list, list) {
                ndev = hv_get_drvdata(ndev_ctx->device_ctx);
-               if (ether_addr_equal(vf_netdev->perm_addr, ndev->perm_addr)) {
-                       netdev_notice(vf_netdev,
-                                     "falling back to mac addr based matching\n");
+               if (ether_addr_equal(vf_netdev->perm_addr, ndev->perm_addr) ||
+                   ether_addr_equal(vf_netdev->dev_addr, ndev->perm_addr))
                        return ndev;
-               }
        }
 
        netdev_notice(vf_netdev,
@@ -2332,6 +2331,19 @@ static struct net_device *get_netvsc_byslot(const struct net_device *vf_netdev)
        return NULL;
 }
 
+static int netvsc_prepare_bonding(struct net_device *vf_netdev)
+{
+       struct net_device *ndev;
+
+       ndev = get_netvsc_byslot(vf_netdev);
+       if (!ndev)
+               return NOTIFY_DONE;
+
+       /* set slave flag before open to prevent IPv6 addrconf */
+       vf_netdev->flags |= IFF_SLAVE;
+       return NOTIFY_DONE;
+}
+
 static int netvsc_register_vf(struct net_device *vf_netdev)
 {
        struct net_device_context *net_device_ctx;
@@ -2531,15 +2543,6 @@ static int netvsc_probe(struct hv_device *dev,
                goto devinfo_failed;
        }
 
-       nvdev = rndis_filter_device_add(dev, device_info);
-       if (IS_ERR(nvdev)) {
-               ret = PTR_ERR(nvdev);
-               netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
-               goto rndis_failed;
-       }
-
-       eth_hw_addr_set(net, device_info->mac_adr);
-
        /* We must get rtnl lock before scheduling nvdev->subchan_work,
         * otherwise netvsc_subchan_work() can get rtnl lock first and wait
         * all subchannels to show up, but that may not happen because
@@ -2547,9 +2550,23 @@ static int netvsc_probe(struct hv_device *dev,
         * -> ... -> device_add() -> ... -> __device_attach() can't get
         * the device lock, so all the subchannels can't be processed --
         * finally netvsc_subchan_work() hangs forever.
+        *
+        * The rtnl lock also needs to be held before rndis_filter_device_add()
+        * which advertises nvsp_2_vsc_capability / sriov bit, and triggers
+        * VF NIC offering and registering. If VF NIC finished register_netdev()
+        * earlier it may cause name based config failure.
         */
        rtnl_lock();
 
+       nvdev = rndis_filter_device_add(dev, device_info);
+       if (IS_ERR(nvdev)) {
+               ret = PTR_ERR(nvdev);
+               netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
+               goto rndis_failed;
+       }
+
+       eth_hw_addr_set(net, device_info->mac_adr);
+
        if (nvdev->num_chn > 1)
                schedule_work(&nvdev->subchan_work);
 
@@ -2586,9 +2603,9 @@ static int netvsc_probe(struct hv_device *dev,
        return 0;
 
 register_failed:
-       rtnl_unlock();
        rndis_filter_device_remove(dev, nvdev);
 rndis_failed:
+       rtnl_unlock();
        netvsc_devinfo_put(device_info);
 devinfo_failed:
        free_percpu(net_device_ctx->vf_stats);
@@ -2753,6 +2770,8 @@ static int netvsc_netdev_event(struct notifier_block *this,
                return NOTIFY_DONE;
 
        switch (event) {
+       case NETDEV_POST_INIT:
+               return netvsc_prepare_bonding(event_dev);
        case NETDEV_REGISTER:
                return netvsc_register_vf(event_dev);
        case NETDEV_UNREGISTER:
@@ -2788,12 +2807,17 @@ static int __init netvsc_drv_init(void)
        }
        netvsc_ring_bytes = ring_size * PAGE_SIZE;
 
+       register_netdevice_notifier(&netvsc_netdev_notifier);
+
        ret = vmbus_driver_register(&netvsc_drv);
        if (ret)
-               return ret;
+               goto err_vmbus_reg;
 
-       register_netdevice_notifier(&netvsc_netdev_notifier);
        return 0;
+
+err_vmbus_reg:
+       unregister_netdevice_notifier(&netvsc_netdev_notifier);
+       return ret;
 }
 
 MODULE_LICENSE("GPL");
index d7b81a36d673bbe7d6d7a1dab376b2c4be6347f8..145eb0bd096d60466b4bde042d1fc7873830ecb6 100644 (file)
@@ -78,7 +78,7 @@ REG_STRIDE_FIELDS(EV_CH_E_CNTXT_0, ev_ch_e_cntxt_0,
                  0x0001c000 + 0x12000 * GSI_EE_AP, 0x80);
 
 static const u32 reg_ev_ch_e_cntxt_1_fmask[] = {
-       [R_LENGTH]                                      = GENMASK(19, 0),
+       [R_LENGTH]                                      = GENMASK(23, 0),
 };
 
 REG_STRIDE_FIELDS(EV_CH_E_CNTXT_1, ev_ch_e_cntxt_1,
index 5a0f86f38f093123c010beea5ac39c2cda031ec8..97bd6705c24117cff255ebbe34fc9efc4c0da2bd 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/filter.h>
 #include <linux/netfilter_netdev.h>
 #include <linux/bpf_mprog.h>
+#include <linux/indirect_call_wrapper.h>
 
 #include <net/netkit.h>
 #include <net/dst.h>
@@ -68,6 +69,7 @@ static netdev_tx_t netkit_xmit(struct sk_buff *skb, struct net_device *dev)
        netdev_tx_t ret_dev = NET_XMIT_SUCCESS;
        const struct bpf_mprog_entry *entry;
        struct net_device *peer;
+       int len = skb->len;
 
        rcu_read_lock();
        peer = rcu_dereference(nk->peer);
@@ -85,15 +87,22 @@ static netdev_tx_t netkit_xmit(struct sk_buff *skb, struct net_device *dev)
        case NETKIT_PASS:
                skb->protocol = eth_type_trans(skb, skb->dev);
                skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
-               __netif_rx(skb);
+               if (likely(__netif_rx(skb) == NET_RX_SUCCESS)) {
+                       dev_sw_netstats_tx_add(dev, 1, len);
+                       dev_sw_netstats_rx_add(peer, len);
+               } else {
+                       goto drop_stats;
+               }
                break;
        case NETKIT_REDIRECT:
+               dev_sw_netstats_tx_add(dev, 1, len);
                skb_do_redirect(skb);
                break;
        case NETKIT_DROP:
        default:
 drop:
                kfree_skb(skb);
+drop_stats:
                dev_core_stats_tx_dropped_inc(dev);
                ret_dev = NET_XMIT_DROP;
                break;
@@ -169,11 +178,18 @@ out:
        rcu_read_unlock();
 }
 
-static struct net_device *netkit_peer_dev(struct net_device *dev)
+INDIRECT_CALLABLE_SCOPE struct net_device *netkit_peer_dev(struct net_device *dev)
 {
        return rcu_dereference(netkit_priv(dev)->peer);
 }
 
+static void netkit_get_stats(struct net_device *dev,
+                            struct rtnl_link_stats64 *stats)
+{
+       dev_fetch_sw_netstats(stats, dev->tstats);
+       stats->tx_dropped = DEV_STATS_READ(dev, tx_dropped);
+}
+
 static void netkit_uninit(struct net_device *dev);
 
 static const struct net_device_ops netkit_netdev_ops = {
@@ -184,6 +200,7 @@ static const struct net_device_ops netkit_netdev_ops = {
        .ndo_set_rx_headroom    = netkit_set_headroom,
        .ndo_get_iflink         = netkit_get_iflink,
        .ndo_get_peer_dev       = netkit_peer_dev,
+       .ndo_get_stats64        = netkit_get_stats,
        .ndo_uninit             = netkit_uninit,
        .ndo_features_check     = passthru_features_check,
 };
@@ -218,6 +235,7 @@ static void netkit_setup(struct net_device *dev)
 
        ether_setup(dev);
        dev->max_mtu = ETH_MAX_MTU;
+       dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
 
        dev->flags |= IFF_NOARP;
        dev->priv_flags &= ~IFF_TX_SKB_SHARING;
index a017e9de2119d5f5163981b9777e13e94f523f86..7b8afa589a53c457ef07878f207ddbaafa668c54 100644 (file)
@@ -1079,17 +1079,17 @@ static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
        u16 pkt_count = 0;
        u64 desc_hdr = 0;
        u16 vlan_tag = 0;
-       u32 skb_len = 0;
+       u32 skb_len;
 
        if (!skb)
                goto err;
 
-       if (skb->len == 0)
+       skb_len = skb->len;
+       if (skb_len < sizeof(desc_hdr))
                goto err;
 
-       skb_len = skb->len;
        /* RX Descriptor Header */
-       skb_trim(skb, skb->len - sizeof(desc_hdr));
+       skb_trim(skb, skb_len - sizeof(desc_hdr));
        desc_hdr = le64_to_cpup((u64 *)skb_tail_pointer(skb));
 
        /* Check these packets */
index aff39bf3161ded7e5a67289c6cbdac0eacbf0ef0..4ea0e155bb0d5d82d9e3f6f2ffce2f4266e552b7 100644 (file)
@@ -1583,11 +1583,11 @@ static int ax88179_reset(struct usbnet *dev)
 
        *tmp16 = AX_PHYPWR_RSTCTL_IPRL;
        ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16);
-       msleep(200);
+       msleep(500);
 
        *tmp = AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS;
        ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, tmp);
-       msleep(100);
+       msleep(200);
 
        /* Ethernet PHY Auto Detach*/
        ax88179_auto_detach(dev);
index 344af3c5c836683db6e1183214391353df0009d3..e2e181378f4124c64b1d02bbe910f6209b57a356 100644 (file)
@@ -1289,6 +1289,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x19d2, 0x0168, 4)},
        {QMI_FIXED_INTF(0x19d2, 0x0176, 3)},
        {QMI_FIXED_INTF(0x19d2, 0x0178, 3)},
+       {QMI_FIXED_INTF(0x19d2, 0x0189, 4)},    /* ZTE MF290 */
        {QMI_FIXED_INTF(0x19d2, 0x0191, 4)},    /* ZTE EuFi890 */
        {QMI_FIXED_INTF(0x19d2, 0x0199, 1)},    /* ZTE MF820S */
        {QMI_FIXED_INTF(0x19d2, 0x0200, 1)},
index 9980517ed8b0d1bbe26083a8fcdfd217a58bfd63..57efb3454c57aca0c5bf4e790226f2c7176c8468 100644 (file)
@@ -236,8 +236,8 @@ static void veth_get_ethtool_stats(struct net_device *dev,
                                data[tx_idx + j] += *(u64 *)(base + offset);
                        }
                } while (u64_stats_fetch_retry(&rq_stats->syncp, start));
-               pp_idx = tx_idx + VETH_TQ_STATS_LEN;
        }
+       pp_idx = idx + dev->real_num_tx_queues * VETH_TQ_STATS_LEN;
 
 page_pool_stats:
        veth_get_page_pool_stats(dev, &data[pp_idx]);
@@ -373,7 +373,7 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
        skb_tx_timestamp(skb);
        if (likely(veth_forward_skb(rcv, skb, rq, use_napi) == NET_RX_SUCCESS)) {
                if (!use_napi)
-                       dev_lstats_add(dev, length);
+                       dev_sw_netstats_tx_add(dev, 1, length);
                else
                        __veth_xdp_flush(rq);
        } else {
@@ -387,14 +387,6 @@ drop:
        return ret;
 }
 
-static u64 veth_stats_tx(struct net_device *dev, u64 *packets, u64 *bytes)
-{
-       struct veth_priv *priv = netdev_priv(dev);
-
-       dev_lstats_read(dev, packets, bytes);
-       return atomic64_read(&priv->dropped);
-}
-
 static void veth_stats_rx(struct veth_stats *result, struct net_device *dev)
 {
        struct veth_priv *priv = netdev_priv(dev);
@@ -432,24 +424,24 @@ static void veth_get_stats64(struct net_device *dev,
        struct veth_priv *priv = netdev_priv(dev);
        struct net_device *peer;
        struct veth_stats rx;
-       u64 packets, bytes;
 
-       tot->tx_dropped = veth_stats_tx(dev, &packets, &bytes);
-       tot->tx_bytes = bytes;
-       tot->tx_packets = packets;
+       tot->tx_dropped = atomic64_read(&priv->dropped);
+       dev_fetch_sw_netstats(tot, dev->tstats);
 
        veth_stats_rx(&rx, dev);
        tot->tx_dropped += rx.xdp_tx_err;
        tot->rx_dropped = rx.rx_drops + rx.peer_tq_xdp_xmit_err;
-       tot->rx_bytes = rx.xdp_bytes;
-       tot->rx_packets = rx.xdp_packets;
+       tot->rx_bytes += rx.xdp_bytes;
+       tot->rx_packets += rx.xdp_packets;
 
        rcu_read_lock();
        peer = rcu_dereference(priv->peer);
        if (peer) {
-               veth_stats_tx(peer, &packets, &bytes);
-               tot->rx_bytes += bytes;
-               tot->rx_packets += packets;
+               struct rtnl_link_stats64 tot_peer = {};
+
+               dev_fetch_sw_netstats(&tot_peer, peer->tstats);
+               tot->rx_bytes += tot_peer.tx_bytes;
+               tot->rx_packets += tot_peer.tx_packets;
 
                veth_stats_rx(&rx, peer);
                tot->tx_dropped += rx.peer_tq_xdp_xmit_err;
@@ -1506,25 +1498,12 @@ static void veth_free_queues(struct net_device *dev)
 
 static int veth_dev_init(struct net_device *dev)
 {
-       int err;
-
-       dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats);
-       if (!dev->lstats)
-               return -ENOMEM;
-
-       err = veth_alloc_queues(dev);
-       if (err) {
-               free_percpu(dev->lstats);
-               return err;
-       }
-
-       return 0;
+       return veth_alloc_queues(dev);
 }
 
 static void veth_dev_free(struct net_device *dev)
 {
        veth_free_queues(dev);
-       free_percpu(dev->lstats);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1796,6 +1775,7 @@ static void veth_setup(struct net_device *dev)
                               NETIF_F_HW_VLAN_STAG_RX);
        dev->needs_free_netdev = true;
        dev->priv_destructor = veth_dev_free;
+       dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
        dev->max_mtu = ETH_MAX_MTU;
 
        dev->hw_features = VETH_FEATURES;
index db766941b78f67690aae4b0a653af4efa3453e94..bb95ce43cd97d3827e3499ca29bb2f8b51961e1d 100644 (file)
@@ -121,22 +121,12 @@ struct net_vrf {
        int                     ifindex;
 };
 
-struct pcpu_dstats {
-       u64                     tx_pkts;
-       u64                     tx_bytes;
-       u64                     tx_drps;
-       u64                     rx_pkts;
-       u64                     rx_bytes;
-       u64                     rx_drps;
-       struct u64_stats_sync   syncp;
-};
-
 static void vrf_rx_stats(struct net_device *dev, int len)
 {
        struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
 
        u64_stats_update_begin(&dstats->syncp);
-       dstats->rx_pkts++;
+       dstats->rx_packets++;
        dstats->rx_bytes += len;
        u64_stats_update_end(&dstats->syncp);
 }
@@ -161,10 +151,10 @@ static void vrf_get_stats64(struct net_device *dev,
                do {
                        start = u64_stats_fetch_begin(&dstats->syncp);
                        tbytes = dstats->tx_bytes;
-                       tpkts = dstats->tx_pkts;
-                       tdrops = dstats->tx_drps;
+                       tpkts = dstats->tx_packets;
+                       tdrops = dstats->tx_drops;
                        rbytes = dstats->rx_bytes;
-                       rpkts = dstats->rx_pkts;
+                       rpkts = dstats->rx_packets;
                } while (u64_stats_fetch_retry(&dstats->syncp, start));
                stats->tx_bytes += tbytes;
                stats->tx_packets += tpkts;
@@ -421,7 +411,7 @@ static int vrf_local_xmit(struct sk_buff *skb, struct net_device *dev,
        if (likely(__netif_rx(skb) == NET_RX_SUCCESS))
                vrf_rx_stats(dev, len);
        else
-               this_cpu_inc(dev->dstats->rx_drps);
+               this_cpu_inc(dev->dstats->rx_drops);
 
        return NETDEV_TX_OK;
 }
@@ -616,11 +606,11 @@ static netdev_tx_t vrf_xmit(struct sk_buff *skb, struct net_device *dev)
                struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
 
                u64_stats_update_begin(&dstats->syncp);
-               dstats->tx_pkts++;
+               dstats->tx_packets++;
                dstats->tx_bytes += len;
                u64_stats_update_end(&dstats->syncp);
        } else {
-               this_cpu_inc(dev->dstats->tx_drps);
+               this_cpu_inc(dev->dstats->tx_drops);
        }
 
        return ret;
@@ -1174,22 +1164,15 @@ static void vrf_dev_uninit(struct net_device *dev)
 
        vrf_rtable_release(dev, vrf);
        vrf_rt6_release(dev, vrf);
-
-       free_percpu(dev->dstats);
-       dev->dstats = NULL;
 }
 
 static int vrf_dev_init(struct net_device *dev)
 {
        struct net_vrf *vrf = netdev_priv(dev);
 
-       dev->dstats = netdev_alloc_pcpu_stats(struct pcpu_dstats);
-       if (!dev->dstats)
-               goto out_nomem;
-
        /* create the default dst which points back to us */
        if (vrf_rtable_create(dev) != 0)
-               goto out_stats;
+               goto out_nomem;
 
        if (vrf_rt6_create(dev) != 0)
                goto out_rth;
@@ -1203,9 +1186,6 @@ static int vrf_dev_init(struct net_device *dev)
 
 out_rth:
        vrf_rtable_release(dev, vrf);
-out_stats:
-       free_percpu(dev->dstats);
-       dev->dstats = NULL;
 out_nomem:
        return -ENOMEM;
 }
@@ -1704,6 +1684,8 @@ static void vrf_setup(struct net_device *dev)
        dev->min_mtu = IPV6_MIN_MTU;
        dev->max_mtu = IP6_MAX_MTU;
        dev->mtu = dev->max_mtu;
+
+       dev->pcpu_stat_type = NETDEV_PCPU_STAT_DSTATS;
 }
 
 static int vrf_validate(struct nlattr *tb[], struct nlattr *data[],
index 258dcc1039216f311a223fd348295d4b5e03a3ed..deb9636b0ecf8f47e832a0b07e9e049ba19bdf16 100644 (file)
@@ -210,7 +210,7 @@ static netdev_tx_t wg_xmit(struct sk_buff *skb, struct net_device *dev)
         */
        while (skb_queue_len(&peer->staged_packet_queue) > MAX_STAGED_PACKETS) {
                dev_kfree_skb(__skb_dequeue(&peer->staged_packet_queue));
-               ++dev->stats.tx_dropped;
+               DEV_STATS_INC(dev, tx_dropped);
        }
        skb_queue_splice_tail(&packets, &peer->staged_packet_queue);
        spin_unlock_bh(&peer->staged_packet_queue.lock);
@@ -228,7 +228,7 @@ err_icmp:
        else if (skb->protocol == htons(ETH_P_IPV6))
                icmpv6_ndo_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0);
 err:
-       ++dev->stats.tx_errors;
+       DEV_STATS_INC(dev, tx_errors);
        kfree_skb(skb);
        return ret;
 }
index 0b3f0c843550957ee1fe3bed7185a7d990246c2b..a176653c88616b1bc871fe52fcea778b5e189f69 100644 (file)
@@ -416,20 +416,20 @@ dishonest_packet_peer:
        net_dbg_skb_ratelimited("%s: Packet has unallowed src IP (%pISc) from peer %llu (%pISpfsc)\n",
                                dev->name, skb, peer->internal_id,
                                &peer->endpoint.addr);
-       ++dev->stats.rx_errors;
-       ++dev->stats.rx_frame_errors;
+       DEV_STATS_INC(dev, rx_errors);
+       DEV_STATS_INC(dev, rx_frame_errors);
        goto packet_processed;
 dishonest_packet_type:
        net_dbg_ratelimited("%s: Packet is neither ipv4 nor ipv6 from peer %llu (%pISpfsc)\n",
                            dev->name, peer->internal_id, &peer->endpoint.addr);
-       ++dev->stats.rx_errors;
-       ++dev->stats.rx_frame_errors;
+       DEV_STATS_INC(dev, rx_errors);
+       DEV_STATS_INC(dev, rx_frame_errors);
        goto packet_processed;
 dishonest_packet_size:
        net_dbg_ratelimited("%s: Packet has incorrect size from peer %llu (%pISpfsc)\n",
                            dev->name, peer->internal_id, &peer->endpoint.addr);
-       ++dev->stats.rx_errors;
-       ++dev->stats.rx_length_errors;
+       DEV_STATS_INC(dev, rx_errors);
+       DEV_STATS_INC(dev, rx_length_errors);
        goto packet_processed;
 packet_processed:
        dev_kfree_skb(skb);
index 95c853b59e1dae1df8b4e5cbf4e3541e35806b82..0d48e0f4a1ba3e1f11825136a65de0867b204496 100644 (file)
@@ -333,7 +333,8 @@ err:
 void wg_packet_purge_staged_packets(struct wg_peer *peer)
 {
        spin_lock_bh(&peer->staged_packet_queue.lock);
-       peer->device->dev->stats.tx_dropped += peer->staged_packet_queue.qlen;
+       DEV_STATS_ADD(peer->device->dev, tx_dropped,
+                     peer->staged_packet_queue.qlen);
        __skb_queue_purge(&peer->staged_packet_queue);
        spin_unlock_bh(&peer->staged_packet_queue.lock);
 }
index b027be0b0b6ff7781ebeab9ee9b5304a4f2f6d15..590b038e449e5c61c9950ce6074fe94020915207 100644 (file)
@@ -26,10 +26,14 @@ struct virtual_nci_dev {
        struct mutex mtx;
        struct sk_buff *send_buff;
        struct wait_queue_head wq;
+       bool running;
 };
 
 static int virtual_nci_open(struct nci_dev *ndev)
 {
+       struct virtual_nci_dev *vdev = nci_get_drvdata(ndev);
+
+       vdev->running = true;
        return 0;
 }
 
@@ -40,6 +44,7 @@ static int virtual_nci_close(struct nci_dev *ndev)
        mutex_lock(&vdev->mtx);
        kfree_skb(vdev->send_buff);
        vdev->send_buff = NULL;
+       vdev->running = false;
        mutex_unlock(&vdev->mtx);
 
        return 0;
@@ -50,7 +55,7 @@ static int virtual_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
        struct virtual_nci_dev *vdev = nci_get_drvdata(ndev);
 
        mutex_lock(&vdev->mtx);
-       if (vdev->send_buff) {
+       if (vdev->send_buff || !vdev->running) {
                mutex_unlock(&vdev->mtx);
                kfree_skb(skb);
                return -1;
index 48328e36e93bc423974f5089a4ee5fd0bbcc9a6d..72c0525c75f503bb56c7c246c733f9eea57e44ab 100644 (file)
@@ -757,12 +757,11 @@ static void nvme_queue_auth_work(struct work_struct *work)
                __func__, chap->qid);
        mutex_lock(&ctrl->dhchap_auth_mutex);
        ret = nvme_auth_dhchap_setup_host_response(ctrl, chap);
+       mutex_unlock(&ctrl->dhchap_auth_mutex);
        if (ret) {
-               mutex_unlock(&ctrl->dhchap_auth_mutex);
                chap->error = ret;
                goto fail2;
        }
-       mutex_unlock(&ctrl->dhchap_auth_mutex);
 
        /* DH-HMAC-CHAP Step 3: send reply */
        dev_dbg(ctrl->device, "%s: qid %d send reply\n",
@@ -839,6 +838,8 @@ static void nvme_queue_auth_work(struct work_struct *work)
        }
 
 fail2:
+       if (chap->status == 0)
+               chap->status = NVME_AUTH_DHCHAP_FAILURE_FAILED;
        dev_dbg(ctrl->device, "%s: qid %d send failure2, status %x\n",
                __func__, chap->qid, chap->status);
        tl = nvme_auth_set_dhchap_failure2_data(ctrl, chap);
index 88b54cdcbd683cd3e7f0a26742aff156ad4c57b5..46a4c9c5ea9625c7feb11d970ebb95cd4ce8be2b 100644 (file)
@@ -482,7 +482,6 @@ EXPORT_SYMBOL_GPL(nvme_cancel_tagset);
 
 void nvme_cancel_admin_tagset(struct nvme_ctrl *ctrl)
 {
-       nvme_stop_keep_alive(ctrl);
        if (ctrl->admin_tagset) {
                blk_mq_tagset_busy_iter(ctrl->admin_tagset,
                                nvme_cancel_request, ctrl);
@@ -1814,16 +1813,18 @@ set_pi:
        return ret;
 }
 
-static void nvme_configure_metadata(struct nvme_ns *ns, struct nvme_id_ns *id)
+static int nvme_configure_metadata(struct nvme_ns *ns, struct nvme_id_ns *id)
 {
        struct nvme_ctrl *ctrl = ns->ctrl;
+       int ret;
 
-       if (nvme_init_ms(ns, id))
-               return;
+       ret = nvme_init_ms(ns, id);
+       if (ret)
+               return ret;
 
        ns->features &= ~(NVME_NS_METADATA_SUPPORTED | NVME_NS_EXT_LBAS);
        if (!ns->ms || !(ctrl->ops->flags & NVME_F_METADATA_SUPPORTED))
-               return;
+               return 0;
 
        if (ctrl->ops->flags & NVME_F_FABRICS) {
                /*
@@ -1832,7 +1833,7 @@ static void nvme_configure_metadata(struct nvme_ns *ns, struct nvme_id_ns *id)
                 * remap the separate metadata buffer from the block layer.
                 */
                if (WARN_ON_ONCE(!(id->flbas & NVME_NS_FLBAS_META_EXT)))
-                       return;
+                       return 0;
 
                ns->features |= NVME_NS_EXT_LBAS;
 
@@ -1859,6 +1860,7 @@ static void nvme_configure_metadata(struct nvme_ns *ns, struct nvme_id_ns *id)
                else
                        ns->features |= NVME_NS_METADATA_SUPPORTED;
        }
+       return 0;
 }
 
 static void nvme_set_queue_limits(struct nvme_ctrl *ctrl,
@@ -2032,7 +2034,11 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
        ns->lba_shift = id->lbaf[lbaf].ds;
        nvme_set_queue_limits(ns->ctrl, ns->queue);
 
-       nvme_configure_metadata(ns, id);
+       ret = nvme_configure_metadata(ns, id);
+       if (ret < 0) {
+               blk_mq_unfreeze_queue(ns->disk->queue);
+               goto out;
+       }
        nvme_set_chunk_sectors(ns, id);
        nvme_update_disk_info(ns->disk, ns, id);
 
@@ -4348,6 +4354,7 @@ void nvme_stop_ctrl(struct nvme_ctrl *ctrl)
 {
        nvme_mpath_stop(ctrl);
        nvme_auth_stop(ctrl);
+       nvme_stop_keep_alive(ctrl);
        nvme_stop_failfast_work(ctrl);
        flush_work(&ctrl->async_event_work);
        cancel_work_sync(&ctrl->fw_act_work);
index 4673ead69c5f9d9b9e51729ece745b56363989de..aa88606a44c40f2b88c1cb8c0286d57632960755 100644 (file)
@@ -667,8 +667,10 @@ static const match_table_t opt_tokens = {
 #endif
        { NVMF_OPT_FAIL_FAST_TMO,       "fast_io_fail_tmo=%d"   },
        { NVMF_OPT_DISCOVERY,           "discovery"             },
+#ifdef CONFIG_NVME_HOST_AUTH
        { NVMF_OPT_DHCHAP_SECRET,       "dhchap_secret=%s"      },
        { NVMF_OPT_DHCHAP_CTRL_SECRET,  "dhchap_ctrl_secret=%s" },
+#endif
 #ifdef CONFIG_NVME_TCP_TLS
        { NVMF_OPT_TLS,                 "tls"                   },
 #endif
index 49c3e46eaa1eee13b1174044104072dc6390990f..9f9a3b35dc64d3ea03c6fea85599279e2b46b3da 100644 (file)
@@ -2530,12 +2530,6 @@ __nvme_fc_abort_outstanding_ios(struct nvme_fc_ctrl *ctrl, bool start_queues)
         * clean up the admin queue. Same thing as above.
         */
        nvme_quiesce_admin_queue(&ctrl->ctrl);
-
-       /*
-        * Open-coding nvme_cancel_admin_tagset() as fc
-        * is not using nvme_cancel_request().
-        */
-       nvme_stop_keep_alive(&ctrl->ctrl);
        blk_sync_queue(ctrl->ctrl.admin_q);
        blk_mq_tagset_busy_iter(&ctrl->admin_tag_set,
                                nvme_fc_terminate_exchange, &ctrl->ctrl);
@@ -3138,11 +3132,12 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
        nvme_unquiesce_admin_queue(&ctrl->ctrl);
 
        ret = nvme_init_ctrl_finish(&ctrl->ctrl, false);
-       if (!ret && test_bit(ASSOC_FAILED, &ctrl->flags))
-               ret = -EIO;
        if (ret)
                goto out_disconnect_admin_queue;
-
+       if (test_bit(ASSOC_FAILED, &ctrl->flags)) {
+               ret = -EIO;
+               goto out_stop_keep_alive;
+       }
        /* sanity checks */
 
        /* FC-NVME does not have other data in the capsule */
@@ -3150,7 +3145,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
                dev_err(ctrl->ctrl.device, "icdoff %d is not supported!\n",
                                ctrl->ctrl.icdoff);
                ret = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
-               goto out_disconnect_admin_queue;
+               goto out_stop_keep_alive;
        }
 
        /* FC-NVME supports normal SGL Data Block Descriptors */
@@ -3158,7 +3153,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
                dev_err(ctrl->ctrl.device,
                        "Mandatory sgls are not supported!\n");
                ret = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
-               goto out_disconnect_admin_queue;
+               goto out_stop_keep_alive;
        }
 
        if (opts->queue_size > ctrl->ctrl.maxcmd) {
@@ -3205,6 +3200,8 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
 
 out_term_aen_ops:
        nvme_fc_term_aen_ops(ctrl);
+out_stop_keep_alive:
+       nvme_stop_keep_alive(&ctrl->ctrl);
 out_disconnect_admin_queue:
        dev_warn(ctrl->ctrl.device,
                "NVME-FC{%d}: create_assoc failed, assoc_id %llx ret %d\n",
index a7fea4cbacd753cfdf59b2a71c1420c7499b561e..6d178d5559204dc522bd5513663032134da2a410 100644 (file)
@@ -1080,6 +1080,7 @@ destroy_io:
                nvme_rdma_free_io_queues(ctrl);
        }
 destroy_admin:
+       nvme_stop_keep_alive(&ctrl->ctrl);
        nvme_quiesce_admin_queue(&ctrl->ctrl);
        blk_sync_queue(ctrl->ctrl.admin_q);
        nvme_rdma_stop_queue(&ctrl->queues[0]);
index 89661a9cf850d493d0ff6e69b60a5525154cfbc4..d79811cfa0ce88e4d50f57f4e6938e0436eeaa86 100644 (file)
@@ -36,11 +36,11 @@ static int so_priority;
 module_param(so_priority, int, 0644);
 MODULE_PARM_DESC(so_priority, "nvme tcp socket optimize priority");
 
-#ifdef CONFIG_NVME_TCP_TLS
 /*
  * TLS handshake timeout
  */
 static int tls_handshake_timeout = 10;
+#ifdef CONFIG_NVME_TCP_TLS
 module_param(tls_handshake_timeout, int, 0644);
 MODULE_PARM_DESC(tls_handshake_timeout,
                 "nvme TLS handshake timeout in seconds (default 10)");
@@ -161,10 +161,8 @@ struct nvme_tcp_queue {
        struct ahash_request    *snd_hash;
        __le32                  exp_ddgst;
        __le32                  recv_ddgst;
-#ifdef CONFIG_NVME_TCP_TLS
        struct completion       tls_complete;
        int                     tls_err;
-#endif
        struct page_frag_cache  pf_cache;
 
        void (*state_change)(struct sock *);
@@ -207,6 +205,14 @@ static inline int nvme_tcp_queue_id(struct nvme_tcp_queue *queue)
        return queue - queue->ctrl->queues;
 }
 
+static inline bool nvme_tcp_tls(struct nvme_ctrl *ctrl)
+{
+       if (!IS_ENABLED(CONFIG_NVME_TCP_TLS))
+               return 0;
+
+       return ctrl->opts->tls;
+}
+
 static inline struct blk_mq_tags *nvme_tcp_tagset(struct nvme_tcp_queue *queue)
 {
        u32 queue_idx = nvme_tcp_queue_id(queue);
@@ -1412,7 +1418,7 @@ static int nvme_tcp_init_connection(struct nvme_tcp_queue *queue)
        memset(&msg, 0, sizeof(msg));
        iov.iov_base = icresp;
        iov.iov_len = sizeof(*icresp);
-       if (queue->ctrl->ctrl.opts->tls) {
+       if (nvme_tcp_tls(&queue->ctrl->ctrl)) {
                msg.msg_control = cbuf;
                msg.msg_controllen = sizeof(cbuf);
        }
@@ -1424,7 +1430,7 @@ static int nvme_tcp_init_connection(struct nvme_tcp_queue *queue)
                goto free_icresp;
        }
        ret = -ENOTCONN;
-       if (queue->ctrl->ctrl.opts->tls) {
+       if (nvme_tcp_tls(&queue->ctrl->ctrl)) {
                ctype = tls_get_record_type(queue->sock->sk,
                                            (struct cmsghdr *)cbuf);
                if (ctype != TLS_RECORD_TYPE_DATA) {
@@ -1548,7 +1554,6 @@ static void nvme_tcp_set_queue_io_cpu(struct nvme_tcp_queue *queue)
        queue->io_cpu = cpumask_next_wrap(n - 1, cpu_online_mask, -1, false);
 }
 
-#ifdef CONFIG_NVME_TCP_TLS
 static void nvme_tcp_tls_done(void *data, int status, key_serial_t pskid)
 {
        struct nvme_tcp_queue *queue = data;
@@ -1625,14 +1630,6 @@ static int nvme_tcp_start_tls(struct nvme_ctrl *nctrl,
        }
        return ret;
 }
-#else
-static int nvme_tcp_start_tls(struct nvme_ctrl *nctrl,
-                             struct nvme_tcp_queue *queue,
-                             key_serial_t pskid)
-{
-       return -EPROTONOSUPPORT;
-}
-#endif
 
 static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
                                key_serial_t pskid)
@@ -1759,7 +1756,7 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
        }
 
        /* If PSKs are configured try to start TLS */
-       if (pskid) {
+       if (IS_ENABLED(CONFIG_NVME_TCP_TLS) && pskid) {
                ret = nvme_tcp_start_tls(nctrl, queue, pskid);
                if (ret)
                        goto err_init_connect;
@@ -1916,7 +1913,7 @@ static int nvme_tcp_alloc_admin_queue(struct nvme_ctrl *ctrl)
        int ret;
        key_serial_t pskid = 0;
 
-       if (ctrl->opts->tls) {
+       if (nvme_tcp_tls(ctrl)) {
                if (ctrl->opts->tls_key)
                        pskid = key_serial(ctrl->opts->tls_key);
                else
@@ -1949,7 +1946,7 @@ static int __nvme_tcp_alloc_io_queues(struct nvme_ctrl *ctrl)
 {
        int i, ret;
 
-       if (ctrl->opts->tls && !ctrl->tls_key) {
+       if (nvme_tcp_tls(ctrl) && !ctrl->tls_key) {
                dev_err(ctrl->device, "no PSK negotiated\n");
                return -ENOKEY;
        }
@@ -2237,6 +2234,7 @@ destroy_io:
                nvme_tcp_destroy_io_queues(ctrl, new);
        }
 destroy_admin:
+       nvme_stop_keep_alive(ctrl);
        nvme_tcp_teardown_admin_queue(ctrl, false);
        return ret;
 }
index 31633da9427c7f54958ecb0eb514f3df20600cb3..e1ebc73f3e5e0ed95b9d3de3567aae543a835e55 100644 (file)
@@ -4,6 +4,8 @@ config NVME_TARGET
        tristate "NVMe Target support"
        depends on BLOCK
        depends on CONFIGFS_FS
+       select NVME_KEYRING if NVME_TARGET_TCP_TLS
+       select KEYS if NVME_TARGET_TCP_TLS
        select BLK_DEV_INTEGRITY_T10 if BLK_DEV_INTEGRITY
        select SGL_ALLOC
        help
@@ -87,9 +89,7 @@ config NVME_TARGET_TCP
 config NVME_TARGET_TCP_TLS
        bool "NVMe over Fabrics TCP target TLS encryption support"
        depends on NVME_TARGET_TCP
-       select NVME_KEYRING
        select NET_HANDSHAKE
-       select KEYS
        help
          Enables TLS encryption for the NVMe TCP target using the netlink handshake API.
 
index 9eed6e6765eaa7c39e5a616227dbb9268533a934..e307a044b1a1bc1fee0b7ca4a87c3be84a828d15 100644 (file)
@@ -1893,7 +1893,7 @@ static struct config_group *nvmet_ports_make(struct config_group *group,
                return ERR_PTR(-ENOMEM);
        }
 
-       if (nvme_keyring_id()) {
+       if (IS_ENABLED(CONFIG_NVME_TARGET_TCP_TLS) && nvme_keyring_id()) {
                port->keyring = key_lookup(nvme_keyring_id());
                if (IS_ERR(port->keyring)) {
                        pr_warn("NVMe keyring not available, disabling TLS\n");
index 43b5bd8bb6a52dc807a62cc29b2d17eb194c0ed9..d8da840a1c0ed1e9c383d59c11227f7fddfe607d 100644 (file)
@@ -244,6 +244,8 @@ static void nvmet_execute_admin_connect(struct nvmet_req *req)
                goto out;
        }
 
+       d->subsysnqn[NVMF_NQN_FIELD_LEN - 1] = '\0';
+       d->hostnqn[NVMF_NQN_FIELD_LEN - 1] = '\0';
        status = nvmet_alloc_ctrl(d->subsysnqn, d->hostnqn, req,
                                  le32_to_cpu(c->kato), &ctrl);
        if (status)
@@ -313,6 +315,8 @@ static void nvmet_execute_io_connect(struct nvmet_req *req)
                goto out;
        }
 
+       d->subsysnqn[NVMF_NQN_FIELD_LEN - 1] = '\0';
+       d->hostnqn[NVMF_NQN_FIELD_LEN - 1] = '\0';
        ctrl = nvmet_ctrl_find_get(d->subsysnqn, d->hostnqn,
                                   le16_to_cpu(d->cntlid), req);
        if (!ctrl) {
index 92b74d0b8686a673c7d049d52d49971f77e7be9f..4cc27856aa8fefc53d2a77044ea3a3ef927c8ba5 100644 (file)
@@ -1854,6 +1854,8 @@ static int nvmet_tcp_tls_handshake(struct nvmet_tcp_queue *queue)
        }
        return ret;
 }
+#else
+static void nvmet_tcp_tls_handshake_timeout(struct work_struct *w) {}
 #endif
 
 static void nvmet_tcp_alloc_queue(struct nvmet_tcp_port *port,
@@ -1911,9 +1913,9 @@ static void nvmet_tcp_alloc_queue(struct nvmet_tcp_port *port,
        list_add_tail(&queue->queue_list, &nvmet_tcp_queue_list);
        mutex_unlock(&nvmet_tcp_queue_mutex);
 
-#ifdef CONFIG_NVME_TARGET_TCP_TLS
        INIT_DELAYED_WORK(&queue->tls_handshake_tmo_work,
                          nvmet_tcp_tls_handshake_timeout);
+#ifdef CONFIG_NVME_TARGET_TCP_TLS
        if (queue->state == NVMET_TCP_Q_TLS_HANDSHAKE) {
                struct sock *sk = queue->sock->sk;
 
index 787354b849c75c34614c41e4bec3a9da235f60ac..4cef568231bf08cde753a83901c0a14be0b97c1d 100644 (file)
@@ -87,7 +87,6 @@ source "drivers/phy/motorola/Kconfig"
 source "drivers/phy/mscc/Kconfig"
 source "drivers/phy/qualcomm/Kconfig"
 source "drivers/phy/ralink/Kconfig"
-source "drivers/phy/realtek/Kconfig"
 source "drivers/phy/renesas/Kconfig"
 source "drivers/phy/rockchip/Kconfig"
 source "drivers/phy/samsung/Kconfig"
index 868a220ed0f6df60ee478df391777a212a210716..fb3dc9de611154abf78ebcf51c055eba03d263b5 100644 (file)
@@ -26,7 +26,6 @@ obj-y                                 += allwinner/   \
                                           mscc/        \
                                           qualcomm/    \
                                           ralink/      \
-                                          realtek/     \
                                           renesas/     \
                                           rockchip/    \
                                           samsung/     \
diff --git a/drivers/phy/realtek/Kconfig b/drivers/phy/realtek/Kconfig
deleted file mode 100644 (file)
index 75ac7e7..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Phy drivers for Realtek platforms
-#
-
-if ARCH_REALTEK || COMPILE_TEST
-
-config PHY_RTK_RTD_USB2PHY
-       tristate "Realtek RTD USB2 PHY Transceiver Driver"
-       depends on USB_SUPPORT
-       select GENERIC_PHY
-       select USB_PHY
-       select USB_COMMON
-       help
-         Enable this to support Realtek SoC USB2 phy transceiver.
-         The DHC (digital home center) RTD series SoCs used the Synopsys
-         DWC3 USB IP. This driver will do the PHY initialization
-         of the parameters.
-
-config PHY_RTK_RTD_USB3PHY
-       tristate "Realtek RTD USB3 PHY Transceiver Driver"
-       depends on USB_SUPPORT
-       select GENERIC_PHY
-       select USB_PHY
-       select USB_COMMON
-       help
-         Enable this to support Realtek SoC USB3 phy transceiver.
-         The DHC (digital home center) RTD series SoCs used the Synopsys
-         DWC3 USB IP. This driver will do the PHY initialization
-         of the parameters.
-
-endif # ARCH_REALTEK || COMPILE_TEST
diff --git a/drivers/phy/realtek/Makefile b/drivers/phy/realtek/Makefile
deleted file mode 100644 (file)
index ed7b47f..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_PHY_RTK_RTD_USB2PHY)      += phy-rtk-usb2.o
-obj-$(CONFIG_PHY_RTK_RTD_USB3PHY)      += phy-rtk-usb3.o
diff --git a/drivers/phy/realtek/phy-rtk-usb2.c b/drivers/phy/realtek/phy-rtk-usb2.c
deleted file mode 100644 (file)
index 0a64262..0000000
+++ /dev/null
@@ -1,1325 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- *  phy-rtk-usb2.c RTK usb2.0 PHY driver
- *
- * Copyright (C) 2023 Realtek Semiconductor Corporation
- *
- */
-
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/platform_device.h>
-#include <linux/uaccess.h>
-#include <linux/debugfs.h>
-#include <linux/nvmem-consumer.h>
-#include <linux/regmap.h>
-#include <linux/sys_soc.h>
-#include <linux/mfd/syscon.h>
-#include <linux/phy/phy.h>
-#include <linux/usb.h>
-#include <linux/usb/phy.h>
-#include <linux/usb/hcd.h>
-
-/* GUSB2PHYACCn register */
-#define PHY_NEW_REG_REQ BIT(25)
-#define PHY_VSTS_BUSY   BIT(23)
-#define PHY_VCTRL_SHIFT 8
-#define PHY_REG_DATA_MASK 0xff
-
-#define GET_LOW_NIBBLE(addr) ((addr) & 0x0f)
-#define GET_HIGH_NIBBLE(addr) (((addr) & 0xf0) >> 4)
-
-#define EFUS_USB_DC_CAL_RATE 2
-#define EFUS_USB_DC_CAL_MAX 7
-
-#define EFUS_USB_DC_DIS_RATE 1
-#define EFUS_USB_DC_DIS_MAX 7
-
-#define MAX_PHY_DATA_SIZE 20
-#define OFFEST_PHY_READ 0x20
-
-#define MAX_USB_PHY_NUM 4
-#define MAX_USB_PHY_PAGE0_DATA_SIZE 16
-#define MAX_USB_PHY_PAGE1_DATA_SIZE 16
-#define MAX_USB_PHY_PAGE2_DATA_SIZE 8
-
-#define SET_PAGE_OFFSET 0xf4
-#define SET_PAGE_0 0x9b
-#define SET_PAGE_1 0xbb
-#define SET_PAGE_2 0xdb
-
-#define PAGE_START 0xe0
-#define PAGE0_0XE4 0xe4
-#define PAGE0_0XE6 0xe6
-#define PAGE0_0XE7 0xe7
-#define PAGE1_0XE0 0xe0
-#define PAGE1_0XE2 0xe2
-
-#define SENSITIVITY_CTRL (BIT(4) | BIT(5) | BIT(6))
-#define ENABLE_AUTO_SENSITIVITY_CALIBRATION BIT(2)
-#define DEFAULT_DC_DRIVING_VALUE (0x8)
-#define DEFAULT_DC_DISCONNECTION_VALUE (0x6)
-#define HS_CLK_SELECT BIT(6)
-
-struct phy_reg {
-       void __iomem *reg_wrap_vstatus;
-       void __iomem *reg_gusb2phyacc0;
-       int vstatus_index;
-};
-
-struct phy_data {
-       u8 addr;
-       u8 data;
-};
-
-struct phy_cfg {
-       int page0_size;
-       struct phy_data page0[MAX_USB_PHY_PAGE0_DATA_SIZE];
-       int page1_size;
-       struct phy_data page1[MAX_USB_PHY_PAGE1_DATA_SIZE];
-       int page2_size;
-       struct phy_data page2[MAX_USB_PHY_PAGE2_DATA_SIZE];
-
-       int num_phy;
-
-       bool check_efuse;
-       int check_efuse_version;
-#define CHECK_EFUSE_V1 1
-#define CHECK_EFUSE_V2 2
-       int efuse_dc_driving_rate;
-       int efuse_dc_disconnect_rate;
-       int dc_driving_mask;
-       int dc_disconnect_mask;
-       bool usb_dc_disconnect_at_page0;
-       int driving_updated_for_dev_dis;
-
-       bool do_toggle;
-       bool do_toggle_driving;
-       bool use_default_parameter;
-       bool is_double_sensitivity_mode;
-};
-
-struct phy_parameter {
-       struct phy_reg phy_reg;
-
-       /* Get from efuse */
-       s8 efuse_usb_dc_cal;
-       s8 efuse_usb_dc_dis;
-
-       /* Get from dts */
-       bool inverse_hstx_sync_clock;
-       u32 driving_level;
-       s32 driving_level_compensate;
-       s32 disconnection_compensate;
-};
-
-struct rtk_phy {
-       struct usb_phy phy;
-       struct device *dev;
-
-       struct phy_cfg *phy_cfg;
-       int num_phy;
-       struct phy_parameter *phy_parameter;
-
-       struct dentry *debug_dir;
-};
-
-/* mapping 0xE0 to 0 ... 0xE7 to 7, 0xF0 to 8 ,,, 0xF7 to 15 */
-static inline int page_addr_to_array_index(u8 addr)
-{
-       return (int)((((addr) - PAGE_START) & 0x7) +
-               ((((addr) - PAGE_START) & 0x10) >> 1));
-}
-
-static inline u8 array_index_to_page_addr(int index)
-{
-       return ((((index) + PAGE_START) & 0x7) +
-               ((((index) & 0x8) << 1) + PAGE_START));
-}
-
-#define PHY_IO_TIMEOUT_USEC            (50000)
-#define PHY_IO_DELAY_US                        (100)
-
-static inline int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
-{
-       int ret;
-       unsigned int val;
-
-       ret = read_poll_timeout(readl, val, ((val & mask) == result),
-                               PHY_IO_DELAY_US, PHY_IO_TIMEOUT_USEC, false, reg);
-       if (ret) {
-               pr_err("%s can't program USB phy\n", __func__);
-               return -ETIMEDOUT;
-       }
-
-       return 0;
-}
-
-static char rtk_phy_read(struct phy_reg *phy_reg, char addr)
-{
-       void __iomem *reg_gusb2phyacc0 = phy_reg->reg_gusb2phyacc0;
-       unsigned int val;
-       int ret = 0;
-
-       addr -= OFFEST_PHY_READ;
-
-       /* polling until VBusy == 0 */
-       ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
-       if (ret)
-               return (char)ret;
-
-       /* VCtrl = low nibble of addr, and set PHY_NEW_REG_REQ */
-       val = PHY_NEW_REG_REQ | (GET_LOW_NIBBLE(addr) << PHY_VCTRL_SHIFT);
-       writel(val, reg_gusb2phyacc0);
-       ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
-       if (ret)
-               return (char)ret;
-
-       /* VCtrl = high nibble of addr, and set PHY_NEW_REG_REQ */
-       val = PHY_NEW_REG_REQ | (GET_HIGH_NIBBLE(addr) << PHY_VCTRL_SHIFT);
-       writel(val, reg_gusb2phyacc0);
-       ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
-       if (ret)
-               return (char)ret;
-
-       val = readl(reg_gusb2phyacc0);
-
-       return (char)(val & PHY_REG_DATA_MASK);
-}
-
-static int rtk_phy_write(struct phy_reg *phy_reg, char addr, char data)
-{
-       unsigned int val;
-       void __iomem *reg_wrap_vstatus = phy_reg->reg_wrap_vstatus;
-       void __iomem *reg_gusb2phyacc0 = phy_reg->reg_gusb2phyacc0;
-       int shift_bits = phy_reg->vstatus_index * 8;
-       int ret = 0;
-
-       /* write data to VStatusOut2 (data output to phy) */
-       writel((u32)data << shift_bits, reg_wrap_vstatus);
-
-       ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
-       if (ret)
-               return ret;
-
-       /* VCtrl = low nibble of addr, set PHY_NEW_REG_REQ */
-       val = PHY_NEW_REG_REQ | (GET_LOW_NIBBLE(addr) << PHY_VCTRL_SHIFT);
-
-       writel(val, reg_gusb2phyacc0);
-       ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
-       if (ret)
-               return ret;
-
-       /* VCtrl = high nibble of addr, set PHY_NEW_REG_REQ */
-       val = PHY_NEW_REG_REQ | (GET_HIGH_NIBBLE(addr) << PHY_VCTRL_SHIFT);
-
-       writel(val, reg_gusb2phyacc0);
-       ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
-static int rtk_phy_set_page(struct phy_reg *phy_reg, int page)
-{
-       switch (page) {
-       case 0:
-               return rtk_phy_write(phy_reg, SET_PAGE_OFFSET, SET_PAGE_0);
-       case 1:
-               return rtk_phy_write(phy_reg, SET_PAGE_OFFSET, SET_PAGE_1);
-       case 2:
-               return rtk_phy_write(phy_reg, SET_PAGE_OFFSET, SET_PAGE_2);
-       default:
-               pr_err("%s error page=%d\n", __func__, page);
-       }
-
-       return -EINVAL;
-}
-
-static u8 __updated_dc_disconnect_level_page0_0xe4(struct phy_cfg *phy_cfg,
-                                                  struct phy_parameter *phy_parameter, u8 data)
-{
-       u8 ret;
-       s32 val;
-       s32 dc_disconnect_mask = phy_cfg->dc_disconnect_mask;
-       int offset = 4;
-
-       val = (s32)((data >> offset) & dc_disconnect_mask)
-                    + phy_parameter->efuse_usb_dc_dis
-                    + phy_parameter->disconnection_compensate;
-
-       if (val > dc_disconnect_mask)
-               val = dc_disconnect_mask;
-       else if (val < 0)
-               val = 0;
-
-       ret = (data & (~(dc_disconnect_mask << offset))) |
-                   (val & dc_disconnect_mask) << offset;
-
-       return ret;
-}
-
-/* updated disconnect level at page0 */
-static void update_dc_disconnect_level_at_page0(struct rtk_phy *rtk_phy,
-                                               struct phy_parameter *phy_parameter, bool update)
-{
-       struct phy_cfg *phy_cfg;
-       struct phy_reg *phy_reg;
-       struct phy_data *phy_data_page;
-       struct phy_data *phy_data;
-       u8 addr, data;
-       int offset = 4;
-       s32 dc_disconnect_mask;
-       int i;
-
-       phy_cfg = rtk_phy->phy_cfg;
-       phy_reg = &phy_parameter->phy_reg;
-
-       /* Set page 0 */
-       phy_data_page = phy_cfg->page0;
-       rtk_phy_set_page(phy_reg, 0);
-
-       i = page_addr_to_array_index(PAGE0_0XE4);
-       phy_data = phy_data_page + i;
-       if (!phy_data->addr) {
-               phy_data->addr = PAGE0_0XE4;
-               phy_data->data = rtk_phy_read(phy_reg, PAGE0_0XE4);
-       }
-
-       addr = phy_data->addr;
-       data = phy_data->data;
-       dc_disconnect_mask = phy_cfg->dc_disconnect_mask;
-
-       if (update)
-               data = __updated_dc_disconnect_level_page0_0xe4(phy_cfg, phy_parameter, data);
-       else
-               data = (data & ~(dc_disconnect_mask << offset)) |
-                       (DEFAULT_DC_DISCONNECTION_VALUE << offset);
-
-       if (rtk_phy_write(phy_reg, addr, data))
-               dev_err(rtk_phy->dev,
-                       "%s: Error to set page1 parameter addr=0x%x value=0x%x\n",
-                       __func__, addr, data);
-}
-
-static u8 __updated_dc_disconnect_level_page1_0xe2(struct phy_cfg *phy_cfg,
-                                                  struct phy_parameter *phy_parameter, u8 data)
-{
-       u8 ret;
-       s32 val;
-       s32 dc_disconnect_mask = phy_cfg->dc_disconnect_mask;
-
-       if (phy_cfg->check_efuse_version == CHECK_EFUSE_V1) {
-               val = (s32)(data & dc_disconnect_mask)
-                           + phy_parameter->efuse_usb_dc_dis
-                           + phy_parameter->disconnection_compensate;
-       } else { /* for CHECK_EFUSE_V2 or no efuse */
-               if (phy_parameter->efuse_usb_dc_dis)
-                       val = (s32)(phy_parameter->efuse_usb_dc_dis +
-                                   phy_parameter->disconnection_compensate);
-               else
-                       val = (s32)((data & dc_disconnect_mask) +
-                                   phy_parameter->disconnection_compensate);
-       }
-
-       if (val > dc_disconnect_mask)
-               val = dc_disconnect_mask;
-       else if (val < 0)
-               val = 0;
-
-       ret = (data & (~dc_disconnect_mask)) | (val & dc_disconnect_mask);
-
-       return ret;
-}
-
-/* updated disconnect level at page1 */
-static void update_dc_disconnect_level_at_page1(struct rtk_phy *rtk_phy,
-                                               struct phy_parameter *phy_parameter, bool update)
-{
-       struct phy_cfg *phy_cfg;
-       struct phy_data *phy_data_page;
-       struct phy_data *phy_data;
-       struct phy_reg *phy_reg;
-       u8 addr, data;
-       s32 dc_disconnect_mask;
-       int i;
-
-       phy_cfg = rtk_phy->phy_cfg;
-       phy_reg = &phy_parameter->phy_reg;
-
-       /* Set page 1 */
-       phy_data_page = phy_cfg->page1;
-       rtk_phy_set_page(phy_reg, 1);
-
-       i = page_addr_to_array_index(PAGE1_0XE2);
-       phy_data = phy_data_page + i;
-       if (!phy_data->addr) {
-               phy_data->addr = PAGE1_0XE2;
-               phy_data->data = rtk_phy_read(phy_reg, PAGE1_0XE2);
-       }
-
-       addr = phy_data->addr;
-       data = phy_data->data;
-       dc_disconnect_mask = phy_cfg->dc_disconnect_mask;
-
-       if (update)
-               data = __updated_dc_disconnect_level_page1_0xe2(phy_cfg, phy_parameter, data);
-       else
-               data = (data & ~dc_disconnect_mask) | DEFAULT_DC_DISCONNECTION_VALUE;
-
-       if (rtk_phy_write(phy_reg, addr, data))
-               dev_err(rtk_phy->dev,
-                       "%s: Error to set page1 parameter addr=0x%x value=0x%x\n",
-                       __func__, addr, data);
-}
-
-static void update_dc_disconnect_level(struct rtk_phy *rtk_phy,
-                                      struct phy_parameter *phy_parameter, bool update)
-{
-       struct phy_cfg *phy_cfg = rtk_phy->phy_cfg;
-
-       if (phy_cfg->usb_dc_disconnect_at_page0)
-               update_dc_disconnect_level_at_page0(rtk_phy, phy_parameter, update);
-       else
-               update_dc_disconnect_level_at_page1(rtk_phy, phy_parameter, update);
-}
-
-static u8 __update_dc_driving_page0_0xe4(struct phy_cfg *phy_cfg,
-                                        struct phy_parameter *phy_parameter, u8 data)
-{
-       s32 driving_level_compensate = phy_parameter->driving_level_compensate;
-       s32 dc_driving_mask = phy_cfg->dc_driving_mask;
-       s32 val;
-       u8 ret;
-
-       if (phy_cfg->check_efuse_version == CHECK_EFUSE_V1) {
-               val = (s32)(data & dc_driving_mask) + driving_level_compensate
-                           + phy_parameter->efuse_usb_dc_cal;
-       } else { /* for CHECK_EFUSE_V2 or no efuse */
-               if (phy_parameter->efuse_usb_dc_cal)
-                       val = (s32)((phy_parameter->efuse_usb_dc_cal & dc_driving_mask)
-                                   + driving_level_compensate);
-               else
-                       val = (s32)(data & dc_driving_mask);
-       }
-
-       if (val > dc_driving_mask)
-               val = dc_driving_mask;
-       else if (val < 0)
-               val = 0;
-
-       ret = (data & (~dc_driving_mask)) | (val & dc_driving_mask);
-
-       return ret;
-}
-
-static void update_dc_driving_level(struct rtk_phy *rtk_phy,
-                                   struct phy_parameter *phy_parameter)
-{
-       struct phy_cfg *phy_cfg;
-       struct phy_reg *phy_reg;
-
-       phy_reg = &phy_parameter->phy_reg;
-       phy_cfg = rtk_phy->phy_cfg;
-       if (!phy_cfg->page0[4].addr) {
-               rtk_phy_set_page(phy_reg, 0);
-               phy_cfg->page0[4].addr = PAGE0_0XE4;
-               phy_cfg->page0[4].data = rtk_phy_read(phy_reg, PAGE0_0XE4);
-       }
-
-       if (phy_parameter->driving_level != DEFAULT_DC_DRIVING_VALUE) {
-               u32 dc_driving_mask;
-               u8 driving_level;
-               u8 data;
-
-               data = phy_cfg->page0[4].data;
-               dc_driving_mask = phy_cfg->dc_driving_mask;
-               driving_level = data & dc_driving_mask;
-
-               dev_dbg(rtk_phy->dev, "%s driving_level=%d => dts driving_level=%d\n",
-                       __func__, driving_level, phy_parameter->driving_level);
-
-               phy_cfg->page0[4].data = (data & (~dc_driving_mask)) |
-                           (phy_parameter->driving_level & dc_driving_mask);
-       }
-
-       phy_cfg->page0[4].data = __update_dc_driving_page0_0xe4(phy_cfg,
-                                                               phy_parameter,
-                                                               phy_cfg->page0[4].data);
-}
-
-static void update_hs_clk_select(struct rtk_phy *rtk_phy,
-                                struct phy_parameter *phy_parameter)
-{
-       struct phy_cfg *phy_cfg;
-       struct phy_reg *phy_reg;
-
-       phy_cfg = rtk_phy->phy_cfg;
-       phy_reg = &phy_parameter->phy_reg;
-
-       if (phy_parameter->inverse_hstx_sync_clock) {
-               if (!phy_cfg->page0[6].addr) {
-                       rtk_phy_set_page(phy_reg, 0);
-                       phy_cfg->page0[6].addr = PAGE0_0XE6;
-                       phy_cfg->page0[6].data = rtk_phy_read(phy_reg, PAGE0_0XE6);
-               }
-
-               phy_cfg->page0[6].data = phy_cfg->page0[6].data | HS_CLK_SELECT;
-       }
-}
-
-static void do_rtk_phy_toggle(struct rtk_phy *rtk_phy,
-                             int index, bool connect)
-{
-       struct phy_parameter *phy_parameter;
-       struct phy_cfg *phy_cfg;
-       struct phy_reg *phy_reg;
-       struct phy_data *phy_data_page;
-       u8 addr, data;
-       int i;
-
-       phy_cfg = rtk_phy->phy_cfg;
-       phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
-       phy_reg = &phy_parameter->phy_reg;
-
-       if (!phy_cfg->do_toggle)
-               goto out;
-
-       if (phy_cfg->is_double_sensitivity_mode)
-               goto do_toggle_driving;
-
-       /* Set page 0 */
-       rtk_phy_set_page(phy_reg, 0);
-
-       addr = PAGE0_0XE7;
-       data = rtk_phy_read(phy_reg, addr);
-
-       if (connect)
-               rtk_phy_write(phy_reg, addr, data & (~SENSITIVITY_CTRL));
-       else
-               rtk_phy_write(phy_reg, addr, data | (SENSITIVITY_CTRL));
-
-do_toggle_driving:
-
-       if (!phy_cfg->do_toggle_driving)
-               goto do_toggle;
-
-       /* Page 0 addr 0xE4 driving capability */
-
-       /* Set page 0 */
-       phy_data_page = phy_cfg->page0;
-       rtk_phy_set_page(phy_reg, 0);
-
-       i = page_addr_to_array_index(PAGE0_0XE4);
-       addr = phy_data_page[i].addr;
-       data = phy_data_page[i].data;
-
-       if (connect) {
-               rtk_phy_write(phy_reg, addr, data);
-       } else {
-               u8 value;
-               s32 tmp;
-               s32 driving_updated =
-                           phy_cfg->driving_updated_for_dev_dis;
-               s32 dc_driving_mask = phy_cfg->dc_driving_mask;
-
-               tmp = (s32)(data & dc_driving_mask) + driving_updated;
-
-               if (tmp > dc_driving_mask)
-                       tmp = dc_driving_mask;
-               else if (tmp < 0)
-                       tmp = 0;
-
-               value = (data & (~dc_driving_mask)) | (tmp & dc_driving_mask);
-
-               rtk_phy_write(phy_reg, addr, value);
-       }
-
-do_toggle:
-       /* restore dc disconnect level before toggle */
-       update_dc_disconnect_level(rtk_phy, phy_parameter, false);
-
-       /* Set page 1 */
-       rtk_phy_set_page(phy_reg, 1);
-
-       addr = PAGE1_0XE0;
-       data = rtk_phy_read(phy_reg, addr);
-
-       rtk_phy_write(phy_reg, addr, data &
-                     (~ENABLE_AUTO_SENSITIVITY_CALIBRATION));
-       mdelay(1);
-       rtk_phy_write(phy_reg, addr, data |
-                     (ENABLE_AUTO_SENSITIVITY_CALIBRATION));
-
-       /* update dc disconnect level after toggle */
-       update_dc_disconnect_level(rtk_phy, phy_parameter, true);
-
-out:
-       return;
-}
-
-static int do_rtk_phy_init(struct rtk_phy *rtk_phy, int index)
-{
-       struct phy_parameter *phy_parameter;
-       struct phy_cfg *phy_cfg;
-       struct phy_data *phy_data_page;
-       struct phy_reg *phy_reg;
-       int i;
-
-       phy_cfg = rtk_phy->phy_cfg;
-       phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
-       phy_reg = &phy_parameter->phy_reg;
-
-       if (phy_cfg->use_default_parameter) {
-               dev_dbg(rtk_phy->dev, "%s phy#%d use default parameter\n",
-                       __func__, index);
-               goto do_toggle;
-       }
-
-       /* Set page 0 */
-       phy_data_page = phy_cfg->page0;
-       rtk_phy_set_page(phy_reg, 0);
-
-       for (i = 0; i < phy_cfg->page0_size; i++) {
-               struct phy_data *phy_data = phy_data_page + i;
-               u8 addr = phy_data->addr;
-               u8 data = phy_data->data;
-
-               if (!addr)
-                       continue;
-
-               if (rtk_phy_write(phy_reg, addr, data)) {
-                       dev_err(rtk_phy->dev,
-                               "%s: Error to set page0 parameter addr=0x%x value=0x%x\n",
-                               __func__, addr, data);
-                       return -EINVAL;
-               }
-       }
-
-       /* Set page 1 */
-       phy_data_page = phy_cfg->page1;
-       rtk_phy_set_page(phy_reg, 1);
-
-       for (i = 0; i < phy_cfg->page1_size; i++) {
-               struct phy_data *phy_data = phy_data_page + i;
-               u8 addr = phy_data->addr;
-               u8 data = phy_data->data;
-
-               if (!addr)
-                       continue;
-
-               if (rtk_phy_write(phy_reg, addr, data)) {
-                       dev_err(rtk_phy->dev,
-                               "%s: Error to set page1 parameter addr=0x%x value=0x%x\n",
-                               __func__, addr, data);
-                       return -EINVAL;
-               }
-       }
-
-       if (phy_cfg->page2_size == 0)
-               goto do_toggle;
-
-       /* Set page 2 */
-       phy_data_page = phy_cfg->page2;
-       rtk_phy_set_page(phy_reg, 2);
-
-       for (i = 0; i < phy_cfg->page2_size; i++) {
-               struct phy_data *phy_data = phy_data_page + i;
-               u8 addr = phy_data->addr;
-               u8 data = phy_data->data;
-
-               if (!addr)
-                       continue;
-
-               if (rtk_phy_write(phy_reg, addr, data)) {
-                       dev_err(rtk_phy->dev,
-                               "%s: Error to set page2 parameter addr=0x%x value=0x%x\n",
-                               __func__, addr, data);
-                       return -EINVAL;
-               }
-       }
-
-do_toggle:
-       do_rtk_phy_toggle(rtk_phy, index, false);
-
-       return 0;
-}
-
-static int rtk_phy_init(struct phy *phy)
-{
-       struct rtk_phy *rtk_phy = phy_get_drvdata(phy);
-       unsigned long phy_init_time = jiffies;
-       int i, ret = 0;
-
-       if (!rtk_phy)
-               return -EINVAL;
-
-       for (i = 0; i < rtk_phy->num_phy; i++)
-               ret = do_rtk_phy_init(rtk_phy, i);
-
-       dev_dbg(rtk_phy->dev, "Initialized RTK USB 2.0 PHY (take %dms)\n",
-               jiffies_to_msecs(jiffies - phy_init_time));
-       return ret;
-}
-
-static int rtk_phy_exit(struct phy *phy)
-{
-       return 0;
-}
-
-static const struct phy_ops ops = {
-       .init           = rtk_phy_init,
-       .exit           = rtk_phy_exit,
-       .owner          = THIS_MODULE,
-};
-
-static void rtk_phy_toggle(struct usb_phy *usb2_phy, bool connect, int port)
-{
-       int index = port;
-       struct rtk_phy *rtk_phy = NULL;
-
-       rtk_phy = dev_get_drvdata(usb2_phy->dev);
-
-       if (index > rtk_phy->num_phy) {
-               dev_err(rtk_phy->dev, "%s: The port=%d is not in usb phy (num_phy=%d)\n",
-                       __func__, index, rtk_phy->num_phy);
-               return;
-       }
-
-       do_rtk_phy_toggle(rtk_phy, index, connect);
-}
-
-static int rtk_phy_notify_port_status(struct usb_phy *x, int port,
-                                     u16 portstatus, u16 portchange)
-{
-       bool connect = false;
-
-       pr_debug("%s port=%d portstatus=0x%x portchange=0x%x\n",
-                __func__, port, (int)portstatus, (int)portchange);
-       if (portstatus & USB_PORT_STAT_CONNECTION)
-               connect = true;
-
-       if (portchange & USB_PORT_STAT_C_CONNECTION)
-               rtk_phy_toggle(x, connect, port);
-
-       return 0;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static struct dentry *create_phy_debug_root(void)
-{
-       struct dentry *phy_debug_root;
-
-       phy_debug_root = debugfs_lookup("phy", usb_debug_root);
-       if (!phy_debug_root)
-               phy_debug_root = debugfs_create_dir("phy", usb_debug_root);
-
-       return phy_debug_root;
-}
-
-static int rtk_usb2_parameter_show(struct seq_file *s, void *unused)
-{
-       struct rtk_phy *rtk_phy = s->private;
-       struct phy_cfg *phy_cfg;
-       int i, index;
-
-       phy_cfg = rtk_phy->phy_cfg;
-
-       seq_puts(s, "Property:\n");
-       seq_printf(s, "  check_efuse: %s\n",
-                  phy_cfg->check_efuse ? "Enable" : "Disable");
-       seq_printf(s, "  check_efuse_version: %d\n",
-                  phy_cfg->check_efuse_version);
-       seq_printf(s, "  efuse_dc_driving_rate: %d\n",
-                  phy_cfg->efuse_dc_driving_rate);
-       seq_printf(s, "  dc_driving_mask: 0x%x\n",
-                  phy_cfg->dc_driving_mask);
-       seq_printf(s, "  efuse_dc_disconnect_rate: %d\n",
-                  phy_cfg->efuse_dc_disconnect_rate);
-       seq_printf(s, "  dc_disconnect_mask: 0x%x\n",
-                  phy_cfg->dc_disconnect_mask);
-       seq_printf(s, "  usb_dc_disconnect_at_page0: %s\n",
-                  phy_cfg->usb_dc_disconnect_at_page0 ? "true" : "false");
-       seq_printf(s, "  do_toggle: %s\n",
-                  phy_cfg->do_toggle ? "Enable" : "Disable");
-       seq_printf(s, "  do_toggle_driving: %s\n",
-                  phy_cfg->do_toggle_driving ? "Enable" : "Disable");
-       seq_printf(s, "  driving_updated_for_dev_dis: 0x%x\n",
-                  phy_cfg->driving_updated_for_dev_dis);
-       seq_printf(s, "  use_default_parameter: %s\n",
-                  phy_cfg->use_default_parameter ? "Enable" : "Disable");
-       seq_printf(s, "  is_double_sensitivity_mode: %s\n",
-                  phy_cfg->is_double_sensitivity_mode ? "Enable" : "Disable");
-
-       for (index = 0; index < rtk_phy->num_phy; index++) {
-               struct phy_parameter *phy_parameter;
-               struct phy_reg *phy_reg;
-               struct phy_data *phy_data_page;
-
-               phy_parameter =  &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
-               phy_reg = &phy_parameter->phy_reg;
-
-               seq_printf(s, "PHY %d:\n", index);
-
-               seq_puts(s, "Page 0:\n");
-               /* Set page 0 */
-               phy_data_page = phy_cfg->page0;
-               rtk_phy_set_page(phy_reg, 0);
-
-               for (i = 0; i < phy_cfg->page0_size; i++) {
-                       struct phy_data *phy_data = phy_data_page + i;
-                       u8 addr = array_index_to_page_addr(i);
-                       u8 data = phy_data->data;
-                       u8 value = rtk_phy_read(phy_reg, addr);
-
-                       if (phy_data->addr)
-                               seq_printf(s, "  Page 0: addr=0x%x data=0x%02x ==> read value=0x%02x\n",
-                                          addr, data, value);
-                       else
-                               seq_printf(s, "  Page 0: addr=0x%x data=none ==> read value=0x%02x\n",
-                                          addr, value);
-               }
-
-               seq_puts(s, "Page 1:\n");
-               /* Set page 1 */
-               phy_data_page = phy_cfg->page1;
-               rtk_phy_set_page(phy_reg, 1);
-
-               for (i = 0; i < phy_cfg->page1_size; i++) {
-                       struct phy_data *phy_data = phy_data_page + i;
-                       u8 addr = array_index_to_page_addr(i);
-                       u8 data = phy_data->data;
-                       u8 value = rtk_phy_read(phy_reg, addr);
-
-                       if (phy_data->addr)
-                               seq_printf(s, "  Page 1: addr=0x%x data=0x%02x ==> read value=0x%02x\n",
-                                          addr, data, value);
-                       else
-                               seq_printf(s, "  Page 1: addr=0x%x data=none ==> read value=0x%02x\n",
-                                          addr, value);
-               }
-
-               if (phy_cfg->page2_size == 0)
-                       goto out;
-
-               seq_puts(s, "Page 2:\n");
-               /* Set page 2 */
-               phy_data_page = phy_cfg->page2;
-               rtk_phy_set_page(phy_reg, 2);
-
-               for (i = 0; i < phy_cfg->page2_size; i++) {
-                       struct phy_data *phy_data = phy_data_page + i;
-                       u8 addr = array_index_to_page_addr(i);
-                       u8 data = phy_data->data;
-                       u8 value = rtk_phy_read(phy_reg, addr);
-
-                       if (phy_data->addr)
-                               seq_printf(s, "  Page 2: addr=0x%x data=0x%02x ==> read value=0x%02x\n",
-                                          addr, data, value);
-                       else
-                               seq_printf(s, "  Page 2: addr=0x%x data=none ==> read value=0x%02x\n",
-                                          addr, value);
-               }
-
-out:
-               seq_puts(s, "PHY Property:\n");
-               seq_printf(s, "  efuse_usb_dc_cal: %d\n",
-                          (int)phy_parameter->efuse_usb_dc_cal);
-               seq_printf(s, "  efuse_usb_dc_dis: %d\n",
-                          (int)phy_parameter->efuse_usb_dc_dis);
-               seq_printf(s, "  inverse_hstx_sync_clock: %s\n",
-                          phy_parameter->inverse_hstx_sync_clock ? "Enable" : "Disable");
-               seq_printf(s, "  driving_level: %d\n",
-                          phy_parameter->driving_level);
-               seq_printf(s, "  driving_level_compensate: %d\n",
-                          phy_parameter->driving_level_compensate);
-               seq_printf(s, "  disconnection_compensate: %d\n",
-                          phy_parameter->disconnection_compensate);
-       }
-
-       return 0;
-}
-DEFINE_SHOW_ATTRIBUTE(rtk_usb2_parameter);
-
-static inline void create_debug_files(struct rtk_phy *rtk_phy)
-{
-       struct dentry *phy_debug_root = NULL;
-
-       phy_debug_root = create_phy_debug_root();
-       if (!phy_debug_root)
-               return;
-
-       rtk_phy->debug_dir = debugfs_create_dir(dev_name(rtk_phy->dev),
-                                               phy_debug_root);
-
-       debugfs_create_file("parameter", 0444, rtk_phy->debug_dir, rtk_phy,
-                           &rtk_usb2_parameter_fops);
-
-       return;
-}
-
-static inline void remove_debug_files(struct rtk_phy *rtk_phy)
-{
-       debugfs_remove_recursive(rtk_phy->debug_dir);
-}
-#else
-static inline void create_debug_files(struct rtk_phy *rtk_phy) { }
-static inline void remove_debug_files(struct rtk_phy *rtk_phy) { }
-#endif /* CONFIG_DEBUG_FS */
-
-static int get_phy_data_by_efuse(struct rtk_phy *rtk_phy,
-                                struct phy_parameter *phy_parameter, int index)
-{
-       struct phy_cfg *phy_cfg = rtk_phy->phy_cfg;
-       u8 value = 0;
-       struct nvmem_cell *cell;
-       struct soc_device_attribute rtk_soc_groot[] = {
-                   { .family = "Realtek Groot",},
-                   { /* empty */ } };
-
-       if (!phy_cfg->check_efuse)
-               goto out;
-
-       /* Read efuse for usb dc cal */
-       cell = nvmem_cell_get(rtk_phy->dev, "usb-dc-cal");
-       if (IS_ERR(cell)) {
-               dev_dbg(rtk_phy->dev, "%s no usb-dc-cal: %ld\n",
-                       __func__, PTR_ERR(cell));
-       } else {
-               unsigned char *buf;
-               size_t buf_size;
-
-               buf = nvmem_cell_read(cell, &buf_size);
-               if (!IS_ERR(buf)) {
-                       value = buf[0] & phy_cfg->dc_driving_mask;
-                       kfree(buf);
-               }
-               nvmem_cell_put(cell);
-       }
-
-       if (phy_cfg->check_efuse_version == CHECK_EFUSE_V1) {
-               int rate = phy_cfg->efuse_dc_driving_rate;
-
-               if (value <= EFUS_USB_DC_CAL_MAX)
-                       phy_parameter->efuse_usb_dc_cal = (int8_t)(value * rate);
-               else
-                       phy_parameter->efuse_usb_dc_cal = -(int8_t)
-                                   ((EFUS_USB_DC_CAL_MAX & value) * rate);
-
-               if (soc_device_match(rtk_soc_groot)) {
-                       dev_dbg(rtk_phy->dev, "For groot IC we need a workaround to adjust efuse_usb_dc_cal\n");
-
-                       /* We don't multiple dc_cal_rate=2 for positive dc cal compensate */
-                       if (value <= EFUS_USB_DC_CAL_MAX)
-                               phy_parameter->efuse_usb_dc_cal = (int8_t)(value);
-
-                       /* We set max dc cal compensate is 0x8 if otp is 0x7 */
-                       if (value == 0x7)
-                               phy_parameter->efuse_usb_dc_cal = (int8_t)(value + 1);
-               }
-       } else { /* for CHECK_EFUSE_V2 */
-               phy_parameter->efuse_usb_dc_cal = value & phy_cfg->dc_driving_mask;
-       }
-
-       /* Read efuse for usb dc disconnect level */
-       value = 0;
-       cell = nvmem_cell_get(rtk_phy->dev, "usb-dc-dis");
-       if (IS_ERR(cell)) {
-               dev_dbg(rtk_phy->dev, "%s no usb-dc-dis: %ld\n",
-                       __func__, PTR_ERR(cell));
-       } else {
-               unsigned char *buf;
-               size_t buf_size;
-
-               buf = nvmem_cell_read(cell, &buf_size);
-               if (!IS_ERR(buf)) {
-                       value = buf[0] & phy_cfg->dc_disconnect_mask;
-                       kfree(buf);
-               }
-               nvmem_cell_put(cell);
-       }
-
-       if (phy_cfg->check_efuse_version == CHECK_EFUSE_V1) {
-               int rate = phy_cfg->efuse_dc_disconnect_rate;
-
-               if (value <= EFUS_USB_DC_DIS_MAX)
-                       phy_parameter->efuse_usb_dc_dis = (int8_t)(value * rate);
-               else
-                       phy_parameter->efuse_usb_dc_dis = -(int8_t)
-                                   ((EFUS_USB_DC_DIS_MAX & value) * rate);
-       } else { /* for CHECK_EFUSE_V2 */
-               phy_parameter->efuse_usb_dc_dis = value & phy_cfg->dc_disconnect_mask;
-       }
-
-out:
-       return 0;
-}
-
-static int parse_phy_data(struct rtk_phy *rtk_phy)
-{
-       struct device *dev = rtk_phy->dev;
-       struct device_node *np = dev->of_node;
-       struct phy_parameter *phy_parameter;
-       int ret = 0;
-       int index;
-
-       rtk_phy->phy_parameter = devm_kzalloc(dev, sizeof(struct phy_parameter) *
-                                               rtk_phy->num_phy, GFP_KERNEL);
-       if (!rtk_phy->phy_parameter)
-               return -ENOMEM;
-
-       for (index = 0; index < rtk_phy->num_phy; index++) {
-               phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
-
-               phy_parameter->phy_reg.reg_wrap_vstatus = of_iomap(np, 0);
-               phy_parameter->phy_reg.reg_gusb2phyacc0 = of_iomap(np, 1) + index;
-               phy_parameter->phy_reg.vstatus_index = index;
-
-               if (of_property_read_bool(np, "realtek,inverse-hstx-sync-clock"))
-                       phy_parameter->inverse_hstx_sync_clock = true;
-               else
-                       phy_parameter->inverse_hstx_sync_clock = false;
-
-               if (of_property_read_u32_index(np, "realtek,driving-level",
-                                              index, &phy_parameter->driving_level))
-                       phy_parameter->driving_level = DEFAULT_DC_DRIVING_VALUE;
-
-               if (of_property_read_u32_index(np, "realtek,driving-level-compensate",
-                                              index, &phy_parameter->driving_level_compensate))
-                       phy_parameter->driving_level_compensate = 0;
-
-               if (of_property_read_u32_index(np, "realtek,disconnection-compensate",
-                                              index, &phy_parameter->disconnection_compensate))
-                       phy_parameter->disconnection_compensate = 0;
-
-               get_phy_data_by_efuse(rtk_phy, phy_parameter, index);
-
-               update_dc_driving_level(rtk_phy, phy_parameter);
-
-               update_hs_clk_select(rtk_phy, phy_parameter);
-       }
-
-       return ret;
-}
-
-static int rtk_usb2phy_probe(struct platform_device *pdev)
-{
-       struct rtk_phy *rtk_phy;
-       struct device *dev = &pdev->dev;
-       struct phy *generic_phy;
-       struct phy_provider *phy_provider;
-       const struct phy_cfg *phy_cfg;
-       int ret = 0;
-
-       phy_cfg = of_device_get_match_data(dev);
-       if (!phy_cfg) {
-               dev_err(dev, "phy config are not assigned!\n");
-               return -EINVAL;
-       }
-
-       rtk_phy = devm_kzalloc(dev, sizeof(*rtk_phy), GFP_KERNEL);
-       if (!rtk_phy)
-               return -ENOMEM;
-
-       rtk_phy->dev                    = &pdev->dev;
-       rtk_phy->phy.dev                = rtk_phy->dev;
-       rtk_phy->phy.label              = "rtk-usb2phy";
-       rtk_phy->phy.notify_port_status = rtk_phy_notify_port_status;
-
-       rtk_phy->phy_cfg = devm_kzalloc(dev, sizeof(*phy_cfg), GFP_KERNEL);
-
-       memcpy(rtk_phy->phy_cfg, phy_cfg, sizeof(*phy_cfg));
-
-       rtk_phy->num_phy = phy_cfg->num_phy;
-
-       ret = parse_phy_data(rtk_phy);
-       if (ret)
-               goto err;
-
-       platform_set_drvdata(pdev, rtk_phy);
-
-       generic_phy = devm_phy_create(rtk_phy->dev, NULL, &ops);
-       if (IS_ERR(generic_phy))
-               return PTR_ERR(generic_phy);
-
-       phy_set_drvdata(generic_phy, rtk_phy);
-
-       phy_provider = devm_of_phy_provider_register(rtk_phy->dev,
-                                                    of_phy_simple_xlate);
-       if (IS_ERR(phy_provider))
-               return PTR_ERR(phy_provider);
-
-       ret = usb_add_phy_dev(&rtk_phy->phy);
-       if (ret)
-               goto err;
-
-       create_debug_files(rtk_phy);
-
-err:
-       return ret;
-}
-
-static void rtk_usb2phy_remove(struct platform_device *pdev)
-{
-       struct rtk_phy *rtk_phy = platform_get_drvdata(pdev);
-
-       remove_debug_files(rtk_phy);
-
-       usb_remove_phy(&rtk_phy->phy);
-}
-
-static const struct phy_cfg rtd1295_phy_cfg = {
-       .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
-       .page0 = { [0] = {0xe0, 0x90},
-                  [3] = {0xe3, 0x3a},
-                  [4] = {0xe4, 0x68},
-                  [6] = {0xe6, 0x91},
-                 [13] = {0xf5, 0x81},
-                 [15] = {0xf7, 0x02}, },
-       .page1_size = 8,
-       .page1 = { /* default parameter */ },
-       .page2_size = 0,
-       .page2 = { /* no parameter */ },
-       .num_phy = 1,
-       .check_efuse = false,
-       .check_efuse_version = CHECK_EFUSE_V1,
-       .efuse_dc_driving_rate = 1,
-       .dc_driving_mask = 0xf,
-       .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
-       .dc_disconnect_mask = 0xf,
-       .usb_dc_disconnect_at_page0 = true,
-       .do_toggle = true,
-       .do_toggle_driving = false,
-       .driving_updated_for_dev_dis = 0xf,
-       .use_default_parameter = false,
-       .is_double_sensitivity_mode = false,
-};
-
-static const struct phy_cfg rtd1395_phy_cfg = {
-       .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
-       .page0 = { [4] = {0xe4, 0xac},
-                 [13] = {0xf5, 0x00},
-                 [15] = {0xf7, 0x02}, },
-       .page1_size = 8,
-       .page1 = { /* default parameter */ },
-       .page2_size = 0,
-       .page2 = { /* no parameter */ },
-       .num_phy = 1,
-       .check_efuse = false,
-       .check_efuse_version = CHECK_EFUSE_V1,
-       .efuse_dc_driving_rate = 1,
-       .dc_driving_mask = 0xf,
-       .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
-       .dc_disconnect_mask = 0xf,
-       .usb_dc_disconnect_at_page0 = true,
-       .do_toggle = true,
-       .do_toggle_driving = false,
-       .driving_updated_for_dev_dis = 0xf,
-       .use_default_parameter = false,
-       .is_double_sensitivity_mode = false,
-};
-
-static const struct phy_cfg rtd1395_phy_cfg_2port = {
-       .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
-       .page0 = { [4] = {0xe4, 0xac},
-                 [13] = {0xf5, 0x00},
-                 [15] = {0xf7, 0x02}, },
-       .page1_size = 8,
-       .page1 = { /* default parameter */ },
-       .page2_size = 0,
-       .page2 = { /* no parameter */ },
-       .num_phy = 2,
-       .check_efuse = false,
-       .check_efuse_version = CHECK_EFUSE_V1,
-       .efuse_dc_driving_rate = 1,
-       .dc_driving_mask = 0xf,
-       .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
-       .dc_disconnect_mask = 0xf,
-       .usb_dc_disconnect_at_page0 = true,
-       .do_toggle = true,
-       .do_toggle_driving = false,
-       .driving_updated_for_dev_dis = 0xf,
-       .use_default_parameter = false,
-       .is_double_sensitivity_mode = false,
-};
-
-static const struct phy_cfg rtd1619_phy_cfg = {
-       .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
-       .page0 = { [4] = {0xe4, 0x68}, },
-       .page1_size = 8,
-       .page1 = { /* default parameter */ },
-       .page2_size = 0,
-       .page2 = { /* no parameter */ },
-       .num_phy = 1,
-       .check_efuse = true,
-       .check_efuse_version = CHECK_EFUSE_V1,
-       .efuse_dc_driving_rate = 1,
-       .dc_driving_mask = 0xf,
-       .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
-       .dc_disconnect_mask = 0xf,
-       .usb_dc_disconnect_at_page0 = true,
-       .do_toggle = true,
-       .do_toggle_driving = false,
-       .driving_updated_for_dev_dis = 0xf,
-       .use_default_parameter = false,
-       .is_double_sensitivity_mode = false,
-};
-
-static const struct phy_cfg rtd1319_phy_cfg = {
-       .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
-       .page0 = { [0] = {0xe0, 0x18},
-                  [4] = {0xe4, 0x6a},
-                  [7] = {0xe7, 0x71},
-                 [13] = {0xf5, 0x15},
-                 [15] = {0xf7, 0x32}, },
-       .page1_size = 8,
-       .page1 = { [3] = {0xe3, 0x44}, },
-       .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE,
-       .page2 = { [0] = {0xe0, 0x01}, },
-       .num_phy = 1,
-       .check_efuse = true,
-       .check_efuse_version = CHECK_EFUSE_V1,
-       .efuse_dc_driving_rate = 1,
-       .dc_driving_mask = 0xf,
-       .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
-       .dc_disconnect_mask = 0xf,
-       .usb_dc_disconnect_at_page0 = true,
-       .do_toggle = true,
-       .do_toggle_driving = true,
-       .driving_updated_for_dev_dis = 0xf,
-       .use_default_parameter = false,
-       .is_double_sensitivity_mode = true,
-};
-
-static const struct phy_cfg rtd1312c_phy_cfg = {
-       .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
-       .page0 = { [0] = {0xe0, 0x14},
-                  [4] = {0xe4, 0x67},
-                  [5] = {0xe5, 0x55}, },
-       .page1_size = 8,
-       .page1 = { [3] = {0xe3, 0x23},
-                  [6] = {0xe6, 0x58}, },
-       .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE,
-       .page2 = { /* default parameter */ },
-       .num_phy = 1,
-       .check_efuse = true,
-       .check_efuse_version = CHECK_EFUSE_V1,
-       .efuse_dc_driving_rate = 1,
-       .dc_driving_mask = 0xf,
-       .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
-       .dc_disconnect_mask = 0xf,
-       .usb_dc_disconnect_at_page0 = true,
-       .do_toggle = true,
-       .do_toggle_driving = true,
-       .driving_updated_for_dev_dis = 0xf,
-       .use_default_parameter = false,
-       .is_double_sensitivity_mode = true,
-};
-
-static const struct phy_cfg rtd1619b_phy_cfg = {
-       .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
-       .page0 = { [0] = {0xe0, 0xa3},
-                  [4] = {0xe4, 0x88},
-                  [5] = {0xe5, 0x4f},
-                  [6] = {0xe6, 0x02}, },
-       .page1_size = 8,
-       .page1 = { [3] = {0xe3, 0x64}, },
-       .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE,
-       .page2 = { [7] = {0xe7, 0x45}, },
-       .num_phy = 1,
-       .check_efuse = true,
-       .check_efuse_version = CHECK_EFUSE_V1,
-       .efuse_dc_driving_rate = EFUS_USB_DC_CAL_RATE,
-       .dc_driving_mask = 0x1f,
-       .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
-       .dc_disconnect_mask = 0xf,
-       .usb_dc_disconnect_at_page0 = false,
-       .do_toggle = true,
-       .do_toggle_driving = true,
-       .driving_updated_for_dev_dis = 0x8,
-       .use_default_parameter = false,
-       .is_double_sensitivity_mode = true,
-};
-
-static const struct phy_cfg rtd1319d_phy_cfg = {
-       .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
-       .page0 = { [0] = {0xe0, 0xa3},
-                  [4] = {0xe4, 0x8e},
-                  [5] = {0xe5, 0x4f},
-                  [6] = {0xe6, 0x02}, },
-       .page1_size = MAX_USB_PHY_PAGE1_DATA_SIZE,
-       .page1 = { [14] = {0xf5, 0x1}, },
-       .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE,
-       .page2 = { [7] = {0xe7, 0x44}, },
-       .check_efuse = true,
-       .num_phy = 1,
-       .check_efuse_version = CHECK_EFUSE_V1,
-       .efuse_dc_driving_rate = EFUS_USB_DC_CAL_RATE,
-       .dc_driving_mask = 0x1f,
-       .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
-       .dc_disconnect_mask = 0xf,
-       .usb_dc_disconnect_at_page0 = false,
-       .do_toggle = true,
-       .do_toggle_driving = false,
-       .driving_updated_for_dev_dis = 0x8,
-       .use_default_parameter = false,
-       .is_double_sensitivity_mode = true,
-};
-
-static const struct phy_cfg rtd1315e_phy_cfg = {
-       .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
-       .page0 = { [0] = {0xe0, 0xa3},
-                  [4] = {0xe4, 0x8c},
-                  [5] = {0xe5, 0x4f},
-                  [6] = {0xe6, 0x02}, },
-       .page1_size = MAX_USB_PHY_PAGE1_DATA_SIZE,
-       .page1 = { [3] = {0xe3, 0x7f},
-                 [14] = {0xf5, 0x01}, },
-       .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE,
-       .page2 = { [7] = {0xe7, 0x44}, },
-       .num_phy = 1,
-       .check_efuse = true,
-       .check_efuse_version = CHECK_EFUSE_V2,
-       .efuse_dc_driving_rate = EFUS_USB_DC_CAL_RATE,
-       .dc_driving_mask = 0x1f,
-       .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
-       .dc_disconnect_mask = 0xf,
-       .usb_dc_disconnect_at_page0 = false,
-       .do_toggle = true,
-       .do_toggle_driving = false,
-       .driving_updated_for_dev_dis = 0x8,
-       .use_default_parameter = false,
-       .is_double_sensitivity_mode = true,
-};
-
-static const struct of_device_id usbphy_rtk_dt_match[] = {
-       { .compatible = "realtek,rtd1295-usb2phy", .data = &rtd1295_phy_cfg },
-       { .compatible = "realtek,rtd1312c-usb2phy", .data = &rtd1312c_phy_cfg },
-       { .compatible = "realtek,rtd1315e-usb2phy", .data = &rtd1315e_phy_cfg },
-       { .compatible = "realtek,rtd1319-usb2phy", .data = &rtd1319_phy_cfg },
-       { .compatible = "realtek,rtd1319d-usb2phy", .data = &rtd1319d_phy_cfg },
-       { .compatible = "realtek,rtd1395-usb2phy", .data = &rtd1395_phy_cfg },
-       { .compatible = "realtek,rtd1395-usb2phy-2port", .data = &rtd1395_phy_cfg_2port },
-       { .compatible = "realtek,rtd1619-usb2phy", .data = &rtd1619_phy_cfg },
-       { .compatible = "realtek,rtd1619b-usb2phy", .data = &rtd1619b_phy_cfg },
-       {},
-};
-MODULE_DEVICE_TABLE(of, usbphy_rtk_dt_match);
-
-static struct platform_driver rtk_usb2phy_driver = {
-       .probe          = rtk_usb2phy_probe,
-       .remove_new     = rtk_usb2phy_remove,
-       .driver         = {
-               .name   = "rtk-usb2phy",
-               .of_match_table = usbphy_rtk_dt_match,
-       },
-};
-
-module_platform_driver(rtk_usb2phy_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform: rtk-usb2phy");
-MODULE_AUTHOR("Stanley Chang <stanley_chang@realtek.com>");
-MODULE_DESCRIPTION("Realtek usb 2.0 phy driver");
diff --git a/drivers/phy/realtek/phy-rtk-usb3.c b/drivers/phy/realtek/phy-rtk-usb3.c
deleted file mode 100644 (file)
index 67446a8..0000000
+++ /dev/null
@@ -1,761 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- *  phy-rtk-usb3.c RTK usb3.0 phy driver
- *
- * copyright (c) 2023 realtek semiconductor corporation
- *
- */
-
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/platform_device.h>
-#include <linux/uaccess.h>
-#include <linux/debugfs.h>
-#include <linux/nvmem-consumer.h>
-#include <linux/regmap.h>
-#include <linux/sys_soc.h>
-#include <linux/mfd/syscon.h>
-#include <linux/phy/phy.h>
-#include <linux/usb.h>
-#include <linux/usb/hcd.h>
-#include <linux/usb/phy.h>
-
-#define USB_MDIO_CTRL_PHY_BUSY BIT(7)
-#define USB_MDIO_CTRL_PHY_WRITE BIT(0)
-#define USB_MDIO_CTRL_PHY_ADDR_SHIFT 8
-#define USB_MDIO_CTRL_PHY_DATA_SHIFT 16
-
-#define MAX_USB_PHY_DATA_SIZE 0x30
-#define PHY_ADDR_0X09 0x09
-#define PHY_ADDR_0X0B 0x0b
-#define PHY_ADDR_0X0D 0x0d
-#define PHY_ADDR_0X10 0x10
-#define PHY_ADDR_0X1F 0x1f
-#define PHY_ADDR_0X20 0x20
-#define PHY_ADDR_0X21 0x21
-#define PHY_ADDR_0X30 0x30
-
-#define REG_0X09_FORCE_CALIBRATION BIT(9)
-#define REG_0X0B_RX_OFFSET_RANGE_MASK 0xc
-#define REG_0X0D_RX_DEBUG_TEST_EN BIT(6)
-#define REG_0X10_DEBUG_MODE_SETTING 0x3c0
-#define REG_0X10_DEBUG_MODE_SETTING_MASK 0x3f8
-#define REG_0X1F_RX_OFFSET_CODE_MASK 0x1e
-
-#define USB_U3_TX_LFPS_SWING_TRIM_SHIFT 4
-#define USB_U3_TX_LFPS_SWING_TRIM_MASK 0xf
-#define AMPLITUDE_CONTROL_COARSE_MASK 0xff
-#define AMPLITUDE_CONTROL_FINE_MASK 0xffff
-#define AMPLITUDE_CONTROL_COARSE_DEFAULT 0xff
-#define AMPLITUDE_CONTROL_FINE_DEFAULT 0xffff
-
-#define PHY_ADDR_MAP_ARRAY_INDEX(addr) (addr)
-#define ARRAY_INDEX_MAP_PHY_ADDR(index) (index)
-
-struct phy_reg {
-       void __iomem *reg_mdio_ctl;
-};
-
-struct phy_data {
-       u8 addr;
-       u16 data;
-};
-
-struct phy_cfg {
-       int param_size;
-       struct phy_data param[MAX_USB_PHY_DATA_SIZE];
-
-       bool check_efuse;
-       bool do_toggle;
-       bool do_toggle_once;
-       bool use_default_parameter;
-       bool check_rx_front_end_offset;
-};
-
-struct phy_parameter {
-       struct phy_reg phy_reg;
-
-       /* Get from efuse */
-       u8 efuse_usb_u3_tx_lfps_swing_trim;
-
-       /* Get from dts */
-       u32 amplitude_control_coarse;
-       u32 amplitude_control_fine;
-};
-
-struct rtk_phy {
-       struct usb_phy phy;
-       struct device *dev;
-
-       struct phy_cfg *phy_cfg;
-       int num_phy;
-       struct phy_parameter *phy_parameter;
-
-       struct dentry *debug_dir;
-};
-
-#define PHY_IO_TIMEOUT_USEC            (50000)
-#define PHY_IO_DELAY_US                        (100)
-
-static inline int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
-{
-       int ret;
-       unsigned int val;
-
-       ret = read_poll_timeout(readl, val, ((val & mask) == result),
-                               PHY_IO_DELAY_US, PHY_IO_TIMEOUT_USEC, false, reg);
-       if (ret) {
-               pr_err("%s can't program USB phy\n", __func__);
-               return -ETIMEDOUT;
-       }
-
-       return 0;
-}
-
-static int rtk_phy3_wait_vbusy(struct phy_reg *phy_reg)
-{
-       return utmi_wait_register(phy_reg->reg_mdio_ctl, USB_MDIO_CTRL_PHY_BUSY, 0);
-}
-
-static u16 rtk_phy_read(struct phy_reg *phy_reg, char addr)
-{
-       unsigned int tmp;
-       u32 value;
-
-       tmp = (addr << USB_MDIO_CTRL_PHY_ADDR_SHIFT);
-
-       writel(tmp, phy_reg->reg_mdio_ctl);
-
-       rtk_phy3_wait_vbusy(phy_reg);
-
-       value = readl(phy_reg->reg_mdio_ctl);
-       value = value >> USB_MDIO_CTRL_PHY_DATA_SHIFT;
-
-       return (u16)value;
-}
-
-static int rtk_phy_write(struct phy_reg *phy_reg, char addr, u16 data)
-{
-       unsigned int val;
-
-       val = USB_MDIO_CTRL_PHY_WRITE |
-                   (addr << USB_MDIO_CTRL_PHY_ADDR_SHIFT) |
-                   (data << USB_MDIO_CTRL_PHY_DATA_SHIFT);
-
-       writel(val, phy_reg->reg_mdio_ctl);
-
-       rtk_phy3_wait_vbusy(phy_reg);
-
-       return 0;
-}
-
-static void do_rtk_usb3_phy_toggle(struct rtk_phy *rtk_phy, int index, bool connect)
-{
-       struct phy_cfg *phy_cfg = rtk_phy->phy_cfg;
-       struct phy_reg *phy_reg;
-       struct phy_parameter *phy_parameter;
-       struct phy_data *phy_data;
-       u8 addr;
-       u16 data;
-       int i;
-
-       phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
-       phy_reg = &phy_parameter->phy_reg;
-
-       if (!phy_cfg->do_toggle)
-               return;
-
-       i = PHY_ADDR_MAP_ARRAY_INDEX(PHY_ADDR_0X09);
-       phy_data = phy_cfg->param + i;
-       addr = phy_data->addr;
-       data = phy_data->data;
-
-       if (!addr && !data) {
-               addr = PHY_ADDR_0X09;
-               data = rtk_phy_read(phy_reg, addr);
-               phy_data->addr = addr;
-               phy_data->data = data;
-       }
-
-       rtk_phy_write(phy_reg, addr, data & (~REG_0X09_FORCE_CALIBRATION));
-       mdelay(1);
-       rtk_phy_write(phy_reg, addr, data | REG_0X09_FORCE_CALIBRATION);
-}
-
-static int do_rtk_phy_init(struct rtk_phy *rtk_phy, int index)
-{
-       struct phy_cfg *phy_cfg;
-       struct phy_reg *phy_reg;
-       struct phy_parameter *phy_parameter;
-       int i = 0;
-
-       phy_cfg = rtk_phy->phy_cfg;
-       phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
-       phy_reg = &phy_parameter->phy_reg;
-
-       if (phy_cfg->use_default_parameter)
-               goto do_toggle;
-
-       for (i = 0; i < phy_cfg->param_size; i++) {
-               struct phy_data *phy_data = phy_cfg->param + i;
-               u8 addr = phy_data->addr;
-               u16 data = phy_data->data;
-
-               if (!addr && !data)
-                       continue;
-
-               rtk_phy_write(phy_reg, addr, data);
-       }
-
-do_toggle:
-       if (phy_cfg->do_toggle_once)
-               phy_cfg->do_toggle = true;
-
-       do_rtk_usb3_phy_toggle(rtk_phy, index, false);
-
-       if (phy_cfg->do_toggle_once) {
-               u16 check_value = 0;
-               int count = 10;
-               u16 value_0x0d, value_0x10;
-
-               /* Enable Debug mode by set 0x0D and 0x10 */
-               value_0x0d = rtk_phy_read(phy_reg, PHY_ADDR_0X0D);
-               value_0x10 = rtk_phy_read(phy_reg, PHY_ADDR_0X10);
-
-               rtk_phy_write(phy_reg, PHY_ADDR_0X0D,
-                             value_0x0d | REG_0X0D_RX_DEBUG_TEST_EN);
-               rtk_phy_write(phy_reg, PHY_ADDR_0X10,
-                             (value_0x10 & ~REG_0X10_DEBUG_MODE_SETTING_MASK) |
-                             REG_0X10_DEBUG_MODE_SETTING);
-
-               check_value = rtk_phy_read(phy_reg, PHY_ADDR_0X30);
-
-               while (!(check_value & BIT(15))) {
-                       check_value = rtk_phy_read(phy_reg, PHY_ADDR_0X30);
-                       mdelay(1);
-                       if (count-- < 0)
-                               break;
-               }
-
-               if (!(check_value & BIT(15)))
-                       dev_info(rtk_phy->dev, "toggle fail addr=0x%02x, data=0x%04x\n",
-                                PHY_ADDR_0X30, check_value);
-
-               /* Disable Debug mode by set 0x0D and 0x10 to default*/
-               rtk_phy_write(phy_reg, PHY_ADDR_0X0D, value_0x0d);
-               rtk_phy_write(phy_reg, PHY_ADDR_0X10, value_0x10);
-
-               phy_cfg->do_toggle = false;
-       }
-
-       if (phy_cfg->check_rx_front_end_offset) {
-               u16 rx_offset_code, rx_offset_range;
-               u16 code_mask = REG_0X1F_RX_OFFSET_CODE_MASK;
-               u16 range_mask = REG_0X0B_RX_OFFSET_RANGE_MASK;
-               bool do_update = false;
-
-               rx_offset_code = rtk_phy_read(phy_reg, PHY_ADDR_0X1F);
-               if (((rx_offset_code & code_mask) == 0x0) ||
-                   ((rx_offset_code & code_mask) == code_mask))
-                       do_update = true;
-
-               rx_offset_range = rtk_phy_read(phy_reg, PHY_ADDR_0X0B);
-               if (((rx_offset_range & range_mask) == range_mask) && do_update) {
-                       dev_warn(rtk_phy->dev, "Don't update rx_offset_range (rx_offset_code=0x%x, rx_offset_range=0x%x)\n",
-                                rx_offset_code, rx_offset_range);
-                       do_update = false;
-               }
-
-               if (do_update) {
-                       u16 tmp1, tmp2;
-
-                       tmp1 = rx_offset_range & (~range_mask);
-                       tmp2 = rx_offset_range & range_mask;
-                       tmp2 += (1 << 2);
-                       rx_offset_range = tmp1 | (tmp2 & range_mask);
-                       rtk_phy_write(phy_reg, PHY_ADDR_0X0B, rx_offset_range);
-                       goto do_toggle;
-               }
-       }
-
-       return 0;
-}
-
-static int rtk_phy_init(struct phy *phy)
-{
-       struct rtk_phy *rtk_phy = phy_get_drvdata(phy);
-       int ret = 0;
-       int i;
-       unsigned long phy_init_time = jiffies;
-
-       for (i = 0; i < rtk_phy->num_phy; i++)
-               ret = do_rtk_phy_init(rtk_phy, i);
-
-       dev_dbg(rtk_phy->dev, "Initialized RTK USB 3.0 PHY (take %dms)\n",
-               jiffies_to_msecs(jiffies - phy_init_time));
-
-       return ret;
-}
-
-static int rtk_phy_exit(struct phy *phy)
-{
-       return 0;
-}
-
-static const struct phy_ops ops = {
-       .init           = rtk_phy_init,
-       .exit           = rtk_phy_exit,
-       .owner          = THIS_MODULE,
-};
-
-static void rtk_phy_toggle(struct usb_phy *usb3_phy, bool connect, int port)
-{
-       int index = port;
-       struct rtk_phy *rtk_phy = NULL;
-
-       rtk_phy = dev_get_drvdata(usb3_phy->dev);
-
-       if (index > rtk_phy->num_phy) {
-               dev_err(rtk_phy->dev, "%s: The port=%d is not in usb phy (num_phy=%d)\n",
-                       __func__, index, rtk_phy->num_phy);
-               return;
-       }
-
-       do_rtk_usb3_phy_toggle(rtk_phy, index, connect);
-}
-
-static int rtk_phy_notify_port_status(struct usb_phy *x, int port,
-                                     u16 portstatus, u16 portchange)
-{
-       bool connect = false;
-
-       pr_debug("%s port=%d portstatus=0x%x portchange=0x%x\n",
-                __func__, port, (int)portstatus, (int)portchange);
-       if (portstatus & USB_PORT_STAT_CONNECTION)
-               connect = true;
-
-       if (portchange & USB_PORT_STAT_C_CONNECTION)
-               rtk_phy_toggle(x, connect, port);
-
-       return 0;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static struct dentry *create_phy_debug_root(void)
-{
-       struct dentry *phy_debug_root;
-
-       phy_debug_root = debugfs_lookup("phy", usb_debug_root);
-       if (!phy_debug_root)
-               phy_debug_root = debugfs_create_dir("phy", usb_debug_root);
-
-       return phy_debug_root;
-}
-
-static int rtk_usb3_parameter_show(struct seq_file *s, void *unused)
-{
-       struct rtk_phy *rtk_phy = s->private;
-       struct phy_cfg *phy_cfg;
-       int i, index;
-
-       phy_cfg = rtk_phy->phy_cfg;
-
-       seq_puts(s, "Property:\n");
-       seq_printf(s, "  check_efuse: %s\n",
-                  phy_cfg->check_efuse ? "Enable" : "Disable");
-       seq_printf(s, "  do_toggle: %s\n",
-                  phy_cfg->do_toggle ? "Enable" : "Disable");
-       seq_printf(s, "  do_toggle_once: %s\n",
-                  phy_cfg->do_toggle_once ? "Enable" : "Disable");
-       seq_printf(s, "  use_default_parameter: %s\n",
-                  phy_cfg->use_default_parameter ? "Enable" : "Disable");
-
-       for (index = 0; index < rtk_phy->num_phy; index++) {
-               struct phy_reg *phy_reg;
-               struct phy_parameter *phy_parameter;
-
-               phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
-               phy_reg = &phy_parameter->phy_reg;
-
-               seq_printf(s, "PHY %d:\n", index);
-
-               for (i = 0; i < phy_cfg->param_size; i++) {
-                       struct phy_data *phy_data = phy_cfg->param + i;
-                       u8 addr = ARRAY_INDEX_MAP_PHY_ADDR(i);
-                       u16 data = phy_data->data;
-
-                       if (!phy_data->addr && !data)
-                               seq_printf(s, "  addr = 0x%02x, data = none   ==> read value = 0x%04x\n",
-                                          addr, rtk_phy_read(phy_reg, addr));
-                       else
-                               seq_printf(s, "  addr = 0x%02x, data = 0x%04x ==> read value = 0x%04x\n",
-                                          addr, data, rtk_phy_read(phy_reg, addr));
-               }
-
-               seq_puts(s, "PHY Property:\n");
-               seq_printf(s, "  efuse_usb_u3_tx_lfps_swing_trim: 0x%x\n",
-                          (int)phy_parameter->efuse_usb_u3_tx_lfps_swing_trim);
-               seq_printf(s, "  amplitude_control_coarse: 0x%x\n",
-                          (int)phy_parameter->amplitude_control_coarse);
-               seq_printf(s, "  amplitude_control_fine: 0x%x\n",
-                          (int)phy_parameter->amplitude_control_fine);
-       }
-
-       return 0;
-}
-DEFINE_SHOW_ATTRIBUTE(rtk_usb3_parameter);
-
-static inline void create_debug_files(struct rtk_phy *rtk_phy)
-{
-       struct dentry *phy_debug_root = NULL;
-
-       phy_debug_root = create_phy_debug_root();
-
-       if (!phy_debug_root)
-               return;
-
-       rtk_phy->debug_dir = debugfs_create_dir(dev_name(rtk_phy->dev), phy_debug_root);
-
-       debugfs_create_file("parameter", 0444, rtk_phy->debug_dir, rtk_phy,
-                           &rtk_usb3_parameter_fops);
-
-       return;
-}
-
-static inline void remove_debug_files(struct rtk_phy *rtk_phy)
-{
-       debugfs_remove_recursive(rtk_phy->debug_dir);
-}
-#else
-static inline void create_debug_files(struct rtk_phy *rtk_phy) { }
-static inline void remove_debug_files(struct rtk_phy *rtk_phy) { }
-#endif /* CONFIG_DEBUG_FS */
-
-static int get_phy_data_by_efuse(struct rtk_phy *rtk_phy,
-                                struct phy_parameter *phy_parameter, int index)
-{
-       struct phy_cfg *phy_cfg = rtk_phy->phy_cfg;
-       u8 value = 0;
-       struct nvmem_cell *cell;
-
-       if (!phy_cfg->check_efuse)
-               goto out;
-
-       cell = nvmem_cell_get(rtk_phy->dev, "usb_u3_tx_lfps_swing_trim");
-       if (IS_ERR(cell)) {
-               dev_dbg(rtk_phy->dev, "%s no usb_u3_tx_lfps_swing_trim: %ld\n",
-                       __func__, PTR_ERR(cell));
-       } else {
-               unsigned char *buf;
-               size_t buf_size;
-
-               buf = nvmem_cell_read(cell, &buf_size);
-               if (!IS_ERR(buf)) {
-                       value = buf[0] & USB_U3_TX_LFPS_SWING_TRIM_MASK;
-                       kfree(buf);
-               }
-               nvmem_cell_put(cell);
-       }
-
-       if (value > 0 && value < 0x8)
-               phy_parameter->efuse_usb_u3_tx_lfps_swing_trim = 0x8;
-       else
-               phy_parameter->efuse_usb_u3_tx_lfps_swing_trim = (u8)value;
-
-out:
-       return 0;
-}
-
-static void update_amplitude_control_value(struct rtk_phy *rtk_phy,
-                                          struct phy_parameter *phy_parameter)
-{
-       struct phy_cfg *phy_cfg;
-       struct phy_reg *phy_reg;
-
-       phy_reg = &phy_parameter->phy_reg;
-       phy_cfg = rtk_phy->phy_cfg;
-
-       if (phy_parameter->amplitude_control_coarse != AMPLITUDE_CONTROL_COARSE_DEFAULT) {
-               u16 val_mask = AMPLITUDE_CONTROL_COARSE_MASK;
-               u16 data;
-
-               if (!phy_cfg->param[PHY_ADDR_0X20].addr && !phy_cfg->param[PHY_ADDR_0X20].data) {
-                       phy_cfg->param[PHY_ADDR_0X20].addr = PHY_ADDR_0X20;
-                       data = rtk_phy_read(phy_reg, PHY_ADDR_0X20);
-               } else {
-                       data = phy_cfg->param[PHY_ADDR_0X20].data;
-               }
-
-               data &= (~val_mask);
-               data |= (phy_parameter->amplitude_control_coarse & val_mask);
-
-               phy_cfg->param[PHY_ADDR_0X20].data = data;
-       }
-
-       if (phy_parameter->efuse_usb_u3_tx_lfps_swing_trim) {
-               u8 efuse_val = phy_parameter->efuse_usb_u3_tx_lfps_swing_trim;
-               u16 val_mask = USB_U3_TX_LFPS_SWING_TRIM_MASK;
-               int val_shift = USB_U3_TX_LFPS_SWING_TRIM_SHIFT;
-               u16 data;
-
-               if (!phy_cfg->param[PHY_ADDR_0X20].addr && !phy_cfg->param[PHY_ADDR_0X20].data) {
-                       phy_cfg->param[PHY_ADDR_0X20].addr = PHY_ADDR_0X20;
-                       data = rtk_phy_read(phy_reg, PHY_ADDR_0X20);
-               } else {
-                       data = phy_cfg->param[PHY_ADDR_0X20].data;
-               }
-
-               data &= ~(val_mask << val_shift);
-               data |= ((efuse_val & val_mask) << val_shift);
-
-               phy_cfg->param[PHY_ADDR_0X20].data = data;
-       }
-
-       if (phy_parameter->amplitude_control_fine != AMPLITUDE_CONTROL_FINE_DEFAULT) {
-               u16 val_mask = AMPLITUDE_CONTROL_FINE_MASK;
-
-               if (!phy_cfg->param[PHY_ADDR_0X21].addr && !phy_cfg->param[PHY_ADDR_0X21].data)
-                       phy_cfg->param[PHY_ADDR_0X21].addr = PHY_ADDR_0X21;
-
-               phy_cfg->param[PHY_ADDR_0X21].data =
-                           phy_parameter->amplitude_control_fine & val_mask;
-       }
-}
-
-static int parse_phy_data(struct rtk_phy *rtk_phy)
-{
-       struct device *dev = rtk_phy->dev;
-       struct phy_parameter *phy_parameter;
-       int ret = 0;
-       int index;
-
-       rtk_phy->phy_parameter = devm_kzalloc(dev, sizeof(struct phy_parameter) *
-                                             rtk_phy->num_phy, GFP_KERNEL);
-       if (!rtk_phy->phy_parameter)
-               return -ENOMEM;
-
-       for (index = 0; index < rtk_phy->num_phy; index++) {
-               phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
-
-               phy_parameter->phy_reg.reg_mdio_ctl = of_iomap(dev->of_node, 0) + index;
-
-               /* Amplitude control address 0x20 bit 0 to bit 7 */
-               if (of_property_read_u32(dev->of_node, "realtek,amplitude-control-coarse-tuning",
-                                        &phy_parameter->amplitude_control_coarse))
-                       phy_parameter->amplitude_control_coarse = AMPLITUDE_CONTROL_COARSE_DEFAULT;
-
-               /* Amplitude control address 0x21 bit 0 to bit 16 */
-               if (of_property_read_u32(dev->of_node, "realtek,amplitude-control-fine-tuning",
-                                        &phy_parameter->amplitude_control_fine))
-                       phy_parameter->amplitude_control_fine = AMPLITUDE_CONTROL_FINE_DEFAULT;
-
-               get_phy_data_by_efuse(rtk_phy, phy_parameter, index);
-
-               update_amplitude_control_value(rtk_phy, phy_parameter);
-       }
-
-       return ret;
-}
-
-static int rtk_usb3phy_probe(struct platform_device *pdev)
-{
-       struct rtk_phy *rtk_phy;
-       struct device *dev = &pdev->dev;
-       struct phy *generic_phy;
-       struct phy_provider *phy_provider;
-       const struct phy_cfg *phy_cfg;
-       int ret;
-
-       phy_cfg = of_device_get_match_data(dev);
-       if (!phy_cfg) {
-               dev_err(dev, "phy config are not assigned!\n");
-               return -EINVAL;
-       }
-
-       rtk_phy = devm_kzalloc(dev, sizeof(*rtk_phy), GFP_KERNEL);
-       if (!rtk_phy)
-               return -ENOMEM;
-
-       rtk_phy->dev                    = &pdev->dev;
-       rtk_phy->phy.dev                = rtk_phy->dev;
-       rtk_phy->phy.label              = "rtk-usb3phy";
-       rtk_phy->phy.notify_port_status = rtk_phy_notify_port_status;
-
-       rtk_phy->phy_cfg = devm_kzalloc(dev, sizeof(*phy_cfg), GFP_KERNEL);
-
-       memcpy(rtk_phy->phy_cfg, phy_cfg, sizeof(*phy_cfg));
-
-       rtk_phy->num_phy = 1;
-
-       ret = parse_phy_data(rtk_phy);
-       if (ret)
-               goto err;
-
-       platform_set_drvdata(pdev, rtk_phy);
-
-       generic_phy = devm_phy_create(rtk_phy->dev, NULL, &ops);
-       if (IS_ERR(generic_phy))
-               return PTR_ERR(generic_phy);
-
-       phy_set_drvdata(generic_phy, rtk_phy);
-
-       phy_provider = devm_of_phy_provider_register(rtk_phy->dev, of_phy_simple_xlate);
-       if (IS_ERR(phy_provider))
-               return PTR_ERR(phy_provider);
-
-       ret = usb_add_phy_dev(&rtk_phy->phy);
-       if (ret)
-               goto err;
-
-       create_debug_files(rtk_phy);
-
-err:
-       return ret;
-}
-
-static void rtk_usb3phy_remove(struct platform_device *pdev)
-{
-       struct rtk_phy *rtk_phy = platform_get_drvdata(pdev);
-
-       remove_debug_files(rtk_phy);
-
-       usb_remove_phy(&rtk_phy->phy);
-}
-
-static const struct phy_cfg rtd1295_phy_cfg = {
-       .param_size = MAX_USB_PHY_DATA_SIZE,
-       .param = {  [0] = {0x01, 0x4008},  [1] = {0x01, 0xe046},
-                   [2] = {0x02, 0x6046},  [3] = {0x03, 0x2779},
-                   [4] = {0x04, 0x72f5},  [5] = {0x05, 0x2ad3},
-                   [6] = {0x06, 0x000e},  [7] = {0x07, 0x2e00},
-                   [8] = {0x08, 0x3591},  [9] = {0x09, 0x525c},
-                  [10] = {0x0a, 0xa600}, [11] = {0x0b, 0xa904},
-                  [12] = {0x0c, 0xc000}, [13] = {0x0d, 0xef1c},
-                  [14] = {0x0e, 0x2000}, [15] = {0x0f, 0x0000},
-                  [16] = {0x10, 0x000c}, [17] = {0x11, 0x4c00},
-                  [18] = {0x12, 0xfc00}, [19] = {0x13, 0x0c81},
-                  [20] = {0x14, 0xde01}, [21] = {0x15, 0x0000},
-                  [22] = {0x16, 0x0000}, [23] = {0x17, 0x0000},
-                  [24] = {0x18, 0x0000}, [25] = {0x19, 0x4004},
-                  [26] = {0x1a, 0x1260}, [27] = {0x1b, 0xff00},
-                  [28] = {0x1c, 0xcb00}, [29] = {0x1d, 0xa03f},
-                  [30] = {0x1e, 0xc2e0}, [31] = {0x1f, 0x2807},
-                  [32] = {0x20, 0x947a}, [33] = {0x21, 0x88aa},
-                  [34] = {0x22, 0x0057}, [35] = {0x23, 0xab66},
-                  [36] = {0x24, 0x0800}, [37] = {0x25, 0x0000},
-                  [38] = {0x26, 0x040a}, [39] = {0x27, 0x01d6},
-                  [40] = {0x28, 0xf8c2}, [41] = {0x29, 0x3080},
-                  [42] = {0x2a, 0x3082}, [43] = {0x2b, 0x2078},
-                  [44] = {0x2c, 0xffff}, [45] = {0x2d, 0xffff},
-                  [46] = {0x2e, 0x0000}, [47] = {0x2f, 0x0040}, },
-       .check_efuse = false,
-       .do_toggle = true,
-       .do_toggle_once = false,
-       .use_default_parameter = false,
-       .check_rx_front_end_offset = false,
-};
-
-static const struct phy_cfg rtd1619_phy_cfg = {
-       .param_size = MAX_USB_PHY_DATA_SIZE,
-       .param = {  [8] = {0x08, 0x3591},
-                  [38] = {0x26, 0x840b},
-                  [40] = {0x28, 0xf842}, },
-       .check_efuse = false,
-       .do_toggle = true,
-       .do_toggle_once = false,
-       .use_default_parameter = false,
-       .check_rx_front_end_offset = false,
-};
-
-static const struct phy_cfg rtd1319_phy_cfg = {
-       .param_size = MAX_USB_PHY_DATA_SIZE,
-       .param = {  [1] = {0x01, 0xac86},
-                   [6] = {0x06, 0x0003},
-                   [9] = {0x09, 0x924c},
-                  [10] = {0x0a, 0xa608},
-                  [11] = {0x0b, 0xb905},
-                  [14] = {0x0e, 0x2010},
-                  [32] = {0x20, 0x705a},
-                  [33] = {0x21, 0xf645},
-                  [34] = {0x22, 0x0013},
-                  [35] = {0x23, 0xcb66},
-                  [41] = {0x29, 0xff00}, },
-       .check_efuse = true,
-       .do_toggle = true,
-       .do_toggle_once = false,
-       .use_default_parameter = false,
-       .check_rx_front_end_offset = false,
-};
-
-static const struct phy_cfg rtd1619b_phy_cfg = {
-       .param_size = MAX_USB_PHY_DATA_SIZE,
-       .param = {  [1] = {0x01, 0xac8c},
-                   [6] = {0x06, 0x0017},
-                   [9] = {0x09, 0x724c},
-                  [10] = {0x0a, 0xb610},
-                  [11] = {0x0b, 0xb90d},
-                  [13] = {0x0d, 0xef2a},
-                  [15] = {0x0f, 0x9050},
-                  [16] = {0x10, 0x000c},
-                  [32] = {0x20, 0x70ff},
-                  [34] = {0x22, 0x0013},
-                  [35] = {0x23, 0xdb66},
-                  [38] = {0x26, 0x8609},
-                  [41] = {0x29, 0xff13},
-                  [42] = {0x2a, 0x3070}, },
-       .check_efuse = true,
-       .do_toggle = false,
-       .do_toggle_once = true,
-       .use_default_parameter = false,
-       .check_rx_front_end_offset = false,
-};
-
-static const  struct phy_cfg rtd1319d_phy_cfg = {
-       .param_size = MAX_USB_PHY_DATA_SIZE,
-       .param = {  [1] = {0x01, 0xac89},
-                   [4] = {0x04, 0xf2f5},
-                   [6] = {0x06, 0x0017},
-                   [9] = {0x09, 0x424c},
-                  [10] = {0x0a, 0x9610},
-                  [11] = {0x0b, 0x9901},
-                  [12] = {0x0c, 0xf000},
-                  [13] = {0x0d, 0xef2a},
-                  [14] = {0x0e, 0x1000},
-                  [15] = {0x0f, 0x9050},
-                  [32] = {0x20, 0x7077},
-                  [35] = {0x23, 0x0b62},
-                  [37] = {0x25, 0x10ec},
-                  [42] = {0x2a, 0x3070}, },
-       .check_efuse = true,
-       .do_toggle = false,
-       .do_toggle_once = true,
-       .use_default_parameter = false,
-       .check_rx_front_end_offset = true,
-};
-
-static const struct of_device_id usbphy_rtk_dt_match[] = {
-       { .compatible = "realtek,rtd1295-usb3phy", .data = &rtd1295_phy_cfg },
-       { .compatible = "realtek,rtd1319-usb3phy", .data = &rtd1319_phy_cfg },
-       { .compatible = "realtek,rtd1319d-usb3phy", .data = &rtd1319d_phy_cfg },
-       { .compatible = "realtek,rtd1619-usb3phy", .data = &rtd1619_phy_cfg },
-       { .compatible = "realtek,rtd1619b-usb3phy", .data = &rtd1619b_phy_cfg },
-       {},
-};
-MODULE_DEVICE_TABLE(of, usbphy_rtk_dt_match);
-
-static struct platform_driver rtk_usb3phy_driver = {
-       .probe          = rtk_usb3phy_probe,
-       .remove_new     = rtk_usb3phy_remove,
-       .driver         = {
-               .name   = "rtk-usb3phy",
-               .of_match_table = usbphy_rtk_dt_match,
-       },
-};
-
-module_platform_driver(rtk_usb3phy_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform: rtk-usb3phy");
-MODULE_AUTHOR("Stanley Chang <stanley_chang@realtek.com>");
-MODULE_DESCRIPTION("Realtek usb 3.0 phy driver");
index cd6ac04c14680da86a2cf3b2f7b3b64830685a63..c3104714b48027956e7004899961e770aaa0eccf 100644 (file)
@@ -964,33 +964,6 @@ static const struct pci_device_id pmc_pci_ids[] = {
        { }
 };
 
-static int amd_pmc_get_dram_size(struct amd_pmc_dev *dev)
-{
-       int ret;
-
-       switch (dev->cpu_id) {
-       case AMD_CPU_ID_YC:
-               if (!(dev->major > 90 || (dev->major == 90 && dev->minor > 39))) {
-                       ret = -EINVAL;
-                       goto err_dram_size;
-               }
-               break;
-       default:
-               ret = -EINVAL;
-               goto err_dram_size;
-       }
-
-       ret = amd_pmc_send_cmd(dev, S2D_DRAM_SIZE, &dev->dram_size, dev->s2d_msg_id, true);
-       if (ret || !dev->dram_size)
-               goto err_dram_size;
-
-       return 0;
-
-err_dram_size:
-       dev_err(dev->dev, "DRAM size command not supported for this platform\n");
-       return ret;
-}
-
 static int amd_pmc_s2d_init(struct amd_pmc_dev *dev)
 {
        u32 phys_addr_low, phys_addr_hi;
@@ -1009,8 +982,8 @@ static int amd_pmc_s2d_init(struct amd_pmc_dev *dev)
                return -EIO;
 
        /* Get DRAM size */
-       ret = amd_pmc_get_dram_size(dev);
-       if (ret)
+       ret = amd_pmc_send_cmd(dev, S2D_DRAM_SIZE, &dev->dram_size, dev->s2d_msg_id, true);
+       if (ret || !dev->dram_size)
                dev->dram_size = S2D_TELEMETRY_DRAMBYTES_MAX;
 
        /* Get STB DRAM address */
index 5798b49ddaba901db74a072b123b7cfbb1e2ef0b..8c9f4f3227fc6dcf244210edd932301f491efb15 100644 (file)
@@ -588,17 +588,14 @@ static void release_attributes_data(void)
 static int hp_add_other_attributes(int attr_type)
 {
        struct kobject *attr_name_kobj;
-       union acpi_object *obj = NULL;
        int ret;
        char *attr_name;
 
-       mutex_lock(&bioscfg_drv.mutex);
-
        attr_name_kobj = kzalloc(sizeof(*attr_name_kobj), GFP_KERNEL);
-       if (!attr_name_kobj) {
-               ret = -ENOMEM;
-               goto err_other_attr_init;
-       }
+       if (!attr_name_kobj)
+               return -ENOMEM;
+
+       mutex_lock(&bioscfg_drv.mutex);
 
        /* Check if attribute type is supported */
        switch (attr_type) {
@@ -615,14 +612,14 @@ static int hp_add_other_attributes(int attr_type)
        default:
                pr_err("Error: Unknown attr_type: %d\n", attr_type);
                ret = -EINVAL;
-               goto err_other_attr_init;
+               kfree(attr_name_kobj);
+               goto unlock_drv_mutex;
        }
 
        ret = kobject_init_and_add(attr_name_kobj, &attr_name_ktype,
                                   NULL, "%s", attr_name);
        if (ret) {
                pr_err("Error encountered [%d]\n", ret);
-               kobject_put(attr_name_kobj);
                goto err_other_attr_init;
        }
 
@@ -630,27 +627,26 @@ static int hp_add_other_attributes(int attr_type)
        switch (attr_type) {
        case HPWMI_SECURE_PLATFORM_TYPE:
                ret = hp_populate_secure_platform_data(attr_name_kobj);
-               if (ret)
-                       goto err_other_attr_init;
                break;
 
        case HPWMI_SURE_START_TYPE:
                ret = hp_populate_sure_start_data(attr_name_kobj);
-               if (ret)
-                       goto err_other_attr_init;
                break;
 
        default:
                ret = -EINVAL;
-               goto err_other_attr_init;
        }
 
+       if (ret)
+               goto err_other_attr_init;
+
        mutex_unlock(&bioscfg_drv.mutex);
        return 0;
 
 err_other_attr_init:
+       kobject_put(attr_name_kobj);
+unlock_drv_mutex:
        mutex_unlock(&bioscfg_drv.mutex);
-       kfree(obj);
        return ret;
 }
 
index ac037540acfc602d45706c3a39fd87ce1e80620f..88eefccb6ed276a60a3c6d02b03f4716a48aea8f 100644 (file)
@@ -1425,18 +1425,17 @@ static int ideapad_kbd_bl_init(struct ideapad_private *priv)
        if (WARN_ON(priv->kbd_bl.initialized))
                return -EEXIST;
 
-       brightness = ideapad_kbd_bl_brightness_get(priv);
-       if (brightness < 0)
-               return brightness;
-
-       priv->kbd_bl.last_brightness = brightness;
-
        if (ideapad_kbd_bl_check_tristate(priv->kbd_bl.type)) {
                priv->kbd_bl.led.max_brightness = 2;
        } else {
                priv->kbd_bl.led.max_brightness = 1;
        }
 
+       brightness = ideapad_kbd_bl_brightness_get(priv);
+       if (brightness < 0)
+               return brightness;
+
+       priv->kbd_bl.last_brightness = brightness;
        priv->kbd_bl.led.name                    = "platform::" LED_FUNCTION_KBD_BACKLIGHT;
        priv->kbd_bl.led.brightness_get          = ideapad_kbd_bl_led_cdev_brightness_get;
        priv->kbd_bl.led.brightness_set_blocking = ideapad_kbd_bl_led_cdev_brightness_set;
index fdf55b5d69480e4a12765a15b42bb8ac6dee287b..e4be40f73eebfc3db68defdc11647e01ac5b604b 100644 (file)
@@ -102,7 +102,7 @@ static const struct telemetry_core_ops telm_defpltops = {
 /**
  * telemetry_update_events() - Update telemetry Configuration
  * @pss_evtconfig: PSS related config. No change if num_evts = 0.
- * @pss_evtconfig: IOSS related config. No change if num_evts = 0.
+ * @ioss_evtconfig: IOSS related config. No change if num_evts = 0.
  *
  * This API updates the IOSS & PSS Telemetry configuration. Old config
  * is overwritten. Call telemetry_reset_events when logging is over
@@ -176,7 +176,7 @@ EXPORT_SYMBOL_GPL(telemetry_reset_events);
 /**
  * telemetry_get_eventconfig() - Returns the pss and ioss events enabled
  * @pss_evtconfig: Pointer to PSS related configuration.
- * @pss_evtconfig: Pointer to IOSS related configuration.
+ * @ioss_evtconfig: Pointer to IOSS related configuration.
  * @pss_len:      Number of u32 elements allocated for pss_evtconfig array
  * @ioss_len:     Number of u32 elements allocated for ioss_evtconfig array
  *
index d440319a7945b8b772c39af354f57dee412fbc16..833cfab7d8776d810a0a111bad3008880643618b 100644 (file)
@@ -676,18 +676,20 @@ static void dasd_profile_start(struct dasd_block *block,
         * we count each request only once.
         */
        device = cqr->startdev;
-       if (device->profile.data) {
-               counter = 1; /* request is not yet queued on the start device */
-               list_for_each(l, &device->ccw_queue)
-                       if (++counter >= 31)
-                               break;
-       }
+       if (!device->profile.data)
+               return;
+
+       spin_lock(get_ccwdev_lock(device->cdev));
+       counter = 1; /* request is not yet queued on the start device */
+       list_for_each(l, &device->ccw_queue)
+               if (++counter >= 31)
+                       break;
+       spin_unlock(get_ccwdev_lock(device->cdev));
+
        spin_lock(&device->profile.lock);
-       if (device->profile.data) {
-               device->profile.data->dasd_io_nr_req[counter]++;
-               if (rq_data_dir(req) == READ)
-                       device->profile.data->dasd_read_nr_req[counter]++;
-       }
+       device->profile.data->dasd_io_nr_req[counter]++;
+       if (rq_data_dir(req) == READ)
+               device->profile.data->dasd_read_nr_req[counter]++;
        spin_unlock(&device->profile.lock);
 }
 
index 2e663131adaf67b869796953d89bd494048aa875..1b1b8a41c4d42e6145be51537785b609e37c73be 100644 (file)
@@ -283,7 +283,7 @@ struct dasd_pprc_dev_info {
        __u8 secondary;         /* 7       Secondary device address */
        __u16 pprc_id;          /* 8-9     Peer-to-Peer Remote Copy ID */
        __u8 reserved2[12];     /* 10-21   reserved */
-       __u16 prim_cu_ssid;     /* 22-23   Pimary Control Unit SSID */
+       __u16 prim_cu_ssid;     /* 22-23   Primary Control Unit SSID */
        __u8 reserved3[12];     /* 24-35   reserved */
        __u16 sec_cu_ssid;      /* 36-37   Secondary Control Unit SSID */
        __u8 reserved4[90];     /* 38-127  reserved */
index 4902d45e929ce2ad009cb3cc9fc00fac2f45483c..c61e6427384c34b44473af0b6965232c254e1710 100644 (file)
@@ -103,10 +103,11 @@ config CCWGROUP
 config ISM
        tristate "Support for ISM vPCI Adapter"
        depends on PCI
+       imply SMC
        default n
        help
          Select this option if you want to use the Internal Shared Memory
-         vPCI Adapter.
+         vPCI Adapter. The adapter can be used with the SMC network protocol.
 
          To compile as a module choose M. The module name is ism.
          If unsure, choose N.
index 6df7f377d2f90cabb7aeb76d7f6fa680f1aa5104..81aabbfbbe2ca4240533bc3ca3485ffb3af3bd20 100644 (file)
@@ -30,7 +30,6 @@ static const struct pci_device_id ism_device_table[] = {
 MODULE_DEVICE_TABLE(pci, ism_device_table);
 
 static debug_info_t *ism_debug_info;
-static const struct smcd_ops ism_ops;
 
 #define NO_CLIENT              0xff            /* must be >= MAX_CLIENTS */
 static struct ism_client *clients[MAX_CLIENTS];        /* use an array rather than */
@@ -289,22 +288,6 @@ out:
        return ret;
 }
 
-static int ism_query_rgid(struct ism_dev *ism, u64 rgid, u32 vid_valid,
-                         u32 vid)
-{
-       union ism_query_rgid cmd;
-
-       memset(&cmd, 0, sizeof(cmd));
-       cmd.request.hdr.cmd = ISM_QUERY_RGID;
-       cmd.request.hdr.len = sizeof(cmd.request);
-
-       cmd.request.rgid = rgid;
-       cmd.request.vlan_valid = vid_valid;
-       cmd.request.vlan_id = vid;
-
-       return ism_cmd(ism, &cmd);
-}
-
 static void ism_free_dmb(struct ism_dev *ism, struct ism_dmb *dmb)
 {
        clear_bit(dmb->sba_idx, ism->sba_bitmap);
@@ -429,23 +412,6 @@ static int ism_del_vlan_id(struct ism_dev *ism, u64 vlan_id)
        return ism_cmd(ism, &cmd);
 }
 
-static int ism_signal_ieq(struct ism_dev *ism, u64 rgid, u32 trigger_irq,
-                         u32 event_code, u64 info)
-{
-       union ism_sig_ieq cmd;
-
-       memset(&cmd, 0, sizeof(cmd));
-       cmd.request.hdr.cmd = ISM_SIGNAL_IEQ;
-       cmd.request.hdr.len = sizeof(cmd.request);
-
-       cmd.request.rgid = rgid;
-       cmd.request.trigger_irq = trigger_irq;
-       cmd.request.event_code = event_code;
-       cmd.request.info = info;
-
-       return ism_cmd(ism, &cmd);
-}
-
 static unsigned int max_bytes(unsigned int start, unsigned int len,
                              unsigned int boundary)
 {
@@ -503,14 +469,6 @@ u8 *ism_get_seid(void)
 }
 EXPORT_SYMBOL_GPL(ism_get_seid);
 
-static u16 ism_get_chid(struct ism_dev *ism)
-{
-       if (!ism || !ism->pdev)
-               return 0;
-
-       return to_zpci(ism->pdev)->pchid;
-}
-
 static void ism_handle_event(struct ism_dev *ism)
 {
        struct ism_event *entry;
@@ -569,11 +527,6 @@ static irqreturn_t ism_handle_irq(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-static u64 ism_get_local_gid(struct ism_dev *ism)
-{
-       return ism->local_gid;
-}
-
 static int ism_dev_init(struct ism_dev *ism)
 {
        struct pci_dev *pdev = ism->pdev;
@@ -774,6 +727,22 @@ module_exit(ism_exit);
 /*************************** SMC-D Implementation *****************************/
 
 #if IS_ENABLED(CONFIG_SMC)
+static int ism_query_rgid(struct ism_dev *ism, u64 rgid, u32 vid_valid,
+                         u32 vid)
+{
+       union ism_query_rgid cmd;
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.request.hdr.cmd = ISM_QUERY_RGID;
+       cmd.request.hdr.len = sizeof(cmd.request);
+
+       cmd.request.rgid = rgid;
+       cmd.request.vlan_valid = vid_valid;
+       cmd.request.vlan_id = vid;
+
+       return ism_cmd(ism, &cmd);
+}
+
 static int smcd_query_rgid(struct smcd_dev *smcd, u64 rgid, u32 vid_valid,
                           u32 vid)
 {
@@ -811,6 +780,23 @@ static int smcd_reset_vlan_required(struct smcd_dev *smcd)
        return ism_cmd_simple(smcd->priv, ISM_RESET_VLAN);
 }
 
+static int ism_signal_ieq(struct ism_dev *ism, u64 rgid, u32 trigger_irq,
+                         u32 event_code, u64 info)
+{
+       union ism_sig_ieq cmd;
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.request.hdr.cmd = ISM_SIGNAL_IEQ;
+       cmd.request.hdr.len = sizeof(cmd.request);
+
+       cmd.request.rgid = rgid;
+       cmd.request.trigger_irq = trigger_irq;
+       cmd.request.event_code = event_code;
+       cmd.request.info = info;
+
+       return ism_cmd(ism, &cmd);
+}
+
 static int smcd_signal_ieq(struct smcd_dev *smcd, u64 rgid, u32 trigger_irq,
                           u32 event_code, u64 info)
 {
@@ -830,11 +816,24 @@ static int smcd_supports_v2(void)
                SYSTEM_EID.type[0] != '0';
 }
 
+static u64 ism_get_local_gid(struct ism_dev *ism)
+{
+       return ism->local_gid;
+}
+
 static u64 smcd_get_local_gid(struct smcd_dev *smcd)
 {
        return ism_get_local_gid(smcd->priv);
 }
 
+static u16 ism_get_chid(struct ism_dev *ism)
+{
+       if (!ism || !ism->pdev)
+               return 0;
+
+       return to_zpci(ism->pdev)->pchid;
+}
+
 static u16 smcd_get_chid(struct smcd_dev *smcd)
 {
        return ism_get_chid(smcd->priv);
index 1e15ffa792955d7382b19546226bdcfa603a5685..44e9b09de47a5a01a0a22d48c9d637bdd7c7bf68 100644 (file)
@@ -1143,7 +1143,7 @@ int tb_port_lane_bonding_enable(struct tb_port *port)
         * Only set bonding if the link was not already bonded. This
         * avoids the lane adapter to re-enter bonding state.
         */
-       if (width == TB_LINK_WIDTH_SINGLE) {
+       if (width == TB_LINK_WIDTH_SINGLE && !tb_is_upstream_port(port)) {
                ret = tb_port_set_lane_bonding(port, true);
                if (ret)
                        goto err_lane1;
@@ -2880,6 +2880,7 @@ static int tb_switch_lane_bonding_disable(struct tb_switch *sw)
        return tb_port_wait_for_link_width(down, TB_LINK_WIDTH_SINGLE, 100);
 }
 
+/* Note updating sw->link_width done in tb_switch_update_link_attributes() */
 static int tb_switch_asym_enable(struct tb_switch *sw, enum tb_link_width width)
 {
        struct tb_port *up, *down, *port;
@@ -2919,10 +2920,10 @@ static int tb_switch_asym_enable(struct tb_switch *sw, enum tb_link_width width)
                        return ret;
        }
 
-       sw->link_width = width;
        return 0;
 }
 
+/* Note updating sw->link_width done in tb_switch_update_link_attributes() */
 static int tb_switch_asym_disable(struct tb_switch *sw)
 {
        struct tb_port *up, *down;
@@ -2957,7 +2958,6 @@ static int tb_switch_asym_disable(struct tb_switch *sw)
                        return ret;
        }
 
-       sw->link_width = TB_LINK_WIDTH_DUAL;
        return 0;
 }
 
index 5acdeb766860da51f912677a37c99c6b0166d922..fd49f86e03532c140557af4bb822eb2d7665ef95 100644 (file)
@@ -213,7 +213,17 @@ static void tb_add_dp_resources(struct tb_switch *sw)
                if (!tb_switch_query_dp_resource(sw, port))
                        continue;
 
-               list_add(&port->list, &tcm->dp_resources);
+               /*
+                * If DP IN on device router exist, position it at the
+                * beginning of the DP resources list, so that it is used
+                * before DP IN of the host router. This way external GPU(s)
+                * will be prioritized when pairing DP IN to a DP OUT.
+                */
+               if (tb_route(sw))
+                       list_add(&port->list, &tcm->dp_resources);
+               else
+                       list_add_tail(&port->list, &tcm->dp_resources);
+
                tb_port_dbg(port, "DP IN resource available\n");
        }
 }
index af981778382df71d6c109e3a2f7a83b0b3fb2d6a..02f297f5637d7562a1228e0e860af608ac6beda5 100644 (file)
@@ -1529,6 +1529,7 @@ irqreturn_t cdnsp_thread_irq_handler(int irq, void *data)
        unsigned long flags;
        int counter = 0;
 
+       local_bh_disable();
        spin_lock_irqsave(&pdev->lock, flags);
 
        if (pdev->cdnsp_state & (CDNSP_STATE_HALTED | CDNSP_STATE_DYING)) {
@@ -1541,6 +1542,7 @@ irqreturn_t cdnsp_thread_irq_handler(int irq, void *data)
                        cdnsp_died(pdev);
 
                spin_unlock_irqrestore(&pdev->lock, flags);
+               local_bh_enable();
                return IRQ_HANDLED;
        }
 
@@ -1557,6 +1559,7 @@ irqreturn_t cdnsp_thread_irq_handler(int irq, void *data)
        cdnsp_update_erst_dequeue(pdev, event_ring_deq, 1);
 
        spin_unlock_irqrestore(&pdev->lock, flags);
+       local_bh_enable();
 
        return IRQ_HANDLED;
 }
index b19e38d5fd10c1a4dfd84240df9e8203e4314f8f..7f8d33f92ddb5f5cfa3dbb0c9b845cd4f2903e78 100644 (file)
@@ -1047,7 +1047,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
 
                if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) {
                        dev_notice(ddev, "descriptor type invalid, skip\n");
-                       continue;
+                       goto skip_to_next_descriptor;
                }
 
                switch (cap_type) {
@@ -1078,6 +1078,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
                        break;
                }
 
+skip_to_next_descriptor:
                total_len -= length;
                buffer += length;
        }
index b4584a0cd484562633488d1552f60281d527bd6a..87480a6e6d934893a6096cbf7e58f5d1cc5358f1 100644 (file)
@@ -622,29 +622,6 @@ static int hub_ext_port_status(struct usb_hub *hub, int port1, int type,
                ret = 0;
        }
        mutex_unlock(&hub->status_mutex);
-
-       /*
-        * There is no need to lock status_mutex here, because status_mutex
-        * protects hub->status, and the phy driver only checks the port
-        * status without changing the status.
-        */
-       if (!ret) {
-               struct usb_device *hdev = hub->hdev;
-
-               /*
-                * Only roothub will be notified of port state changes,
-                * since the USB PHY only cares about changes at the next
-                * level.
-                */
-               if (is_root_hub(hdev)) {
-                       struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
-
-                       if (hcd->usb_phy)
-                               usb_phy_notify_port_status(hcd->usb_phy,
-                                                          port1 - 1, *status, *change);
-               }
-       }
-
        return ret;
 }
 
index 0144ca8350c31234956b5aea4bbb38bed7134a87..5c7538d498dd1194d9d328511f583b40c557cd5e 100644 (file)
@@ -2015,15 +2015,17 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
 {
        struct dwc2_qtd *qtd;
        struct dwc2_host_chan *chan;
-       u32 hcint, hcintmsk;
+       u32 hcint, hcintraw, hcintmsk;
 
        chan = hsotg->hc_ptr_array[chnum];
 
-       hcint = dwc2_readl(hsotg, HCINT(chnum));
+       hcintraw = dwc2_readl(hsotg, HCINT(chnum));
        hcintmsk = dwc2_readl(hsotg, HCINTMSK(chnum));
+       hcint = hcintraw & hcintmsk;
+       dwc2_writel(hsotg, hcint, HCINT(chnum));
+
        if (!chan) {
                dev_err(hsotg->dev, "## hc_ptr_array for channel is NULL ##\n");
-               dwc2_writel(hsotg, hcint, HCINT(chnum));
                return;
        }
 
@@ -2032,11 +2034,9 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
                         chnum);
                dev_vdbg(hsotg->dev,
                         "  hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",
-                        hcint, hcintmsk, hcint & hcintmsk);
+                        hcintraw, hcintmsk, hcint);
        }
 
-       dwc2_writel(hsotg, hcint, HCINT(chnum));
-
        /*
         * If we got an interrupt after someone called
         * dwc2_hcd_endpoint_disable() we don't want to crash below
@@ -2046,8 +2046,7 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
                return;
        }
 
-       chan->hcint = hcint;
-       hcint &= hcintmsk;
+       chan->hcint = hcintraw;
 
        /*
         * If the channel was halted due to a dequeue, the qtd list might
index 0328c86ef80613a8e3296c3cab8ee6a94a96604d..b101dbf8c5dcc775797da2ce3ea0f2c34ebd9323 100644 (file)
@@ -2034,6 +2034,8 @@ static int dwc3_probe(struct platform_device *pdev)
 
        pm_runtime_put(dev);
 
+       dma_set_max_seg_size(dev, UINT_MAX);
+
        return 0;
 
 err_exit_debugfs:
index 039bf241769afb789f7f09130e7af91eba62f12d..57ddd2e43022eb8f896acaf9c7e82d307bc145b2 100644 (file)
@@ -505,6 +505,7 @@ static int dwc3_setup_role_switch(struct dwc3 *dwc)
                dwc->role_switch_default_mode = USB_DR_MODE_PERIPHERAL;
                mode = DWC3_GCTL_PRTCAP_DEVICE;
        }
+       dwc3_set_mode(dwc, mode);
 
        dwc3_role_switch.fwnode = dev_fwnode(dwc->dev);
        dwc3_role_switch.set = dwc3_usb_role_switch_set;
@@ -526,7 +527,6 @@ static int dwc3_setup_role_switch(struct dwc3 *dwc)
                }
        }
 
-       dwc3_set_mode(dwc, mode);
        return 0;
 }
 #else
index 3de43df6bbe814a16e1c1d7578711129843fef10..fdf6d5d3c2ada4357bcf1a0156410e4fc0809cfa 100644 (file)
@@ -546,10 +546,9 @@ static int dwc3_qcom_setup_irq(struct platform_device *pdev)
                                pdata ? pdata->hs_phy_irq_index : -1);
        if (irq > 0) {
                /* Keep wakeup interrupts disabled until suspend */
-               irq_set_status_flags(irq, IRQ_NOAUTOEN);
                ret = devm_request_threaded_irq(qcom->dev, irq, NULL,
                                        qcom_dwc3_resume_irq,
-                                       IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+                                       IRQF_ONESHOT | IRQF_NO_AUTOEN,
                                        "qcom_dwc3 HS", qcom);
                if (ret) {
                        dev_err(qcom->dev, "hs_phy_irq failed: %d\n", ret);
@@ -561,10 +560,9 @@ static int dwc3_qcom_setup_irq(struct platform_device *pdev)
        irq = dwc3_qcom_get_irq(pdev, "dp_hs_phy_irq",
                                pdata ? pdata->dp_hs_phy_irq_index : -1);
        if (irq > 0) {
-               irq_set_status_flags(irq, IRQ_NOAUTOEN);
                ret = devm_request_threaded_irq(qcom->dev, irq, NULL,
                                        qcom_dwc3_resume_irq,
-                                       IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+                                       IRQF_ONESHOT | IRQF_NO_AUTOEN,
                                        "qcom_dwc3 DP_HS", qcom);
                if (ret) {
                        dev_err(qcom->dev, "dp_hs_phy_irq failed: %d\n", ret);
@@ -576,10 +574,9 @@ static int dwc3_qcom_setup_irq(struct platform_device *pdev)
        irq = dwc3_qcom_get_irq(pdev, "dm_hs_phy_irq",
                                pdata ? pdata->dm_hs_phy_irq_index : -1);
        if (irq > 0) {
-               irq_set_status_flags(irq, IRQ_NOAUTOEN);
                ret = devm_request_threaded_irq(qcom->dev, irq, NULL,
                                        qcom_dwc3_resume_irq,
-                                       IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+                                       IRQF_ONESHOT | IRQF_NO_AUTOEN,
                                        "qcom_dwc3 DM_HS", qcom);
                if (ret) {
                        dev_err(qcom->dev, "dm_hs_phy_irq failed: %d\n", ret);
@@ -591,10 +588,9 @@ static int dwc3_qcom_setup_irq(struct platform_device *pdev)
        irq = dwc3_qcom_get_irq(pdev, "ss_phy_irq",
                                pdata ? pdata->ss_phy_irq_index : -1);
        if (irq > 0) {
-               irq_set_status_flags(irq, IRQ_NOAUTOEN);
                ret = devm_request_threaded_irq(qcom->dev, irq, NULL,
                                        qcom_dwc3_resume_irq,
-                                       IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+                                       IRQF_ONESHOT | IRQF_NO_AUTOEN,
                                        "qcom_dwc3 SS", qcom);
                if (ret) {
                        dev_err(qcom->dev, "ss_phy_irq failed: %d\n", ret);
@@ -758,6 +754,7 @@ static int dwc3_qcom_of_register_core(struct platform_device *pdev)
        if (!qcom->dwc3) {
                ret = -ENODEV;
                dev_err(dev, "failed to get dwc3 platform device\n");
+               of_platform_depopulate(dev);
        }
 
 node_put:
@@ -766,9 +763,9 @@ node_put:
        return ret;
 }
 
-static struct platform_device *
-dwc3_qcom_create_urs_usb_platdev(struct device *dev)
+static struct platform_device *dwc3_qcom_create_urs_usb_platdev(struct device *dev)
 {
+       struct platform_device *urs_usb = NULL;
        struct fwnode_handle *fwh;
        struct acpi_device *adev;
        char name[8];
@@ -788,9 +785,26 @@ dwc3_qcom_create_urs_usb_platdev(struct device *dev)
 
        adev = to_acpi_device_node(fwh);
        if (!adev)
-               return NULL;
+               goto err_put_handle;
+
+       urs_usb = acpi_create_platform_device(adev, NULL);
+       if (IS_ERR_OR_NULL(urs_usb))
+               goto err_put_handle;
+
+       return urs_usb;
+
+err_put_handle:
+       fwnode_handle_put(fwh);
+
+       return urs_usb;
+}
 
-       return acpi_create_platform_device(adev, NULL);
+static void dwc3_qcom_destroy_urs_usb_platdev(struct platform_device *urs_usb)
+{
+       struct fwnode_handle *fwh = urs_usb->dev.fwnode;
+
+       platform_device_unregister(urs_usb);
+       fwnode_handle_put(fwh);
 }
 
 static int dwc3_qcom_probe(struct platform_device *pdev)
@@ -874,13 +888,13 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
        qcom->qscratch_base = devm_ioremap_resource(dev, parent_res);
        if (IS_ERR(qcom->qscratch_base)) {
                ret = PTR_ERR(qcom->qscratch_base);
-               goto clk_disable;
+               goto free_urs;
        }
 
        ret = dwc3_qcom_setup_irq(pdev);
        if (ret) {
                dev_err(dev, "failed to setup IRQs, err=%d\n", ret);
-               goto clk_disable;
+               goto free_urs;
        }
 
        /*
@@ -899,7 +913,7 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
 
        if (ret) {
                dev_err(dev, "failed to register DWC3 Core, err=%d\n", ret);
-               goto depopulate;
+               goto free_urs;
        }
 
        ret = dwc3_qcom_interconnect_init(qcom);
@@ -931,10 +945,16 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
 interconnect_exit:
        dwc3_qcom_interconnect_exit(qcom);
 depopulate:
-       if (np)
+       if (np) {
                of_platform_depopulate(&pdev->dev);
-       else
-               platform_device_put(pdev);
+       } else {
+               device_remove_software_node(&qcom->dwc3->dev);
+               platform_device_del(qcom->dwc3);
+       }
+       platform_device_put(qcom->dwc3);
+free_urs:
+       if (qcom->urs_usb)
+               dwc3_qcom_destroy_urs_usb_platdev(qcom->urs_usb);
 clk_disable:
        for (i = qcom->num_clocks - 1; i >= 0; i--) {
                clk_disable_unprepare(qcom->clks[i]);
@@ -953,11 +973,16 @@ static void dwc3_qcom_remove(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        int i;
 
-       device_remove_software_node(&qcom->dwc3->dev);
-       if (np)
+       if (np) {
                of_platform_depopulate(&pdev->dev);
-       else
-               platform_device_put(pdev);
+       } else {
+               device_remove_software_node(&qcom->dwc3->dev);
+               platform_device_del(qcom->dwc3);
+       }
+       platform_device_put(qcom->dwc3);
+
+       if (qcom->urs_usb)
+               dwc3_qcom_destroy_urs_usb_platdev(qcom->urs_usb);
 
        for (i = qcom->num_clocks - 1; i >= 0; i--) {
                clk_disable_unprepare(qcom->clks[i]);
index 590028e8fdcb2338f76c2b8c68ff84f909cc178f..3cd6b184551ce2695e31bf6cf96fe63e8121550c 100644 (file)
@@ -183,10 +183,13 @@ static enum usb_device_speed __get_dwc3_maximum_speed(struct device_node *np)
 
        ret = of_property_read_string(dwc3_np, "maximum-speed", &maximum_speed);
        if (ret < 0)
-               return USB_SPEED_UNKNOWN;
+               goto out;
 
        ret = match_string(speed_names, ARRAY_SIZE(speed_names), maximum_speed);
 
+out:
+       of_node_put(dwc3_np);
+
        return (ret < 0) ? USB_SPEED_UNKNOWN : ret;
 }
 
@@ -339,6 +342,9 @@ static int dwc3_rtk_probe_dwc3_core(struct dwc3_rtk *rtk)
 
        switch_usb2_role(rtk, rtk->cur_role);
 
+       platform_device_put(dwc3_pdev);
+       of_node_put(dwc3_node);
+
        return 0;
 
 err_pdev_put:
index 5b3cd455adecc21bd3fcc70316cb4ceab8e51609..61f3f8bbdcead3f325b60128c8bf648acf32dc2b 100644 (file)
@@ -650,9 +650,8 @@ static int check_isoc_ss_overlap(struct mu3h_sch_ep_info *sch_ep, u32 offset)
 
                if (sch_ep->ep_type == ISOC_OUT_EP) {
                        for (j = 0; j < sch_ep->num_budget_microframes; j++) {
-                               k = XHCI_MTK_BW_INDEX(base + j + CS_OFFSET);
-                               /* use cs to indicate existence of in-ss @(base+j) */
-                               if (tt->fs_bus_bw_in[k])
+                               k = XHCI_MTK_BW_INDEX(base + j);
+                               if (tt->in_ss_cnt[k])
                                        return -ESCH_SS_OVERLAP;
                        }
                } else if (sch_ep->ep_type == ISOC_IN_EP || sch_ep->ep_type == INT_IN_EP) {
@@ -769,6 +768,14 @@ static void update_sch_tt(struct mu3h_sch_ep_info *sch_ep, bool used)
                                tt->fs_frame_bw[f] -= (u16)sch_ep->bw_budget_table[j];
                        }
                }
+
+               if (sch_ep->ep_type == ISOC_IN_EP || sch_ep->ep_type == INT_IN_EP) {
+                       k = XHCI_MTK_BW_INDEX(base);
+                       if (used)
+                               tt->in_ss_cnt[k]++;
+                       else
+                               tt->in_ss_cnt[k]--;
+               }
        }
 
        if (used)
index 865b55e23b15948f68ec933395077df1f7d71960..39f7ae7d30871d074e832a44fcd6dc9708d971c0 100644 (file)
@@ -38,6 +38,7 @@
  * @fs_bus_bw_in: save bandwidth used by FS/LS IN eps in each uframes
  * @ls_bus_bw: save bandwidth used by LS eps in each uframes
  * @fs_frame_bw: save bandwidth used by FS/LS eps in each FS frames
+ * @in_ss_cnt: the count of Start-Split for IN eps
  * @ep_list: Endpoints using this TT
  */
 struct mu3h_sch_tt {
@@ -45,6 +46,7 @@ struct mu3h_sch_tt {
        u16 fs_bus_bw_in[XHCI_MTK_MAX_ESIT];
        u8 ls_bus_bw[XHCI_MTK_MAX_ESIT];
        u16 fs_frame_bw[XHCI_MTK_FRAMES_CNT];
+       u8 in_ss_cnt[XHCI_MTK_MAX_ESIT];
        struct list_head ep_list;
 };
 
index b93161374293b3b9f272b9a9c77a282a3a5795b1..732cdeb739202e112a4bfd0a00b63dcae7c984d2 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/usb/phy.h>
 #include <linux/slab.h>
@@ -148,7 +149,7 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s
        int                     ret;
        int                     irq;
        struct xhci_plat_priv   *priv = NULL;
-
+       bool                    of_match;
 
        if (usb_disabled())
                return -ENODEV;
@@ -253,16 +254,23 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s
                                         &xhci->imod_interval);
        }
 
-       hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, "usb-phy", 0);
-       if (IS_ERR(hcd->usb_phy)) {
-               ret = PTR_ERR(hcd->usb_phy);
-               if (ret == -EPROBE_DEFER)
-                       goto disable_clk;
-               hcd->usb_phy = NULL;
-       } else {
-               ret = usb_phy_init(hcd->usb_phy);
-               if (ret)
-                       goto disable_clk;
+       /*
+        * Drivers such as dwc3 manages PHYs themself (and rely on driver name
+        * matching for the xhci platform device).
+        */
+       of_match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev);
+       if (of_match) {
+               hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, "usb-phy", 0);
+               if (IS_ERR(hcd->usb_phy)) {
+                       ret = PTR_ERR(hcd->usb_phy);
+                       if (ret == -EPROBE_DEFER)
+                               goto disable_clk;
+                       hcd->usb_phy = NULL;
+               } else {
+                       ret = usb_phy_init(hcd->usb_phy);
+                       if (ret)
+                               goto disable_clk;
+               }
        }
 
        hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node);
@@ -285,15 +293,17 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s
                        goto dealloc_usb2_hcd;
                }
 
-               xhci->shared_hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev,
-                           "usb-phy", 1);
-               if (IS_ERR(xhci->shared_hcd->usb_phy)) {
-                       xhci->shared_hcd->usb_phy = NULL;
-               } else {
-                       ret = usb_phy_init(xhci->shared_hcd->usb_phy);
-                       if (ret)
-                               dev_err(sysdev, "%s init usb3phy fail (ret=%d)\n",
-                                           __func__, ret);
+               if (of_match) {
+                       xhci->shared_hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev,
+                                                                               "usb-phy", 1);
+                       if (IS_ERR(xhci->shared_hcd->usb_phy)) {
+                               xhci->shared_hcd->usb_phy = NULL;
+                       } else {
+                               ret = usb_phy_init(xhci->shared_hcd->usb_phy);
+                               if (ret)
+                                       dev_err(sysdev, "%s init usb3phy fail (ret=%d)\n",
+                                               __func__, ret);
+                       }
                }
 
                xhci->shared_hcd->tpl_support = hcd->tpl_support;
index a341b2fbb7b44f9a02a29b6ec7972be69caf9d17..2b45404e9732cefca8b6a8cd93fa4f08a015cc76 100644 (file)
@@ -432,6 +432,8 @@ static const struct usb_device_id onboard_hub_id_table[] = {
        { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2412) }, /* USB2412 USB 2.0 */
        { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2514) }, /* USB2514B USB 2.0 */
        { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2517) }, /* USB2517 USB 2.0 */
+       { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2744) }, /* USB5744 USB 2.0 */
+       { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x5744) }, /* USB5744 USB 3.0 */
        { USB_DEVICE(VENDOR_ID_REALTEK, 0x0411) }, /* RTS5411 USB 3.1 */
        { USB_DEVICE(VENDOR_ID_REALTEK, 0x5411) }, /* RTS5411 USB 2.1 */
        { USB_DEVICE(VENDOR_ID_REALTEK, 0x0414) }, /* RTS5414 USB 3.2 */
index c4e24a7b92904cc060d398c55d8b396239c813f7..292110e64a1d91c6697eb3bd18290d75dee5eebd 100644 (file)
@@ -16,6 +16,11 @@ static const struct onboard_hub_pdata microchip_usb424_data = {
        .num_supplies = 1,
 };
 
+static const struct onboard_hub_pdata microchip_usb5744_data = {
+       .reset_us = 0,
+       .num_supplies = 2,
+};
+
 static const struct onboard_hub_pdata realtek_rts5411_data = {
        .reset_us = 0,
        .num_supplies = 1,
@@ -50,6 +55,8 @@ static const struct of_device_id onboard_hub_match[] = {
        { .compatible = "usb424,2412", .data = &microchip_usb424_data, },
        { .compatible = "usb424,2514", .data = &microchip_usb424_data, },
        { .compatible = "usb424,2517", .data = &microchip_usb424_data, },
+       { .compatible = "usb424,2744", .data = &microchip_usb5744_data, },
+       { .compatible = "usb424,5744", .data = &microchip_usb5744_data, },
        { .compatible = "usb451,8140", .data = &ti_tusb8041_data, },
        { .compatible = "usb451,8142", .data = &ti_tusb8041_data, },
        { .compatible = "usb4b4,6504", .data = &cypress_hx3_data, },
index c9decd0396d4990db1c8f1d2d01e157636f416a1..35770e608c6497bbb1e5eeb73da1f8e6ef89cb72 100644 (file)
@@ -457,8 +457,8 @@ static void ljca_auxdev_acpi_bind(struct ljca_adapter *adap,
                                  u64 adr, u8 id)
 {
        struct ljca_match_ids_walk_data wd = { 0 };
-       struct acpi_device *parent, *adev;
        struct device *dev = adap->dev;
+       struct acpi_device *parent;
        char uid[4];
 
        parent = ACPI_COMPANION(dev);
@@ -466,17 +466,7 @@ static void ljca_auxdev_acpi_bind(struct ljca_adapter *adap,
                return;
 
        /*
-        * get auxdev ACPI handle from the ACPI device directly
-        * under the parent that matches _ADR.
-        */
-       adev = acpi_find_child_device(parent, adr, false);
-       if (adev) {
-               ACPI_COMPANION_SET(&auxdev->dev, adev);
-               return;
-       }
-
-       /*
-        * _ADR is a grey area in the ACPI specification, some
+        * Currently LJCA hw doesn't use _ADR instead the shipped
         * platforms use _HID to distinguish children devices.
         */
        switch (adr) {
@@ -656,10 +646,11 @@ static int ljca_enumerate_spi(struct ljca_adapter *adap)
        unsigned int i;
        int ret;
 
+       /* Not all LJCA chips implement SPI, a timeout reading the descriptors is normal */
        ret = ljca_send(adap, LJCA_CLIENT_MNG, LJCA_MNG_ENUM_SPI, NULL, 0, buf,
                        sizeof(buf), true, LJCA_ENUM_CLIENT_TIMEOUT_MS);
        if (ret < 0)
-               return ret;
+               return (ret == -ETIMEDOUT) ? 0 : ret;
 
        /* check firmware response */
        desc = (struct ljca_spi_descriptor *)buf;
index 45dcfaadaf98eb6f6216975764722228d204ea22..4dffcfefd62da22360ba1cc8b467c3946a425030 100644 (file)
@@ -203,8 +203,8 @@ static void option_instat_callback(struct urb *urb);
 #define DELL_PRODUCT_5829E_ESIM                        0x81e4
 #define DELL_PRODUCT_5829E                     0x81e6
 
-#define DELL_PRODUCT_FM101R                    0x8213
-#define DELL_PRODUCT_FM101R_ESIM               0x8215
+#define DELL_PRODUCT_FM101R_ESIM               0x8213
+#define DELL_PRODUCT_FM101R                    0x8215
 
 #define KYOCERA_VENDOR_ID                      0x0c88
 #define KYOCERA_PRODUCT_KPC650                 0x17da
@@ -609,6 +609,8 @@ static void option_instat_callback(struct urb *urb);
 #define UNISOC_VENDOR_ID                       0x1782
 /* TOZED LT70-C based on UNISOC SL8563 uses UNISOC's vendor ID */
 #define TOZED_PRODUCT_LT70C                    0x4055
+/* Luat Air72*U series based on UNISOC UIS8910 uses UNISOC's vendor ID */
+#define LUAT_PRODUCT_AIR720U                   0x4e00
 
 /* Device flags */
 
@@ -1546,7 +1548,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff),
          .driver_info = RSVD(4) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0189, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0189, 0xff, 0xff, 0xff),
+         .driver_info = RSVD(4) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0191, 0xff, 0xff, 0xff), /* ZTE EuFi890 */
          .driver_info = RSVD(4) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0196, 0xff, 0xff, 0xff) },
@@ -2249,6 +2252,7 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = RSVD(4) | RSVD(5) | RSVD(6) },
        { USB_DEVICE(0x1782, 0x4d10) },                                         /* Fibocom L610 (AT mode) */
        { USB_DEVICE_INTERFACE_CLASS(0x1782, 0x4d11, 0xff) },                   /* Fibocom L610 (ECM/RNDIS mode) */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x0001, 0xff, 0xff, 0xff) },    /* Fibocom L716-EU (ECM/RNDIS mode) */
        { USB_DEVICE(0x2cb7, 0x0104),                                           /* Fibocom NL678 series */
          .driver_info = RSVD(4) | RSVD(5) },
        { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0105, 0xff),                     /* Fibocom NL678 series */
@@ -2271,6 +2275,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x40) },
        { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0, 0) },
        { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) },
+       { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) },
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
index 058d5b853b5749d0b9743554380ccaf7880c75c0..bfb6f9481e87f7aa32464ea344278eba6613b5ff 100644 (file)
@@ -4273,7 +4273,8 @@ static void run_state_machine(struct tcpm_port *port)
                                current_lim = PD_P_SNK_STDBY_MW / 5;
                        tcpm_set_current_limit(port, current_lim, 5000);
                        /* Not sink vbus if operational current is 0mA */
-                       tcpm_set_charge(port, !!pdo_max_current(port->snk_pdo[0]));
+                       tcpm_set_charge(port, !port->pd_supported ||
+                                       pdo_max_current(port->snk_pdo[0]));
 
                        if (!port->pd_supported)
                                tcpm_set_state(port, SNK_READY, 0);
@@ -5391,6 +5392,15 @@ static void _tcpm_pd_hard_reset(struct tcpm_port *port)
        if (port->bist_request == BDO_MODE_TESTDATA && port->tcpc->set_bist_data)
                port->tcpc->set_bist_data(port->tcpc, false);
 
+       switch (port->state) {
+       case ERROR_RECOVERY:
+       case PORT_RESET:
+       case PORT_RESET_WAIT_OFF:
+               return;
+       default:
+               break;
+       }
+
        if (port->ams != NONE_AMS)
                port->ams = NONE_AMS;
        if (port->hard_reset_count < PD_N_HARD_RESET_COUNT)
index 0e867f531d344bea87596b8522dc70d2375a7ef4..196535ad996d080ff50340472e32e00e2445b257 100644 (file)
@@ -968,16 +968,17 @@ static int tps25750_start_patch_burst_mode(struct tps6598x *tps)
        ret = of_property_match_string(np, "reg-names", "patch-address");
        if (ret < 0) {
                dev_err(tps->dev, "failed to get patch-address %d\n", ret);
-               return ret;
+               goto release_fw;
        }
 
        ret = of_property_read_u32_index(np, "reg", ret, &addr);
        if (ret)
-               return ret;
+               goto release_fw;
 
        if (addr == 0 || (addr >= 0x20 && addr <= 0x23)) {
                dev_err(tps->dev, "wrong patch address %u\n", addr);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto release_fw;
        }
 
        bpms_data.addr = (u8)addr;
@@ -1226,7 +1227,10 @@ static int tps6598x_probe(struct i2c_client *client)
                        TPS_REG_INT_PLUG_EVENT;
        }
 
-       tps->data = device_get_match_data(tps->dev);
+       if (dev_fwnode(tps->dev))
+               tps->data = device_get_match_data(tps->dev);
+       else
+               tps->data = i2c_get_match_data(client);
        if (!tps->data)
                return -EINVAL;
 
@@ -1425,7 +1429,7 @@ static const struct of_device_id tps6598x_of_match[] = {
 MODULE_DEVICE_TABLE(of, tps6598x_of_match);
 
 static const struct i2c_device_id tps6598x_id[] = {
-       { "tps6598x" },
+       { "tps6598x", (kernel_ulong_t)&tps6598x_data },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, tps6598x_id);
index 1ce7f3c7a950931e0655df5f8587aee3adacd6be..0eb337a8ec0fa2a1df0bd392b9ec0381a8658758 100644 (file)
@@ -1115,7 +1115,7 @@ struct privcmd_kernel_ioreq {
        spinlock_t lock; /* Protects ioeventfds list */
        struct list_head ioeventfds;
        struct list_head list;
-       struct ioreq_port ports[0];
+       struct ioreq_port ports[] __counted_by(vcpus);
 };
 
 static irqreturn_t ioeventfd_interrupt(int irq, void *dev_id)
index 946bd56f0ac53e23a4f5215fd4412901b9be296f..0e6c6c25d154f5e2e439aa261397298fb0ac8118 100644 (file)
@@ -405,4 +405,5 @@ const struct dma_map_ops xen_swiotlb_dma_ops = {
        .get_sgtable = dma_common_get_sgtable,
        .alloc_pages = dma_common_alloc_pages,
        .free_pages = dma_common_free_pages,
+       .max_mapping_size = swiotlb_max_mapping_size,
 };
index 4d04ef2d3ae7bb8eeb00ae317bc2c659f71077f0..1fa8cf23bd3609bc35d3ba1ee2e8835fae2b55f2 100644 (file)
@@ -132,8 +132,8 @@ static int afs_probe_cell_name(struct dentry *dentry)
 
        ret = dns_query(net->net, "afsdb", name, len, "srv=1",
                        NULL, NULL, false);
-       if (ret == -ENODATA)
-               ret = -EDESTADDRREQ;
+       if (ret == -ENODATA || ret == -ENOKEY)
+               ret = -ENOENT;
        return ret;
 }
 
index c9cef3782b4ae48dee3be851aead7fb7de4fd42b..a812952be1c948d059991d1d67562284e340303a 100644 (file)
@@ -553,6 +553,7 @@ struct afs_server_entry {
 };
 
 struct afs_server_list {
+       struct rcu_head         rcu;
        afs_volid_t             vids[AFS_MAXTYPES]; /* Volume IDs */
        refcount_t              usage;
        unsigned char           nr_servers;
index ed9056703505fe073bb3d7c5fa8050b70574efd2..b59896b1de0af29986fbd4670cc95f170f177b62 100644 (file)
@@ -17,7 +17,7 @@ void afs_put_serverlist(struct afs_net *net, struct afs_server_list *slist)
                for (i = 0; i < slist->nr_servers; i++)
                        afs_unuse_server(net, slist->servers[i].server,
                                         afs_server_trace_put_slist);
-               kfree(slist);
+               kfree_rcu(slist, rcu);
        }
 }
 
index 95d713074dc8130125e55da2cd4e19b693682f8f..a01a0fb2cdbb5c472def4f5352a0ba3ced962cd1 100644 (file)
@@ -407,6 +407,10 @@ static int afs_validate_fc(struct fs_context *fc)
                        return PTR_ERR(volume);
 
                ctx->volume = volume;
+               if (volume->type != AFSVL_RWVOL) {
+                       ctx->flock_mode = afs_flock_mode_local;
+                       fc->sb_flags |= SB_RDONLY;
+               }
        }
 
        return 0;
index 488e58490b16e7b9781b651b4ab70e8b4b968b2a..eb415ce563600e98124521c2d45ce5a3c47b89ab 100644 (file)
@@ -58,6 +58,12 @@ static bool afs_start_vl_iteration(struct afs_vl_cursor *vc)
                }
 
                /* Status load is ordered after lookup counter load */
+               if (cell->dns_status == DNS_LOOKUP_GOT_NOT_FOUND) {
+                       pr_warn("No record of cell %s\n", cell->name);
+                       vc->error = -ENOENT;
+                       return false;
+               }
+
                if (cell->dns_source == DNS_RECORD_UNAVAILABLE) {
                        vc->error = -EDESTADDRREQ;
                        return false;
@@ -285,6 +291,7 @@ failed:
  */
 static void afs_vl_dump_edestaddrreq(const struct afs_vl_cursor *vc)
 {
+       struct afs_cell *cell = vc->cell;
        static int count;
        int i;
 
@@ -294,6 +301,9 @@ static void afs_vl_dump_edestaddrreq(const struct afs_vl_cursor *vc)
 
        rcu_read_lock();
        pr_notice("EDESTADDR occurred\n");
+       pr_notice("CELL: %s err=%d\n", cell->name, cell->error);
+       pr_notice("DNS: src=%u st=%u lc=%x\n",
+                 cell->dns_source, cell->dns_status, cell->dns_lookup_count);
        pr_notice("VC: ut=%lx ix=%u ni=%hu fl=%hx err=%hd\n",
                  vc->untried, vc->index, vc->nr_iterations, vc->flags, vc->error);
 
index a5083d447a62f140492a638b406205a5eb3b8052..1f5db686366316d22236221a8d2d11f559019d9b 100644 (file)
@@ -309,9 +309,7 @@ static int autofs_fill_super(struct super_block *s, struct fs_context *fc)
        struct autofs_fs_context *ctx = fc->fs_private;
        struct autofs_sb_info *sbi = s->s_fs_info;
        struct inode *root_inode;
-       struct dentry *root;
        struct autofs_info *ino;
-       int ret = -ENOMEM;
 
        pr_debug("starting up, sbi = %p\n", sbi);
 
@@ -328,56 +326,44 @@ static int autofs_fill_super(struct super_block *s, struct fs_context *fc)
         */
        ino = autofs_new_ino(sbi);
        if (!ino)
-               goto fail;
+               return -ENOMEM;
 
        root_inode = autofs_get_inode(s, S_IFDIR | 0755);
+       if (!root_inode)
+               return -ENOMEM;
+
        root_inode->i_uid = ctx->uid;
        root_inode->i_gid = ctx->gid;
+       root_inode->i_fop = &autofs_root_operations;
+       root_inode->i_op = &autofs_dir_inode_operations;
 
-       root = d_make_root(root_inode);
-       if (!root)
-               goto fail_ino;
-
-       root->d_fsdata = ino;
+       s->s_root = d_make_root(root_inode);
+       if (unlikely(!s->s_root)) {
+               autofs_free_ino(ino);
+               return -ENOMEM;
+       }
+       s->s_root->d_fsdata = ino;
 
        if (ctx->pgrp_set) {
                sbi->oz_pgrp = find_get_pid(ctx->pgrp);
-               if (!sbi->oz_pgrp) {
-                       ret = invalf(fc, "Could not find process group %d",
-                                    ctx->pgrp);
-                       goto fail_dput;
-               }
-       } else {
+               if (!sbi->oz_pgrp)
+                       return invalf(fc, "Could not find process group %d",
+                                     ctx->pgrp);
+       } else
                sbi->oz_pgrp = get_task_pid(current, PIDTYPE_PGID);
-       }
 
        if (autofs_type_trigger(sbi->type))
-               __managed_dentry_set_managed(root);
-
-       root_inode->i_fop = &autofs_root_operations;
-       root_inode->i_op = &autofs_dir_inode_operations;
+               /* s->s_root won't be contended so there's little to
+                * be gained by not taking the d_lock when setting
+                * d_flags, even when a lot mounts are being done.
+                */
+               managed_dentry_set_managed(s->s_root);
 
        pr_debug("pipe fd = %d, pgrp = %u\n",
                 sbi->pipefd, pid_nr(sbi->oz_pgrp));
 
        sbi->flags &= ~AUTOFS_SBI_CATATONIC;
-
-       /*
-        * Success! Install the root dentry now to indicate completion.
-        */
-       s->s_root = root;
        return 0;
-
-       /*
-        * Failure ... clean up.
-        */
-fail_dput:
-       dput(root);
-       goto fail;
-fail_ino:
-       autofs_free_ino(ino);
-fail:
-       return ret;
 }
 
 /*
index a25dd3d20008bfa40d2fc81b797f4dfa3f9118db..b0e8774c435a4b1c2cf54b0efb3cd514a673ec9d 100644 (file)
@@ -998,6 +998,14 @@ static int ecryptfs_getattr_link(struct mnt_idmap *idmap,
        return rc;
 }
 
+static int ecryptfs_do_getattr(const struct path *path, struct kstat *stat,
+                              u32 request_mask, unsigned int flags)
+{
+       if (flags & AT_GETATTR_NOSEC)
+               return vfs_getattr_nosec(path, stat, request_mask, flags);
+       return vfs_getattr(path, stat, request_mask, flags);
+}
+
 static int ecryptfs_getattr(struct mnt_idmap *idmap,
                            const struct path *path, struct kstat *stat,
                            u32 request_mask, unsigned int flags)
@@ -1006,8 +1014,8 @@ static int ecryptfs_getattr(struct mnt_idmap *idmap,
        struct kstat lower_stat;
        int rc;
 
-       rc = vfs_getattr(ecryptfs_dentry_to_lower_path(dentry), &lower_stat,
-                        request_mask, flags);
+       rc = ecryptfs_do_getattr(ecryptfs_dentry_to_lower_path(dentry),
+                                &lower_stat, request_mask, flags);
        if (!rc) {
                fsstack_copy_attr_all(d_inode(dentry),
                                      ecryptfs_inode_to_lower(d_inode(dentry)));
index e540648dedc28084596e97b2052124c76d247693..1d318f85232de9361714471ac973762ed2e6b0e6 100644 (file)
@@ -21,7 +21,7 @@ config EROFS_FS
          performance under extremely memory pressure without extra cost.
 
          See the documentation at <file:Documentation/filesystems/erofs.rst>
-         for more details.
+         and the web pages at <https://erofs.docs.kernel.org> for more details.
 
          If unsure, say N.
 
index 029c761670bfcd20389d7b1fb5ec75d32aa89376..c98aeda8abb215e9be577d1b27dea2713b0b6e87 100644 (file)
@@ -220,7 +220,7 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
                        up_read(&devs->rwsem);
                        return 0;
                }
-               map->m_bdev = dif->bdev_handle->bdev;
+               map->m_bdev = dif->bdev_handle ? dif->bdev_handle->bdev : NULL;
                map->m_daxdev = dif->dax_dev;
                map->m_dax_part_off = dif->dax_part_off;
                map->m_fscache = dif->fscache;
@@ -238,7 +238,8 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
                        if (map->m_pa >= startoff &&
                            map->m_pa < startoff + length) {
                                map->m_pa -= startoff;
-                               map->m_bdev = dif->bdev_handle->bdev;
+                               map->m_bdev = dif->bdev_handle ?
+                                             dif->bdev_handle->bdev : NULL;
                                map->m_daxdev = dif->dax_dev;
                                map->m_dax_part_off = dif->dax_part_off;
                                map->m_fscache = dif->fscache;
index b8ad05b4509d58f1e64ab2a1994c405e0aa80b04..14a79d3226abf4d6ce49c27123bba14394bf5f29 100644 (file)
@@ -15,11 +15,11 @@ static void *erofs_read_inode(struct erofs_buf *buf,
        struct erofs_sb_info *sbi = EROFS_SB(sb);
        struct erofs_inode *vi = EROFS_I(inode);
        const erofs_off_t inode_loc = erofs_iloc(inode);
-
        erofs_blk_t blkaddr, nblks = 0;
        void *kaddr;
        struct erofs_inode_compact *dic;
        struct erofs_inode_extended *die, *copied = NULL;
+       union erofs_inode_i_u iu;
        unsigned int ifmt;
        int err;
 
@@ -35,9 +35,8 @@ static void *erofs_read_inode(struct erofs_buf *buf,
 
        dic = kaddr + *ofs;
        ifmt = le16_to_cpu(dic->i_format);
-
        if (ifmt & ~EROFS_I_ALL) {
-               erofs_err(inode->i_sb, "unsupported i_format %u of nid %llu",
+               erofs_err(sb, "unsupported i_format %u of nid %llu",
                          ifmt, vi->nid);
                err = -EOPNOTSUPP;
                goto err_out;
@@ -45,7 +44,7 @@ static void *erofs_read_inode(struct erofs_buf *buf,
 
        vi->datalayout = erofs_inode_datalayout(ifmt);
        if (vi->datalayout >= EROFS_INODE_DATALAYOUT_MAX) {
-               erofs_err(inode->i_sb, "unsupported datalayout %u of nid %llu",
+               erofs_err(sb, "unsupported datalayout %u of nid %llu",
                          vi->datalayout, vi->nid);
                err = -EOPNOTSUPP;
                goto err_out;
@@ -82,40 +81,15 @@ static void *erofs_read_inode(struct erofs_buf *buf,
                vi->xattr_isize = erofs_xattr_ibody_size(die->i_xattr_icount);
 
                inode->i_mode = le16_to_cpu(die->i_mode);
-               switch (inode->i_mode & S_IFMT) {
-               case S_IFREG:
-               case S_IFDIR:
-               case S_IFLNK:
-                       vi->raw_blkaddr = le32_to_cpu(die->i_u.raw_blkaddr);
-                       break;
-               case S_IFCHR:
-               case S_IFBLK:
-                       inode->i_rdev =
-                               new_decode_dev(le32_to_cpu(die->i_u.rdev));
-                       break;
-               case S_IFIFO:
-               case S_IFSOCK:
-                       inode->i_rdev = 0;
-                       break;
-               default:
-                       goto bogusimode;
-               }
+               iu = die->i_u;
                i_uid_write(inode, le32_to_cpu(die->i_uid));
                i_gid_write(inode, le32_to_cpu(die->i_gid));
                set_nlink(inode, le32_to_cpu(die->i_nlink));
-
-               /* extended inode has its own timestamp */
+               /* each extended inode has its own timestamp */
                inode_set_ctime(inode, le64_to_cpu(die->i_mtime),
                                le32_to_cpu(die->i_mtime_nsec));
 
                inode->i_size = le64_to_cpu(die->i_size);
-
-               /* total blocks for compressed files */
-               if (erofs_inode_is_data_compressed(vi->datalayout))
-                       nblks = le32_to_cpu(die->i_u.compressed_blocks);
-               else if (vi->datalayout == EROFS_INODE_CHUNK_BASED)
-                       /* fill chunked inode summary info */
-                       vi->chunkformat = le16_to_cpu(die->i_u.c.format);
                kfree(copied);
                copied = NULL;
                break;
@@ -125,49 +99,51 @@ static void *erofs_read_inode(struct erofs_buf *buf,
                vi->xattr_isize = erofs_xattr_ibody_size(dic->i_xattr_icount);
 
                inode->i_mode = le16_to_cpu(dic->i_mode);
-               switch (inode->i_mode & S_IFMT) {
-               case S_IFREG:
-               case S_IFDIR:
-               case S_IFLNK:
-                       vi->raw_blkaddr = le32_to_cpu(dic->i_u.raw_blkaddr);
-                       break;
-               case S_IFCHR:
-               case S_IFBLK:
-                       inode->i_rdev =
-                               new_decode_dev(le32_to_cpu(dic->i_u.rdev));
-                       break;
-               case S_IFIFO:
-               case S_IFSOCK:
-                       inode->i_rdev = 0;
-                       break;
-               default:
-                       goto bogusimode;
-               }
+               iu = dic->i_u;
                i_uid_write(inode, le16_to_cpu(dic->i_uid));
                i_gid_write(inode, le16_to_cpu(dic->i_gid));
                set_nlink(inode, le16_to_cpu(dic->i_nlink));
-
                /* use build time for compact inodes */
                inode_set_ctime(inode, sbi->build_time, sbi->build_time_nsec);
 
                inode->i_size = le32_to_cpu(dic->i_size);
-               if (erofs_inode_is_data_compressed(vi->datalayout))
-                       nblks = le32_to_cpu(dic->i_u.compressed_blocks);
-               else if (vi->datalayout == EROFS_INODE_CHUNK_BASED)
-                       vi->chunkformat = le16_to_cpu(dic->i_u.c.format);
                break;
        default:
-               erofs_err(inode->i_sb,
-                         "unsupported on-disk inode version %u of nid %llu",
+               erofs_err(sb, "unsupported on-disk inode version %u of nid %llu",
                          erofs_inode_version(ifmt), vi->nid);
                err = -EOPNOTSUPP;
                goto err_out;
        }
 
-       if (vi->datalayout == EROFS_INODE_CHUNK_BASED) {
+       switch (inode->i_mode & S_IFMT) {
+       case S_IFREG:
+       case S_IFDIR:
+       case S_IFLNK:
+               vi->raw_blkaddr = le32_to_cpu(iu.raw_blkaddr);
+               break;
+       case S_IFCHR:
+       case S_IFBLK:
+               inode->i_rdev = new_decode_dev(le32_to_cpu(iu.rdev));
+               break;
+       case S_IFIFO:
+       case S_IFSOCK:
+               inode->i_rdev = 0;
+               break;
+       default:
+               erofs_err(sb, "bogus i_mode (%o) @ nid %llu", inode->i_mode,
+                         vi->nid);
+               err = -EFSCORRUPTED;
+               goto err_out;
+       }
+
+       /* total blocks for compressed files */
+       if (erofs_inode_is_data_compressed(vi->datalayout)) {
+               nblks = le32_to_cpu(iu.compressed_blocks);
+       } else if (vi->datalayout == EROFS_INODE_CHUNK_BASED) {
+               /* fill chunked inode summary info */
+               vi->chunkformat = le16_to_cpu(iu.c.format);
                if (vi->chunkformat & ~EROFS_CHUNK_FORMAT_ALL) {
-                       erofs_err(inode->i_sb,
-                                 "unsupported chunk format %x of nid %llu",
+                       erofs_err(sb, "unsupported chunk format %x of nid %llu",
                                  vi->chunkformat, vi->nid);
                        err = -EOPNOTSUPP;
                        goto err_out;
@@ -191,10 +167,6 @@ static void *erofs_read_inode(struct erofs_buf *buf,
                inode->i_blocks = nblks << (sb->s_blocksize_bits - 9);
        return kaddr;
 
-bogusimode:
-       erofs_err(inode->i_sb, "bogus i_mode (%o) @ nid %llu",
-                 inode->i_mode, vi->nid);
-       err = -EFSCORRUPTED;
 err_out:
        DBG_BUGON(1);
        kfree(copied);
index edcd8a61975f34c7a4cf467589848870430b3b8a..f238d987dec901150ac759d51a7996dc208bd1f8 100644 (file)
@@ -215,6 +215,8 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
        lockdep_set_class_and_name(&mapping->invalidate_lock,
                                   &sb->s_type->invalidate_lock_key,
                                   "mapping.invalidate_lock");
+       if (sb->s_iflags & SB_I_STABLE_WRITES)
+               mapping_set_stable_writes(mapping);
        inode->i_private = NULL;
        inode->i_mapping = mapping;
        INIT_HLIST_HEAD(&inode->i_dentry);      /* buggered by rcu freeing */
index e9440d55073c50962486f3f4f047a7872544fcff..c2aa6fd4795c44340fbc16c0c4138ff004b8f53e 100644 (file)
@@ -399,6 +399,8 @@ static loff_t offset_dir_llseek(struct file *file, loff_t offset, int whence)
                return -EINVAL;
        }
 
+       /* In this case, ->private_data is protected by f_pos_lock */
+       file->private_data = NULL;
        return vfs_setpos(file, offset, U32_MAX);
 }
 
@@ -428,7 +430,7 @@ static bool offset_dir_emit(struct dir_context *ctx, struct dentry *dentry)
                          inode->i_ino, fs_umode_to_dtype(inode->i_mode));
 }
 
-static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
+static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
 {
        struct offset_ctx *so_ctx = inode->i_op->get_offset_ctx(inode);
        XA_STATE(xas, &so_ctx->xa, ctx->pos);
@@ -437,7 +439,7 @@ static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
        while (true) {
                dentry = offset_find_next(&xas);
                if (!dentry)
-                       break;
+                       return ERR_PTR(-ENOENT);
 
                if (!offset_dir_emit(ctx, dentry)) {
                        dput(dentry);
@@ -447,6 +449,7 @@ static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
                dput(dentry);
                ctx->pos = xas.xa_index + 1;
        }
+       return NULL;
 }
 
 /**
@@ -479,7 +482,12 @@ static int offset_readdir(struct file *file, struct dir_context *ctx)
        if (!dir_emit_dots(file, ctx))
                return 0;
 
-       offset_iterate_dir(d_inode(dir), ctx);
+       /* In this case, ->private_data is protected by f_pos_lock */
+       if (ctx->pos == 2)
+               file->private_data = NULL;
+       else if (file->private_data == ERR_PTR(-ENOENT))
+               return 0;
+       file->private_data = offset_iterate_dir(d_inode(dir), ctx);
        return 0;
 }
 
index 345b8f161ca4c3da0b81fb397e9ef3dc21dde0ea..c63b31a460befcc9f35a573618a1fb13cd20657f 100644 (file)
@@ -171,7 +171,7 @@ int ovl_getattr(struct mnt_idmap *idmap, const struct path *path,
 
        type = ovl_path_real(dentry, &realpath);
        old_cred = ovl_override_creds(dentry->d_sb);
-       err = vfs_getattr(&realpath, stat, request_mask, flags);
+       err = ovl_do_getattr(&realpath, stat, request_mask, flags);
        if (err)
                goto out;
 
@@ -196,8 +196,8 @@ int ovl_getattr(struct mnt_idmap *idmap, const struct path *path,
                                        (!is_dir ? STATX_NLINK : 0);
 
                        ovl_path_lower(dentry, &realpath);
-                       err = vfs_getattr(&realpath, &lowerstat,
-                                         lowermask, flags);
+                       err = ovl_do_getattr(&realpath, &lowerstat, lowermask,
+                                            flags);
                        if (err)
                                goto out;
 
@@ -249,8 +249,8 @@ int ovl_getattr(struct mnt_idmap *idmap, const struct path *path,
 
                        ovl_path_lowerdata(dentry, &realpath);
                        if (realpath.dentry) {
-                               err = vfs_getattr(&realpath, &lowerdatastat,
-                                                 lowermask, flags);
+                               err = ovl_do_getattr(&realpath, &lowerdatastat,
+                                                    lowermask, flags);
                                if (err)
                                        goto out;
                        } else {
index ca88b2636a5729604221000fe450729d661e8e7e..05c3dd597fa8d98650da5660dbdb9a786f583aad 100644 (file)
@@ -408,6 +408,14 @@ static inline bool ovl_open_flags_need_copy_up(int flags)
        return ((OPEN_FMODE(flags) & FMODE_WRITE) || (flags & O_TRUNC));
 }
 
+static inline int ovl_do_getattr(const struct path *path, struct kstat *stat,
+                                u32 request_mask, unsigned int flags)
+{
+       if (flags & AT_GETATTR_NOSEC)
+               return vfs_getattr_nosec(path, stat, request_mask, flags);
+       return vfs_getattr(path, stat, request_mask, flags);
+}
+
 /* util.c */
 int ovl_get_write_access(struct dentry *dentry);
 void ovl_put_write_access(struct dentry *dentry);
index 6ffbd81bd109a0acf71f1ed1e60146c6538e1384..7558167f603c383d706a84b6ebbf4314091abe5b 100644 (file)
@@ -191,7 +191,13 @@ struct cifs_open_info_data {
                bool reparse_point;
                bool symlink;
        };
-       __u32 reparse_tag;
+       struct {
+               __u32 tag;
+               union {
+                       struct reparse_data_buffer *buf;
+                       struct reparse_posix_data *posix;
+               };
+       } reparse;
        char *symlink_target;
        union {
                struct smb2_file_all_info fi;
@@ -395,8 +401,7 @@ struct smb_version_operations {
                             struct cifs_tcon *tcon,
                             struct cifs_sb_info *cifs_sb,
                             const char *full_path,
-                            char **target_path,
-                            struct kvec *rsp_iov);
+                            char **target_path);
        /* open a file for non-posix mounts */
        int (*open)(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock,
                    void *buf);
@@ -551,6 +556,9 @@ struct smb_version_operations {
        bool (*is_status_io_timeout)(char *buf);
        /* Check for STATUS_NETWORK_NAME_DELETED */
        bool (*is_network_name_deleted)(char *buf, struct TCP_Server_Info *srv);
+       int (*parse_reparse_point)(struct cifs_sb_info *cifs_sb,
+                                  struct kvec *rsp_iov,
+                                  struct cifs_open_info_data *data);
 };
 
 struct smb_version_values {
index a75220db5c1e1893ea852c0ad761a63bd7adbfdf..83ccc51a54d03363df2c6b22ad84494305259374 100644 (file)
@@ -1356,7 +1356,7 @@ typedef struct smb_com_transaction_ioctl_rsp {
        __le32 DataDisplacement;
        __u8 SetupCount;        /* 1 */
        __le16 ReturnedDataLen;
-       __u16 ByteCount;
+       __le16 ByteCount;
 } __attribute__((packed)) TRANSACT_IOCTL_RSP;
 
 #define CIFS_ACL_OWNER 1
@@ -1509,7 +1509,7 @@ struct reparse_posix_data {
        __le16  ReparseDataLength;
        __u16   Reserved;
        __le64  InodeType; /* LNK, FIFO, CHR etc. */
-       char    PathBuffer[];
+       __u8    DataBuffer[];
 } __attribute__((packed));
 
 struct cifs_quota_data {
index d87e2c26cce2b22dc8a2f85870410cf80176e6e5..46feaa0880bdf18f54eff409694c7d06c501ebf4 100644 (file)
@@ -210,7 +210,7 @@ int cifs_get_inode_info(struct inode **inode, const char *full_path,
                        const struct cifs_fid *fid);
 bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
                                 struct cifs_fattr *fattr,
-                                u32 tag);
+                                struct cifs_open_info_data *data);
 extern int smb311_posix_get_inode_info(struct inode **pinode, const char *search_path,
                        struct super_block *sb, unsigned int xid);
 extern int cifs_get_inode_info_unix(struct inode **pinode,
@@ -458,6 +458,12 @@ extern int CIFSSMBUnixQuerySymLink(const unsigned int xid,
                        struct cifs_tcon *tcon,
                        const unsigned char *searchName, char **syminfo,
                        const struct nls_table *nls_codepage, int remap);
+extern int cifs_query_reparse_point(const unsigned int xid,
+                                   struct cifs_tcon *tcon,
+                                   struct cifs_sb_info *cifs_sb,
+                                   const char *full_path,
+                                   u32 *tag, struct kvec *rsp,
+                                   int *rsp_buftype);
 extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
                               __u16 fid, char **symlinkinfo,
                               const struct nls_table *nls_codepage);
@@ -659,6 +665,12 @@ void cifs_put_tcp_super(struct super_block *sb);
 int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix);
 char *extract_hostname(const char *unc);
 char *extract_sharename(const char *unc);
+int parse_reparse_point(struct reparse_data_buffer *buf,
+                       u32 plen, struct cifs_sb_info *cifs_sb,
+                       bool unicode, struct cifs_open_info_data *data);
+int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
+                      struct dentry *dentry, struct cifs_tcon *tcon,
+                      const char *full_path, umode_t mode, dev_t dev);
 
 #ifdef CONFIG_CIFS_DFS_UPCALL
 static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses,
index 25503f1a4fd21313304fabe4b8d6fab89b231cd5..bad91ba6c3a9cc5bf1a1d97a3054fa263c426285 100644 (file)
@@ -2690,136 +2690,97 @@ querySymLinkRetry:
        return rc;
 }
 
-/*
- *     Recent Windows versions now create symlinks more frequently
- *     and they use the "reparse point" mechanism below.  We can of course
- *     do symlinks nicely to Samba and other servers which support the
- *     CIFS Unix Extensions and we can also do SFU symlinks and "client only"
- *     "MF" symlinks optionally, but for recent Windows we really need to
- *     reenable the code below and fix the cifs_symlink callers to handle this.
- *     In the interim this code has been moved to its own config option so
- *     it is not compiled in by default until callers fixed up and more tested.
- */
-int
-CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
-                   __u16 fid, char **symlinkinfo,
-                   const struct nls_table *nls_codepage)
+int cifs_query_reparse_point(const unsigned int xid,
+                            struct cifs_tcon *tcon,
+                            struct cifs_sb_info *cifs_sb,
+                            const char *full_path,
+                            u32 *tag, struct kvec *rsp,
+                            int *rsp_buftype)
 {
-       int rc = 0;
-       int bytes_returned;
-       struct smb_com_transaction_ioctl_req *pSMB;
-       struct smb_com_transaction_ioctl_rsp *pSMBr;
-       bool is_unicode;
-       unsigned int sub_len;
-       char *sub_start;
-       struct reparse_symlink_data *reparse_buf;
-       struct reparse_posix_data *posix_buf;
+       struct cifs_open_parms oparms;
+       TRANSACT_IOCTL_REQ *io_req = NULL;
+       TRANSACT_IOCTL_RSP *io_rsp = NULL;
+       struct cifs_fid fid;
        __u32 data_offset, data_count;
-       char *end_of_smb;
+       __u8 *start, *end;
+       int io_rsp_len;
+       int oplock = 0;
+       int rc;
 
-       cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid);
-       rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
-                     (void **) &pSMBr);
+       cifs_tcon_dbg(FYI, "%s: path=%s\n", __func__, full_path);
+
+       if (cap_unix(tcon->ses))
+               return -EOPNOTSUPP;
+
+       oparms = (struct cifs_open_parms) {
+               .tcon = tcon,
+               .cifs_sb = cifs_sb,
+               .desired_access = FILE_READ_ATTRIBUTES,
+               .create_options = cifs_create_options(cifs_sb,
+                                                     OPEN_REPARSE_POINT),
+               .disposition = FILE_OPEN,
+               .path = full_path,
+               .fid = &fid,
+       };
+
+       rc = CIFS_open(xid, &oparms, &oplock, NULL);
        if (rc)
                return rc;
 
-       pSMB->TotalParameterCount = 0 ;
-       pSMB->TotalDataCount = 0;
-       pSMB->MaxParameterCount = cpu_to_le32(2);
-       /* BB find exact data count max from sess structure BB */
-       pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
-       pSMB->MaxSetupCount = 4;
-       pSMB->Reserved = 0;
-       pSMB->ParameterOffset = 0;
-       pSMB->DataCount = 0;
-       pSMB->DataOffset = 0;
-       pSMB->SetupCount = 4;
-       pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
-       pSMB->ParameterCount = pSMB->TotalParameterCount;
-       pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
-       pSMB->IsFsctl = 1; /* FSCTL */
-       pSMB->IsRootFlag = 0;
-       pSMB->Fid = fid; /* file handle always le */
-       pSMB->ByteCount = 0;
+       rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon,
+                     (void **)&io_req, (void **)&io_rsp);
+       if (rc)
+               goto error;
 
-       rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-                        (struct smb_hdr *) pSMBr, &bytes_returned, 0);
-       if (rc) {
-               cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
-               goto qreparse_out;
-       }
+       io_req->TotalParameterCount = 0;
+       io_req->TotalDataCount = 0;
+       io_req->MaxParameterCount = cpu_to_le32(2);
+       /* BB find exact data count max from sess structure BB */
+       io_req->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
+       io_req->MaxSetupCount = 4;
+       io_req->Reserved = 0;
+       io_req->ParameterOffset = 0;
+       io_req->DataCount = 0;
+       io_req->DataOffset = 0;
+       io_req->SetupCount = 4;
+       io_req->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
+       io_req->ParameterCount = io_req->TotalParameterCount;
+       io_req->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
+       io_req->IsFsctl = 1;
+       io_req->IsRootFlag = 0;
+       io_req->Fid = fid.netfid;
+       io_req->ByteCount = 0;
+
+       rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)io_req,
+                        (struct smb_hdr *)io_rsp, &io_rsp_len, 0);
+       if (rc)
+               goto error;
 
-       data_offset = le32_to_cpu(pSMBr->DataOffset);
-       data_count = le32_to_cpu(pSMBr->DataCount);
-       if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
-               /* BB also check enough total bytes returned */
-               rc = -EIO;      /* bad smb */
-               goto qreparse_out;
-       }
-       if (!data_count || (data_count > 2048)) {
+       data_offset = le32_to_cpu(io_rsp->DataOffset);
+       data_count = le32_to_cpu(io_rsp->DataCount);
+       if (get_bcc(&io_rsp->hdr) < 2 || data_offset > 512 ||
+           !data_count || data_count > 2048) {
                rc = -EIO;
-               cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
-               goto qreparse_out;
-       }
-       end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
-       reparse_buf = (struct reparse_symlink_data *)
-                               ((char *)&pSMBr->hdr.Protocol + data_offset);
-       if ((char *)reparse_buf >= end_of_smb) {
-               rc = -EIO;
-               goto qreparse_out;
-       }
-       if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
-               cifs_dbg(FYI, "NFS style reparse tag\n");
-               posix_buf =  (struct reparse_posix_data *)reparse_buf;
-
-               if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
-                       cifs_dbg(FYI, "unsupported file type 0x%llx\n",
-                                le64_to_cpu(posix_buf->InodeType));
-                       rc = -EOPNOTSUPP;
-                       goto qreparse_out;
-               }
-               is_unicode = true;
-               sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
-               if (posix_buf->PathBuffer + sub_len > end_of_smb) {
-                       cifs_dbg(FYI, "reparse buf beyond SMB\n");
-                       rc = -EIO;
-                       goto qreparse_out;
-               }
-               *symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
-                               sub_len, is_unicode, nls_codepage);
-               goto qreparse_out;
-       } else if (reparse_buf->ReparseTag !=
-                       cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
-               rc = -EOPNOTSUPP;
-               goto qreparse_out;
+               goto error;
        }
 
-       /* Reparse tag is NTFS symlink */
-       sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
-                               reparse_buf->PathBuffer;
-       sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
-       if (sub_start + sub_len > end_of_smb) {
-               cifs_dbg(FYI, "reparse buf beyond SMB\n");
+       end = 2 + get_bcc(&io_rsp->hdr) + (__u8 *)&io_rsp->ByteCount;
+       start = (__u8 *)&io_rsp->hdr.Protocol + data_offset;
+       if (start >= end) {
                rc = -EIO;
-               goto qreparse_out;
+               goto error;
        }
-       if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
-               is_unicode = true;
-       else
-               is_unicode = false;
-
-       /* BB FIXME investigate remapping reserved chars here */
-       *symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
-                                              nls_codepage);
-       if (!*symlinkinfo)
-               rc = -ENOMEM;
-qreparse_out:
-       cifs_buf_release(pSMB);
 
-       /*
-        * Note: On -EAGAIN error only caller can retry on handle based calls
-        * since file handle passed in no longer valid.
-        */
+       *tag = le32_to_cpu(((struct reparse_data_buffer *)start)->ReparseTag);
+       rsp->iov_base = io_rsp;
+       rsp->iov_len = io_rsp_len;
+       *rsp_buftype = CIFS_LARGE_BUFFER;
+       CIFSSMBClose(xid, tcon, fid.netfid);
+       return 0;
+
+error:
+       cifs_buf_release(io_req);
+       CIFSSMBClose(xid, tcon, fid.netfid);
        return rc;
 }
 
index 86fbd3f847d657f33558455ac8e3ef9b2c991592..47f49be69ced2563b87161538cba78800375eca6 100644 (file)
@@ -459,8 +459,7 @@ static int cifs_get_unix_fattr(const unsigned char *full_path,
                        return -EOPNOTSUPP;
                rc = server->ops->query_symlink(xid, tcon,
                                                cifs_sb, full_path,
-                                               &fattr->cf_symlink_target,
-                                               NULL);
+                                               &fattr->cf_symlink_target);
                cifs_dbg(FYI, "%s: query_symlink: %d\n", __func__, rc);
        }
        return rc;
@@ -722,10 +721,51 @@ static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr,
                fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink);
 }
 
+static inline dev_t nfs_mkdev(struct reparse_posix_data *buf)
+{
+       u64 v = le64_to_cpu(*(__le64 *)buf->DataBuffer);
+
+       return MKDEV(v >> 32, v & 0xffffffff);
+}
+
 bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
                                 struct cifs_fattr *fattr,
-                                u32 tag)
+                                struct cifs_open_info_data *data)
 {
+       struct reparse_posix_data *buf = data->reparse.posix;
+       u32 tag = data->reparse.tag;
+
+       if (tag == IO_REPARSE_TAG_NFS && buf) {
+               switch (le64_to_cpu(buf->InodeType)) {
+               case NFS_SPECFILE_CHR:
+                       fattr->cf_mode |= S_IFCHR | cifs_sb->ctx->file_mode;
+                       fattr->cf_dtype = DT_CHR;
+                       fattr->cf_rdev = nfs_mkdev(buf);
+                       break;
+               case NFS_SPECFILE_BLK:
+                       fattr->cf_mode |= S_IFBLK | cifs_sb->ctx->file_mode;
+                       fattr->cf_dtype = DT_BLK;
+                       fattr->cf_rdev = nfs_mkdev(buf);
+                       break;
+               case NFS_SPECFILE_FIFO:
+                       fattr->cf_mode |= S_IFIFO | cifs_sb->ctx->file_mode;
+                       fattr->cf_dtype = DT_FIFO;
+                       break;
+               case NFS_SPECFILE_SOCK:
+                       fattr->cf_mode |= S_IFSOCK | cifs_sb->ctx->file_mode;
+                       fattr->cf_dtype = DT_SOCK;
+                       break;
+               case NFS_SPECFILE_LNK:
+                       fattr->cf_mode = S_IFLNK | cifs_sb->ctx->file_mode;
+                       fattr->cf_dtype = DT_LNK;
+                       break;
+               default:
+                       WARN_ON_ONCE(1);
+                       return false;
+               }
+               return true;
+       }
+
        switch (tag) {
        case IO_REPARSE_TAG_LX_SYMLINK:
                fattr->cf_mode |= S_IFLNK | cifs_sb->ctx->file_mode;
@@ -791,7 +831,7 @@ static void cifs_open_info_to_fattr(struct cifs_fattr *fattr,
        fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
 
        if (cifs_open_data_reparse(data) &&
-           cifs_reparse_point_to_fattr(cifs_sb, fattr, data->reparse_tag))
+           cifs_reparse_point_to_fattr(cifs_sb, fattr, data))
                goto out_reparse;
 
        if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
@@ -856,7 +896,7 @@ cifs_get_file_info(struct file *filp)
                data.adjust_tz = false;
                if (data.symlink_target) {
                        data.symlink = true;
-                       data.reparse_tag = IO_REPARSE_TAG_SYMLINK;
+                       data.reparse.tag = IO_REPARSE_TAG_SYMLINK;
                }
                cifs_open_info_to_fattr(&fattr, &data, inode->i_sb);
                break;
@@ -1025,7 +1065,7 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
        struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
        struct kvec rsp_iov, *iov = NULL;
        int rsp_buftype = CIFS_NO_BUFFER;
-       u32 tag = data->reparse_tag;
+       u32 tag = data->reparse.tag;
        int rc = 0;
 
        if (!tag && server->ops->query_reparse_point) {
@@ -1035,22 +1075,28 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
                if (!rc)
                        iov = &rsp_iov;
        }
-       switch ((data->reparse_tag = tag)) {
+
+       rc = -EOPNOTSUPP;
+       switch ((data->reparse.tag = tag)) {
        case 0: /* SMB1 symlink */
-               iov = NULL;
-               fallthrough;
-       case IO_REPARSE_TAG_NFS:
-       case IO_REPARSE_TAG_SYMLINK:
-               if (!data->symlink_target && server->ops->query_symlink) {
+               if (server->ops->query_symlink) {
                        rc = server->ops->query_symlink(xid, tcon,
                                                        cifs_sb, full_path,
-                                                       &data->symlink_target,
-                                                       iov);
+                                                       &data->symlink_target);
                }
                break;
        case IO_REPARSE_TAG_MOUNT_POINT:
                cifs_create_junction_fattr(fattr, sb);
+               rc = 0;
                goto out;
+       default:
+               if (data->symlink_target) {
+                       rc = 0;
+               } else if (server->ops->parse_reparse_point) {
+                       rc = server->ops->parse_reparse_point(cifs_sb,
+                                                             iov, data);
+               }
+               break;
        }
 
        cifs_open_info_to_fattr(fattr, data, sb);
index 47fc22de8d20c79c6d03647cfad95c4b392bb584..d30ea2005eb361a9d9af8ba39568d4168409a3ee 100644 (file)
@@ -153,6 +153,10 @@ static bool reparse_file_needs_reval(const struct cifs_fattr *fattr)
 static void
 cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
 {
+       struct cifs_open_info_data data = {
+               .reparse = { .tag = fattr->cf_cifstag, },
+       };
+
        fattr->cf_uid = cifs_sb->ctx->linux_uid;
        fattr->cf_gid = cifs_sb->ctx->linux_gid;
 
@@ -165,7 +169,7 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
         * reasonably map some of them to directories vs. files vs. symlinks
         */
        if ((fattr->cf_cifsattrs & ATTR_REPARSE) &&
-           cifs_reparse_point_to_fattr(cifs_sb, fattr, fattr->cf_cifstag))
+           cifs_reparse_point_to_fattr(cifs_sb, fattr, &data))
                goto out_reparse;
 
        if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
index 8b2d7c1ca4284c76cee2154140eaab89fdb8f4df..816e01c5589b450a9a5b6887c99aec4f48a5f361 100644 (file)
@@ -332,10 +332,10 @@ cifs_disable_secondary_channels(struct cifs_ses *ses)
 
                if (iface) {
                        spin_lock(&ses->iface_lock);
-                       kref_put(&iface->refcount, release_iface);
                        iface->num_channels--;
                        if (iface->weight_fulfilled)
                                iface->weight_fulfilled--;
+                       kref_put(&iface->refcount, release_iface);
                        spin_unlock(&ses->iface_lock);
                }
 
index 9bf8735cdd1e8f61f737435fd82a0cd2a8bed73a..a9eaba8083b0d6b2745ebedb1d3d4705c0f4809d 100644 (file)
@@ -976,64 +976,37 @@ static int cifs_query_symlink(const unsigned int xid,
                              struct cifs_tcon *tcon,
                              struct cifs_sb_info *cifs_sb,
                              const char *full_path,
-                             char **target_path,
-                             struct kvec *rsp_iov)
+                             char **target_path)
 {
        int rc;
-       int oplock = 0;
-       bool is_reparse_point = !!rsp_iov;
-       struct cifs_fid fid;
-       struct cifs_open_parms oparms;
 
-       cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
+       cifs_tcon_dbg(FYI, "%s: path=%s\n", __func__, full_path);
 
-       if (is_reparse_point) {
-               cifs_dbg(VFS, "reparse points not handled for SMB1 symlinks\n");
+       if (!cap_unix(tcon->ses))
                return -EOPNOTSUPP;
-       }
-
-       /* Check for unix extensions */
-       if (cap_unix(tcon->ses)) {
-               rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path,
-                                            cifs_sb->local_nls,
-                                            cifs_remap(cifs_sb));
-               if (rc == -EREMOTE)
-                       rc = cifs_unix_dfs_readlink(xid, tcon, full_path,
-                                                   target_path,
-                                                   cifs_sb->local_nls);
-
-               goto out;
-       }
-
-       oparms = (struct cifs_open_parms) {
-               .tcon = tcon,
-               .cifs_sb = cifs_sb,
-               .desired_access = FILE_READ_ATTRIBUTES,
-               .create_options = cifs_create_options(cifs_sb,
-                                                     OPEN_REPARSE_POINT),
-               .disposition = FILE_OPEN,
-               .path = full_path,
-               .fid = &fid,
-       };
-
-       rc = CIFS_open(xid, &oparms, &oplock, NULL);
-       if (rc)
-               goto out;
-
-       rc = CIFSSMBQuerySymLink(xid, tcon, fid.netfid, target_path,
-                                cifs_sb->local_nls);
-       if (rc)
-               goto out_close;
 
-       convert_delimiter(*target_path, '/');
-out_close:
-       CIFSSMBClose(xid, tcon, fid.netfid);
-out:
-       if (!rc)
-               cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
+       rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path,
+                                    cifs_sb->local_nls, cifs_remap(cifs_sb));
+       if (rc == -EREMOTE)
+               rc = cifs_unix_dfs_readlink(xid, tcon, full_path,
+                                           target_path, cifs_sb->local_nls);
        return rc;
 }
 
+static int cifs_parse_reparse_point(struct cifs_sb_info *cifs_sb,
+                                   struct kvec *rsp_iov,
+                                   struct cifs_open_info_data *data)
+{
+       struct reparse_data_buffer *buf;
+       TRANSACT_IOCTL_RSP *io = rsp_iov->iov_base;
+       bool unicode = !!(io->hdr.Flags2 & SMBFLG2_UNICODE);
+       u32 plen = le16_to_cpu(io->ByteCount);
+
+       buf = (struct reparse_data_buffer *)((__u8 *)&io->hdr.Protocol +
+                                            le32_to_cpu(io->DataOffset));
+       return parse_reparse_point(buf, plen, cifs_sb, unicode, data);
+}
+
 static bool
 cifs_is_read_op(__u32 oplock)
 {
@@ -1068,15 +1041,7 @@ cifs_make_node(unsigned int xid, struct inode *inode,
 {
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct inode *newinode = NULL;
-       int rc = -EPERM;
-       struct cifs_open_info_data buf = {};
-       struct cifs_io_parms io_parms;
-       __u32 oplock = 0;
-       struct cifs_fid fid;
-       struct cifs_open_parms oparms;
-       unsigned int bytes_written;
-       struct win_dev *pdev;
-       struct kvec iov[2];
+       int rc;
 
        if (tcon->unix_ext) {
                /*
@@ -1110,74 +1075,18 @@ cifs_make_node(unsigned int xid, struct inode *inode,
                        d_instantiate(dentry, newinode);
                return rc;
        }
-
        /*
-        * SMB1 SFU emulation: should work with all servers, but only
-        * support block and char device (no socket & fifo)
+        * Check if mounted with mount parm 'sfu' mount parm.
+        * SFU emulation should work with all servers, but only
+        * supports block and char device (no socket & fifo),
+        * and was used by default in earlier versions of Windows
         */
        if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
-               return rc;
-
-       if (!S_ISCHR(mode) && !S_ISBLK(mode))
-               return rc;
-
-       cifs_dbg(FYI, "sfu compat create special file\n");
-
-       oparms = (struct cifs_open_parms) {
-               .tcon = tcon,
-               .cifs_sb = cifs_sb,
-               .desired_access = GENERIC_WRITE,
-               .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR |
-                                                     CREATE_OPTION_SPECIAL),
-               .disposition = FILE_CREATE,
-               .path = full_path,
-               .fid = &fid,
-       };
-
-       if (tcon->ses->server->oplocks)
-               oplock = REQ_OPLOCK;
-       else
-               oplock = 0;
-       rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &buf);
-       if (rc)
-               return rc;
-
-       /*
-        * BB Do not bother to decode buf since no local inode yet to put
-        * timestamps in, but we can reuse it safely.
-        */
-
-       pdev = (struct win_dev *)&buf.fi;
-       io_parms.pid = current->tgid;
-       io_parms.tcon = tcon;
-       io_parms.offset = 0;
-       io_parms.length = sizeof(struct win_dev);
-       iov[1].iov_base = &buf.fi;
-       iov[1].iov_len = sizeof(struct win_dev);
-       if (S_ISCHR(mode)) {
-               memcpy(pdev->type, "IntxCHR", 8);
-               pdev->major = cpu_to_le64(MAJOR(dev));
-               pdev->minor = cpu_to_le64(MINOR(dev));
-               rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
-                                                       &bytes_written, iov, 1);
-       } else if (S_ISBLK(mode)) {
-               memcpy(pdev->type, "IntxBLK", 8);
-               pdev->major = cpu_to_le64(MAJOR(dev));
-               pdev->minor = cpu_to_le64(MINOR(dev));
-               rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
-                                                       &bytes_written, iov, 1);
-       }
-       tcon->ses->server->ops->close(xid, tcon, &fid);
-       d_drop(dentry);
-
-       /* FIXME: add code here to set EAs */
-
-       cifs_free_open_info(&buf);
-       return rc;
+               return -EPERM;
+       return cifs_sfu_make_node(xid, inode, dentry, tcon,
+                                 full_path, mode, dev);
 }
 
-
-
 struct smb_version_operations smb1_operations = {
        .send_cancel = send_nt_cancel,
        .compare_fids = cifs_compare_fids,
@@ -1214,6 +1123,7 @@ struct smb_version_operations smb1_operations = {
        .is_path_accessible = cifs_is_path_accessible,
        .can_echo = cifs_can_echo,
        .query_path_info = cifs_query_path_info,
+       .query_reparse_point = cifs_query_reparse_point,
        .query_file_info = cifs_query_file_info,
        .get_srv_inum = cifs_get_srv_inum,
        .set_path_size = CIFSSMBSetEOF,
@@ -1229,6 +1139,7 @@ struct smb_version_operations smb1_operations = {
        .rename = CIFSSMBRename,
        .create_hardlink = CIFSCreateHardLink,
        .query_symlink = cifs_query_symlink,
+       .parse_reparse_point = cifs_parse_reparse_point,
        .open = cifs_open_file,
        .set_fid = cifs_set_fid,
        .close = cifs_close_file,
index 0b89f7008ac0f429cc1a6b004c70117e19658837..c94940af5d4b8d79453ac766e4e46216b714b47a 100644 (file)
@@ -555,7 +555,7 @@ static int parse_create_response(struct cifs_open_info_data *data,
                break;
        }
        data->reparse_point = reparse_point;
-       data->reparse_tag = tag;
+       data->reparse.tag = tag;
        return rc;
 }
 
index a959ed2c9b22e44a59dc31950c373c2661cc425e..82ab62fd00404d76d11e34632b47f8d6ac182992 100644 (file)
@@ -2866,115 +2866,119 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
        return rc;
 }
 
-static int
-parse_reparse_posix(struct reparse_posix_data *symlink_buf,
-                     u32 plen, char **target_path,
-                     struct cifs_sb_info *cifs_sb)
+/* See MS-FSCC 2.1.2.6 for the 'NFS' style reparse tags */
+static int parse_reparse_posix(struct reparse_posix_data *buf,
+                              struct cifs_sb_info *cifs_sb,
+                              struct cifs_open_info_data *data)
 {
        unsigned int len;
-
-       /* See MS-FSCC 2.1.2.6 for the 'NFS' style reparse tags */
-       len = le16_to_cpu(symlink_buf->ReparseDataLength);
-
-       if (le64_to_cpu(symlink_buf->InodeType) != NFS_SPECFILE_LNK) {
-               cifs_dbg(VFS, "%lld not a supported symlink type\n",
-                       le64_to_cpu(symlink_buf->InodeType));
+       u64 type;
+
+       switch ((type = le64_to_cpu(buf->InodeType))) {
+       case NFS_SPECFILE_LNK:
+               len = le16_to_cpu(buf->ReparseDataLength);
+               data->symlink_target = cifs_strndup_from_utf16(buf->DataBuffer,
+                                                              len, true,
+                                                              cifs_sb->local_nls);
+               if (!data->symlink_target)
+                       return -ENOMEM;
+               convert_delimiter(data->symlink_target, '/');
+               cifs_dbg(FYI, "%s: target path: %s\n",
+                        __func__, data->symlink_target);
+               break;
+       case NFS_SPECFILE_CHR:
+       case NFS_SPECFILE_BLK:
+       case NFS_SPECFILE_FIFO:
+       case NFS_SPECFILE_SOCK:
+               break;
+       default:
+               cifs_dbg(VFS, "%s: unhandled inode type: 0x%llx\n",
+                        __func__, type);
                return -EOPNOTSUPP;
        }
-
-       *target_path = cifs_strndup_from_utf16(
-                               symlink_buf->PathBuffer,
-                               len, true, cifs_sb->local_nls);
-       if (!(*target_path))
-               return -ENOMEM;
-
-       convert_delimiter(*target_path, '/');
-       cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
-
        return 0;
 }
 
-static int
-parse_reparse_symlink(struct reparse_symlink_data_buffer *symlink_buf,
-                     u32 plen, char **target_path,
-                     struct cifs_sb_info *cifs_sb)
+static int parse_reparse_symlink(struct reparse_symlink_data_buffer *sym,
+                                u32 plen, bool unicode,
+                                struct cifs_sb_info *cifs_sb,
+                                struct cifs_open_info_data *data)
 {
-       unsigned int sub_len;
-       unsigned int sub_offset;
+       unsigned int len;
+       unsigned int offs;
 
        /* We handle Symbolic Link reparse tag here. See: MS-FSCC 2.1.2.4 */
 
-       sub_offset = le16_to_cpu(symlink_buf->SubstituteNameOffset);
-       sub_len = le16_to_cpu(symlink_buf->SubstituteNameLength);
-       if (sub_offset + 20 > plen ||
-           sub_offset + sub_len + 20 > plen) {
+       offs = le16_to_cpu(sym->SubstituteNameOffset);
+       len = le16_to_cpu(sym->SubstituteNameLength);
+       if (offs + 20 > plen || offs + len + 20 > plen) {
                cifs_dbg(VFS, "srv returned malformed symlink buffer\n");
                return -EIO;
        }
 
-       *target_path = cifs_strndup_from_utf16(
-                               symlink_buf->PathBuffer + sub_offset,
-                               sub_len, true, cifs_sb->local_nls);
-       if (!(*target_path))
+       data->symlink_target = cifs_strndup_from_utf16(sym->PathBuffer + offs,
+                                                      len, unicode,
+                                                      cifs_sb->local_nls);
+       if (!data->symlink_target)
                return -ENOMEM;
 
-       convert_delimiter(*target_path, '/');
-       cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
+       convert_delimiter(data->symlink_target, '/');
+       cifs_dbg(FYI, "%s: target path: %s\n", __func__, data->symlink_target);
 
        return 0;
 }
 
-static int
-parse_reparse_point(struct reparse_data_buffer *buf,
-                   u32 plen, char **target_path,
-                   struct cifs_sb_info *cifs_sb)
+int parse_reparse_point(struct reparse_data_buffer *buf,
+                       u32 plen, struct cifs_sb_info *cifs_sb,
+                       bool unicode, struct cifs_open_info_data *data)
 {
-       if (plen < sizeof(struct reparse_data_buffer)) {
-               cifs_dbg(VFS, "reparse buffer is too small. Must be at least 8 bytes but was %d\n",
-                        plen);
+       if (plen < sizeof(*buf)) {
+               cifs_dbg(VFS, "%s: reparse buffer is too small. Must be at least 8 bytes but was %d\n",
+                        __func__, plen);
                return -EIO;
        }
 
-       if (plen < le16_to_cpu(buf->ReparseDataLength) +
-           sizeof(struct reparse_data_buffer)) {
-               cifs_dbg(VFS, "srv returned invalid reparse buf length: %d\n",
-                        plen);
+       if (plen < le16_to_cpu(buf->ReparseDataLength) + sizeof(*buf)) {
+               cifs_dbg(VFS, "%s: invalid reparse buf length: %d\n",
+                        __func__, plen);
                return -EIO;
        }
 
+       data->reparse.buf = buf;
+
        /* See MS-FSCC 2.1.2 */
        switch (le32_to_cpu(buf->ReparseTag)) {
        case IO_REPARSE_TAG_NFS:
-               return parse_reparse_posix(
-                       (struct reparse_posix_data *)buf,
-                       plen, target_path, cifs_sb);
+               return parse_reparse_posix((struct reparse_posix_data *)buf,
+                                          cifs_sb, data);
        case IO_REPARSE_TAG_SYMLINK:
                return parse_reparse_symlink(
                        (struct reparse_symlink_data_buffer *)buf,
-                       plen, target_path, cifs_sb);
+                       plen, unicode, cifs_sb, data);
+       case IO_REPARSE_TAG_LX_SYMLINK:
+       case IO_REPARSE_TAG_AF_UNIX:
+       case IO_REPARSE_TAG_LX_FIFO:
+       case IO_REPARSE_TAG_LX_CHR:
+       case IO_REPARSE_TAG_LX_BLK:
+               return 0;
        default:
-               cifs_dbg(VFS, "srv returned unknown symlink buffer tag:0x%08x\n",
-                        le32_to_cpu(buf->ReparseTag));
+               cifs_dbg(VFS, "%s: unhandled reparse tag: 0x%08x\n",
+                        __func__, le32_to_cpu(buf->ReparseTag));
                return -EOPNOTSUPP;
        }
 }
 
-static int smb2_query_symlink(const unsigned int xid,
-                             struct cifs_tcon *tcon,
-                             struct cifs_sb_info *cifs_sb,
-                             const char *full_path,
-                             char **target_path,
-                             struct kvec *rsp_iov)
+static int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb,
+                                   struct kvec *rsp_iov,
+                                   struct cifs_open_info_data *data)
 {
        struct reparse_data_buffer *buf;
        struct smb2_ioctl_rsp *io = rsp_iov->iov_base;
        u32 plen = le32_to_cpu(io->OutputCount);
 
-       cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
-
        buf = (struct reparse_data_buffer *)((u8 *)io +
                                             le32_to_cpu(io->OutputOffset));
-       return parse_reparse_point(buf, plen, target_path, cifs_sb);
+       return parse_reparse_point(buf, plen, cifs_sb, true, data);
 }
 
 static int smb2_query_reparse_point(const unsigned int xid,
@@ -5064,41 +5068,24 @@ smb2_next_header(char *buf)
        return le32_to_cpu(hdr->NextCommand);
 }
 
-static int
-smb2_make_node(unsigned int xid, struct inode *inode,
-              struct dentry *dentry, struct cifs_tcon *tcon,
-              const char *full_path, umode_t mode, dev_t dev)
+int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
+                      struct dentry *dentry, struct cifs_tcon *tcon,
+                      const char *full_path, umode_t mode, dev_t dev)
 {
-       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-       int rc = -EPERM;
        struct cifs_open_info_data buf = {};
-       struct cifs_io_parms io_parms = {0};
-       __u32 oplock = 0;
-       struct cifs_fid fid;
+       struct TCP_Server_Info *server = tcon->ses->server;
        struct cifs_open_parms oparms;
+       struct cifs_io_parms io_parms = {};
+       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+       struct cifs_fid fid;
        unsigned int bytes_written;
        struct win_dev *pdev;
        struct kvec iov[2];
-
-       /*
-        * Check if mounted with mount parm 'sfu' mount parm.
-        * SFU emulation should work with all servers, but only
-        * supports block and char device (no socket & fifo),
-        * and was used by default in earlier versions of Windows
-        */
-       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
-               return rc;
-
-       /*
-        * TODO: Add ability to create instead via reparse point. Windows (e.g.
-        * their current NFS server) uses this approach to expose special files
-        * over SMB2/SMB3 and Samba will do this with SMB3.1.1 POSIX Extensions
-        */
+       __u32 oplock = server->oplocks ? REQ_OPLOCK : 0;
+       int rc;
 
        if (!S_ISCHR(mode) && !S_ISBLK(mode) && !S_ISFIFO(mode))
-               return rc;
-
-       cifs_dbg(FYI, "sfu compat create special file\n");
+               return -EPERM;
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
@@ -5111,11 +5098,7 @@ smb2_make_node(unsigned int xid, struct inode *inode,
                .fid = &fid,
        };
 
-       if (tcon->ses->server->oplocks)
-               oplock = REQ_OPLOCK;
-       else
-               oplock = 0;
-       rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &buf);
+       rc = server->ops->open(xid, &oparms, &oplock, &buf);
        if (rc)
                return rc;
 
@@ -5123,42 +5106,56 @@ smb2_make_node(unsigned int xid, struct inode *inode,
         * BB Do not bother to decode buf since no local inode yet to put
         * timestamps in, but we can reuse it safely.
         */
-
        pdev = (struct win_dev *)&buf.fi;
        io_parms.pid = current->tgid;
        io_parms.tcon = tcon;
-       io_parms.offset = 0;
-       io_parms.length = sizeof(struct win_dev);
-       iov[1].iov_base = &buf.fi;
-       iov[1].iov_len = sizeof(struct win_dev);
+       io_parms.length = sizeof(*pdev);
+       iov[1].iov_base = pdev;
+       iov[1].iov_len = sizeof(*pdev);
        if (S_ISCHR(mode)) {
                memcpy(pdev->type, "IntxCHR", 8);
                pdev->major = cpu_to_le64(MAJOR(dev));
                pdev->minor = cpu_to_le64(MINOR(dev));
-               rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
-                                                       &bytes_written, iov, 1);
        } else if (S_ISBLK(mode)) {
                memcpy(pdev->type, "IntxBLK", 8);
                pdev->major = cpu_to_le64(MAJOR(dev));
                pdev->minor = cpu_to_le64(MINOR(dev));
-               rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
-                                                       &bytes_written, iov, 1);
        } else if (S_ISFIFO(mode)) {
                memcpy(pdev->type, "LnxFIFO", 8);
-               pdev->major = 0;
-               pdev->minor = 0;
-               rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
-                                                       &bytes_written, iov, 1);
        }
-       tcon->ses->server->ops->close(xid, tcon, &fid);
-       d_drop(dentry);
 
+       rc = server->ops->sync_write(xid, &fid, &io_parms,
+                                    &bytes_written, iov, 1);
+       server->ops->close(xid, tcon, &fid);
+       d_drop(dentry);
        /* FIXME: add code here to set EAs */
-
        cifs_free_open_info(&buf);
        return rc;
 }
 
+static int smb2_make_node(unsigned int xid, struct inode *inode,
+                         struct dentry *dentry, struct cifs_tcon *tcon,
+                         const char *full_path, umode_t mode, dev_t dev)
+{
+       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+
+       /*
+        * Check if mounted with mount parm 'sfu' mount parm.
+        * SFU emulation should work with all servers, but only
+        * supports block and char device (no socket & fifo),
+        * and was used by default in earlier versions of Windows
+        */
+       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
+               return -EPERM;
+       /*
+        * TODO: Add ability to create instead via reparse point. Windows (e.g.
+        * their current NFS server) uses this approach to expose special files
+        * over SMB2/SMB3 and Samba will do this with SMB3.1.1 POSIX Extensions
+        */
+       return cifs_sfu_make_node(xid, inode, dentry, tcon,
+                                 full_path, mode, dev);
+}
+
 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
 struct smb_version_operations smb20_operations = {
        .compare_fids = smb2_compare_fids,
@@ -5209,7 +5206,7 @@ struct smb_version_operations smb20_operations = {
        .unlink = smb2_unlink,
        .rename = smb2_rename_path,
        .create_hardlink = smb2_create_hardlink,
-       .query_symlink = smb2_query_symlink,
+       .parse_reparse_point = smb2_parse_reparse_point,
        .query_mf_symlink = smb3_query_mf_symlink,
        .create_mf_symlink = smb3_create_mf_symlink,
        .open = smb2_open_file,
@@ -5311,7 +5308,7 @@ struct smb_version_operations smb21_operations = {
        .unlink = smb2_unlink,
        .rename = smb2_rename_path,
        .create_hardlink = smb2_create_hardlink,
-       .query_symlink = smb2_query_symlink,
+       .parse_reparse_point = smb2_parse_reparse_point,
        .query_mf_symlink = smb3_query_mf_symlink,
        .create_mf_symlink = smb3_create_mf_symlink,
        .open = smb2_open_file,
@@ -5416,7 +5413,7 @@ struct smb_version_operations smb30_operations = {
        .unlink = smb2_unlink,
        .rename = smb2_rename_path,
        .create_hardlink = smb2_create_hardlink,
-       .query_symlink = smb2_query_symlink,
+       .parse_reparse_point = smb2_parse_reparse_point,
        .query_mf_symlink = smb3_query_mf_symlink,
        .create_mf_symlink = smb3_create_mf_symlink,
        .open = smb2_open_file,
@@ -5530,7 +5527,7 @@ struct smb_version_operations smb311_operations = {
        .unlink = smb2_unlink,
        .rename = smb2_rename_path,
        .create_hardlink = smb2_create_hardlink,
-       .query_symlink = smb2_query_symlink,
+       .parse_reparse_point = smb2_parse_reparse_point,
        .query_mf_symlink = smb3_query_mf_symlink,
        .create_mf_symlink = smb3_create_mf_symlink,
        .open = smb2_open_file,
index 24bb0209e4599f934af06f6c0a9f984880b2fb34..f721d26ec3f7e535e85beb695a7330a479fbb851 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -133,7 +133,8 @@ int vfs_getattr_nosec(const struct path *path, struct kstat *stat,
        idmap = mnt_idmap(path->mnt);
        if (inode->i_op->getattr)
                return inode->i_op->getattr(idmap, path, stat,
-                                           request_mask, query_flags);
+                                           request_mask,
+                                           query_flags | AT_GETATTR_NOSEC);
 
        generic_fillattr(idmap, request_mask, inode, stat);
        return 0;
@@ -166,6 +167,9 @@ int vfs_getattr(const struct path *path, struct kstat *stat,
 {
        int retval;
 
+       if (WARN_ON_ONCE(query_flags & AT_GETATTR_NOSEC))
+               return -EPERM;
+
        retval = security_inode_getattr(path);
        if (retval)
                return retval;
index ac6ba646624df5e2a52a16750ced6c3b7da4ca08..a013b87ab8d5e5f7ffcada368e8e7d4c4cb5c0f7 100644 (file)
@@ -562,7 +562,8 @@ xfs_dquot_from_disk(
        struct xfs_dquot        *dqp,
        struct xfs_buf          *bp)
 {
-       struct xfs_disk_dquot   *ddqp = bp->b_addr + dqp->q_bufoffset;
+       struct xfs_dqblk        *dqb = xfs_buf_offset(bp, dqp->q_bufoffset);
+       struct xfs_disk_dquot   *ddqp = &dqb->dd_diskdq;
 
        /*
         * Ensure that we got the type and ID we were looking for.
@@ -1250,7 +1251,7 @@ xfs_qm_dqflush(
        }
 
        /* Flush the incore dquot to the ondisk buffer. */
-       dqblk = bp->b_addr + dqp->q_bufoffset;
+       dqblk = xfs_buf_offset(bp, dqp->q_bufoffset);
        xfs_dquot_to_disk(&dqblk->dd_diskdq, dqp);
 
        /*
index 8966ba842395bfddfcf5fc903600b0bcbf6263aa..2c2720ce692382d3f4a3658e7190fc0f0840e275 100644 (file)
@@ -19,6 +19,7 @@
 #include "xfs_log.h"
 #include "xfs_log_priv.h"
 #include "xfs_log_recover.h"
+#include "xfs_error.h"
 
 STATIC void
 xlog_recover_dquot_ra_pass2(
@@ -65,6 +66,7 @@ xlog_recover_dquot_commit_pass2(
 {
        struct xfs_mount                *mp = log->l_mp;
        struct xfs_buf                  *bp;
+       struct xfs_dqblk                *dqb;
        struct xfs_disk_dquot           *ddq, *recddq;
        struct xfs_dq_logformat         *dq_f;
        xfs_failaddr_t                  fa;
@@ -130,14 +132,14 @@ xlog_recover_dquot_commit_pass2(
                return error;
 
        ASSERT(bp);
-       ddq = xfs_buf_offset(bp, dq_f->qlf_boffset);
+       dqb = xfs_buf_offset(bp, dq_f->qlf_boffset);
+       ddq = &dqb->dd_diskdq;
 
        /*
         * If the dquot has an LSN in it, recover the dquot only if it's less
         * than the lsn of the transaction we are replaying.
         */
        if (xfs_has_crc(mp)) {
-               struct xfs_dqblk *dqb = (struct xfs_dqblk *)ddq;
                xfs_lsn_t       lsn = be64_to_cpu(dqb->dd_lsn);
 
                if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) >= 0) {
@@ -147,10 +149,23 @@ xlog_recover_dquot_commit_pass2(
 
        memcpy(ddq, recddq, item->ri_buf[1].i_len);
        if (xfs_has_crc(mp)) {
-               xfs_update_cksum((char *)ddq, sizeof(struct xfs_dqblk),
+               xfs_update_cksum((char *)dqb, sizeof(struct xfs_dqblk),
                                 XFS_DQUOT_CRC_OFF);
        }
 
+       /* Validate the recovered dquot. */
+       fa = xfs_dqblk_verify(log->l_mp, dqb, dq_f->qlf_id);
+       if (fa) {
+               XFS_CORRUPTION_ERROR("Bad dquot after recovery",
+                               XFS_ERRLEVEL_LOW, mp, dqb,
+                               sizeof(struct xfs_dqblk));
+               xfs_alert(mp,
+ "Metadata corruption detected at %pS, dquot 0x%x",
+                               fa, dq_f->qlf_id);
+               error = -EFSCORRUPTED;
+               goto out_release;
+       }
+
        ASSERT(dq_f->qlf_size == 2);
        ASSERT(bp->b_mount == mp);
        bp->b_flags |= _XBF_LOGRECOVERY;
index 3dc47937da5d17d81e46fd590435f574d11558dc..3beb470f18920d6730b32e5d1edcf5530b93b327 100644 (file)
@@ -569,6 +569,14 @@ extern void xfs_setup_inode(struct xfs_inode *ip);
 extern void xfs_setup_iops(struct xfs_inode *ip);
 extern void xfs_diflags_to_iflags(struct xfs_inode *ip, bool init);
 
+static inline void xfs_update_stable_writes(struct xfs_inode *ip)
+{
+       if (bdev_stable_writes(xfs_inode_buftarg(ip)->bt_bdev))
+               mapping_set_stable_writes(VFS_I(ip)->i_mapping);
+       else
+               mapping_clear_stable_writes(VFS_I(ip)->i_mapping);
+}
+
 /*
  * When setting up a newly allocated inode, we need to call
  * xfs_finish_inode_setup() once the inode is fully instantiated at
index a82470e027f7278ac4b3271cd67a27ed97235c77..6c3919687ea6b306585ea2f32f125c59a4b53a60 100644 (file)
@@ -1121,23 +1121,25 @@ xfs_ioctl_setattr_xflags(
        struct fileattr         *fa)
 {
        struct xfs_mount        *mp = ip->i_mount;
+       bool                    rtflag = (fa->fsx_xflags & FS_XFLAG_REALTIME);
        uint64_t                i_flags2;
 
-       /* Can't change realtime flag if any extents are allocated. */
-       if ((ip->i_df.if_nextents || ip->i_delayed_blks) &&
-           XFS_IS_REALTIME_INODE(ip) != (fa->fsx_xflags & FS_XFLAG_REALTIME))
-               return -EINVAL;
+       if (rtflag != XFS_IS_REALTIME_INODE(ip)) {
+               /* Can't change realtime flag if any extents are allocated. */
+               if (ip->i_df.if_nextents || ip->i_delayed_blks)
+                       return -EINVAL;
+       }
 
-       /* If realtime flag is set then must have realtime device */
-       if (fa->fsx_xflags & FS_XFLAG_REALTIME) {
+       if (rtflag) {
+               /* If realtime flag is set then must have realtime device */
                if (mp->m_sb.sb_rblocks == 0 || mp->m_sb.sb_rextsize == 0 ||
                    xfs_extlen_to_rtxmod(mp, ip->i_extsize))
                        return -EINVAL;
-       }
 
-       /* Clear reflink if we are actually able to set the rt flag. */
-       if ((fa->fsx_xflags & FS_XFLAG_REALTIME) && xfs_is_reflink_inode(ip))
-               ip->i_diflags2 &= ~XFS_DIFLAG2_REFLINK;
+               /* Clear reflink if we are actually able to set the rt flag. */
+               if (xfs_is_reflink_inode(ip))
+                       ip->i_diflags2 &= ~XFS_DIFLAG2_REFLINK;
+       }
 
        /* diflags2 only valid for v3 inodes. */
        i_flags2 = xfs_flags2diflags2(ip, fa->fsx_xflags);
@@ -1148,6 +1150,14 @@ xfs_ioctl_setattr_xflags(
        ip->i_diflags2 = i_flags2;
 
        xfs_diflags_to_iflags(ip, false);
+
+       /*
+        * Make the stable writes flag match that of the device the inode
+        * resides on when flipping the RT flag.
+        */
+       if (rtflag != XFS_IS_REALTIME_INODE(ip) && S_ISREG(VFS_I(ip)->i_mode))
+               xfs_update_stable_writes(ip);
+
        xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
        XFS_STATS_INC(mp, xs_ig_attrchg);
index fdfda4fba12b1e9afd3b8631ec8587ac7295ce13..a0d77f5f512e2412c0e4c89aefacdd5c7c52c00c 100644 (file)
@@ -1298,6 +1298,13 @@ xfs_setup_inode(
        gfp_mask = mapping_gfp_mask(inode->i_mapping);
        mapping_set_gfp_mask(inode->i_mapping, (gfp_mask & ~(__GFP_FS)));
 
+       /*
+        * For real-time inodes update the stable write flags to that of the RT
+        * device instead of the data device.
+        */
+       if (S_ISREG(inode->i_mode) && XFS_IS_REALTIME_INODE(ip))
+               xfs_update_stable_writes(ip);
+
        /*
         * If there is no attribute fork no ACL can exist on this inode,
         * and it can't have any file capabilities attached to it either.
index afeed6e72049e470f836d79753971aa392359662..1216d72c650faee69165b6b9f1545f41b3b9954c 100644 (file)
@@ -542,6 +542,7 @@ int acpi_device_set_power(struct acpi_device *device, int state);
 int acpi_bus_init_power(struct acpi_device *device);
 int acpi_device_fix_up_power(struct acpi_device *device);
 void acpi_device_fix_up_power_extended(struct acpi_device *adev);
+void acpi_device_fix_up_power_children(struct acpi_device *adev);
 int acpi_bus_update_power(acpi_handle handle, int *state_p);
 int acpi_device_update_power(struct acpi_device *device, int *state_p);
 bool acpi_bus_power_manageable(acpi_handle handle);
index 995513fa26904afa113d70e8b0b408af13ee9c65..0655aa5b57b29066286b9c94f477e7d6593f88b8 100644 (file)
@@ -70,7 +70,7 @@ static __always_inline int queued_spin_is_locked(struct qspinlock *lock)
  */
 static __always_inline int queued_spin_value_unlocked(struct qspinlock lock)
 {
-       return !atomic_read(&lock.val);
+       return !lock.val.counter;
 }
 
 /**
index 2580e05a8ab67203efde59504ffb655480b531cb..004b38a538ffef76c9841395a8dbd0f39a58b183 100644 (file)
@@ -15,7 +15,6 @@ extern int blk_pre_runtime_suspend(struct request_queue *q);
 extern void blk_post_runtime_suspend(struct request_queue *q, int err);
 extern void blk_pre_runtime_resume(struct request_queue *q);
 extern void blk_post_runtime_resume(struct request_queue *q);
-extern void blk_set_runtime_active(struct request_queue *q);
 #else
 static inline void blk_pm_runtime_init(struct request_queue *q,
                                       struct device *dev) {}
index 24213a99cc79db4c41ad17f8b28d23bcc7a8be9f..aa4d19d0bc94bb41da7ef238b3b3e7ebc98d7ced 100644 (file)
@@ -301,6 +301,17 @@ struct bpf_func_state {
        struct tnum callback_ret_range;
        bool in_async_callback_fn;
        bool in_exception_callback_fn;
+       /* For callback calling functions that limit number of possible
+        * callback executions (e.g. bpf_loop) keeps track of current
+        * simulated iteration number.
+        * Value in frame N refers to number of times callback with frame
+        * N+1 was simulated, e.g. for the following call:
+        *
+        *   bpf_loop(..., fn, ...); | suppose current frame is N
+        *                           | fn would be simulated in frame N+1
+        *                           | number of simulations is tracked in frame N
+        */
+       u32 callback_depth;
 
        /* The following fields should be last. See copy_func_state() */
        int acquired_refs;
@@ -400,6 +411,7 @@ struct bpf_verifier_state {
        struct bpf_idx_pair *jmp_history;
        u32 jmp_history_cnt;
        u32 dfs_depth;
+       u32 callback_unroll_depth;
 };
 
 #define bpf_get_spilled_reg(slot, frame, mask)                         \
@@ -511,6 +523,10 @@ struct bpf_insn_aux_data {
         * this instruction, regardless of any heuristics
         */
        bool force_checkpoint;
+       /* true if instruction is a call to a helper function that
+        * accepts callback function as a parameter.
+        */
+       bool calls_callback;
 };
 
 #define MAX_USED_MAPS 64 /* max number of maps accessed by one eBPF program */
index 5a8387a4a7126303adcee9553cce3cfb7599e1b2..bf43f3ff666400fb8a5d0fcef9e1c20773dcde1e 100644 (file)
@@ -679,6 +679,7 @@ struct hid_device {                                                 /* device report descriptor */
        struct list_head debug_list;
        spinlock_t  debug_list_lock;
        wait_queue_head_t debug_wait;
+       struct kref                     ref;
 
        unsigned int id;                                                /* system unique id */
 
@@ -687,6 +688,8 @@ struct hid_device {                                                 /* device report descriptor */
 #endif /* CONFIG_BPF */
 };
 
+void hiddev_free(struct kref *ref);
+
 #define to_hid_device(pdev) \
        container_of(pdev, struct hid_device, dev)
 
index a16c9cc063fe0efbaefc7d4ce678846abbd1046e..2564e209465ea8c1cac107402e51c8562eff047e 100644 (file)
@@ -1797,6 +1797,13 @@ enum netdev_ml_priv_type {
        ML_PRIV_CAN,
 };
 
+enum netdev_stat_type {
+       NETDEV_PCPU_STAT_NONE,
+       NETDEV_PCPU_STAT_LSTATS, /* struct pcpu_lstats */
+       NETDEV_PCPU_STAT_TSTATS, /* struct pcpu_sw_netstats */
+       NETDEV_PCPU_STAT_DSTATS, /* struct pcpu_dstats */
+};
+
 /**
  *     struct net_device - The DEVICE structure.
  *
@@ -1991,10 +1998,14 @@ enum netdev_ml_priv_type {
  *
  *     @ml_priv:       Mid-layer private
  *     @ml_priv_type:  Mid-layer private type
- *     @lstats:        Loopback statistics
- *     @tstats:        Tunnel statistics
- *     @dstats:        Dummy statistics
- *     @vstats:        Virtual ethernet statistics
+ *
+ *     @pcpu_stat_type:        Type of device statistics which the core should
+ *                             allocate/free: none, lstats, tstats, dstats. none
+ *                             means the driver is handling statistics allocation/
+ *                             freeing internally.
+ *     @lstats:                Loopback statistics: packets, bytes
+ *     @tstats:                Tunnel statistics: RX/TX packets, RX/TX bytes
+ *     @dstats:                Dummy statistics: RX/TX/drop packets, RX/TX bytes
  *
  *     @garp_port:     GARP
  *     @mrp_port:      MRP
@@ -2354,6 +2365,7 @@ struct net_device {
        void                            *ml_priv;
        enum netdev_ml_priv_type        ml_priv_type;
 
+       enum netdev_stat_type           pcpu_stat_type:8;
        union {
                struct pcpu_lstats __percpu             *lstats;
                struct pcpu_sw_netstats __percpu        *tstats;
@@ -2755,6 +2767,16 @@ struct pcpu_sw_netstats {
        struct u64_stats_sync   syncp;
 } __aligned(4 * sizeof(u64));
 
+struct pcpu_dstats {
+       u64                     rx_packets;
+       u64                     rx_bytes;
+       u64                     rx_drops;
+       u64                     tx_packets;
+       u64                     tx_bytes;
+       u64                     tx_drops;
+       struct u64_stats_sync   syncp;
+} __aligned(8 * sizeof(u64));
+
 struct pcpu_lstats {
        u64_stats_t packets;
        u64_stats_t bytes;
index bcc1ea44b4e8541aea3cfe5fc601d2a9bf8c4295..06142ff7f9ce0ef0c600c3aa24f68b1bd5450bdb 100644 (file)
@@ -204,6 +204,8 @@ enum mapping_flags {
        AS_NO_WRITEBACK_TAGS = 5,
        AS_LARGE_FOLIO_SUPPORT = 6,
        AS_RELEASE_ALWAYS,      /* Call ->release_folio(), even if no private data */
+       AS_STABLE_WRITES,       /* must wait for writeback before modifying
+                                  folio contents */
 };
 
 /**
@@ -289,6 +291,21 @@ static inline void mapping_clear_release_always(struct address_space *mapping)
        clear_bit(AS_RELEASE_ALWAYS, &mapping->flags);
 }
 
+static inline bool mapping_stable_writes(const struct address_space *mapping)
+{
+       return test_bit(AS_STABLE_WRITES, &mapping->flags);
+}
+
+static inline void mapping_set_stable_writes(struct address_space *mapping)
+{
+       set_bit(AS_STABLE_WRITES, &mapping->flags);
+}
+
+static inline void mapping_clear_stable_writes(struct address_space *mapping)
+{
+       clear_bit(AS_STABLE_WRITES, &mapping->flags);
+}
+
 static inline gfp_t mapping_gfp_mask(struct address_space * mapping)
 {
        return mapping->gfp_mask;
index b513749582d775a5f6ee0e87cb0bf98fcd988959..e4de6bc1f69b6287cb49882c3235b824bb474d13 100644 (file)
@@ -144,10 +144,6 @@ struct usb_phy {
         */
        int     (*set_wakeup)(struct usb_phy *x, bool enabled);
 
-       /* notify phy port status change */
-       int     (*notify_port_status)(struct usb_phy *x, int port,
-                                     u16 portstatus, u16 portchange);
-
        /* notify phy connect status change */
        int     (*notify_connect)(struct usb_phy *x,
                        enum usb_device_speed speed);
@@ -320,15 +316,6 @@ usb_phy_set_wakeup(struct usb_phy *x, bool enabled)
                return 0;
 }
 
-static inline int
-usb_phy_notify_port_status(struct usb_phy *x, int port, u16 portstatus, u16 portchange)
-{
-       if (x && x->notify_port_status)
-               return x->notify_port_status(x, port, portstatus, portchange);
-       else
-               return 0;
-}
-
 static inline int
 usb_phy_notify_connect(struct usb_phy *x, enum usb_device_speed speed)
 {
index 0ba2e6b847ca53de6d2bcb480c0d615cc8f2dcc0..9ec0163739f45156657cb0d1b0f895514dd022a9 100644 (file)
@@ -10,6 +10,7 @@ int netkit_prog_attach(const union bpf_attr *attr, struct bpf_prog *prog);
 int netkit_link_attach(const union bpf_attr *attr, struct bpf_prog *prog);
 int netkit_prog_detach(const union bpf_attr *attr, struct bpf_prog *prog);
 int netkit_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr);
+INDIRECT_CALLABLE_DECLARE(struct net_device *netkit_peer_dev(struct net_device *dev));
 #else
 static inline int netkit_prog_attach(const union bpf_attr *attr,
                                     struct bpf_prog *prog)
@@ -34,5 +35,10 @@ static inline int netkit_prog_query(const union bpf_attr *attr,
 {
        return -EINVAL;
 }
+
+static inline struct net_device *netkit_peer_dev(struct net_device *dev)
+{
+       return NULL;
+}
 #endif /* CONFIG_NETKIT */
 #endif /* __NET_NETKIT_H */
index 4c53a5ef6257b8fcbc6ff87163bd9eebd5d5a685..f7e537f64db457f8cb6004dc90c0b84e216b62ab 100644 (file)
        E_(rxrpc_rtt_tx_ping,                   "PING")
 
 #define rxrpc_rtt_rx_traces \
-       EM(rxrpc_rtt_rx_cancel,                 "CNCL") \
+       EM(rxrpc_rtt_rx_other_ack,              "OACK") \
        EM(rxrpc_rtt_rx_obsolete,               "OBSL") \
        EM(rxrpc_rtt_rx_lost,                   "LOST") \
        EM(rxrpc_rtt_rx_ping_response,          "PONG") \
index 6c80f96049bd07d1aa527c103acb07fe52bfd617..282e90aeb163c0288590995b38fe011b19e85111 100644 (file)
 #define AT_HANDLE_FID          AT_REMOVEDIR    /* file handle is needed to
                                        compare object identity and may not
                                        be usable to open_by_handle_at(2) */
+#if defined(__KERNEL__)
+#define AT_GETATTR_NOSEC       0x80000000
+#endif
 
 #endif /* _UAPI_LINUX_FCNTL_H */
index 08e3b175469c685d64186595da74c778210df88a..eccea851dd5a2858936f8f0d9acc6c417614358a 100644 (file)
@@ -254,7 +254,7 @@ int io_linkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        newf = u64_to_user_ptr(READ_ONCE(sqe->addr2));
        lnk->flags = READ_ONCE(sqe->hardlink_flags);
 
-       lnk->oldpath = getname(oldf);
+       lnk->oldpath = getname_uflags(oldf, lnk->flags);
        if (IS_ERR(lnk->oldpath))
                return PTR_ERR(lnk->oldpath);
 
index 7034be555334d2fe51c17a56ca6bb3b1e3981ac0..f521c5965a9331db5375ecfb1c67f5cda4f0f29c 100644 (file)
@@ -1258,7 +1258,7 @@ int io_import_fixed(int ddir, struct iov_iter *iter,
                 */
                const struct bio_vec *bvec = imu->bvec;
 
-               if (offset <= bvec->bv_len) {
+               if (offset < bvec->bv_len) {
                        /*
                         * Note, huge pages buffers consists of one large
                         * bvec entry and should always go this way. The other
index 6da370a047feb90c4866310b57cff4c4d9eafe84..af2819d5c8ee7ceb10e267abae6b7f3fee4ea089 100644 (file)
@@ -547,13 +547,12 @@ static bool is_dynptr_ref_function(enum bpf_func_id func_id)
        return func_id == BPF_FUNC_dynptr_data;
 }
 
-static bool is_callback_calling_kfunc(u32 btf_id);
+static bool is_sync_callback_calling_kfunc(u32 btf_id);
 static bool is_bpf_throw_kfunc(struct bpf_insn *insn);
 
-static bool is_callback_calling_function(enum bpf_func_id func_id)
+static bool is_sync_callback_calling_function(enum bpf_func_id func_id)
 {
        return func_id == BPF_FUNC_for_each_map_elem ||
-              func_id == BPF_FUNC_timer_set_callback ||
               func_id == BPF_FUNC_find_vma ||
               func_id == BPF_FUNC_loop ||
               func_id == BPF_FUNC_user_ringbuf_drain;
@@ -564,6 +563,18 @@ static bool is_async_callback_calling_function(enum bpf_func_id func_id)
        return func_id == BPF_FUNC_timer_set_callback;
 }
 
+static bool is_callback_calling_function(enum bpf_func_id func_id)
+{
+       return is_sync_callback_calling_function(func_id) ||
+              is_async_callback_calling_function(func_id);
+}
+
+static bool is_sync_callback_calling_insn(struct bpf_insn *insn)
+{
+       return (bpf_helper_call(insn) && is_sync_callback_calling_function(insn->imm)) ||
+              (bpf_pseudo_kfunc_call(insn) && is_sync_callback_calling_kfunc(insn->imm));
+}
+
 static bool is_storage_get_function(enum bpf_func_id func_id)
 {
        return func_id == BPF_FUNC_sk_storage_get ||
@@ -1808,6 +1819,7 @@ static int copy_verifier_state(struct bpf_verifier_state *dst_state,
        dst_state->first_insn_idx = src->first_insn_idx;
        dst_state->last_insn_idx = src->last_insn_idx;
        dst_state->dfs_depth = src->dfs_depth;
+       dst_state->callback_unroll_depth = src->callback_unroll_depth;
        dst_state->used_as_loop_entry = src->used_as_loop_entry;
        for (i = 0; i <= src->curframe; i++) {
                dst = dst_state->frame[i];
@@ -3439,13 +3451,11 @@ static void mark_insn_zext(struct bpf_verifier_env *env,
        reg->subreg_def = DEF_NOT_SUBREG;
 }
 
-static int check_reg_arg(struct bpf_verifier_env *env, u32 regno,
-                        enum reg_arg_type t)
+static int __check_reg_arg(struct bpf_verifier_env *env, struct bpf_reg_state *regs, u32 regno,
+                          enum reg_arg_type t)
 {
-       struct bpf_verifier_state *vstate = env->cur_state;
-       struct bpf_func_state *state = vstate->frame[vstate->curframe];
        struct bpf_insn *insn = env->prog->insnsi + env->insn_idx;
-       struct bpf_reg_state *reg, *regs = state->regs;
+       struct bpf_reg_state *reg;
        bool rw64;
 
        if (regno >= MAX_BPF_REG) {
@@ -3486,6 +3496,15 @@ static int check_reg_arg(struct bpf_verifier_env *env, u32 regno,
        return 0;
 }
 
+static int check_reg_arg(struct bpf_verifier_env *env, u32 regno,
+                        enum reg_arg_type t)
+{
+       struct bpf_verifier_state *vstate = env->cur_state;
+       struct bpf_func_state *state = vstate->frame[vstate->curframe];
+
+       return __check_reg_arg(env, state->regs, regno, t);
+}
+
 static void mark_jmp_point(struct bpf_verifier_env *env, int idx)
 {
        env->insn_aux_data[idx].jmp_point = true;
@@ -3724,6 +3743,8 @@ static void fmt_stack_mask(char *buf, ssize_t buf_sz, u64 stack_mask)
        }
 }
 
+static bool calls_callback(struct bpf_verifier_env *env, int insn_idx);
+
 /* For given verifier state backtrack_insn() is called from the last insn to
  * the first insn. Its purpose is to compute a bitmask of registers and
  * stack slots that needs precision in the parent verifier state.
@@ -3899,16 +3920,13 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
                                        return -EFAULT;
                                return 0;
                        }
-               } else if ((bpf_helper_call(insn) &&
-                           is_callback_calling_function(insn->imm) &&
-                           !is_async_callback_calling_function(insn->imm)) ||
-                          (bpf_pseudo_kfunc_call(insn) && is_callback_calling_kfunc(insn->imm))) {
-                       /* callback-calling helper or kfunc call, which means
-                        * we are exiting from subprog, but unlike the subprog
-                        * call handling above, we shouldn't propagate
-                        * precision of r1-r5 (if any requested), as they are
-                        * not actually arguments passed directly to callback
-                        * subprogs
+               } else if (is_sync_callback_calling_insn(insn) && idx != subseq_idx - 1) {
+                       /* exit from callback subprog to callback-calling helper or
+                        * kfunc call. Use idx/subseq_idx check to discern it from
+                        * straight line code backtracking.
+                        * Unlike the subprog call handling above, we shouldn't
+                        * propagate precision of r1-r5 (if any requested), as they are
+                        * not actually arguments passed directly to callback subprogs
                         */
                        if (bt_reg_mask(bt) & ~BPF_REGMASK_ARGS) {
                                verbose(env, "BUG regs %x\n", bt_reg_mask(bt));
@@ -3943,10 +3961,18 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
                } else if (opcode == BPF_EXIT) {
                        bool r0_precise;
 
+                       /* Backtracking to a nested function call, 'idx' is a part of
+                        * the inner frame 'subseq_idx' is a part of the outer frame.
+                        * In case of a regular function call, instructions giving
+                        * precision to registers R1-R5 should have been found already.
+                        * In case of a callback, it is ok to have R1-R5 marked for
+                        * backtracking, as these registers are set by the function
+                        * invoking callback.
+                        */
+                       if (subseq_idx >= 0 && calls_callback(env, subseq_idx))
+                               for (i = BPF_REG_1; i <= BPF_REG_5; i++)
+                                       bt_clear_reg(bt, i);
                        if (bt_reg_mask(bt) & BPF_REGMASK_ARGS) {
-                               /* if backtracing was looking for registers R1-R5
-                                * they should have been found already.
-                                */
                                verbose(env, "BUG regs %x\n", bt_reg_mask(bt));
                                WARN_ONCE(1, "verifier backtracking bug");
                                return -EFAULT;
@@ -9350,7 +9376,7 @@ static void clear_caller_saved_regs(struct bpf_verifier_env *env,
        /* after the call registers r0 - r5 were scratched */
        for (i = 0; i < CALLER_SAVED_REGS; i++) {
                mark_reg_not_init(env, regs, caller_saved[i]);
-               check_reg_arg(env, caller_saved[i], DST_OP_NO_MARK);
+               __check_reg_arg(env, regs, caller_saved[i], DST_OP_NO_MARK);
        }
 }
 
@@ -9363,11 +9389,10 @@ static int set_callee_state(struct bpf_verifier_env *env,
                            struct bpf_func_state *caller,
                            struct bpf_func_state *callee, int insn_idx);
 
-static int __check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
-                            int *insn_idx, int subprog,
-                            set_callee_state_fn set_callee_state_cb)
+static int setup_func_entry(struct bpf_verifier_env *env, int subprog, int callsite,
+                           set_callee_state_fn set_callee_state_cb,
+                           struct bpf_verifier_state *state)
 {
-       struct bpf_verifier_state *state = env->cur_state;
        struct bpf_func_state *caller, *callee;
        int err;
 
@@ -9377,54 +9402,72 @@ static int __check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn
                return -E2BIG;
        }
 
-       caller = state->frame[state->curframe];
        if (state->frame[state->curframe + 1]) {
                verbose(env, "verifier bug. Frame %d already allocated\n",
                        state->curframe + 1);
                return -EFAULT;
        }
 
+       caller = state->frame[state->curframe];
+       callee = kzalloc(sizeof(*callee), GFP_KERNEL);
+       if (!callee)
+               return -ENOMEM;
+       state->frame[state->curframe + 1] = callee;
+
+       /* callee cannot access r0, r6 - r9 for reading and has to write
+        * into its own stack before reading from it.
+        * callee can read/write into caller's stack
+        */
+       init_func_state(env, callee,
+                       /* remember the callsite, it will be used by bpf_exit */
+                       callsite,
+                       state->curframe + 1 /* frameno within this callchain */,
+                       subprog /* subprog number within this prog */);
+       /* Transfer references to the callee */
+       err = copy_reference_state(callee, caller);
+       err = err ?: set_callee_state_cb(env, caller, callee, callsite);
+       if (err)
+               goto err_out;
+
+       /* only increment it after check_reg_arg() finished */
+       state->curframe++;
+
+       return 0;
+
+err_out:
+       free_func_state(callee);
+       state->frame[state->curframe + 1] = NULL;
+       return err;
+}
+
+static int push_callback_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
+                             int insn_idx, int subprog,
+                             set_callee_state_fn set_callee_state_cb)
+{
+       struct bpf_verifier_state *state = env->cur_state, *callback_state;
+       struct bpf_func_state *caller, *callee;
+       int err;
+
+       caller = state->frame[state->curframe];
        err = btf_check_subprog_call(env, subprog, caller->regs);
        if (err == -EFAULT)
                return err;
-       if (subprog_is_global(env, subprog)) {
-               if (err) {
-                       verbose(env, "Caller passes invalid args into func#%d\n",
-                               subprog);
-                       return err;
-               } else {
-                       if (env->log.level & BPF_LOG_LEVEL)
-                               verbose(env,
-                                       "Func#%d is global and valid. Skipping.\n",
-                                       subprog);
-                       clear_caller_saved_regs(env, caller->regs);
-
-                       /* All global functions return a 64-bit SCALAR_VALUE */
-                       mark_reg_unknown(env, caller->regs, BPF_REG_0);
-                       caller->regs[BPF_REG_0].subreg_def = DEF_NOT_SUBREG;
-
-                       /* continue with next insn after call */
-                       return 0;
-               }
-       }
 
        /* set_callee_state is used for direct subprog calls, but we are
         * interested in validating only BPF helpers that can call subprogs as
         * callbacks
         */
-       if (set_callee_state_cb != set_callee_state) {
-               env->subprog_info[subprog].is_cb = true;
-               if (bpf_pseudo_kfunc_call(insn) &&
-                   !is_callback_calling_kfunc(insn->imm)) {
-                       verbose(env, "verifier bug: kfunc %s#%d not marked as callback-calling\n",
-                               func_id_name(insn->imm), insn->imm);
-                       return -EFAULT;
-               } else if (!bpf_pseudo_kfunc_call(insn) &&
-                          !is_callback_calling_function(insn->imm)) { /* helper */
-                       verbose(env, "verifier bug: helper %s#%d not marked as callback-calling\n",
-                               func_id_name(insn->imm), insn->imm);
-                       return -EFAULT;
-               }
+       env->subprog_info[subprog].is_cb = true;
+       if (bpf_pseudo_kfunc_call(insn) &&
+           !is_sync_callback_calling_kfunc(insn->imm)) {
+               verbose(env, "verifier bug: kfunc %s#%d not marked as callback-calling\n",
+                       func_id_name(insn->imm), insn->imm);
+               return -EFAULT;
+       } else if (!bpf_pseudo_kfunc_call(insn) &&
+                  !is_callback_calling_function(insn->imm)) { /* helper */
+               verbose(env, "verifier bug: helper %s#%d not marked as callback-calling\n",
+                       func_id_name(insn->imm), insn->imm);
+               return -EFAULT;
        }
 
        if (insn->code == (BPF_JMP | BPF_CALL) &&
@@ -9435,53 +9478,83 @@ static int __check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn
                /* there is no real recursion here. timer callbacks are async */
                env->subprog_info[subprog].is_async_cb = true;
                async_cb = push_async_cb(env, env->subprog_info[subprog].start,
-                                        *insn_idx, subprog);
+                                        insn_idx, subprog);
                if (!async_cb)
                        return -EFAULT;
                callee = async_cb->frame[0];
                callee->async_entry_cnt = caller->async_entry_cnt + 1;
 
                /* Convert bpf_timer_set_callback() args into timer callback args */
-               err = set_callee_state_cb(env, caller, callee, *insn_idx);
+               err = set_callee_state_cb(env, caller, callee, insn_idx);
                if (err)
                        return err;
 
+               return 0;
+       }
+
+       /* for callback functions enqueue entry to callback and
+        * proceed with next instruction within current frame.
+        */
+       callback_state = push_stack(env, env->subprog_info[subprog].start, insn_idx, false);
+       if (!callback_state)
+               return -ENOMEM;
+
+       err = setup_func_entry(env, subprog, insn_idx, set_callee_state_cb,
+                              callback_state);
+       if (err)
+               return err;
+
+       callback_state->callback_unroll_depth++;
+       callback_state->frame[callback_state->curframe - 1]->callback_depth++;
+       caller->callback_depth = 0;
+       return 0;
+}
+
+static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
+                          int *insn_idx)
+{
+       struct bpf_verifier_state *state = env->cur_state;
+       struct bpf_func_state *caller;
+       int err, subprog, target_insn;
+
+       target_insn = *insn_idx + insn->imm + 1;
+       subprog = find_subprog(env, target_insn);
+       if (subprog < 0) {
+               verbose(env, "verifier bug. No program starts at insn %d\n", target_insn);
+               return -EFAULT;
+       }
+
+       caller = state->frame[state->curframe];
+       err = btf_check_subprog_call(env, subprog, caller->regs);
+       if (err == -EFAULT)
+               return err;
+       if (subprog_is_global(env, subprog)) {
+               if (err) {
+                       verbose(env, "Caller passes invalid args into func#%d\n", subprog);
+                       return err;
+               }
+
+               if (env->log.level & BPF_LOG_LEVEL)
+                       verbose(env, "Func#%d is global and valid. Skipping.\n", subprog);
                clear_caller_saved_regs(env, caller->regs);
+
+               /* All global functions return a 64-bit SCALAR_VALUE */
                mark_reg_unknown(env, caller->regs, BPF_REG_0);
                caller->regs[BPF_REG_0].subreg_def = DEF_NOT_SUBREG;
+
                /* continue with next insn after call */
                return 0;
        }
 
-       callee = kzalloc(sizeof(*callee), GFP_KERNEL);
-       if (!callee)
-               return -ENOMEM;
-       state->frame[state->curframe + 1] = callee;
-
-       /* callee cannot access r0, r6 - r9 for reading and has to write
-        * into its own stack before reading from it.
-        * callee can read/write into caller's stack
+       /* for regular function entry setup new frame and continue
+        * from that frame.
         */
-       init_func_state(env, callee,
-                       /* remember the callsite, it will be used by bpf_exit */
-                       *insn_idx /* callsite */,
-                       state->curframe + 1 /* frameno within this callchain */,
-                       subprog /* subprog number within this prog */);
-
-       /* Transfer references to the callee */
-       err = copy_reference_state(callee, caller);
+       err = setup_func_entry(env, subprog, *insn_idx, set_callee_state, state);
        if (err)
-               goto err_out;
-
-       err = set_callee_state_cb(env, caller, callee, *insn_idx);
-       if (err)
-               goto err_out;
+               return err;
 
        clear_caller_saved_regs(env, caller->regs);
 
-       /* only increment it after check_reg_arg() finished */
-       state->curframe++;
-
        /* and go analyze first insn of the callee */
        *insn_idx = env->subprog_info[subprog].start - 1;
 
@@ -9489,14 +9562,10 @@ static int __check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn
                verbose(env, "caller:\n");
                print_verifier_state(env, caller, true);
                verbose(env, "callee:\n");
-               print_verifier_state(env, callee, true);
+               print_verifier_state(env, state->frame[state->curframe], true);
        }
-       return 0;
 
-err_out:
-       free_func_state(callee);
-       state->frame[state->curframe + 1] = NULL;
-       return err;
+       return 0;
 }
 
 int map_set_for_each_callback_args(struct bpf_verifier_env *env,
@@ -9540,22 +9609,6 @@ static int set_callee_state(struct bpf_verifier_env *env,
        return 0;
 }
 
-static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
-                          int *insn_idx)
-{
-       int subprog, target_insn;
-
-       target_insn = *insn_idx + insn->imm + 1;
-       subprog = find_subprog(env, target_insn);
-       if (subprog < 0) {
-               verbose(env, "verifier bug. No program starts at insn %d\n",
-                       target_insn);
-               return -EFAULT;
-       }
-
-       return __check_func_call(env, insn, insn_idx, subprog, set_callee_state);
-}
-
 static int set_map_elem_callback_state(struct bpf_verifier_env *env,
                                       struct bpf_func_state *caller,
                                       struct bpf_func_state *callee,
@@ -9748,9 +9801,10 @@ static bool in_rbtree_lock_required_cb(struct bpf_verifier_env *env)
 
 static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx)
 {
-       struct bpf_verifier_state *state = env->cur_state;
+       struct bpf_verifier_state *state = env->cur_state, *prev_st;
        struct bpf_func_state *caller, *callee;
        struct bpf_reg_state *r0;
+       bool in_callback_fn;
        int err;
 
        callee = state->frame[state->curframe];
@@ -9779,6 +9833,11 @@ static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx)
                        verbose_invalid_scalar(env, r0, &range, "callback return", "R0");
                        return -EINVAL;
                }
+               if (!calls_callback(env, callee->callsite)) {
+                       verbose(env, "BUG: in callback at %d, callsite %d !calls_callback\n",
+                               *insn_idx, callee->callsite);
+                       return -EFAULT;
+               }
        } else {
                /* return to the caller whatever r0 had in the callee */
                caller->regs[BPF_REG_0] = *r0;
@@ -9796,7 +9855,16 @@ static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx)
                        return err;
        }
 
-       *insn_idx = callee->callsite + 1;
+       /* for callbacks like bpf_loop or bpf_for_each_map_elem go back to callsite,
+        * there function call logic would reschedule callback visit. If iteration
+        * converges is_state_visited() would prune that visit eventually.
+        */
+       in_callback_fn = callee->in_callback_fn;
+       if (in_callback_fn)
+               *insn_idx = callee->callsite;
+       else
+               *insn_idx = callee->callsite + 1;
+
        if (env->log.level & BPF_LOG_LEVEL) {
                verbose(env, "returning from callee:\n");
                print_verifier_state(env, callee, true);
@@ -9807,6 +9875,24 @@ static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx)
         * bpf_throw, this will be done by copy_verifier_state for extra frames. */
        free_func_state(callee);
        state->frame[state->curframe--] = NULL;
+
+       /* for callbacks widen imprecise scalars to make programs like below verify:
+        *
+        *   struct ctx { int i; }
+        *   void cb(int idx, struct ctx *ctx) { ctx->i++; ... }
+        *   ...
+        *   struct ctx = { .i = 0; }
+        *   bpf_loop(100, cb, &ctx, 0);
+        *
+        * This is similar to what is done in process_iter_next_call() for open
+        * coded iterators.
+        */
+       prev_st = in_callback_fn ? find_prev_entry(env, state, *insn_idx) : NULL;
+       if (prev_st) {
+               err = widen_imprecise_scalars(env, prev_st, state);
+               if (err)
+                       return err;
+       }
        return 0;
 }
 
@@ -10209,24 +10295,37 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
                }
                break;
        case BPF_FUNC_for_each_map_elem:
-               err = __check_func_call(env, insn, insn_idx_p, meta.subprogno,
-                                       set_map_elem_callback_state);
+               err = push_callback_call(env, insn, insn_idx, meta.subprogno,
+                                        set_map_elem_callback_state);
                break;
        case BPF_FUNC_timer_set_callback:
-               err = __check_func_call(env, insn, insn_idx_p, meta.subprogno,
-                                       set_timer_callback_state);
+               err = push_callback_call(env, insn, insn_idx, meta.subprogno,
+                                        set_timer_callback_state);
                break;
        case BPF_FUNC_find_vma:
-               err = __check_func_call(env, insn, insn_idx_p, meta.subprogno,
-                                       set_find_vma_callback_state);
+               err = push_callback_call(env, insn, insn_idx, meta.subprogno,
+                                        set_find_vma_callback_state);
                break;
        case BPF_FUNC_snprintf:
                err = check_bpf_snprintf_call(env, regs);
                break;
        case BPF_FUNC_loop:
                update_loop_inline_state(env, meta.subprogno);
-               err = __check_func_call(env, insn, insn_idx_p, meta.subprogno,
-                                       set_loop_callback_state);
+               /* Verifier relies on R1 value to determine if bpf_loop() iteration
+                * is finished, thus mark it precise.
+                */
+               err = mark_chain_precision(env, BPF_REG_1);
+               if (err)
+                       return err;
+               if (cur_func(env)->callback_depth < regs[BPF_REG_1].umax_value) {
+                       err = push_callback_call(env, insn, insn_idx, meta.subprogno,
+                                                set_loop_callback_state);
+               } else {
+                       cur_func(env)->callback_depth = 0;
+                       if (env->log.level & BPF_LOG_LEVEL2)
+                               verbose(env, "frame%d bpf_loop iteration limit reached\n",
+                                       env->cur_state->curframe);
+               }
                break;
        case BPF_FUNC_dynptr_from_mem:
                if (regs[BPF_REG_1].type != PTR_TO_MAP_VALUE) {
@@ -10322,8 +10421,8 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
                break;
        }
        case BPF_FUNC_user_ringbuf_drain:
-               err = __check_func_call(env, insn, insn_idx_p, meta.subprogno,
-                                       set_user_ringbuf_callback_state);
+               err = push_callback_call(env, insn, insn_idx, meta.subprogno,
+                                        set_user_ringbuf_callback_state);
                break;
        }
 
@@ -11211,7 +11310,7 @@ static bool is_bpf_graph_api_kfunc(u32 btf_id)
               btf_id == special_kfunc_list[KF_bpf_refcount_acquire_impl];
 }
 
-static bool is_callback_calling_kfunc(u32 btf_id)
+static bool is_sync_callback_calling_kfunc(u32 btf_id)
 {
        return btf_id == special_kfunc_list[KF_bpf_rbtree_add_impl];
 }
@@ -11963,6 +12062,21 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
                return -EACCES;
        }
 
+       /* Check the arguments */
+       err = check_kfunc_args(env, &meta, insn_idx);
+       if (err < 0)
+               return err;
+
+       if (meta.func_id == special_kfunc_list[KF_bpf_rbtree_add_impl]) {
+               err = push_callback_call(env, insn, insn_idx, meta.subprogno,
+                                        set_rbtree_add_callback_state);
+               if (err) {
+                       verbose(env, "kfunc %s#%d failed callback verification\n",
+                               func_name, meta.func_id);
+                       return err;
+               }
+       }
+
        rcu_lock = is_kfunc_bpf_rcu_read_lock(&meta);
        rcu_unlock = is_kfunc_bpf_rcu_read_unlock(&meta);
 
@@ -11998,10 +12112,6 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
                return -EINVAL;
        }
 
-       /* Check the arguments */
-       err = check_kfunc_args(env, &meta, insn_idx);
-       if (err < 0)
-               return err;
        /* In case of release function, we get register number of refcounted
         * PTR_TO_BTF_ID in bpf_kfunc_arg_meta, do the release now.
         */
@@ -12035,16 +12145,6 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
                }
        }
 
-       if (meta.func_id == special_kfunc_list[KF_bpf_rbtree_add_impl]) {
-               err = __check_func_call(env, insn, insn_idx_p, meta.subprogno,
-                                       set_rbtree_add_callback_state);
-               if (err) {
-                       verbose(env, "kfunc %s#%d failed callback verification\n",
-                               func_name, meta.func_id);
-                       return err;
-               }
-       }
-
        if (meta.func_id == special_kfunc_list[KF_bpf_throw]) {
                if (!bpf_jit_supports_exceptions()) {
                        verbose(env, "JIT does not support calling kfunc %s#%d\n",
@@ -15408,6 +15508,15 @@ static bool is_force_checkpoint(struct bpf_verifier_env *env, int insn_idx)
        return env->insn_aux_data[insn_idx].force_checkpoint;
 }
 
+static void mark_calls_callback(struct bpf_verifier_env *env, int idx)
+{
+       env->insn_aux_data[idx].calls_callback = true;
+}
+
+static bool calls_callback(struct bpf_verifier_env *env, int insn_idx)
+{
+       return env->insn_aux_data[insn_idx].calls_callback;
+}
 
 enum {
        DONE_EXPLORING = 0,
@@ -15521,6 +15630,21 @@ static int visit_insn(int t, struct bpf_verifier_env *env)
                         * async state will be pushed for further exploration.
                         */
                        mark_prune_point(env, t);
+               /* For functions that invoke callbacks it is not known how many times
+                * callback would be called. Verifier models callback calling functions
+                * by repeatedly visiting callback bodies and returning to origin call
+                * instruction.
+                * In order to stop such iteration verifier needs to identify when a
+                * state identical some state from a previous iteration is reached.
+                * Check below forces creation of checkpoint before callback calling
+                * instruction to allow search for such identical states.
+                */
+               if (is_sync_callback_calling_insn(insn)) {
+                       mark_calls_callback(env, t);
+                       mark_force_checkpoint(env, t);
+                       mark_prune_point(env, t);
+                       mark_jmp_point(env, t);
+               }
                if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) {
                        struct bpf_kfunc_call_arg_meta meta;
 
@@ -16990,10 +17114,16 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
                                }
                                goto skip_inf_loop_check;
                        }
+                       if (calls_callback(env, insn_idx)) {
+                               if (states_equal(env, &sl->state, cur, true))
+                                       goto hit;
+                               goto skip_inf_loop_check;
+                       }
                        /* attempt to detect infinite loop to avoid unnecessary doomed work */
                        if (states_maybe_looping(&sl->state, cur) &&
                            states_equal(env, &sl->state, cur, false) &&
-                           !iter_active_depths_differ(&sl->state, cur)) {
+                           !iter_active_depths_differ(&sl->state, cur) &&
+                           sl->state.callback_unroll_depth == cur->callback_unroll_depth) {
                                verbose_linfo(env, insn_idx, "; ");
                                verbose(env, "infinite loop detected at insn %d\n", insn_idx);
                                verbose(env, "cur state:");
index e85b5ad3e206987c1a4d82e81f0386627b01b81e..151bd3de59363a6b67a3a51274fe568bae4b30dd 100644 (file)
@@ -3497,7 +3497,8 @@ static int alloc_chain_hlocks(int req)
                size = chain_block_size(curr);
                if (likely(size >= req)) {
                        del_chain_block(0, size, chain_block_next(curr));
-                       add_chain_block(curr + req, size - req);
+                       if (size > req)
+                               add_chain_block(curr + req, size - req);
                        return curr;
                }
        }
index de7d11cf4c6356deccc37f180fa992dbe4d4c7b0..8ff6824a100539a7894db06edf342c3c362099b8 100644 (file)
@@ -409,7 +409,7 @@ size_t copy_page_to_iter_nofault(struct page *page, unsigned offset, size_t byte
                void *kaddr = kmap_local_page(page);
                size_t n = min(bytes, (size_t)PAGE_SIZE - offset);
 
-               n = iterate_and_advance(i, bytes, kaddr,
+               n = iterate_and_advance(i, n, kaddr + offset,
                                        copy_to_user_iter_nofault,
                                        memcpy_to_iter);
                kunmap_local(kaddr);
index 46f2f5d3d183b586e9936a92ed08ba08f6bf9755..ee2fd6a6af40728b3990773b464f362222be0621 100644 (file)
@@ -3107,7 +3107,7 @@ EXPORT_SYMBOL_GPL(folio_wait_writeback_killable);
  */
 void folio_wait_stable(struct folio *folio)
 {
-       if (folio_inode(folio)->i_sb->s_iflags & SB_I_STABLE_WRITES)
+       if (mapping_stable_writes(folio_mapping(folio)))
                folio_wait_writeback(folio);
 }
 EXPORT_SYMBOL_GPL(folio_wait_stable);
index af53f6d838ce9e5ec73570d31ac39b9f36b1c5c5..c879246be48d82f83072a48b19ec073df8efe27b 100644 (file)
@@ -10051,6 +10051,54 @@ void netif_tx_stop_all_queues(struct net_device *dev)
 }
 EXPORT_SYMBOL(netif_tx_stop_all_queues);
 
+static int netdev_do_alloc_pcpu_stats(struct net_device *dev)
+{
+       void __percpu *v;
+
+       /* Drivers implementing ndo_get_peer_dev must support tstat
+        * accounting, so that skb_do_redirect() can bump the dev's
+        * RX stats upon network namespace switch.
+        */
+       if (dev->netdev_ops->ndo_get_peer_dev &&
+           dev->pcpu_stat_type != NETDEV_PCPU_STAT_TSTATS)
+               return -EOPNOTSUPP;
+
+       switch (dev->pcpu_stat_type) {
+       case NETDEV_PCPU_STAT_NONE:
+               return 0;
+       case NETDEV_PCPU_STAT_LSTATS:
+               v = dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats);
+               break;
+       case NETDEV_PCPU_STAT_TSTATS:
+               v = dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
+               break;
+       case NETDEV_PCPU_STAT_DSTATS:
+               v = dev->dstats = netdev_alloc_pcpu_stats(struct pcpu_dstats);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return v ? 0 : -ENOMEM;
+}
+
+static void netdev_do_free_pcpu_stats(struct net_device *dev)
+{
+       switch (dev->pcpu_stat_type) {
+       case NETDEV_PCPU_STAT_NONE:
+               return;
+       case NETDEV_PCPU_STAT_LSTATS:
+               free_percpu(dev->lstats);
+               break;
+       case NETDEV_PCPU_STAT_TSTATS:
+               free_percpu(dev->tstats);
+               break;
+       case NETDEV_PCPU_STAT_DSTATS:
+               free_percpu(dev->dstats);
+               break;
+       }
+}
+
 /**
  * register_netdevice() - register a network device
  * @dev: device to register
@@ -10111,9 +10159,13 @@ int register_netdevice(struct net_device *dev)
                goto err_uninit;
        }
 
+       ret = netdev_do_alloc_pcpu_stats(dev);
+       if (ret)
+               goto err_uninit;
+
        ret = dev_index_reserve(net, dev->ifindex);
        if (ret < 0)
-               goto err_uninit;
+               goto err_free_pcpu;
        dev->ifindex = ret;
 
        /* Transfer changeable features to wanted_features and enable
@@ -10219,6 +10271,8 @@ err_uninit_notify:
        call_netdevice_notifiers(NETDEV_PRE_UNINIT, dev);
 err_ifindex_release:
        dev_index_release(net, dev->ifindex);
+err_free_pcpu:
+       netdev_do_free_pcpu_stats(dev);
 err_uninit:
        if (dev->netdev_ops->ndo_uninit)
                dev->netdev_ops->ndo_uninit(dev);
@@ -10471,6 +10525,7 @@ void netdev_run_todo(void)
                WARN_ON(rcu_access_pointer(dev->ip_ptr));
                WARN_ON(rcu_access_pointer(dev->ip6_ptr));
 
+               netdev_do_free_pcpu_stats(dev);
                if (dev->priv_destructor)
                        dev->priv_destructor(dev);
                if (dev->needs_free_netdev)
index 383f96b0a1c78026629ef4e6b8c172019d29d35c..7e4d7c3bcc849a9211eca4246cda7fa76af13c36 100644 (file)
@@ -81,6 +81,7 @@
 #include <net/xdp.h>
 #include <net/mptcp.h>
 #include <net/netfilter/nf_conntrack_bpf.h>
+#include <net/netkit.h>
 #include <linux/un.h>
 
 #include "dev.h"
@@ -2468,6 +2469,16 @@ static const struct bpf_func_proto bpf_clone_redirect_proto = {
 DEFINE_PER_CPU(struct bpf_redirect_info, bpf_redirect_info);
 EXPORT_PER_CPU_SYMBOL_GPL(bpf_redirect_info);
 
+static struct net_device *skb_get_peer_dev(struct net_device *dev)
+{
+       const struct net_device_ops *ops = dev->netdev_ops;
+
+       if (likely(ops->ndo_get_peer_dev))
+               return INDIRECT_CALL_1(ops->ndo_get_peer_dev,
+                                      netkit_peer_dev, dev);
+       return NULL;
+}
+
 int skb_do_redirect(struct sk_buff *skb)
 {
        struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
@@ -2481,17 +2492,15 @@ int skb_do_redirect(struct sk_buff *skb)
        if (unlikely(!dev))
                goto out_drop;
        if (flags & BPF_F_PEER) {
-               const struct net_device_ops *ops = dev->netdev_ops;
-
-               if (unlikely(!ops->ndo_get_peer_dev ||
-                            !skb_at_tc_ingress(skb)))
+               if (unlikely(!skb_at_tc_ingress(skb)))
                        goto out_drop;
-               dev = ops->ndo_get_peer_dev(dev);
+               dev = skb_get_peer_dev(dev);
                if (unlikely(!dev ||
                             !(dev->flags & IFF_UP) ||
                             net_eq(net, dev_net(dev))))
                        goto out_drop;
                skb->dev = dev;
+               dev_sw_netstats_rx_add(dev, skb->len);
                return -EAGAIN;
        }
        return flags & BPF_F_NEIGH ?
index f01aee832aab2f97c88808aafdf0f5b6ee0b57c6..7d0e7aaa71e0a1ff79f9e7c622f0f999e0139f18 100644 (file)
@@ -1481,5 +1481,6 @@ static void __exit inet_diag_exit(void)
 module_init(inet_diag_init);
 module_exit(inet_diag_exit);
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("INET/INET6: socket monitoring via SOCK_DIAG");
 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2 /* AF_INET */);
 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 10 /* AF_INET6 */);
index 63a40e4b678f59e29aa4bcbc8fe15116f1b4c568..fe2140c8375c8ebcc69880142c42655233007900 100644 (file)
@@ -257,5 +257,6 @@ static void __exit raw_diag_exit(void)
 module_init(raw_diag_init);
 module_exit(raw_diag_exit);
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("RAW socket monitoring via SOCK_DIAG");
 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-255 /* AF_INET - IPPROTO_RAW */);
 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 10-255 /* AF_INET6 - IPPROTO_RAW */);
index 3290a4442b4ac746a0ace35f909b95aa6cb9c06c..16615d107cf06f3da7988c8e3ab889456d74dd88 100644 (file)
@@ -780,7 +780,7 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow
                        goto reject_redirect;
        }
 
-       n = __ipv4_neigh_lookup(rt->dst.dev, new_gw);
+       n = __ipv4_neigh_lookup(rt->dst.dev, (__force u32)new_gw);
        if (!n)
                n = neigh_create(&arp_tbl, &new_gw, rt->dst.dev);
        if (!IS_ERR(n)) {
index 01b50fa791898831dc777bb3a64ad93ad57c1bfd..4cbe4b44425a6a5daf55abe348c167932ca07222 100644 (file)
@@ -247,4 +247,5 @@ static void __exit tcp_diag_exit(void)
 module_init(tcp_diag_init);
 module_exit(tcp_diag_exit);
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TCP socket monitoring via SOCK_DIAG");
 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-6 /* AF_INET - IPPROTO_TCP */);
index de3f2d31f510a9f1c41ec8c9a830df2e07d768fc..dc41a22ee80e829582349e8e644f204eff07df0e 100644 (file)
@@ -296,5 +296,6 @@ static void __exit udp_diag_exit(void)
 module_init(udp_diag_init);
 module_exit(udp_diag_exit);
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("UDP socket monitoring via SOCK_DIAG");
 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-17 /* AF_INET - IPPROTO_UDP */);
 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-136 /* AF_INET - IPPROTO_UDPLITE */);
index 8df1bdb647e299344110610688618ca74ec32026..5409c2ea3f5728a05999db17b7af1b1fb56f757e 100644 (file)
@@ -245,4 +245,5 @@ static void __exit mptcp_diag_exit(void)
 module_init(mptcp_diag_init);
 module_exit(mptcp_diag_exit);
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MPTCP socket monitoring via SOCK_DIAG");
 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-262 /* AF_INET - IPPROTO_MPTCP */);
index f6b200cb3c0668db7bf380d0868583440edca89b..9a7980e3309d6a2950688f8b69b08c15c288f601 100644 (file)
@@ -262,4 +262,5 @@ static void __exit packet_diag_exit(void)
 module_init(packet_diag_init);
 module_exit(packet_diag_exit);
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PACKET socket monitoring via SOCK_DIAG");
 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 17 /* AF_PACKET */);
index 981ca5b98bcb9096fa9bd6ee3561d2792a17782f..1d95f8bc769fa28eb203d6c4afc00815f47a230d 100644 (file)
@@ -73,6 +73,7 @@ static void rxrpc_destroy_client_conn_ids(struct rxrpc_local *local)
 static struct rxrpc_bundle *rxrpc_alloc_bundle(struct rxrpc_call *call,
                                               gfp_t gfp)
 {
+       static atomic_t rxrpc_bundle_id;
        struct rxrpc_bundle *bundle;
 
        bundle = kzalloc(sizeof(*bundle), gfp);
@@ -85,6 +86,7 @@ static struct rxrpc_bundle *rxrpc_alloc_bundle(struct rxrpc_call *call,
                bundle->upgrade         = test_bit(RXRPC_CALL_UPGRADE, &call->flags);
                bundle->service_id      = call->dest_srx.srx_service;
                bundle->security_level  = call->security_level;
+               bundle->debug_id        = atomic_inc_return(&rxrpc_bundle_id);
                refcount_set(&bundle->ref, 1);
                atomic_set(&bundle->active, 1);
                INIT_LIST_HEAD(&bundle->waiting_calls);
@@ -105,7 +107,8 @@ struct rxrpc_bundle *rxrpc_get_bundle(struct rxrpc_bundle *bundle,
 
 static void rxrpc_free_bundle(struct rxrpc_bundle *bundle)
 {
-       trace_rxrpc_bundle(bundle->debug_id, 1, rxrpc_bundle_free);
+       trace_rxrpc_bundle(bundle->debug_id, refcount_read(&bundle->ref),
+                          rxrpc_bundle_free);
        rxrpc_put_peer(bundle->peer, rxrpc_peer_put_bundle);
        key_put(bundle->key);
        kfree(bundle);
@@ -239,7 +242,6 @@ dont_reuse:
  */
 int rxrpc_look_up_bundle(struct rxrpc_call *call, gfp_t gfp)
 {
-       static atomic_t rxrpc_bundle_id;
        struct rxrpc_bundle *bundle, *candidate;
        struct rxrpc_local *local = call->local;
        struct rb_node *p, **pp, *parent;
@@ -306,7 +308,6 @@ int rxrpc_look_up_bundle(struct rxrpc_call *call, gfp_t gfp)
        }
 
        _debug("new bundle");
-       candidate->debug_id = atomic_inc_return(&rxrpc_bundle_id);
        rb_link_node(&candidate->local_node, parent, pp);
        rb_insert_color(&candidate->local_node, &local->client_bundles);
        call->bundle = rxrpc_get_bundle(candidate, rxrpc_bundle_get_client_call);
index 030d64f282f3704fbdb8d312554c440c9721d809..92495e73b8699185cf76c60aa88f62d77a29dd56 100644 (file)
@@ -643,12 +643,8 @@ static void rxrpc_complete_rtt_probe(struct rxrpc_call *call,
                        clear_bit(i + RXRPC_CALL_RTT_PEND_SHIFT, &call->rtt_avail);
                        smp_mb(); /* Read data before setting avail bit */
                        set_bit(i, &call->rtt_avail);
-                       if (type != rxrpc_rtt_rx_cancel)
-                               rxrpc_peer_add_rtt(call, type, i, acked_serial, ack_serial,
-                                                  sent_at, resp_time);
-                       else
-                               trace_rxrpc_rtt_rx(call, rxrpc_rtt_rx_cancel, i,
-                                                  orig_serial, acked_serial, 0, 0);
+                       rxrpc_peer_add_rtt(call, type, i, acked_serial, ack_serial,
+                                          sent_at, resp_time);
                        matched = true;
                }
 
@@ -801,28 +797,21 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
                           summary.ack_reason, nr_acks);
        rxrpc_inc_stat(call->rxnet, stat_rx_acks[ack.reason]);
 
-       switch (ack.reason) {
-       case RXRPC_ACK_PING_RESPONSE:
-               rxrpc_complete_rtt_probe(call, skb->tstamp, acked_serial, ack_serial,
-                                        rxrpc_rtt_rx_ping_response);
-               break;
-       case RXRPC_ACK_REQUESTED:
-               rxrpc_complete_rtt_probe(call, skb->tstamp, acked_serial, ack_serial,
-                                        rxrpc_rtt_rx_requested_ack);
-               break;
-       default:
-               if (acked_serial != 0)
+       if (acked_serial != 0) {
+               switch (ack.reason) {
+               case RXRPC_ACK_PING_RESPONSE:
                        rxrpc_complete_rtt_probe(call, skb->tstamp, acked_serial, ack_serial,
-                                                rxrpc_rtt_rx_cancel);
-               break;
-       }
-
-       if (ack.reason == RXRPC_ACK_PING) {
-               rxrpc_send_ACK(call, RXRPC_ACK_PING_RESPONSE, ack_serial,
-                              rxrpc_propose_ack_respond_to_ping);
-       } else if (sp->hdr.flags & RXRPC_REQUEST_ACK) {
-               rxrpc_send_ACK(call, RXRPC_ACK_REQUESTED, ack_serial,
-                              rxrpc_propose_ack_respond_to_ack);
+                                                rxrpc_rtt_rx_ping_response);
+                       break;
+               case RXRPC_ACK_REQUESTED:
+                       rxrpc_complete_rtt_probe(call, skb->tstamp, acked_serial, ack_serial,
+                                                rxrpc_rtt_rx_requested_ack);
+                       break;
+               default:
+                       rxrpc_complete_rtt_probe(call, skb->tstamp, acked_serial, ack_serial,
+                                                rxrpc_rtt_rx_other_ack);
+                       break;
+               }
        }
 
        /* If we get an EXCEEDS_WINDOW ACK from the server, it probably
@@ -835,7 +824,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
            rxrpc_is_client_call(call)) {
                rxrpc_set_call_completion(call, RXRPC_CALL_REMOTELY_ABORTED,
                                          0, -ENETRESET);
-               return;
+               goto send_response;
        }
 
        /* If we get an OUT_OF_SEQUENCE ACK from the server, that can also
@@ -849,7 +838,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
            rxrpc_is_client_call(call)) {
                rxrpc_set_call_completion(call, RXRPC_CALL_REMOTELY_ABORTED,
                                          0, -ENETRESET);
-               return;
+               goto send_response;
        }
 
        /* Discard any out-of-order or duplicate ACKs (outside lock). */
@@ -857,7 +846,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
                trace_rxrpc_rx_discard_ack(call->debug_id, ack_serial,
                                           first_soft_ack, call->acks_first_seq,
                                           prev_pkt, call->acks_prev_seq);
-               return;
+               goto send_response;
        }
 
        info.rxMTU = 0;
@@ -897,7 +886,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
        case RXRPC_CALL_SERVER_AWAIT_ACK:
                break;
        default:
-               return;
+               goto send_response;
        }
 
        if (before(hard_ack, call->acks_hard_ack) ||
@@ -909,7 +898,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
        if (after(hard_ack, call->acks_hard_ack)) {
                if (rxrpc_rotate_tx_window(call, hard_ack, &summary)) {
                        rxrpc_end_tx_phase(call, false, rxrpc_eproto_unexpected_ack);
-                       return;
+                       goto send_response;
                }
        }
 
@@ -927,6 +916,14 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
                                   rxrpc_propose_ack_ping_for_lost_reply);
 
        rxrpc_congestion_management(call, skb, &summary, acked_serial);
+
+send_response:
+       if (ack.reason == RXRPC_ACK_PING)
+               rxrpc_send_ACK(call, RXRPC_ACK_PING_RESPONSE, ack_serial,
+                              rxrpc_propose_ack_respond_to_ping);
+       else if (sp->hdr.flags & RXRPC_REQUEST_ACK)
+               rxrpc_send_ACK(call, RXRPC_ACK_REQUESTED, ack_serial,
+                              rxrpc_propose_ack_respond_to_ack);
 }
 
 /*
index c3d6b92dd3862fc79947456a8d2eb342509406d1..eb05131ff1dd671e734457e28b2d7b64eab07f85 100644 (file)
@@ -527,4 +527,5 @@ static void __exit sctp_diag_exit(void)
 module_init(sctp_diag_init);
 module_exit(sctp_diag_exit);
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SCTP socket monitoring via SOCK_DIAG");
 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-132);
index da97f946b79b00c82c8dbd496a2c4304dcd164b7..2a1388841951e4b6d447ab1f7b2dff4586ad4218 100644 (file)
@@ -598,8 +598,12 @@ static int smcr_clnt_conf_first_link(struct smc_sock *smc)
        struct smc_llc_qentry *qentry;
        int rc;
 
-       /* receive CONFIRM LINK request from server over RoCE fabric */
-       qentry = smc_llc_wait(link->lgr, NULL, SMC_LLC_WAIT_TIME,
+       /* Receive CONFIRM LINK request from server over RoCE fabric.
+        * Increasing the client's timeout by twice as much as the server's
+        * timeout by default can temporarily avoid decline messages of
+        * both sides crossing or colliding
+        */
+       qentry = smc_llc_wait(link->lgr, NULL, 2 * SMC_LLC_WAIT_TIME,
                              SMC_LLC_CONFIRM_LINK);
        if (!qentry) {
                struct smc_clc_msg_decline dclc;
index 7ff2152971a5b8a57ab746bf8ed2cc006b9546e9..a584613aca125620338d07344bb0911b15c0285a 100644 (file)
@@ -268,5 +268,6 @@ static void __exit smc_diag_exit(void)
 module_init(smc_diag_init);
 module_exit(smc_diag_exit);
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SMC socket monitoring via SOCK_DIAG");
 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 43 /* AF_SMC */);
 MODULE_ALIAS_GENL_FAMILY(SMCR_GENL_FAMILY_NAME);
index 73137f4aeb68f95677e34a3b2d5e823565024483..18733451c9e0c23a63d9400d408979aab46ecf19 100644 (file)
@@ -113,4 +113,5 @@ module_init(tipc_diag_init);
 module_exit(tipc_diag_exit);
 
 MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("TIPC socket monitoring via SOCK_DIAG");
 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, AF_TIPC);
index a78e8e7224091331e0ca86049a14d02139c056e6..316f761879624d688af85b60527868d5f0d00a49 100644 (file)
@@ -1232,11 +1232,14 @@ void tls_sw_splice_eof(struct socket *sock)
        lock_sock(sk);
 
 retry:
+       /* same checks as in tls_sw_push_pending_record() */
        rec = ctx->open_rec;
        if (!rec)
                goto unlock;
 
        msg_pl = &rec->msg_plaintext;
+       if (msg_pl->sg.size == 0)
+               goto unlock;
 
        /* Check the BPF advisor and perform transmission. */
        ret = bpf_exec_tx_verdict(msg_pl, sk, false, TLS_RECORD_TYPE_DATA,
index 616b55c5b89080c86f27b0d5b02fa9a6945e740e..bec09a3a1d44ce56d43e16583fdf3b417cce4033 100644 (file)
@@ -339,4 +339,5 @@ static void __exit unix_diag_exit(void)
 module_init(unix_diag_init);
 module_exit(unix_diag_exit);
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("UNIX socket monitoring via SOCK_DIAG");
 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 1 /* AF_LOCAL */);
index a2823b1c5e28b15d745e7a5b4a7c9de83698e70a..2e29994f92ffa2facee45cd53ec791034182508c 100644 (file)
@@ -174,5 +174,6 @@ static void __exit vsock_diag_exit(void)
 module_init(vsock_diag_init);
 module_exit(vsock_diag_exit);
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("VMware Virtual Sockets monitoring via SOCK_DIAG");
 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG,
                               40 /* AF_VSOCK */);
index 22b36c8143cfd5a96ccb7e1934880a98f16f179c..9f8955367275e2439d910f978fc3b2b7a1669978 100644 (file)
@@ -211,4 +211,5 @@ static void __exit xsk_diag_exit(void)
 module_init(xsk_diag_init);
 module_exit(xsk_diag_exit);
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("XDP socket monitoring via SOCK_DIAG");
 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, AF_XDP);
index 84f5fb7f1cecc2e5b99902b5734e4d30a1afeebe..d83ba5d8f3f49f6c5e7349fefff382c0264fafb8 100755 (executable)
@@ -97,8 +97,7 @@ my (@stack, $re, $dre, $sub, $x, $xs, $funcre, $min_stack);
                #   11160:       a7 fb ff 60             aghi   %r15,-160
                # or
                #  100092:       e3 f0 ff c8 ff 71       lay     %r15,-56(%r15)
-               $re = qr/.*(?:lay|ag?hi).*\%r15,-(([0-9]{2}|[3-9])[0-9]{2})
-                     (?:\(\%r15\))?$/ox;
+               $re = qr/.*(?:lay|ag?hi).*\%r15,-([0-9]+)(?:\(\%r15\))?$/o;
        } elsif ($arch eq 'sparc' || $arch eq 'sparc64') {
                # f0019d10:       9d e3 bf 90     save  %sp, -112, %sp
                $re = qr/.*save.*%sp, -(([0-9]{2}|[3-9])[0-9]{2}), %sp/o;
index 264eeb9c46a9f5ea9264829b41eda164e72d0d2e..318e2dad27e048c08fea615cef8654aa1fcb7d81 100644 (file)
@@ -1421,7 +1421,7 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
        if (error)
                goto setval_error;
 
-       if (new_val->addr_family == ADDR_FAMILY_IPV6) {
+       if (new_val->addr_family & ADDR_FAMILY_IPV6) {
                error = fprintf(nmfile, "\n[ipv6]\n");
                if (error < 0)
                        goto setval_error;
@@ -1455,14 +1455,18 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
        if (error < 0)
                goto setval_error;
 
-       error = fprintf(nmfile, "gateway=%s\n", (char *)new_val->gate_way);
-       if (error < 0)
-               goto setval_error;
-
-       error = fprintf(nmfile, "dns=%s\n", (char *)new_val->dns_addr);
-       if (error < 0)
-               goto setval_error;
+       /* we do not want ipv4 addresses in ipv6 section and vice versa */
+       if (is_ipv6 != is_ipv4((char *)new_val->gate_way)) {
+               error = fprintf(nmfile, "gateway=%s\n", (char *)new_val->gate_way);
+               if (error < 0)
+                       goto setval_error;
+       }
 
+       if (is_ipv6 != is_ipv4((char *)new_val->dns_addr)) {
+               error = fprintf(nmfile, "dns=%s\n", (char *)new_val->dns_addr);
+               if (error < 0)
+                       goto setval_error;
+       }
        fclose(nmfile);
        fclose(ifcfg_file);
 
index ae5a7a8249a208cf5782e8627ba4354959d38e2b..440a91b35823bfaa3cc6d8b38baa86362dbddf61 100755 (executable)
@@ -53,7 +53,7 @@
 #                       or "manual" if no boot-time protocol should be used)
 #
 # address1=ipaddr1/plen
-# address=ipaddr2/plen
+# address2=ipaddr2/plen
 #
 # gateway=gateway1;gateway2
 #
@@ -61,7 +61,7 @@
 #
 # [ipv6]
 # address1=ipaddr1/plen
-# address2=ipaddr1/plen
+# address2=ipaddr2/plen
 #
 # gateway=gateway1;gateway2
 #
index 64d139400db1034c83144cc93c0633990a90e82c..3110f84dd02944641276f76c3b87f79f3165022e 100644 (file)
@@ -18,4 +18,4 @@ CFLAGS_devlink:=$(call get_hdr_inc,_LINUX_DEVLINK_H_,devlink.h)
 CFLAGS_ethtool:=$(call get_hdr_inc,_LINUX_ETHTOOL_NETLINK_H_,ethtool_netlink.h)
 CFLAGS_handshake:=$(call get_hdr_inc,_LINUX_HANDSHAKE_H,handshake.h)
 CFLAGS_netdev:=$(call get_hdr_inc,_LINUX_NETDEV_H,netdev.h)
-CFLAGS_nfsd:=$(call get_hdr_inc,_LINUX_NFSD_H,nfsd.h)
+CFLAGS_nfsd:=$(call get_hdr_inc,_LINUX_NFSD_NETLINK_H,nfsd_netlink.h)
index bc5065bd99b2f05f4835da18d8a2a1a6fd28ce26..c12ca87ca2bb3f95f74d4854341a75edd5808822 100644 (file)
@@ -15,7 +15,7 @@
 /* Enums */
 static const char * const devlink_op_strmap[] = {
        [3] = "get",
-       [7] = "port-get",
+       // skip "port-get", duplicate reply value
        [DEVLINK_CMD_PORT_NEW] = "port-new",
        [13] = "sb-get",
        [17] = "sb-pool-get",
index c4003a83cd5d87dc1764f83f230b0aca5ce7a1a3..3bd6b928c14ff7c1e7e67e83ad19f2c7568db410 100755 (executable)
@@ -1505,6 +1505,12 @@ def put_op_name(family, cw):
     cw.block_start(line=f"static const char * const {map_name}[] =")
     for op_name, op in family.msgs.items():
         if op.rsp_value:
+            # Make sure we don't add duplicated entries, if multiple commands
+            # produce the same response in legacy families.
+            if family.rsp_by_value[op.rsp_value] != op:
+                cw.p(f'// skip "{op_name}", duplicate reply value')
+                continue
+
             if op.req_value == op.rsp_value:
                 cw.p(f'[{op.enum_name}] = "{op_name}",')
             else:
index 4a356a706785549bc248ed431f78a16a4c409f6c..40ad221e88811b0fc18993983ca91808f61fd739 100755 (executable)
@@ -4151,7 +4151,7 @@ def parseKernelLog(data):
                        elif(re.match('Enabling non-boot CPUs .*', msg)):
                                # start of first cpu resume
                                cpu_start = ktime
-                       elif(re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg)) \
+                       elif(re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg) \
                                or re.match('psci: CPU(?P<cpu>[0-9]*) killed.*', msg)):
                                # end of a cpu suspend, start of the next
                                m = re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg)
index b86cb1049497f39647566dcf03e39a96a69e2d23..587b9464822261df0482c3157c619b075c315b87 100644 (file)
@@ -85,7 +85,7 @@ int main(int argc, char **argv)
         */
        ret = open("/proc/sys/abi/sme_default_vector_length", O_RDONLY, 0);
        if (ret >= 0) {
-               ksft_test_result(fork_test(), "fork_test");
+               ksft_test_result(fork_test(), "fork_test\n");
 
        } else {
                ksft_print_msg("SME not supported\n");
index 6ee22c3b251ad0d6c9677fda5d46a65820d00d8b..518f143c5b0fec333c33d5c78ecad3cb1b0169dc 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "test_progs.h"
 #include "network_helpers.h"
+#include "netlink_helpers.h"
 #include "test_tc_neigh_fib.skel.h"
 #include "test_tc_neigh.skel.h"
 #include "test_tc_peer.skel.h"
@@ -110,11 +111,17 @@ static void netns_setup_namespaces_nofail(const char *verb)
        }
 }
 
+enum dev_mode {
+       MODE_VETH,
+       MODE_NETKIT,
+};
+
 struct netns_setup_result {
-       int ifindex_veth_src;
-       int ifindex_veth_src_fwd;
-       int ifindex_veth_dst;
-       int ifindex_veth_dst_fwd;
+       enum dev_mode dev_mode;
+       int ifindex_src;
+       int ifindex_src_fwd;
+       int ifindex_dst;
+       int ifindex_dst_fwd;
 };
 
 static int get_ifaddr(const char *name, char *ifaddr)
@@ -137,58 +144,110 @@ static int get_ifaddr(const char *name, char *ifaddr)
        return 0;
 }
 
+static int create_netkit(int mode, char *prim, char *peer)
+{
+       struct rtattr *linkinfo, *data, *peer_info;
+       struct rtnl_handle rth = { .fd = -1 };
+       const char *type = "netkit";
+       struct {
+               struct nlmsghdr n;
+               struct ifinfomsg i;
+               char buf[1024];
+       } req = {};
+       int err;
+
+       err = rtnl_open(&rth, 0);
+       if (!ASSERT_OK(err, "open_rtnetlink"))
+               return err;
+
+       memset(&req, 0, sizeof(req));
+       req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+       req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
+       req.n.nlmsg_type = RTM_NEWLINK;
+       req.i.ifi_family = AF_UNSPEC;
+
+       addattr_l(&req.n, sizeof(req), IFLA_IFNAME, prim, strlen(prim));
+       linkinfo = addattr_nest(&req.n, sizeof(req), IFLA_LINKINFO);
+       addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type, strlen(type));
+       data = addattr_nest(&req.n, sizeof(req), IFLA_INFO_DATA);
+       addattr32(&req.n, sizeof(req), IFLA_NETKIT_MODE, mode);
+       peer_info = addattr_nest(&req.n, sizeof(req), IFLA_NETKIT_PEER_INFO);
+       req.n.nlmsg_len += sizeof(struct ifinfomsg);
+       addattr_l(&req.n, sizeof(req), IFLA_IFNAME, peer, strlen(peer));
+       addattr_nest_end(&req.n, peer_info);
+       addattr_nest_end(&req.n, data);
+       addattr_nest_end(&req.n, linkinfo);
+
+       err = rtnl_talk(&rth, &req.n, NULL);
+       ASSERT_OK(err, "talk_rtnetlink");
+       rtnl_close(&rth);
+       return err;
+}
+
 static int netns_setup_links_and_routes(struct netns_setup_result *result)
 {
        struct nstoken *nstoken = NULL;
-       char veth_src_fwd_addr[IFADDR_STR_LEN+1] = {};
-
-       SYS(fail, "ip link add veth_src type veth peer name veth_src_fwd");
-       SYS(fail, "ip link add veth_dst type veth peer name veth_dst_fwd");
+       char src_fwd_addr[IFADDR_STR_LEN+1] = {};
+       int err;
 
-       SYS(fail, "ip link set veth_dst_fwd address " MAC_DST_FWD);
-       SYS(fail, "ip link set veth_dst address " MAC_DST);
+       if (result->dev_mode == MODE_VETH) {
+               SYS(fail, "ip link add src type veth peer name src_fwd");
+               SYS(fail, "ip link add dst type veth peer name dst_fwd");
+
+               SYS(fail, "ip link set dst_fwd address " MAC_DST_FWD);
+               SYS(fail, "ip link set dst address " MAC_DST);
+       } else if (result->dev_mode == MODE_NETKIT) {
+               err = create_netkit(NETKIT_L3, "src", "src_fwd");
+               if (!ASSERT_OK(err, "create_ifindex_src"))
+                       goto fail;
+               err = create_netkit(NETKIT_L3, "dst", "dst_fwd");
+               if (!ASSERT_OK(err, "create_ifindex_dst"))
+                       goto fail;
+       }
 
-       if (get_ifaddr("veth_src_fwd", veth_src_fwd_addr))
+       if (get_ifaddr("src_fwd", src_fwd_addr))
                goto fail;
 
-       result->ifindex_veth_src = if_nametoindex("veth_src");
-       if (!ASSERT_GT(result->ifindex_veth_src, 0, "ifindex_veth_src"))
+       result->ifindex_src = if_nametoindex("src");
+       if (!ASSERT_GT(result->ifindex_src, 0, "ifindex_src"))
                goto fail;
 
-       result->ifindex_veth_src_fwd = if_nametoindex("veth_src_fwd");
-       if (!ASSERT_GT(result->ifindex_veth_src_fwd, 0, "ifindex_veth_src_fwd"))
+       result->ifindex_src_fwd = if_nametoindex("src_fwd");
+       if (!ASSERT_GT(result->ifindex_src_fwd, 0, "ifindex_src_fwd"))
                goto fail;
 
-       result->ifindex_veth_dst = if_nametoindex("veth_dst");
-       if (!ASSERT_GT(result->ifindex_veth_dst, 0, "ifindex_veth_dst"))
+       result->ifindex_dst = if_nametoindex("dst");
+       if (!ASSERT_GT(result->ifindex_dst, 0, "ifindex_dst"))
                goto fail;
 
-       result->ifindex_veth_dst_fwd = if_nametoindex("veth_dst_fwd");
-       if (!ASSERT_GT(result->ifindex_veth_dst_fwd, 0, "ifindex_veth_dst_fwd"))
+       result->ifindex_dst_fwd = if_nametoindex("dst_fwd");
+       if (!ASSERT_GT(result->ifindex_dst_fwd, 0, "ifindex_dst_fwd"))
                goto fail;
 
-       SYS(fail, "ip link set veth_src netns " NS_SRC);
-       SYS(fail, "ip link set veth_src_fwd netns " NS_FWD);
-       SYS(fail, "ip link set veth_dst_fwd netns " NS_FWD);
-       SYS(fail, "ip link set veth_dst netns " NS_DST);
+       SYS(fail, "ip link set src netns " NS_SRC);
+       SYS(fail, "ip link set src_fwd netns " NS_FWD);
+       SYS(fail, "ip link set dst_fwd netns " NS_FWD);
+       SYS(fail, "ip link set dst netns " NS_DST);
 
        /** setup in 'src' namespace */
        nstoken = open_netns(NS_SRC);
        if (!ASSERT_OK_PTR(nstoken, "setns src"))
                goto fail;
 
-       SYS(fail, "ip addr add " IP4_SRC "/32 dev veth_src");
-       SYS(fail, "ip addr add " IP6_SRC "/128 dev veth_src nodad");
-       SYS(fail, "ip link set dev veth_src up");
+       SYS(fail, "ip addr add " IP4_SRC "/32 dev src");
+       SYS(fail, "ip addr add " IP6_SRC "/128 dev src nodad");
+       SYS(fail, "ip link set dev src up");
 
-       SYS(fail, "ip route add " IP4_DST "/32 dev veth_src scope global");
-       SYS(fail, "ip route add " IP4_NET "/16 dev veth_src scope global");
-       SYS(fail, "ip route add " IP6_DST "/128 dev veth_src scope global");
+       SYS(fail, "ip route add " IP4_DST "/32 dev src scope global");
+       SYS(fail, "ip route add " IP4_NET "/16 dev src scope global");
+       SYS(fail, "ip route add " IP6_DST "/128 dev src scope global");
 
-       SYS(fail, "ip neigh add " IP4_DST " dev veth_src lladdr %s",
-           veth_src_fwd_addr);
-       SYS(fail, "ip neigh add " IP6_DST " dev veth_src lladdr %s",
-           veth_src_fwd_addr);
+       if (result->dev_mode == MODE_VETH) {
+               SYS(fail, "ip neigh add " IP4_DST " dev src lladdr %s",
+                   src_fwd_addr);
+               SYS(fail, "ip neigh add " IP6_DST " dev src lladdr %s",
+                   src_fwd_addr);
+       }
 
        close_netns(nstoken);
 
@@ -201,15 +260,15 @@ static int netns_setup_links_and_routes(struct netns_setup_result *result)
         * needs v4 one in order to start ARP probing. IP4_NET route is added
         * to the endpoints so that the ARP processing will reply.
         */
-       SYS(fail, "ip addr add " IP4_SLL "/32 dev veth_src_fwd");
-       SYS(fail, "ip addr add " IP4_DLL "/32 dev veth_dst_fwd");
-       SYS(fail, "ip link set dev veth_src_fwd up");
-       SYS(fail, "ip link set dev veth_dst_fwd up");
+       SYS(fail, "ip addr add " IP4_SLL "/32 dev src_fwd");
+       SYS(fail, "ip addr add " IP4_DLL "/32 dev dst_fwd");
+       SYS(fail, "ip link set dev src_fwd up");
+       SYS(fail, "ip link set dev dst_fwd up");
 
-       SYS(fail, "ip route add " IP4_SRC "/32 dev veth_src_fwd scope global");
-       SYS(fail, "ip route add " IP6_SRC "/128 dev veth_src_fwd scope global");
-       SYS(fail, "ip route add " IP4_DST "/32 dev veth_dst_fwd scope global");
-       SYS(fail, "ip route add " IP6_DST "/128 dev veth_dst_fwd scope global");
+       SYS(fail, "ip route add " IP4_SRC "/32 dev src_fwd scope global");
+       SYS(fail, "ip route add " IP6_SRC "/128 dev src_fwd scope global");
+       SYS(fail, "ip route add " IP4_DST "/32 dev dst_fwd scope global");
+       SYS(fail, "ip route add " IP6_DST "/128 dev dst_fwd scope global");
 
        close_netns(nstoken);
 
@@ -218,16 +277,18 @@ static int netns_setup_links_and_routes(struct netns_setup_result *result)
        if (!ASSERT_OK_PTR(nstoken, "setns dst"))
                goto fail;
 
-       SYS(fail, "ip addr add " IP4_DST "/32 dev veth_dst");
-       SYS(fail, "ip addr add " IP6_DST "/128 dev veth_dst nodad");
-       SYS(fail, "ip link set dev veth_dst up");
+       SYS(fail, "ip addr add " IP4_DST "/32 dev dst");
+       SYS(fail, "ip addr add " IP6_DST "/128 dev dst nodad");
+       SYS(fail, "ip link set dev dst up");
 
-       SYS(fail, "ip route add " IP4_SRC "/32 dev veth_dst scope global");
-       SYS(fail, "ip route add " IP4_NET "/16 dev veth_dst scope global");
-       SYS(fail, "ip route add " IP6_SRC "/128 dev veth_dst scope global");
+       SYS(fail, "ip route add " IP4_SRC "/32 dev dst scope global");
+       SYS(fail, "ip route add " IP4_NET "/16 dev dst scope global");
+       SYS(fail, "ip route add " IP6_SRC "/128 dev dst scope global");
 
-       SYS(fail, "ip neigh add " IP4_SRC " dev veth_dst lladdr " MAC_DST_FWD);
-       SYS(fail, "ip neigh add " IP6_SRC " dev veth_dst lladdr " MAC_DST_FWD);
+       if (result->dev_mode == MODE_VETH) {
+               SYS(fail, "ip neigh add " IP4_SRC " dev dst lladdr " MAC_DST_FWD);
+               SYS(fail, "ip neigh add " IP6_SRC " dev dst lladdr " MAC_DST_FWD);
+       }
 
        close_netns(nstoken);
 
@@ -293,23 +354,23 @@ static int netns_load_bpf(const struct bpf_program *src_prog,
                          const struct bpf_program *chk_prog,
                          const struct netns_setup_result *setup_result)
 {
-       LIBBPF_OPTS(bpf_tc_hook, qdisc_veth_src_fwd);
-       LIBBPF_OPTS(bpf_tc_hook, qdisc_veth_dst_fwd);
+       LIBBPF_OPTS(bpf_tc_hook, qdisc_src_fwd);
+       LIBBPF_OPTS(bpf_tc_hook, qdisc_dst_fwd);
        int err;
 
-       /* tc qdisc add dev veth_src_fwd clsact */
-       QDISC_CLSACT_CREATE(&qdisc_veth_src_fwd, setup_result->ifindex_veth_src_fwd);
-       /* tc filter add dev veth_src_fwd ingress bpf da src_prog */
-       XGRESS_FILTER_ADD(&qdisc_veth_src_fwd, BPF_TC_INGRESS, src_prog, 0);
-       /* tc filter add dev veth_src_fwd egress bpf da chk_prog */
-       XGRESS_FILTER_ADD(&qdisc_veth_src_fwd, BPF_TC_EGRESS, chk_prog, 0);
+       /* tc qdisc add dev src_fwd clsact */
+       QDISC_CLSACT_CREATE(&qdisc_src_fwd, setup_result->ifindex_src_fwd);
+       /* tc filter add dev src_fwd ingress bpf da src_prog */
+       XGRESS_FILTER_ADD(&qdisc_src_fwd, BPF_TC_INGRESS, src_prog, 0);
+       /* tc filter add dev src_fwd egress bpf da chk_prog */
+       XGRESS_FILTER_ADD(&qdisc_src_fwd, BPF_TC_EGRESS, chk_prog, 0);
 
-       /* tc qdisc add dev veth_dst_fwd clsact */
-       QDISC_CLSACT_CREATE(&qdisc_veth_dst_fwd, setup_result->ifindex_veth_dst_fwd);
-       /* tc filter add dev veth_dst_fwd ingress bpf da dst_prog */
-       XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_INGRESS, dst_prog, 0);
-       /* tc filter add dev veth_dst_fwd egress bpf da chk_prog */
-       XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_EGRESS, chk_prog, 0);
+       /* tc qdisc add dev dst_fwd clsact */
+       QDISC_CLSACT_CREATE(&qdisc_dst_fwd, setup_result->ifindex_dst_fwd);
+       /* tc filter add dev dst_fwd ingress bpf da dst_prog */
+       XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_INGRESS, dst_prog, 0);
+       /* tc filter add dev dst_fwd egress bpf da chk_prog */
+       XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_EGRESS, chk_prog, 0);
 
        return 0;
 fail:
@@ -539,10 +600,10 @@ done:
 static int netns_load_dtime_bpf(struct test_tc_dtime *skel,
                                const struct netns_setup_result *setup_result)
 {
-       LIBBPF_OPTS(bpf_tc_hook, qdisc_veth_src_fwd);
-       LIBBPF_OPTS(bpf_tc_hook, qdisc_veth_dst_fwd);
-       LIBBPF_OPTS(bpf_tc_hook, qdisc_veth_src);
-       LIBBPF_OPTS(bpf_tc_hook, qdisc_veth_dst);
+       LIBBPF_OPTS(bpf_tc_hook, qdisc_src_fwd);
+       LIBBPF_OPTS(bpf_tc_hook, qdisc_dst_fwd);
+       LIBBPF_OPTS(bpf_tc_hook, qdisc_src);
+       LIBBPF_OPTS(bpf_tc_hook, qdisc_dst);
        struct nstoken *nstoken;
        int err;
 
@@ -550,58 +611,58 @@ static int netns_load_dtime_bpf(struct test_tc_dtime *skel,
        nstoken = open_netns(NS_SRC);
        if (!ASSERT_OK_PTR(nstoken, "setns " NS_SRC))
                return -1;
-       /* tc qdisc add dev veth_src clsact */
-       QDISC_CLSACT_CREATE(&qdisc_veth_src, setup_result->ifindex_veth_src);
-       /* tc filter add dev veth_src ingress bpf da ingress_host */
-       XGRESS_FILTER_ADD(&qdisc_veth_src, BPF_TC_INGRESS, skel->progs.ingress_host, 0);
-       /* tc filter add dev veth_src egress bpf da egress_host */
-       XGRESS_FILTER_ADD(&qdisc_veth_src, BPF_TC_EGRESS, skel->progs.egress_host, 0);
+       /* tc qdisc add dev src clsact */
+       QDISC_CLSACT_CREATE(&qdisc_src, setup_result->ifindex_src);
+       /* tc filter add dev src ingress bpf da ingress_host */
+       XGRESS_FILTER_ADD(&qdisc_src, BPF_TC_INGRESS, skel->progs.ingress_host, 0);
+       /* tc filter add dev src egress bpf da egress_host */
+       XGRESS_FILTER_ADD(&qdisc_src, BPF_TC_EGRESS, skel->progs.egress_host, 0);
        close_netns(nstoken);
 
        /* setup ns_dst tc progs */
        nstoken = open_netns(NS_DST);
        if (!ASSERT_OK_PTR(nstoken, "setns " NS_DST))
                return -1;
-       /* tc qdisc add dev veth_dst clsact */
-       QDISC_CLSACT_CREATE(&qdisc_veth_dst, setup_result->ifindex_veth_dst);
-       /* tc filter add dev veth_dst ingress bpf da ingress_host */
-       XGRESS_FILTER_ADD(&qdisc_veth_dst, BPF_TC_INGRESS, skel->progs.ingress_host, 0);
-       /* tc filter add dev veth_dst egress bpf da egress_host */
-       XGRESS_FILTER_ADD(&qdisc_veth_dst, BPF_TC_EGRESS, skel->progs.egress_host, 0);
+       /* tc qdisc add dev dst clsact */
+       QDISC_CLSACT_CREATE(&qdisc_dst, setup_result->ifindex_dst);
+       /* tc filter add dev dst ingress bpf da ingress_host */
+       XGRESS_FILTER_ADD(&qdisc_dst, BPF_TC_INGRESS, skel->progs.ingress_host, 0);
+       /* tc filter add dev dst egress bpf da egress_host */
+       XGRESS_FILTER_ADD(&qdisc_dst, BPF_TC_EGRESS, skel->progs.egress_host, 0);
        close_netns(nstoken);
 
        /* setup ns_fwd tc progs */
        nstoken = open_netns(NS_FWD);
        if (!ASSERT_OK_PTR(nstoken, "setns " NS_FWD))
                return -1;
-       /* tc qdisc add dev veth_dst_fwd clsact */
-       QDISC_CLSACT_CREATE(&qdisc_veth_dst_fwd, setup_result->ifindex_veth_dst_fwd);
-       /* tc filter add dev veth_dst_fwd ingress prio 100 bpf da ingress_fwdns_prio100 */
-       XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_INGRESS,
+       /* tc qdisc add dev dst_fwd clsact */
+       QDISC_CLSACT_CREATE(&qdisc_dst_fwd, setup_result->ifindex_dst_fwd);
+       /* tc filter add dev dst_fwd ingress prio 100 bpf da ingress_fwdns_prio100 */
+       XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_INGRESS,
                          skel->progs.ingress_fwdns_prio100, 100);
-       /* tc filter add dev veth_dst_fwd ingress prio 101 bpf da ingress_fwdns_prio101 */
-       XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_INGRESS,
+       /* tc filter add dev dst_fwd ingress prio 101 bpf da ingress_fwdns_prio101 */
+       XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_INGRESS,
                          skel->progs.ingress_fwdns_prio101, 101);
-       /* tc filter add dev veth_dst_fwd egress prio 100 bpf da egress_fwdns_prio100 */
-       XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_EGRESS,
+       /* tc filter add dev dst_fwd egress prio 100 bpf da egress_fwdns_prio100 */
+       XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_EGRESS,
                          skel->progs.egress_fwdns_prio100, 100);
-       /* tc filter add dev veth_dst_fwd egress prio 101 bpf da egress_fwdns_prio101 */
-       XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_EGRESS,
+       /* tc filter add dev dst_fwd egress prio 101 bpf da egress_fwdns_prio101 */
+       XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_EGRESS,
                          skel->progs.egress_fwdns_prio101, 101);
 
-       /* tc qdisc add dev veth_src_fwd clsact */
-       QDISC_CLSACT_CREATE(&qdisc_veth_src_fwd, setup_result->ifindex_veth_src_fwd);
-       /* tc filter add dev veth_src_fwd ingress prio 100 bpf da ingress_fwdns_prio100 */
-       XGRESS_FILTER_ADD(&qdisc_veth_src_fwd, BPF_TC_INGRESS,
+       /* tc qdisc add dev src_fwd clsact */
+       QDISC_CLSACT_CREATE(&qdisc_src_fwd, setup_result->ifindex_src_fwd);
+       /* tc filter add dev src_fwd ingress prio 100 bpf da ingress_fwdns_prio100 */
+       XGRESS_FILTER_ADD(&qdisc_src_fwd, BPF_TC_INGRESS,
                          skel->progs.ingress_fwdns_prio100, 100);
-       /* tc filter add dev veth_src_fwd ingress prio 101 bpf da ingress_fwdns_prio101 */
-       XGRESS_FILTER_ADD(&qdisc_veth_src_fwd, BPF_TC_INGRESS,
+       /* tc filter add dev src_fwd ingress prio 101 bpf da ingress_fwdns_prio101 */
+       XGRESS_FILTER_ADD(&qdisc_src_fwd, BPF_TC_INGRESS,
                          skel->progs.ingress_fwdns_prio101, 101);
-       /* tc filter add dev veth_src_fwd egress prio 100 bpf da egress_fwdns_prio100 */
-       XGRESS_FILTER_ADD(&qdisc_veth_src_fwd, BPF_TC_EGRESS,
+       /* tc filter add dev src_fwd egress prio 100 bpf da egress_fwdns_prio100 */
+       XGRESS_FILTER_ADD(&qdisc_src_fwd, BPF_TC_EGRESS,
                          skel->progs.egress_fwdns_prio100, 100);
-       /* tc filter add dev veth_src_fwd egress prio 101 bpf da egress_fwdns_prio101 */
-       XGRESS_FILTER_ADD(&qdisc_veth_src_fwd, BPF_TC_EGRESS,
+       /* tc filter add dev src_fwd egress prio 101 bpf da egress_fwdns_prio101 */
+       XGRESS_FILTER_ADD(&qdisc_src_fwd, BPF_TC_EGRESS,
                          skel->progs.egress_fwdns_prio101, 101);
        close_netns(nstoken);
        return 0;
@@ -777,8 +838,8 @@ static void test_tc_redirect_dtime(struct netns_setup_result *setup_result)
        if (!ASSERT_OK_PTR(skel, "test_tc_dtime__open"))
                return;
 
-       skel->rodata->IFINDEX_SRC = setup_result->ifindex_veth_src_fwd;
-       skel->rodata->IFINDEX_DST = setup_result->ifindex_veth_dst_fwd;
+       skel->rodata->IFINDEX_SRC = setup_result->ifindex_src_fwd;
+       skel->rodata->IFINDEX_DST = setup_result->ifindex_dst_fwd;
 
        err = test_tc_dtime__load(skel);
        if (!ASSERT_OK(err, "test_tc_dtime__load"))
@@ -868,8 +929,8 @@ static void test_tc_redirect_neigh(struct netns_setup_result *setup_result)
        if (!ASSERT_OK_PTR(skel, "test_tc_neigh__open"))
                goto done;
 
-       skel->rodata->IFINDEX_SRC = setup_result->ifindex_veth_src_fwd;
-       skel->rodata->IFINDEX_DST = setup_result->ifindex_veth_dst_fwd;
+       skel->rodata->IFINDEX_SRC = setup_result->ifindex_src_fwd;
+       skel->rodata->IFINDEX_DST = setup_result->ifindex_dst_fwd;
 
        err = test_tc_neigh__load(skel);
        if (!ASSERT_OK(err, "test_tc_neigh__load"))
@@ -904,8 +965,8 @@ static void test_tc_redirect_peer(struct netns_setup_result *setup_result)
        if (!ASSERT_OK_PTR(skel, "test_tc_peer__open"))
                goto done;
 
-       skel->rodata->IFINDEX_SRC = setup_result->ifindex_veth_src_fwd;
-       skel->rodata->IFINDEX_DST = setup_result->ifindex_veth_dst_fwd;
+       skel->rodata->IFINDEX_SRC = setup_result->ifindex_src_fwd;
+       skel->rodata->IFINDEX_DST = setup_result->ifindex_dst_fwd;
 
        err = test_tc_peer__load(skel);
        if (!ASSERT_OK(err, "test_tc_peer__load"))
@@ -996,7 +1057,7 @@ static int tun_relay_loop(int src_fd, int target_fd)
 static void test_tc_redirect_peer_l3(struct netns_setup_result *setup_result)
 {
        LIBBPF_OPTS(bpf_tc_hook, qdisc_tun_fwd);
-       LIBBPF_OPTS(bpf_tc_hook, qdisc_veth_dst_fwd);
+       LIBBPF_OPTS(bpf_tc_hook, qdisc_dst_fwd);
        struct test_tc_peer *skel = NULL;
        struct nstoken *nstoken = NULL;
        int err;
@@ -1045,7 +1106,7 @@ static void test_tc_redirect_peer_l3(struct netns_setup_result *setup_result)
                goto fail;
 
        skel->rodata->IFINDEX_SRC = ifindex;
-       skel->rodata->IFINDEX_DST = setup_result->ifindex_veth_dst_fwd;
+       skel->rodata->IFINDEX_DST = setup_result->ifindex_dst_fwd;
 
        err = test_tc_peer__load(skel);
        if (!ASSERT_OK(err, "test_tc_peer__load"))
@@ -1053,19 +1114,19 @@ static void test_tc_redirect_peer_l3(struct netns_setup_result *setup_result)
 
        /* Load "tc_src_l3" to the tun_fwd interface to redirect packets
         * towards dst, and "tc_dst" to redirect packets
-        * and "tc_chk" on veth_dst_fwd to drop non-redirected packets.
+        * and "tc_chk" on dst_fwd to drop non-redirected packets.
         */
        /* tc qdisc add dev tun_fwd clsact */
        QDISC_CLSACT_CREATE(&qdisc_tun_fwd, ifindex);
        /* tc filter add dev tun_fwd ingress bpf da tc_src_l3 */
        XGRESS_FILTER_ADD(&qdisc_tun_fwd, BPF_TC_INGRESS, skel->progs.tc_src_l3, 0);
 
-       /* tc qdisc add dev veth_dst_fwd clsact */
-       QDISC_CLSACT_CREATE(&qdisc_veth_dst_fwd, setup_result->ifindex_veth_dst_fwd);
-       /* tc filter add dev veth_dst_fwd ingress bpf da tc_dst_l3 */
-       XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_INGRESS, skel->progs.tc_dst_l3, 0);
-       /* tc filter add dev veth_dst_fwd egress bpf da tc_chk */
-       XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_EGRESS, skel->progs.tc_chk, 0);
+       /* tc qdisc add dev dst_fwd clsact */
+       QDISC_CLSACT_CREATE(&qdisc_dst_fwd, setup_result->ifindex_dst_fwd);
+       /* tc filter add dev dst_fwd ingress bpf da tc_dst_l3 */
+       XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_INGRESS, skel->progs.tc_dst_l3, 0);
+       /* tc filter add dev dst_fwd egress bpf da tc_chk */
+       XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_EGRESS, skel->progs.tc_chk, 0);
 
        /* Setup route and neigh tables */
        SYS(fail, "ip -netns " NS_SRC " addr add dev tun_src " IP4_TUN_SRC "/24");
@@ -1074,17 +1135,17 @@ static void test_tc_redirect_peer_l3(struct netns_setup_result *setup_result)
        SYS(fail, "ip -netns " NS_SRC " addr add dev tun_src " IP6_TUN_SRC "/64 nodad");
        SYS(fail, "ip -netns " NS_FWD " addr add dev tun_fwd " IP6_TUN_FWD "/64 nodad");
 
-       SYS(fail, "ip -netns " NS_SRC " route del " IP4_DST "/32 dev veth_src scope global");
+       SYS(fail, "ip -netns " NS_SRC " route del " IP4_DST "/32 dev src scope global");
        SYS(fail, "ip -netns " NS_SRC " route add " IP4_DST "/32 via " IP4_TUN_FWD
            " dev tun_src scope global");
-       SYS(fail, "ip -netns " NS_DST " route add " IP4_TUN_SRC "/32 dev veth_dst scope global");
-       SYS(fail, "ip -netns " NS_SRC " route del " IP6_DST "/128 dev veth_src scope global");
+       SYS(fail, "ip -netns " NS_DST " route add " IP4_TUN_SRC "/32 dev dst scope global");
+       SYS(fail, "ip -netns " NS_SRC " route del " IP6_DST "/128 dev src scope global");
        SYS(fail, "ip -netns " NS_SRC " route add " IP6_DST "/128 via " IP6_TUN_FWD
            " dev tun_src scope global");
-       SYS(fail, "ip -netns " NS_DST " route add " IP6_TUN_SRC "/128 dev veth_dst scope global");
+       SYS(fail, "ip -netns " NS_DST " route add " IP6_TUN_SRC "/128 dev dst scope global");
 
-       SYS(fail, "ip -netns " NS_DST " neigh add " IP4_TUN_SRC " dev veth_dst lladdr " MAC_DST_FWD);
-       SYS(fail, "ip -netns " NS_DST " neigh add " IP6_TUN_SRC " dev veth_dst lladdr " MAC_DST_FWD);
+       SYS(fail, "ip -netns " NS_DST " neigh add " IP4_TUN_SRC " dev dst lladdr " MAC_DST_FWD);
+       SYS(fail, "ip -netns " NS_DST " neigh add " IP6_TUN_SRC " dev dst lladdr " MAC_DST_FWD);
 
        if (!ASSERT_OK(set_forwarding(false), "disable forwarding"))
                goto fail;
@@ -1106,9 +1167,9 @@ fail:
                close_netns(nstoken);
 }
 
-#define RUN_TEST(name)                                                                      \
+#define RUN_TEST(name, mode)                                                                \
        ({                                                                                  \
-               struct netns_setup_result setup_result;                                     \
+               struct netns_setup_result setup_result = { .dev_mode = mode, };             \
                if (test__start_subtest(#name))                                             \
                        if (ASSERT_OK(netns_setup_namespaces("add"), "setup namespaces")) { \
                                if (ASSERT_OK(netns_setup_links_and_routes(&setup_result),  \
@@ -1122,11 +1183,13 @@ static void *test_tc_redirect_run_tests(void *arg)
 {
        netns_setup_namespaces_nofail("delete");
 
-       RUN_TEST(tc_redirect_peer);
-       RUN_TEST(tc_redirect_peer_l3);
-       RUN_TEST(tc_redirect_neigh);
-       RUN_TEST(tc_redirect_neigh_fib);
-       RUN_TEST(tc_redirect_dtime);
+       RUN_TEST(tc_redirect_peer, MODE_VETH);
+       RUN_TEST(tc_redirect_peer, MODE_NETKIT);
+       RUN_TEST(tc_redirect_peer_l3, MODE_VETH);
+       RUN_TEST(tc_redirect_peer_l3, MODE_NETKIT);
+       RUN_TEST(tc_redirect_neigh, MODE_VETH);
+       RUN_TEST(tc_redirect_neigh_fib, MODE_VETH);
+       RUN_TEST(tc_redirect_dtime, MODE_VETH);
        return NULL;
 }
 
index e5c61aa6604ace3fb1b70c22d353a065a4c9162d..5cfa7a6316b63c7ac3e2263ec99f3c9592e038f4 100644 (file)
@@ -31,6 +31,7 @@
 #include "verifier_helper_restricted.skel.h"
 #include "verifier_helper_value_access.skel.h"
 #include "verifier_int_ptr.skel.h"
+#include "verifier_iterating_callbacks.skel.h"
 #include "verifier_jeq_infer_not_null.skel.h"
 #include "verifier_ld_ind.skel.h"
 #include "verifier_ldsx.skel.h"
@@ -139,6 +140,7 @@ void test_verifier_helper_packet_access(void) { RUN(verifier_helper_packet_acces
 void test_verifier_helper_restricted(void)    { RUN(verifier_helper_restricted); }
 void test_verifier_helper_value_access(void)  { RUN(verifier_helper_value_access); }
 void test_verifier_int_ptr(void)              { RUN(verifier_int_ptr); }
+void test_verifier_iterating_callbacks(void)  { RUN(verifier_iterating_callbacks); }
 void test_verifier_jeq_infer_not_null(void)   { RUN(verifier_jeq_infer_not_null); }
 void test_verifier_ld_ind(void)               { RUN(verifier_ld_ind); }
 void test_verifier_ldsx(void)                  { RUN(verifier_ldsx); }
index 4ce76eb064c41c8b886fe7c1f430c54c4b845dd3..d461746fd3c1e7974b69de7e7621abc172b068fb 100644 (file)
@@ -15,13 +15,16 @@ static int empty_callback(__u32 index, void *data)
        return 0;
 }
 
+static int outer_loop(__u32 index, void *data)
+{
+       bpf_loop(nr_loops, empty_callback, NULL, 0);
+       __sync_add_and_fetch(&hits, nr_loops);
+       return 0;
+}
+
 SEC("fentry/" SYS_PREFIX "sys_getpgid")
 int benchmark(void *ctx)
 {
-       for (int i = 0; i < 1000; i++) {
-               bpf_loop(nr_loops, empty_callback, NULL, 0);
-
-               __sync_add_and_fetch(&hits, nr_loops);
-       }
+       bpf_loop(1000, outer_loop, NULL, 0);
        return 0;
 }
index 76d661b20e87d0db55973ef697e083d5aadf92e0..56c764df8196793155d69967ca1c4a28099d2540 100644 (file)
@@ -33,6 +33,7 @@ int underflow_prog(void *ctx)
        if (!p)
                return 0;
        bpf_for_each_map_elem(&array_map, cb1, &p, 0);
+       bpf_kfunc_call_test_release(p);
        return 0;
 }
 
index 4c39e920dac223c7f2e6e83e80bd083379bbe405..8c0ef2742208ae929293a0aa7f24269d52c7a94a 100644 (file)
@@ -171,6 +171,7 @@ int reject_with_rbtree_add_throw(void *ctx)
                return 0;
        bpf_spin_lock(&lock);
        bpf_rbtree_add(&rbtree, &f->node, rbless);
+       bpf_spin_unlock(&lock);
        return 0;
 }
 
@@ -214,6 +215,7 @@ int reject_with_cb_reference(void *ctx)
        if (!f)
                return 0;
        bpf_loop(5, subprog_cb_ref, NULL, 0);
+       bpf_obj_drop(f);
        return 0;
 }
 
index e02cfd3807469599eef5e1438ed8167e10b8f205..40df2cc26eaf9d83005756fa8c67fd2e20171847 100644 (file)
@@ -24,9 +24,11 @@ struct task_struct {};
 #define STACK_TABLE_EPOCH_SHIFT 20
 #define STROBE_MAX_STR_LEN 1
 #define STROBE_MAX_CFGS 32
+#define READ_MAP_VAR_PAYLOAD_CAP                                       \
+       ((1 + STROBE_MAX_MAP_ENTRIES * 2) * STROBE_MAX_STR_LEN)
 #define STROBE_MAX_PAYLOAD                                             \
        (STROBE_MAX_STRS * STROBE_MAX_STR_LEN +                         \
-       STROBE_MAX_MAPS * (1 + STROBE_MAX_MAP_ENTRIES * 2) * STROBE_MAX_STR_LEN)
+        STROBE_MAX_MAPS * READ_MAP_VAR_PAYLOAD_CAP)
 
 struct strobe_value_header {
        /*
@@ -355,7 +357,7 @@ static __always_inline uint64_t read_str_var(struct strobemeta_cfg *cfg,
                                             size_t idx, void *tls_base,
                                             struct strobe_value_generic *value,
                                             struct strobemeta_payload *data,
-                                            void *payload)
+                                            size_t off)
 {
        void *location;
        uint64_t len;
@@ -366,7 +368,7 @@ static __always_inline uint64_t read_str_var(struct strobemeta_cfg *cfg,
                return 0;
 
        bpf_probe_read_user(value, sizeof(struct strobe_value_generic), location);
-       len = bpf_probe_read_user_str(payload, STROBE_MAX_STR_LEN, value->ptr);
+       len = bpf_probe_read_user_str(&data->payload[off], STROBE_MAX_STR_LEN, value->ptr);
        /*
         * if bpf_probe_read_user_str returns error (<0), due to casting to
         * unsinged int, it will become big number, so next check is
@@ -378,14 +380,14 @@ static __always_inline uint64_t read_str_var(struct strobemeta_cfg *cfg,
                return 0;
 
        data->str_lens[idx] = len;
-       return len;
+       return off + len;
 }
 
-static __always_inline void *read_map_var(struct strobemeta_cfg *cfg,
-                                         size_t idx, void *tls_base,
-                                         struct strobe_value_generic *value,
-                                         struct strobemeta_payload *data,
-                                         void *payload)
+static __always_inline uint64_t read_map_var(struct strobemeta_cfg *cfg,
+                                            size_t idx, void *tls_base,
+                                            struct strobe_value_generic *value,
+                                            struct strobemeta_payload *data,
+                                            size_t off)
 {
        struct strobe_map_descr* descr = &data->map_descrs[idx];
        struct strobe_map_raw map;
@@ -397,11 +399,11 @@ static __always_inline void *read_map_var(struct strobemeta_cfg *cfg,
 
        location = calc_location(&cfg->map_locs[idx], tls_base);
        if (!location)
-               return payload;
+               return off;
 
        bpf_probe_read_user(value, sizeof(struct strobe_value_generic), location);
        if (bpf_probe_read_user(&map, sizeof(struct strobe_map_raw), value->ptr))
-               return payload;
+               return off;
 
        descr->id = map.id;
        descr->cnt = map.cnt;
@@ -410,10 +412,10 @@ static __always_inline void *read_map_var(struct strobemeta_cfg *cfg,
                data->req_meta_valid = 1;
        }
 
-       len = bpf_probe_read_user_str(payload, STROBE_MAX_STR_LEN, map.tag);
+       len = bpf_probe_read_user_str(&data->payload[off], STROBE_MAX_STR_LEN, map.tag);
        if (len <= STROBE_MAX_STR_LEN) {
                descr->tag_len = len;
-               payload += len;
+               off += len;
        }
 
 #ifdef NO_UNROLL
@@ -426,22 +428,22 @@ static __always_inline void *read_map_var(struct strobemeta_cfg *cfg,
                        break;
 
                descr->key_lens[i] = 0;
-               len = bpf_probe_read_user_str(payload, STROBE_MAX_STR_LEN,
+               len = bpf_probe_read_user_str(&data->payload[off], STROBE_MAX_STR_LEN,
                                              map.entries[i].key);
                if (len <= STROBE_MAX_STR_LEN) {
                        descr->key_lens[i] = len;
-                       payload += len;
+                       off += len;
                }
                descr->val_lens[i] = 0;
-               len = bpf_probe_read_user_str(payload, STROBE_MAX_STR_LEN,
+               len = bpf_probe_read_user_str(&data->payload[off], STROBE_MAX_STR_LEN,
                                              map.entries[i].val);
                if (len <= STROBE_MAX_STR_LEN) {
                        descr->val_lens[i] = len;
-                       payload += len;
+                       off += len;
                }
        }
 
-       return payload;
+       return off;
 }
 
 #ifdef USE_BPF_LOOP
@@ -455,14 +457,20 @@ struct read_var_ctx {
        struct strobemeta_payload *data;
        void *tls_base;
        struct strobemeta_cfg *cfg;
-       void *payload;
+       size_t payload_off;
        /* value gets mutated */
        struct strobe_value_generic *value;
        enum read_type type;
 };
 
-static int read_var_callback(__u32 index, struct read_var_ctx *ctx)
+static int read_var_callback(__u64 index, struct read_var_ctx *ctx)
 {
+       /* lose precision info for ctx->payload_off, verifier won't track
+        * double xor, barrier_var() is needed to force clang keep both xors.
+        */
+       ctx->payload_off ^= index;
+       barrier_var(ctx->payload_off);
+       ctx->payload_off ^= index;
        switch (ctx->type) {
        case READ_INT_VAR:
                if (index >= STROBE_MAX_INTS)
@@ -472,14 +480,18 @@ static int read_var_callback(__u32 index, struct read_var_ctx *ctx)
        case READ_MAP_VAR:
                if (index >= STROBE_MAX_MAPS)
                        return 1;
-               ctx->payload = read_map_var(ctx->cfg, index, ctx->tls_base,
-                                           ctx->value, ctx->data, ctx->payload);
+               if (ctx->payload_off > sizeof(ctx->data->payload) - READ_MAP_VAR_PAYLOAD_CAP)
+                       return 1;
+               ctx->payload_off = read_map_var(ctx->cfg, index, ctx->tls_base,
+                                               ctx->value, ctx->data, ctx->payload_off);
                break;
        case READ_STR_VAR:
                if (index >= STROBE_MAX_STRS)
                        return 1;
-               ctx->payload += read_str_var(ctx->cfg, index, ctx->tls_base,
-                                            ctx->value, ctx->data, ctx->payload);
+               if (ctx->payload_off > sizeof(ctx->data->payload) - STROBE_MAX_STR_LEN)
+                       return 1;
+               ctx->payload_off = read_str_var(ctx->cfg, index, ctx->tls_base,
+                                               ctx->value, ctx->data, ctx->payload_off);
                break;
        }
        return 0;
@@ -501,7 +513,8 @@ static void *read_strobe_meta(struct task_struct *task,
        pid_t pid = bpf_get_current_pid_tgid() >> 32;
        struct strobe_value_generic value = {0};
        struct strobemeta_cfg *cfg;
-       void *tls_base, *payload;
+       size_t payload_off;
+       void *tls_base;
 
        cfg = bpf_map_lookup_elem(&strobemeta_cfgs, &pid);
        if (!cfg)
@@ -509,7 +522,7 @@ static void *read_strobe_meta(struct task_struct *task,
 
        data->int_vals_set_mask = 0;
        data->req_meta_valid = 0;
-       payload = data->payload;
+       payload_off = 0;
        /*
         * we don't have struct task_struct definition, it should be:
         * tls_base = (void *)task->thread.fsbase;
@@ -522,7 +535,7 @@ static void *read_strobe_meta(struct task_struct *task,
                .tls_base = tls_base,
                .value = &value,
                .data = data,
-               .payload = payload,
+               .payload_off = 0,
        };
        int err;
 
@@ -540,6 +553,11 @@ static void *read_strobe_meta(struct task_struct *task,
        err = bpf_loop(STROBE_MAX_MAPS, read_var_callback, &ctx, 0);
        if (err != STROBE_MAX_MAPS)
                return NULL;
+
+       payload_off = ctx.payload_off;
+       /* this should not really happen, here only to satisfy verifer */
+       if (payload_off > sizeof(data->payload))
+               payload_off = sizeof(data->payload);
 #else
 #ifdef NO_UNROLL
 #pragma clang loop unroll(disable)
@@ -555,7 +573,7 @@ static void *read_strobe_meta(struct task_struct *task,
 #pragma unroll
 #endif /* NO_UNROLL */
        for (int i = 0; i < STROBE_MAX_STRS; ++i) {
-               payload += read_str_var(cfg, i, tls_base, &value, data, payload);
+               payload_off = read_str_var(cfg, i, tls_base, &value, data, payload_off);
        }
 #ifdef NO_UNROLL
 #pragma clang loop unroll(disable)
@@ -563,7 +581,7 @@ static void *read_strobe_meta(struct task_struct *task,
 #pragma unroll
 #endif /* NO_UNROLL */
        for (int i = 0; i < STROBE_MAX_MAPS; ++i) {
-               payload = read_map_var(cfg, i, tls_base, &value, data, payload);
+               payload_off = read_map_var(cfg, i, tls_base, &value, data, payload_off);
        }
 #endif /* USE_BPF_LOOP */
 
@@ -571,7 +589,7 @@ static void *read_strobe_meta(struct task_struct *task,
         * return pointer right after end of payload, so it's possible to
         * calculate exact amount of useful data that needs to be sent
         */
-       return payload;
+       return &data->payload[payload_off];
 }
 
 SEC("raw_tracepoint/kfree_skb")
diff --git a/tools/testing/selftests/bpf/progs/verifier_iterating_callbacks.c b/tools/testing/selftests/bpf/progs/verifier_iterating_callbacks.c
new file mode 100644 (file)
index 0000000..5905e03
--- /dev/null
@@ -0,0 +1,242 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include "bpf_misc.h"
+
+struct {
+       __uint(type, BPF_MAP_TYPE_ARRAY);
+       __uint(max_entries, 8);
+       __type(key, __u32);
+       __type(value, __u64);
+} map SEC(".maps");
+
+struct {
+       __uint(type, BPF_MAP_TYPE_USER_RINGBUF);
+       __uint(max_entries, 8);
+} ringbuf SEC(".maps");
+
+struct vm_area_struct;
+struct bpf_map;
+
+struct buf_context {
+       char *buf;
+};
+
+struct num_context {
+       __u64 i;
+       __u64 j;
+};
+
+__u8 choice_arr[2] = { 0, 1 };
+
+static int unsafe_on_2nd_iter_cb(__u32 idx, struct buf_context *ctx)
+{
+       if (idx == 0) {
+               ctx->buf = (char *)(0xDEAD);
+               return 0;
+       }
+
+       if (bpf_probe_read_user(ctx->buf, 8, (void *)(0xBADC0FFEE)))
+               return 1;
+
+       return 0;
+}
+
+SEC("?raw_tp")
+__failure __msg("R1 type=scalar expected=fp")
+int unsafe_on_2nd_iter(void *unused)
+{
+       char buf[4];
+       struct buf_context loop_ctx = { .buf = buf };
+
+       bpf_loop(100, unsafe_on_2nd_iter_cb, &loop_ctx, 0);
+       return 0;
+}
+
+static int unsafe_on_zero_iter_cb(__u32 idx, struct num_context *ctx)
+{
+       ctx->i = 0;
+       return 0;
+}
+
+SEC("?raw_tp")
+__failure __msg("invalid access to map value, value_size=2 off=32 size=1")
+int unsafe_on_zero_iter(void *unused)
+{
+       struct num_context loop_ctx = { .i = 32 };
+
+       bpf_loop(100, unsafe_on_zero_iter_cb, &loop_ctx, 0);
+       return choice_arr[loop_ctx.i];
+}
+
+static int widening_cb(__u32 idx, struct num_context *ctx)
+{
+       ++ctx->i;
+       return 0;
+}
+
+SEC("?raw_tp")
+__success
+int widening(void *unused)
+{
+       struct num_context loop_ctx = { .i = 0, .j = 1 };
+
+       bpf_loop(100, widening_cb, &loop_ctx, 0);
+       /* loop_ctx.j is not changed during callback iteration,
+        * verifier should not apply widening to it.
+        */
+       return choice_arr[loop_ctx.j];
+}
+
+static int loop_detection_cb(__u32 idx, struct num_context *ctx)
+{
+       for (;;) {}
+       return 0;
+}
+
+SEC("?raw_tp")
+__failure __msg("infinite loop detected")
+int loop_detection(void *unused)
+{
+       struct num_context loop_ctx = { .i = 0 };
+
+       bpf_loop(100, loop_detection_cb, &loop_ctx, 0);
+       return 0;
+}
+
+static __always_inline __u64 oob_state_machine(struct num_context *ctx)
+{
+       switch (ctx->i) {
+       case 0:
+               ctx->i = 1;
+               break;
+       case 1:
+               ctx->i = 32;
+               break;
+       }
+       return 0;
+}
+
+static __u64 for_each_map_elem_cb(struct bpf_map *map, __u32 *key, __u64 *val, void *data)
+{
+       return oob_state_machine(data);
+}
+
+SEC("?raw_tp")
+__failure __msg("invalid access to map value, value_size=2 off=32 size=1")
+int unsafe_for_each_map_elem(void *unused)
+{
+       struct num_context loop_ctx = { .i = 0 };
+
+       bpf_for_each_map_elem(&map, for_each_map_elem_cb, &loop_ctx, 0);
+       return choice_arr[loop_ctx.i];
+}
+
+static __u64 ringbuf_drain_cb(struct bpf_dynptr *dynptr, void *data)
+{
+       return oob_state_machine(data);
+}
+
+SEC("?raw_tp")
+__failure __msg("invalid access to map value, value_size=2 off=32 size=1")
+int unsafe_ringbuf_drain(void *unused)
+{
+       struct num_context loop_ctx = { .i = 0 };
+
+       bpf_user_ringbuf_drain(&ringbuf, ringbuf_drain_cb, &loop_ctx, 0);
+       return choice_arr[loop_ctx.i];
+}
+
+static __u64 find_vma_cb(struct task_struct *task, struct vm_area_struct *vma, void *data)
+{
+       return oob_state_machine(data);
+}
+
+SEC("?raw_tp")
+__failure __msg("invalid access to map value, value_size=2 off=32 size=1")
+int unsafe_find_vma(void *unused)
+{
+       struct task_struct *task = bpf_get_current_task_btf();
+       struct num_context loop_ctx = { .i = 0 };
+
+       bpf_find_vma(task, 0, find_vma_cb, &loop_ctx, 0);
+       return choice_arr[loop_ctx.i];
+}
+
+static int iter_limit_cb(__u32 idx, struct num_context *ctx)
+{
+       ctx->i++;
+       return 0;
+}
+
+SEC("?raw_tp")
+__success
+int bpf_loop_iter_limit_ok(void *unused)
+{
+       struct num_context ctx = { .i = 0 };
+
+       bpf_loop(1, iter_limit_cb, &ctx, 0);
+       return choice_arr[ctx.i];
+}
+
+SEC("?raw_tp")
+__failure __msg("invalid access to map value, value_size=2 off=2 size=1")
+int bpf_loop_iter_limit_overflow(void *unused)
+{
+       struct num_context ctx = { .i = 0 };
+
+       bpf_loop(2, iter_limit_cb, &ctx, 0);
+       return choice_arr[ctx.i];
+}
+
+static int iter_limit_level2a_cb(__u32 idx, struct num_context *ctx)
+{
+       ctx->i += 100;
+       return 0;
+}
+
+static int iter_limit_level2b_cb(__u32 idx, struct num_context *ctx)
+{
+       ctx->i += 10;
+       return 0;
+}
+
+static int iter_limit_level1_cb(__u32 idx, struct num_context *ctx)
+{
+       ctx->i += 1;
+       bpf_loop(1, iter_limit_level2a_cb, ctx, 0);
+       bpf_loop(1, iter_limit_level2b_cb, ctx, 0);
+       return 0;
+}
+
+/* Check that path visiting every callback function once had been
+ * reached by verifier. Variables 'ctx{1,2}i' below serve as flags,
+ * with each decimal digit corresponding to a callback visit marker.
+ */
+SEC("socket")
+__success __retval(111111)
+int bpf_loop_iter_limit_nested(void *unused)
+{
+       struct num_context ctx1 = { .i = 0 };
+       struct num_context ctx2 = { .i = 0 };
+       __u64 a, b, c;
+
+       bpf_loop(1, iter_limit_level1_cb, &ctx1, 0);
+       bpf_loop(1, iter_limit_level1_cb, &ctx2, 0);
+       a = ctx1.i;
+       b = ctx2.i;
+       /* Force 'ctx1.i' and 'ctx2.i' precise. */
+       c = choice_arr[(a + b) % 2];
+       /* This makes 'c' zero, but neither clang nor verifier know it. */
+       c /= 10;
+       /* Make sure that verifier does not visit 'impossible' states:
+        * enumerate all possible callback visit masks.
+        */
+       if (a != 0 && a != 1 && a != 11 && a != 101 && a != 111 &&
+           b != 0 && b != 1 && b != 11 && b != 101 && b != 111)
+               asm volatile ("r0 /= 0;" ::: "r0");
+       return 1000 * a + b + c;
+}
+
+char _license[] SEC("license") = "GPL";
index db6b3143338b613c8062ff519068abaa26f2234e..f61d623b1ce8dfe1c4b1355c036e2b74e71d7227 100644 (file)
@@ -119,15 +119,41 @@ __naked int global_subprog_result_precise(void)
 
 SEC("?raw_tp")
 __success __log_level(2)
+/* First simulated path does not include callback body,
+ * r1 and r4 are always precise for bpf_loop() calls.
+ */
+__msg("9: (85) call bpf_loop#181")
+__msg("mark_precise: frame0: last_idx 9 first_idx 9 subseq_idx -1")
+__msg("mark_precise: frame0: parent state regs=r4 stack=:")
+__msg("mark_precise: frame0: last_idx 8 first_idx 0 subseq_idx 9")
+__msg("mark_precise: frame0: regs=r4 stack= before 8: (b7) r4 = 0")
+__msg("mark_precise: frame0: last_idx 9 first_idx 9 subseq_idx -1")
+__msg("mark_precise: frame0: parent state regs=r1 stack=:")
+__msg("mark_precise: frame0: last_idx 8 first_idx 0 subseq_idx 9")
+__msg("mark_precise: frame0: regs=r1 stack= before 8: (b7) r4 = 0")
+__msg("mark_precise: frame0: regs=r1 stack= before 7: (b7) r3 = 0")
+__msg("mark_precise: frame0: regs=r1 stack= before 6: (bf) r2 = r8")
+__msg("mark_precise: frame0: regs=r1 stack= before 5: (bf) r1 = r6")
+__msg("mark_precise: frame0: regs=r6 stack= before 4: (b7) r6 = 3")
+/* r6 precision propagation */
 __msg("14: (0f) r1 += r6")
-__msg("mark_precise: frame0: last_idx 14 first_idx 10")
+__msg("mark_precise: frame0: last_idx 14 first_idx 9")
 __msg("mark_precise: frame0: regs=r6 stack= before 13: (bf) r1 = r7")
 __msg("mark_precise: frame0: regs=r6 stack= before 12: (27) r6 *= 4")
 __msg("mark_precise: frame0: regs=r6 stack= before 11: (25) if r6 > 0x3 goto pc+4")
 __msg("mark_precise: frame0: regs=r6 stack= before 10: (bf) r6 = r0")
-__msg("mark_precise: frame0: parent state regs=r0 stack=:")
-__msg("mark_precise: frame0: last_idx 18 first_idx 0")
-__msg("mark_precise: frame0: regs=r0 stack= before 18: (95) exit")
+__msg("mark_precise: frame0: regs=r0 stack= before 9: (85) call bpf_loop")
+/* State entering callback body popped from states stack */
+__msg("from 9 to 17: frame1:")
+__msg("17: frame1: R1=scalar() R2=0 R10=fp0 cb")
+__msg("17: (b7) r0 = 0")
+__msg("18: (95) exit")
+__msg("returning from callee:")
+__msg("to caller at 9:")
+__msg("frame 0: propagating r1,r4")
+__msg("mark_precise: frame0: last_idx 9 first_idx 9 subseq_idx -1")
+__msg("mark_precise: frame0: regs=r1,r4 stack= before 18: (95) exit")
+__msg("from 18 to 9: safe")
 __naked int callback_result_precise(void)
 {
        asm volatile (
@@ -233,20 +259,36 @@ __naked int parent_callee_saved_reg_precise_global(void)
 
 SEC("?raw_tp")
 __success __log_level(2)
+/* First simulated path does not include callback body */
 __msg("12: (0f) r1 += r6")
-__msg("mark_precise: frame0: last_idx 12 first_idx 10")
+__msg("mark_precise: frame0: last_idx 12 first_idx 9")
 __msg("mark_precise: frame0: regs=r6 stack= before 11: (bf) r1 = r7")
 __msg("mark_precise: frame0: regs=r6 stack= before 10: (27) r6 *= 4")
+__msg("mark_precise: frame0: regs=r6 stack= before 9: (85) call bpf_loop")
 __msg("mark_precise: frame0: parent state regs=r6 stack=:")
-__msg("mark_precise: frame0: last_idx 16 first_idx 0")
-__msg("mark_precise: frame0: regs=r6 stack= before 16: (95) exit")
-__msg("mark_precise: frame1: regs= stack= before 15: (b7) r0 = 0")
-__msg("mark_precise: frame1: regs= stack= before 9: (85) call bpf_loop#181")
+__msg("mark_precise: frame0: last_idx 8 first_idx 0 subseq_idx 9")
 __msg("mark_precise: frame0: regs=r6 stack= before 8: (b7) r4 = 0")
 __msg("mark_precise: frame0: regs=r6 stack= before 7: (b7) r3 = 0")
 __msg("mark_precise: frame0: regs=r6 stack= before 6: (bf) r2 = r8")
 __msg("mark_precise: frame0: regs=r6 stack= before 5: (b7) r1 = 1")
 __msg("mark_precise: frame0: regs=r6 stack= before 4: (b7) r6 = 3")
+/* State entering callback body popped from states stack */
+__msg("from 9 to 15: frame1:")
+__msg("15: frame1: R1=scalar() R2=0 R10=fp0 cb")
+__msg("15: (b7) r0 = 0")
+__msg("16: (95) exit")
+__msg("returning from callee:")
+__msg("to caller at 9:")
+/* r1, r4 are always precise for bpf_loop(),
+ * r6 was marked before backtracking to callback body.
+ */
+__msg("frame 0: propagating r1,r4,r6")
+__msg("mark_precise: frame0: last_idx 9 first_idx 9 subseq_idx -1")
+__msg("mark_precise: frame0: regs=r1,r4,r6 stack= before 16: (95) exit")
+__msg("mark_precise: frame1: regs= stack= before 15: (b7) r0 = 0")
+__msg("mark_precise: frame1: regs= stack= before 9: (85) call bpf_loop")
+__msg("mark_precise: frame0: parent state regs= stack=:")
+__msg("from 16 to 9: safe")
 __naked int parent_callee_saved_reg_precise_with_callback(void)
 {
        asm volatile (
@@ -373,22 +415,38 @@ __naked int parent_stack_slot_precise_global(void)
 
 SEC("?raw_tp")
 __success __log_level(2)
+/* First simulated path does not include callback body */
 __msg("14: (0f) r1 += r6")
-__msg("mark_precise: frame0: last_idx 14 first_idx 11")
+__msg("mark_precise: frame0: last_idx 14 first_idx 10")
 __msg("mark_precise: frame0: regs=r6 stack= before 13: (bf) r1 = r7")
 __msg("mark_precise: frame0: regs=r6 stack= before 12: (27) r6 *= 4")
 __msg("mark_precise: frame0: regs=r6 stack= before 11: (79) r6 = *(u64 *)(r10 -8)")
+__msg("mark_precise: frame0: regs= stack=-8 before 10: (85) call bpf_loop")
 __msg("mark_precise: frame0: parent state regs= stack=-8:")
-__msg("mark_precise: frame0: last_idx 18 first_idx 0")
-__msg("mark_precise: frame0: regs= stack=-8 before 18: (95) exit")
-__msg("mark_precise: frame1: regs= stack= before 17: (b7) r0 = 0")
-__msg("mark_precise: frame1: regs= stack= before 10: (85) call bpf_loop#181")
+__msg("mark_precise: frame0: last_idx 9 first_idx 0 subseq_idx 10")
 __msg("mark_precise: frame0: regs= stack=-8 before 9: (b7) r4 = 0")
 __msg("mark_precise: frame0: regs= stack=-8 before 8: (b7) r3 = 0")
 __msg("mark_precise: frame0: regs= stack=-8 before 7: (bf) r2 = r8")
 __msg("mark_precise: frame0: regs= stack=-8 before 6: (bf) r1 = r6")
 __msg("mark_precise: frame0: regs= stack=-8 before 5: (7b) *(u64 *)(r10 -8) = r6")
 __msg("mark_precise: frame0: regs=r6 stack= before 4: (b7) r6 = 3")
+/* State entering callback body popped from states stack */
+__msg("from 10 to 17: frame1:")
+__msg("17: frame1: R1=scalar() R2=0 R10=fp0 cb")
+__msg("17: (b7) r0 = 0")
+__msg("18: (95) exit")
+__msg("returning from callee:")
+__msg("to caller at 10:")
+/* r1, r4 are always precise for bpf_loop(),
+ * fp-8 was marked before backtracking to callback body.
+ */
+__msg("frame 0: propagating r1,r4,fp-8")
+__msg("mark_precise: frame0: last_idx 10 first_idx 10 subseq_idx -1")
+__msg("mark_precise: frame0: regs=r1,r4 stack=-8 before 18: (95) exit")
+__msg("mark_precise: frame1: regs= stack= before 17: (b7) r0 = 0")
+__msg("mark_precise: frame1: regs= stack= before 10: (85) call bpf_loop#181")
+__msg("mark_precise: frame0: parent state regs= stack=:")
+__msg("from 18 to 10: safe")
 __naked int parent_stack_slot_precise_with_callback(void)
 {
        asm volatile (
index e959336c7a7304be409ffac7d3a34f64538d5f74..80f620602d50ffc1e4598e6c5e45c5dfa4880412 100644 (file)
@@ -53,6 +53,8 @@
 #define DEFAULT_TTL 64
 #define MAX_ALLOWED_PORTS 8
 
+#define MAX_PACKET_OFF 0xffff
+
 #define swap(a, b) \
        do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0)
 
@@ -183,63 +185,76 @@ static __always_inline __u32 tcp_clock_ms(void)
 }
 
 struct tcpopt_context {
-       __u8 *ptr;
-       __u8 *end;
+       void *data;
        void *data_end;
        __be32 *tsecr;
        __u8 wscale;
        bool option_timestamp;
        bool option_sack;
+       __u32 off;
 };
 
-static int tscookie_tcpopt_parse(struct tcpopt_context *ctx)
+static __always_inline u8 *next(struct tcpopt_context *ctx, __u32 sz)
 {
-       __u8 opcode, opsize;
+       __u64 off = ctx->off;
+       __u8 *data;
 
-       if (ctx->ptr >= ctx->end)
-               return 1;
-       if (ctx->ptr >= ctx->data_end)
-               return 1;
+       /* Verifier forbids access to packet when offset exceeds MAX_PACKET_OFF */
+       if (off > MAX_PACKET_OFF - sz)
+               return NULL;
 
-       opcode = ctx->ptr[0];
+       data = ctx->data + off;
+       barrier_var(data);
+       if (data + sz >= ctx->data_end)
+               return NULL;
 
-       if (opcode == TCPOPT_EOL)
-               return 1;
-       if (opcode == TCPOPT_NOP) {
-               ++ctx->ptr;
-               return 0;
-       }
+       ctx->off += sz;
+       return data;
+}
 
-       if (ctx->ptr + 1 >= ctx->end)
-               return 1;
-       if (ctx->ptr + 1 >= ctx->data_end)
+static int tscookie_tcpopt_parse(struct tcpopt_context *ctx)
+{
+       __u8 *opcode, *opsize, *wscale, *tsecr;
+       __u32 off = ctx->off;
+
+       opcode = next(ctx, 1);
+       if (!opcode)
                return 1;
-       opsize = ctx->ptr[1];
-       if (opsize < 2)
+
+       if (*opcode == TCPOPT_EOL)
                return 1;
+       if (*opcode == TCPOPT_NOP)
+               return 0;
 
-       if (ctx->ptr + opsize > ctx->end)
+       opsize = next(ctx, 1);
+       if (!opsize || *opsize < 2)
                return 1;
 
-       switch (opcode) {
+       switch (*opcode) {
        case TCPOPT_WINDOW:
-               if (opsize == TCPOLEN_WINDOW && ctx->ptr + TCPOLEN_WINDOW <= ctx->data_end)
-                       ctx->wscale = ctx->ptr[2] < TCP_MAX_WSCALE ? ctx->ptr[2] : TCP_MAX_WSCALE;
+               wscale = next(ctx, 1);
+               if (!wscale)
+                       return 1;
+               if (*opsize == TCPOLEN_WINDOW)
+                       ctx->wscale = *wscale < TCP_MAX_WSCALE ? *wscale : TCP_MAX_WSCALE;
                break;
        case TCPOPT_TIMESTAMP:
-               if (opsize == TCPOLEN_TIMESTAMP && ctx->ptr + TCPOLEN_TIMESTAMP <= ctx->data_end) {
+               tsecr = next(ctx, 4);
+               if (!tsecr)
+                       return 1;
+               if (*opsize == TCPOLEN_TIMESTAMP) {
                        ctx->option_timestamp = true;
                        /* Client's tsval becomes our tsecr. */
-                       *ctx->tsecr = get_unaligned((__be32 *)(ctx->ptr + 2));
+                       *ctx->tsecr = get_unaligned((__be32 *)tsecr);
                }
                break;
        case TCPOPT_SACK_PERM:
-               if (opsize == TCPOLEN_SACK_PERM)
+               if (*opsize == TCPOLEN_SACK_PERM)
                        ctx->option_sack = true;
                break;
        }
 
-       ctx->ptr += opsize;
+       ctx->off = off + *opsize;
 
        return 0;
 }
@@ -256,16 +271,21 @@ static int tscookie_tcpopt_parse_batch(__u32 index, void *context)
 
 static __always_inline bool tscookie_init(struct tcphdr *tcp_header,
                                          __u16 tcp_len, __be32 *tsval,
-                                         __be32 *tsecr, void *data_end)
+                                         __be32 *tsecr, void *data, void *data_end)
 {
        struct tcpopt_context loop_ctx = {
-               .ptr = (__u8 *)(tcp_header + 1),
-               .end = (__u8 *)tcp_header + tcp_len,
+               .data = data,
                .data_end = data_end,
                .tsecr = tsecr,
                .wscale = TS_OPT_WSCALE_MASK,
                .option_timestamp = false,
                .option_sack = false,
+               /* Note: currently verifier would track .off as unbound scalar.
+                *       In case if verifier would at some point get smarter and
+                *       compute bounded value for this var, beware that it might
+                *       hinder bpf_loop() convergence validation.
+                */
+               .off = (__u8 *)(tcp_header + 1) - (__u8 *)data,
        };
        u32 cookie;
 
@@ -635,7 +655,7 @@ static __always_inline int syncookie_handle_syn(struct header_pointers *hdr,
        cookie = (__u32)value;
 
        if (tscookie_init((void *)hdr->tcp, hdr->tcp_len,
-                         &tsopt_buf[0], &tsopt_buf[1], data_end))
+                         &tsopt_buf[0], &tsopt_buf[1], data, data_end))
                tsopt = tsopt_buf;
 
        /* Check that there is enough space for a SYNACK. It also covers
index 5f2b3f6c0d74991372726d3c8b5f1a28c3d9d27e..38be9706c45f18e410d12694a43696c09a47c211 100755 (executable)
@@ -859,7 +859,7 @@ kci_test_gretap()
 
 
        run_cmd ip -netns "$testns" addr add dev "$DEV_NS" 10.1.1.100/24
-       run_cmd ip -netns "$testns" link set dev $DEV_NS ups
+       run_cmd ip -netns "$testns" link set dev $DEV_NS up
        run_cmd ip -netns "$testns" link del "$DEV_NS"
 
        # test external mode
index 5b0e93f9996cb18cc390d33645132532ab6bb85c..01fa816868bc4c2bc4659663e0f7e15bc79090c3 100644 (file)
@@ -353,11 +353,12 @@ static void test_stream_msg_peek_server(const struct test_opts *opts)
 }
 
 #define SOCK_BUF_SIZE (2 * 1024 * 1024)
-#define MAX_MSG_SIZE (32 * 1024)
+#define MAX_MSG_PAGES 4
 
 static void test_seqpacket_msg_bounds_client(const struct test_opts *opts)
 {
        unsigned long curr_hash;
+       size_t max_msg_size;
        int page_size;
        int msg_count;
        int fd;
@@ -373,7 +374,8 @@ static void test_seqpacket_msg_bounds_client(const struct test_opts *opts)
 
        curr_hash = 0;
        page_size = getpagesize();
-       msg_count = SOCK_BUF_SIZE / MAX_MSG_SIZE;
+       max_msg_size = MAX_MSG_PAGES * page_size;
+       msg_count = SOCK_BUF_SIZE / max_msg_size;
 
        for (int i = 0; i < msg_count; i++) {
                size_t buf_size;
@@ -383,7 +385,7 @@ static void test_seqpacket_msg_bounds_client(const struct test_opts *opts)
                /* Use "small" buffers and "big" buffers. */
                if (i & 1)
                        buf_size = page_size +
-                                       (rand() % (MAX_MSG_SIZE - page_size));
+                                       (rand() % (max_msg_size - page_size));
                else
                        buf_size = 1 + (rand() % page_size);
 
@@ -429,7 +431,6 @@ static void test_seqpacket_msg_bounds_server(const struct test_opts *opts)
        unsigned long remote_hash;
        unsigned long curr_hash;
        int fd;
-       char buf[MAX_MSG_SIZE];
        struct msghdr msg = {0};
        struct iovec iov = {0};
 
@@ -457,8 +458,13 @@ static void test_seqpacket_msg_bounds_server(const struct test_opts *opts)
        control_writeln("SRVREADY");
        /* Wait, until peer sends whole data. */
        control_expectln("SENDDONE");
-       iov.iov_base = buf;
-       iov.iov_len = sizeof(buf);
+       iov.iov_len = MAX_MSG_PAGES * getpagesize();
+       iov.iov_base = malloc(iov.iov_len);
+       if (!iov.iov_base) {
+               perror("malloc");
+               exit(EXIT_FAILURE);
+       }
+
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
 
@@ -483,6 +489,7 @@ static void test_seqpacket_msg_bounds_server(const struct test_opts *opts)
                curr_hash += hash_djb2(msg.msg_iov[0].iov_base, recv_size);
        }
 
+       free(iov.iov_base);
        close(fd);
        remote_hash = control_readulong();