Cross-merge networking fixes after downstream PR. No conflicts. Adjacent changes: drivers/net/ethernet/stmicro/stmmac/common.h 38cc3c6dcc09 ("net: stmmac: protect updates of 64-bit statistics counters") fd5a6a71313e ("net: stmmac: est: Per Tx-queue error count for HLBF") c5c3e1bfc9e0 ("net: stmmac: Offload queueMaxSDU from tc-taprio") drivers/net/wireless/microchip/wilc1000/netdev.c c9013880284d ("wifi: fill in MODULE_DESCRIPTION()s for wilc1000") 328efda22af8 ("wifi: wilc1000: do not realloc workqueue everytime an interface is added") net/unix/garbage.c 11498715f266 ("af_unix: Remove io_uring code for GC.") 1279f9d9dec2 ("af_unix: Call kfree_skb() for dead unix_(sk)->oob_skb in GC.")
Unified · Split
| @@ -1,4 +1,4 @@ | ||
| 1 | −What: /sys/devices/.../hwmon/hwmon<i>/in0_input | |
| 1 | +What: /sys/bus/pci/drivers/i915/.../hwmon/hwmon<i>/in0_input | |
| 2 | 2 | Date: February 2023 |
| 3 | 3 | KernelVersion: 6.2 |
| 4 | 4 | Contact: intel-gfx@lists.freedesktop.org |
| @@ -6,7 +6,7 @@ Description: RO. Current Voltage in millivolt. · 1 unmodified line | ||
| 6 | 6 | |
| 7 | 7 | Only supported for particular Intel i915 graphics platforms. |
| 8 | 8 | |
| 9 | −What: /sys/devices/.../hwmon/hwmon<i>/power1_max | |
| 9 | +What: /sys/bus/pci/drivers/i915/.../hwmon/hwmon<i>/power1_max | |
| 10 | 10 | Date: February 2023 |
| 11 | 11 | KernelVersion: 6.2 |
| 12 | 12 | Contact: intel-gfx@lists.freedesktop.org |
| @@ -20,7 +20,7 @@ Description: RW. Card reactive sustained (PL1/Tau) power limit in microwatts. · 7 unmodified lines | ||
| 20 | 20 | |
| 21 | 21 | Only supported for particular Intel i915 graphics platforms. |
| 22 | 22 | |
| 23 | −What: /sys/devices/.../hwmon/hwmon<i>/power1_rated_max | |
| 23 | +What: /sys/bus/pci/drivers/i915/.../hwmon/hwmon<i>/power1_rated_max | |
| 24 | 24 | Date: February 2023 |
| 25 | 25 | KernelVersion: 6.2 |
| 26 | 26 | Contact: intel-gfx@lists.freedesktop.org |
| @@ -28,7 +28,7 @@ Description: RO. Card default power limit (default TDP setting). · 1 unmodified line | ||
| 28 | 28 | |
| 29 | 29 | Only supported for particular Intel i915 graphics platforms. |
| 30 | 30 | |
| 31 | −What: /sys/devices/.../hwmon/hwmon<i>/power1_max_interval | |
| 31 | +What: /sys/bus/pci/drivers/i915/.../hwmon/hwmon<i>/power1_max_interval | |
| 32 | 32 | Date: February 2023 |
| 33 | 33 | KernelVersion: 6.2 |
| 34 | 34 | Contact: intel-gfx@lists.freedesktop.org |
| @@ -37,7 +37,7 @@ Description: RW. Sustained power limit interval (Tau in PL1/Tau) in · 2 unmodified lines | ||
| 37 | 37 | |
| 38 | 38 | Only supported for particular Intel i915 graphics platforms. |
| 39 | 39 | |
| 40 | −What: /sys/devices/.../hwmon/hwmon<i>/power1_crit | |
| 40 | +What: /sys/bus/pci/drivers/i915/.../hwmon/hwmon<i>/power1_crit | |
| 41 | 41 | Date: February 2023 |
| 42 | 42 | KernelVersion: 6.2 |
| 43 | 43 | Contact: intel-gfx@lists.freedesktop.org |
| @@ -50,7 +50,7 @@ Description: RW. Card reactive critical (I1) power limit in microwatts. · 6 unmodified lines | ||
| 50 | 50 | |
| 51 | 51 | Only supported for particular Intel i915 graphics platforms. |
| 52 | 52 | |
| 53 | −What: /sys/devices/.../hwmon/hwmon<i>/curr1_crit | |
| 53 | +What: /sys/bus/pci/drivers/i915/.../hwmon/hwmon<i>/curr1_crit | |
| 54 | 54 | Date: February 2023 |
| 55 | 55 | KernelVersion: 6.2 |
| 56 | 56 | Contact: intel-gfx@lists.freedesktop.org |
| @@ -63,7 +63,7 @@ Description: RW. Card reactive critical (I1) power limit in milliamperes. · 6 unmodified lines | ||
| 63 | 63 | |
| 64 | 64 | Only supported for particular Intel i915 graphics platforms. |
| 65 | 65 | |
| 66 | −What: /sys/devices/.../hwmon/hwmon<i>/energy1_input | |
| 66 | +What: /sys/bus/pci/drivers/i915/.../hwmon/hwmon<i>/energy1_input | |
| 67 | 67 | Date: February 2023 |
| 68 | 68 | KernelVersion: 6.2 |
| 69 | 69 | Contact: intel-gfx@lists.freedesktop.org |
| @@ -1,4 +1,4 @@ | ||
| 1 | −What: /sys/devices/.../hwmon/hwmon<i>/power1_max | |
| 1 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/power1_max | |
| 2 | 2 | Date: September 2023 |
| 3 | 3 | KernelVersion: 6.5 |
| 4 | 4 | Contact: intel-xe@lists.freedesktop.org |
| @@ -12,7 +12,7 @@ Description: RW. Card reactive sustained (PL1) power limit in microwatts. · 7 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | Only supported for particular Intel xe graphics platforms. |
| 14 | 14 | |
| 15 | −What: /sys/devices/.../hwmon/hwmon<i>/power1_rated_max | |
| 15 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/power1_rated_max | |
| 16 | 16 | Date: September 2023 |
| 17 | 17 | KernelVersion: 6.5 |
| 18 | 18 | Contact: intel-xe@lists.freedesktop.org |
| @@ -20,7 +20,7 @@ Description: RO. Card default power limit (default TDP setting). · 1 unmodified line | ||
| 20 | 20 | |
| 21 | 21 | Only supported for particular Intel xe graphics platforms. |
| 22 | 22 | |
| 23 | −What: /sys/devices/.../hwmon/hwmon<i>/power1_crit | |
| 23 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/power1_crit | |
| 24 | 24 | Date: September 2023 |
| 25 | 25 | KernelVersion: 6.5 |
| 26 | 26 | Contact: intel-xe@lists.freedesktop.org |
| @@ -33,7 +33,7 @@ Description: RW. Card reactive critical (I1) power limit in microwatts. · 6 unmodified lines | ||
| 33 | 33 | |
| 34 | 34 | Only supported for particular Intel xe graphics platforms. |
| 35 | 35 | |
| 36 | −What: /sys/devices/.../hwmon/hwmon<i>/curr1_crit | |
| 36 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/curr1_crit | |
| 37 | 37 | Date: September 2023 |
| 38 | 38 | KernelVersion: 6.5 |
| 39 | 39 | Contact: intel-xe@lists.freedesktop.org |
| @@ -44,7 +44,7 @@ Description: RW. Card reactive critical (I1) power limit in milliamperes. · 4 unmodified lines | ||
| 44 | 44 | the operating frequency if the power averaged over a window |
| 45 | 45 | exceeds this limit. |
| 46 | 46 | |
| 47 | −What: /sys/devices/.../hwmon/hwmon<i>/in0_input | |
| 47 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/in0_input | |
| 48 | 48 | Date: September 2023 |
| 49 | 49 | KernelVersion: 6.5 |
| 50 | 50 | Contact: intel-xe@lists.freedesktop.org |
| @@ -52,7 +52,7 @@ Description: RO. Current Voltage in millivolt. · 1 unmodified line | ||
| 52 | 52 | |
| 53 | 53 | Only supported for particular Intel xe graphics platforms. |
| 54 | 54 | |
| 55 | −What: /sys/devices/.../hwmon/hwmon<i>/energy1_input | |
| 55 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/energy1_input | |
| 56 | 56 | Date: September 2023 |
| 57 | 57 | KernelVersion: 6.5 |
| 58 | 58 | Contact: intel-xe@lists.freedesktop.org |
| @@ -60,7 +60,7 @@ Description: RO. Energy input of device in microjoules. · 1 unmodified line | ||
| 60 | 60 | |
| 61 | 61 | Only supported for particular Intel xe graphics platforms. |
| 62 | 62 | |
| 63 | −What: /sys/devices/.../hwmon/hwmon<i>/power1_max_interval | |
| 63 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/power1_max_interval | |
| 64 | 64 | Date: October 2023 |
| 65 | 65 | KernelVersion: 6.6 |
| 66 | 66 | Contact: intel-xe@lists.freedesktop.org |
| @@ -22,6 +22,7 @@ properties: · 21 unmodified lines | ||
| 22 | 22 | - const: allwinner,sun6i-a31-spdif |
| 23 | 23 | - const: allwinner,sun8i-h3-spdif |
| 24 | 24 | - const: allwinner,sun50i-h6-spdif |
| 25 | + - const: allwinner,sun50i-h616-spdif | |
| 25 | 26 | - items: |
| 26 | 27 | - const: allwinner,sun8i-a83t-spdif |
| 27 | 28 | - const: allwinner,sun8i-h3-spdif |
| @@ -62,6 +63,8 @@ allOf: · 34 unmodified lines | ||
| 62 | 63 | enum: |
| 63 | 64 | - allwinner,sun6i-a31-spdif |
| 64 | 65 | - allwinner,sun8i-h3-spdif |
| 66 | + - allwinner,sun50i-h6-spdif | |
| 67 | + - allwinner,sun50i-h616-spdif | |
| 65 | 68 | |
| 66 | 69 | then: |
| 67 | 70 | required: |
| @@ -73,7 +76,7 @@ allOf: · 5 unmodified lines | ||
| 73 | 76 | contains: |
| 74 | 77 | enum: |
| 75 | 78 | - allwinner,sun8i-h3-spdif |
| 76 | − - allwinner,sun50i-h6-spdif | |
| 79 | + - allwinner,sun50i-h616-spdif | |
| 77 | 80 | |
| 78 | 81 | then: |
| 79 | 82 | properties: |
| @@ -448,17 +448,17 @@ Function-specific configfs interface · 447 unmodified lines | ||
| 448 | 448 | The function name to use when creating the function directory is "ncm". |
| 449 | 449 | The NCM function provides these attributes in its function directory: |
| 450 | 450 | |
| 451 | − =============== ================================================== | |
| 452 | − ifname network device interface name associated with this | |
| 453 | − function instance | |
| 454 | − qmult queue length multiplier for high and super speed | |
| 455 | − host_addr MAC address of host's end of this | |
| 456 | − Ethernet over USB link | |
| 457 | − dev_addr MAC address of device's end of this | |
| 458 | − Ethernet over USB link | |
| 459 | − max_segment_size Segment size required for P2P connections. This | |
| 460 | − will set MTU to (max_segment_size - 14 bytes) | |
| 461 | − =============== ================================================== | |
| 451 | + ======================= ================================================== | |
| 452 | + ifname network device interface name associated with this | |
| 453 | + function instance | |
| 454 | + qmult queue length multiplier for high and super speed | |
| 455 | + host_addr MAC address of host's end of this | |
| 456 | + Ethernet over USB link | |
| 457 | + dev_addr MAC address of device's end of this | |
| 458 | + Ethernet over USB link | |
| 459 | + max_segment_size Segment size required for P2P connections. This | |
| 460 | + will set MTU to 14 bytes | |
| 461 | + ======================= ================================================== | |
| 462 | 462 | |
| 463 | 463 | and after creating the functions/ncm.<instance name> they contain default |
| 464 | 464 | values: qmult is 5, dev_addr and host_addr are randomly selected. |
| @@ -4172,14 +4172,14 @@ F: drivers/firmware/broadcom/tee_bnxt_fw.c · 4171 unmodified lines | ||
| 4172 | 4172 | F: drivers/net/ethernet/broadcom/bnxt/ |
| 4173 | 4173 | F: include/linux/firmware/broadcom/tee_bnxt_fw.h |
| 4174 | 4174 | |
| 4175 | −BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER | |
| 4176 | −M: Arend van Spriel <aspriel@gmail.com> | |
| 4177 | −M: Franky Lin <franky.lin@broadcom.com> | |
| 4178 | −M: Hante Meuleman <hante.meuleman@broadcom.com> | |
| 4175 | +BROADCOM BRCM80211 IEEE802.11 WIRELESS DRIVERS | |
| 4176 | +M: Arend van Spriel <arend.vanspriel@broadcom.com> | |
| 4179 | 4177 | L: linux-wireless@vger.kernel.org |
| 4178 | +L: brcm80211@lists.linux.dev | |
| 4180 | 4179 | L: brcm80211-dev-list.pdl@broadcom.com |
| 4181 | 4180 | S: Supported |
| 4182 | 4181 | F: drivers/net/wireless/broadcom/brcm80211/ |
| 4182 | +F: include/linux/platform_data/brcmfmac.h | |
| 4183 | 4183 | |
| 4184 | 4184 | BROADCOM BRCMSTB GPIO DRIVER |
| 4185 | 4185 | M: Doug Berger <opendmb@gmail.com> |
| @@ -10094,7 +10094,7 @@ L: linux-i2c@vger.kernel.org · 5908 unmodified lines | ||
| 10094 | 10094 | S: Maintained |
| 10095 | 10095 | W: https://i2c.wiki.kernel.org/ |
| 10096 | 10096 | Q: https://patchwork.ozlabs.org/project/linux-i2c/list/ |
| 10097 | −T: git git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git | |
| 10097 | +T: git git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux.git | |
| 10098 | 10098 | F: Documentation/devicetree/bindings/i2c/ |
| 10099 | 10099 | F: drivers/i2c/algos/ |
| 10100 | 10100 | F: drivers/i2c/busses/ |
| @@ -11130,7 +11130,6 @@ S: Supported · 1029 unmodified lines | ||
| 11130 | 11130 | F: drivers/net/wireless/intel/iwlegacy/ |
| 11131 | 11131 | |
| 11132 | 11132 | INTEL WIRELESS WIFI LINK (iwlwifi) |
| 11133 | −M: Gregory Greenman <gregory.greenman@intel.com> | |
| 11134 | 11133 | M: Miri Korenblit <miriam.rachel.korenblit@intel.com> |
| 11135 | 11134 | L: linux-wireless@vger.kernel.org |
| 11136 | 11135 | S: Supported |
| @@ -16866,9 +16865,8 @@ F: Documentation/devicetree/bindings/pci/xilinx-versal-cpm.yaml · 5729 unmodified lines | ||
| 16866 | 16865 | F: drivers/pci/controller/pcie-xilinx-cpm.c |
| 16867 | 16866 | |
| 16868 | 16867 | PCI ENDPOINT SUBSYSTEM |
| 16869 | −M: Lorenzo Pieralisi <lpieralisi@kernel.org> | |
| 16868 | +M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> | |
| 16870 | 16869 | M: Krzysztof Wilczyński <kw@linux.com> |
| 16871 | −R: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> | |
| 16872 | 16870 | R: Kishon Vijay Abraham I <kishon@kernel.org> |
| 16873 | 16871 | L: linux-pci@vger.kernel.org |
| 16874 | 16872 | S: Supported |
| @@ -18444,7 +18442,7 @@ S: Supported · 1569 unmodified lines | ||
| 18444 | 18442 | F: drivers/infiniband/sw/rdmavt |
| 18445 | 18443 | |
| 18446 | 18444 | RDS - RELIABLE DATAGRAM SOCKETS |
| 18447 | −M: Santosh Shilimkar <santosh.shilimkar@oracle.com> | |
| 18445 | +M: Allison Henderson <allison.henderson@oracle.com> | |
| 18448 | 18446 | L: netdev@vger.kernel.org |
| 18449 | 18447 | L: linux-rdma@vger.kernel.org |
| 18450 | 18448 | L: rds-devel@oss.oracle.com (moderated for non-subscribers) |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | VERSION = 6 |
| 3 | 3 | PATCHLEVEL = 8 |
| 4 | 4 | SUBLEVEL = 0 |
| 5 | −EXTRAVERSION = -rc2 | |
| 5 | +EXTRAVERSION = -rc3 | |
| 6 | 6 | NAME = Hurr durr I'ma ninja sloth |
| 7 | 7 | |
| 8 | 8 | # *DOCUMENTATION* |
| @@ -195,7 +195,7 @@ vdso_prepare: prepare0 · 194 unmodified lines | ||
| 195 | 195 | include/generated/vdso-offsets.h arch/arm64/kernel/vdso/vdso.so |
| 196 | 196 | ifdef CONFIG_COMPAT_VDSO |
| 197 | 197 | $(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso32 \ |
| 198 | − include/generated/vdso32-offsets.h arch/arm64/kernel/vdso32/vdso.so | |
| 198 | + arch/arm64/kernel/vdso32/vdso.so | |
| 199 | 199 | endif |
| 200 | 200 | endif |
| 201 | 201 | |
| @@ -17,9 +17,6 @@ · 16 unmodified lines | ||
| 17 | 17 | #ifndef __ASSEMBLY__ |
| 18 | 18 | |
| 19 | 19 | #include <generated/vdso-offsets.h> |
| 20 | −#ifdef CONFIG_COMPAT_VDSO | |
| 21 | −#include <generated/vdso32-offsets.h> | |
| 22 | −#endif | |
| 23 | 20 | |
| 24 | 21 | #define VDSO_SYMBOL(base, name) \ |
| 25 | 22 | ({ \ |
| @@ -77,9 +77,9 @@ obj-$(CONFIG_UNWIND_PATCH_PAC_INTO_SCS) += patch-scs.o · 76 unmodified lines | ||
| 77 | 77 | # We need to prevent the SCS patching code from patching itself. Using |
| 78 | 78 | # -mbranch-protection=none here to avoid the patchable PAC opcodes from being |
| 79 | 79 | # generated triggers an issue with full LTO on Clang, which stops emitting PAC |
| 80 | −# instructions altogether. So instead, omit the unwind tables used by the | |
| 81 | −# patching code, so it will not be able to locate its own PAC instructions. | |
| 82 | −CFLAGS_patch-scs.o += -fno-asynchronous-unwind-tables -fno-unwind-tables | |
| 80 | +# instructions altogether. So disable LTO as well for the compilation unit. | |
| 81 | +CFLAGS_patch-scs.o += -mbranch-protection=none | |
| 82 | +CFLAGS_REMOVE_patch-scs.o += $(CC_FLAGS_LTO) | |
| 83 | 83 | |
| 84 | 84 | # Force dependency (vdso*-wrap.S includes vdso.so through incbin) |
| 85 | 85 | $(obj)/vdso-wrap.o: $(obj)/vdso/vdso.so |
| @@ -127,9 +127,6 @@ obj-vdso := $(c-obj-vdso) $(c-obj-vdso-gettimeofday) $(asm-obj-vdso) · 126 unmodified lines | ||
| 127 | 127 | targets += vdso.lds |
| 128 | 128 | CPPFLAGS_vdso.lds += -P -C -U$(ARCH) |
| 129 | 129 | |
| 130 | −include/generated/vdso32-offsets.h: $(obj)/vdso32.so.dbg FORCE | |
| 131 | − $(call if_changed,vdsosym) | |
| 132 | − | |
| 133 | 130 | # Strip rule for vdso.so |
| 134 | 131 | $(obj)/vdso.so: OBJCOPYFLAGS := -S |
| 135 | 132 | $(obj)/vdso.so: $(obj)/vdso32.so.dbg FORCE |
| @@ -166,9 +163,3 @@ quiet_cmd_vdsoas = AS32 $@ · 30 unmodified lines | ||
| 166 | 163 | |
| 167 | 164 | quiet_cmd_vdsomunge = MUNGE $@ |
| 168 | 165 | cmd_vdsomunge = $(obj)/$(munge) $< $@ |
| 169 | − | |
| 170 | −# Generate vDSO offsets using helper script (borrowed from the 64-bit vDSO) | |
| 171 | −gen-vdsosym := $(srctree)/$(src)/../vdso/gen_vdso_offsets.sh | |
| 172 | −quiet_cmd_vdsosym = VDSOSYM $@ | |
| 173 | −# The AArch64 nm should be able to read an AArch32 binary | |
| 174 | − cmd_vdsosym = $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@ | |
| @@ -12,6 +12,7 @@ config LOONGARCH · 11 unmodified lines | ||
| 12 | 12 | select ARCH_DISABLE_KASAN_INLINE |
| 13 | 13 | select ARCH_ENABLE_MEMORY_HOTPLUG |
| 14 | 14 | select ARCH_ENABLE_MEMORY_HOTREMOVE |
| 15 | + select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE | |
| 15 | 16 | select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI |
| 16 | 17 | select ARCH_HAS_CPU_FINALIZE_INIT |
| 17 | 18 | select ARCH_HAS_FORTIFY_SOURCE |
| @@ -99,6 +100,7 @@ config LOONGARCH · 81 unmodified lines | ||
| 99 | 100 | select HAVE_ARCH_KFENCE |
| 100 | 101 | select HAVE_ARCH_KGDB if PERF_EVENTS |
| 101 | 102 | select HAVE_ARCH_MMAP_RND_BITS if MMU |
| 103 | + select HAVE_ARCH_SECCOMP | |
| 102 | 104 | select HAVE_ARCH_SECCOMP_FILTER |
| 103 | 105 | select HAVE_ARCH_TRACEHOOK |
| 104 | 106 | select HAVE_ARCH_TRANSPARENT_HUGEPAGE |
| @@ -632,23 +634,6 @@ config RANDOMIZE_BASE_MAX_OFFSET · 527 unmodified lines | ||
| 632 | 634 | |
| 633 | 635 | This is limited by the size of the lower address memory, 256MB. |
| 634 | 636 | |
| 635 | −config SECCOMP | |
| 636 | − bool "Enable seccomp to safely compute untrusted bytecode" | |
| 637 | − depends on PROC_FS | |
| 638 | − default y | |
| 639 | − help | |
| 640 | − This kernel feature is useful for number crunching applications | |
| 641 | − that may need to compute untrusted bytecode during their | |
| 642 | − execution. By using pipes or other transports made available to | |
| 643 | − the process as file descriptors supporting the read/write | |
| 644 | − syscalls, it's possible to isolate those applications in | |
| 645 | − their own address space using seccomp. Once seccomp is | |
| 646 | − enabled via /proc/<pid>/seccomp, it cannot be disabled | |
| 647 | − and the task is only allowed to execute a few safe syscalls | |
| 648 | − defined by each seccomp mode. | |
| 649 | − | |
| 650 | − If unsure, say Y. Only embedded should say N here. | |
| 651 | − | |
| 652 | 637 | endmenu |
| 653 | 638 | |
| 654 | 639 | config ARCH_SELECT_MEMORY_MODEL |
| @@ -667,10 +652,6 @@ config ARCH_SPARSEMEM_ENABLE · 12 unmodified lines | ||
| 667 | 652 | or have huge holes in the physical address space for other reasons. |
| 668 | 653 | See <file:Documentation/mm/numa.rst> for more. |
| 669 | 654 | |
| 670 | −config ARCH_ENABLE_THP_MIGRATION | |
| 671 | − def_bool y | |
| 672 | − depends on TRANSPARENT_HUGEPAGE | |
| 673 | − | |
| 674 | 655 | config ARCH_MEMORY_PROBE |
| 675 | 656 | def_bool y |
| 676 | 657 | depends on MEMORY_HOTPLUG |
| @@ -32,8 +32,10 @@ static inline bool acpi_has_cpu_in_madt(void) · 31 unmodified lines | ||
| 32 | 32 | return true; |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | +#define MAX_CORE_PIC 256 | |
| 36 | + | |
| 35 | 37 | extern struct list_head acpi_wakeup_device_list; |
| 36 | −extern struct acpi_madt_core_pic acpi_core_pic[NR_CPUS]; | |
| 38 | +extern struct acpi_madt_core_pic acpi_core_pic[MAX_CORE_PIC]; | |
| 37 | 39 | |
| 38 | 40 | extern int __init parse_acpi_topology(void); |
| 39 | 41 | |
| @@ -29,11 +29,9 @@ int disabled_cpus; · 28 unmodified lines | ||
| 29 | 29 | |
| 30 | 30 | u64 acpi_saved_sp; |
| 31 | 31 | |
| 32 | −#define MAX_CORE_PIC 256 | |
| 33 | − | |
| 34 | 32 | #define PREFIX "ACPI: " |
| 35 | 33 | |
| 36 | −struct acpi_madt_core_pic acpi_core_pic[NR_CPUS]; | |
| 34 | +struct acpi_madt_core_pic acpi_core_pic[MAX_CORE_PIC]; | |
| 37 | 35 | |
| 38 | 36 | void __init __iomem * __acpi_map_table(unsigned long phys, unsigned long size) |
| 39 | 37 | { |
| @@ -44,6 +44,9 @@ void *kasan_mem_to_shadow(const void *addr) · 43 unmodified lines | ||
| 44 | 44 | unsigned long xrange = (maddr >> XRANGE_SHIFT) & 0xffff; |
| 45 | 45 | unsigned long offset = 0; |
| 46 | 46 | |
| 47 | + if (maddr >= FIXADDR_START) | |
| 48 | + return (void *)(kasan_early_shadow_page); | |
| 49 | + | |
| 47 | 50 | maddr &= XRANGE_SHADOW_MASK; |
| 48 | 51 | switch (xrange) { |
| 49 | 52 | case XKPRANGE_CC_SEG: |
| @@ -2,6 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | # Objects to go into the VDSO. |
| 3 | 3 | |
| 4 | 4 | KASAN_SANITIZE := n |
| 5 | +UBSAN_SANITIZE := n | |
| 5 | 6 | KCOV_INSTRUMENT := n |
| 6 | 7 | |
| 7 | 8 | # Include the generic Makefile to check the built vdso. |
| @@ -1287,20 +1287,20 @@ spapr_tce_platform_iommu_attach_dev(struct iommu_domain *platform_domain, · 1286 unmodified lines | ||
| 1287 | 1287 | struct iommu_domain *domain = iommu_get_domain_for_dev(dev); |
| 1288 | 1288 | struct iommu_group *grp = iommu_group_get(dev); |
| 1289 | 1289 | struct iommu_table_group *table_group; |
| 1290 | − int ret = -EINVAL; | |
| 1291 | 1290 | |
| 1292 | 1291 | /* At first attach the ownership is already set */ |
| 1293 | 1292 | if (!domain) |
| 1294 | 1293 | return 0; |
| 1295 | 1294 | |
| 1296 | − if (!grp) | |
| 1297 | − return -ENODEV; | |
| 1298 | − | |
| 1299 | 1295 | table_group = iommu_group_get_iommudata(grp); |
| 1300 | − ret = table_group->ops->take_ownership(table_group); | |
| 1296 | + /* | |
| 1297 | + * The domain being set to PLATFORM from earlier | |
| 1298 | + * BLOCKED. The table_group ownership has to be released. | |
| 1299 | + */ | |
| 1300 | + table_group->ops->release_ownership(table_group); | |
| 1301 | 1301 | iommu_group_put(grp); |
| 1302 | 1302 | |
| 1303 | − return ret; | |
| 1303 | + return 0; | |
| 1304 | 1304 | } |
| 1305 | 1305 | |
| 1306 | 1306 | static const struct iommu_domain_ops spapr_tce_platform_domain_ops = { |
| @@ -1312,13 +1312,32 @@ static struct iommu_domain spapr_tce_platform_domain = { · 5 unmodified lines | ||
| 1312 | 1312 | .ops = &spapr_tce_platform_domain_ops, |
| 1313 | 1313 | }; |
| 1314 | 1314 | |
| 1315 | −static struct iommu_domain spapr_tce_blocked_domain = { | |
| 1316 | − .type = IOMMU_DOMAIN_BLOCKED, | |
| 1315 | +static int | |
| 1316 | +spapr_tce_blocked_iommu_attach_dev(struct iommu_domain *platform_domain, | |
| 1317 | + struct device *dev) | |
| 1318 | +{ | |
| 1319 | + struct iommu_group *grp = iommu_group_get(dev); | |
| 1320 | + struct iommu_table_group *table_group; | |
| 1321 | + int ret = -EINVAL; | |
| 1322 | + | |
| 1317 | 1323 | /* |
| 1318 | 1324 | * FIXME: SPAPR mixes blocked and platform behaviors, the blocked domain |
| 1319 | 1325 | * also sets the dma_api ops |
| 1320 | 1326 | */ |
| 1321 | − .ops = &spapr_tce_platform_domain_ops, | |
| 1327 | + table_group = iommu_group_get_iommudata(grp); | |
| 1328 | + ret = table_group->ops->take_ownership(table_group); | |
| 1329 | + iommu_group_put(grp); | |
| 1330 | + | |
| 1331 | + return ret; | |
| 1332 | +} | |
| 1333 | + | |
| 1334 | +static const struct iommu_domain_ops spapr_tce_blocked_domain_ops = { | |
| 1335 | + .attach_dev = spapr_tce_blocked_iommu_attach_dev, | |
| 1336 | +}; | |
| 1337 | + | |
| 1338 | +static struct iommu_domain spapr_tce_blocked_domain = { | |
| 1339 | + .type = IOMMU_DOMAIN_BLOCKED, | |
| 1340 | + .ops = &spapr_tce_blocked_domain_ops, | |
| 1322 | 1341 | }; |
| 1323 | 1342 | |
| 1324 | 1343 | static bool spapr_tce_iommu_capable(struct device *dev, enum iommu_cap cap) |
| @@ -139,6 +139,33 @@ enum KVM_RISCV_ISA_EXT_ID { · 138 unmodified lines | ||
| 139 | 139 | KVM_RISCV_ISA_EXT_ZIHPM, |
| 140 | 140 | KVM_RISCV_ISA_EXT_SMSTATEEN, |
| 141 | 141 | KVM_RISCV_ISA_EXT_ZICOND, |
| 142 | + KVM_RISCV_ISA_EXT_ZBC, | |
| 143 | + KVM_RISCV_ISA_EXT_ZBKB, | |
| 144 | + KVM_RISCV_ISA_EXT_ZBKC, | |
| 145 | + KVM_RISCV_ISA_EXT_ZBKX, | |
| 146 | + KVM_RISCV_ISA_EXT_ZKND, | |
| 147 | + KVM_RISCV_ISA_EXT_ZKNE, | |
| 148 | + KVM_RISCV_ISA_EXT_ZKNH, | |
| 149 | + KVM_RISCV_ISA_EXT_ZKR, | |
| 150 | + KVM_RISCV_ISA_EXT_ZKSED, | |
| 151 | + KVM_RISCV_ISA_EXT_ZKSH, | |
| 152 | + KVM_RISCV_ISA_EXT_ZKT, | |
| 153 | + KVM_RISCV_ISA_EXT_ZVBB, | |
| 154 | + KVM_RISCV_ISA_EXT_ZVBC, | |
| 155 | + KVM_RISCV_ISA_EXT_ZVKB, | |
| 156 | + KVM_RISCV_ISA_EXT_ZVKG, | |
| 157 | + KVM_RISCV_ISA_EXT_ZVKNED, | |
| 158 | + KVM_RISCV_ISA_EXT_ZVKNHA, | |
| 159 | + KVM_RISCV_ISA_EXT_ZVKNHB, | |
| 160 | + KVM_RISCV_ISA_EXT_ZVKSED, | |
| 161 | + KVM_RISCV_ISA_EXT_ZVKSH, | |
| 162 | + KVM_RISCV_ISA_EXT_ZVKT, | |
| 163 | + KVM_RISCV_ISA_EXT_ZFH, | |
| 164 | + KVM_RISCV_ISA_EXT_ZFHMIN, | |
| 165 | + KVM_RISCV_ISA_EXT_ZIHINTNTL, | |
| 166 | + KVM_RISCV_ISA_EXT_ZVFH, | |
| 167 | + KVM_RISCV_ISA_EXT_ZVFHMIN, | |
| 168 | + KVM_RISCV_ISA_EXT_ZFA, | |
| 142 | 169 | KVM_RISCV_ISA_EXT_MAX, |
| 143 | 170 | }; |
| 144 | 171 | |
| @@ -42,15 +42,42 @@ static const unsigned long kvm_isa_ext_arr[] = { · 41 unmodified lines | ||
| 42 | 42 | KVM_ISA_EXT_ARR(SVPBMT), |
| 43 | 43 | KVM_ISA_EXT_ARR(ZBA), |
| 44 | 44 | KVM_ISA_EXT_ARR(ZBB), |
| 45 | + KVM_ISA_EXT_ARR(ZBC), | |
| 46 | + KVM_ISA_EXT_ARR(ZBKB), | |
| 47 | + KVM_ISA_EXT_ARR(ZBKC), | |
| 48 | + KVM_ISA_EXT_ARR(ZBKX), | |
| 45 | 49 | KVM_ISA_EXT_ARR(ZBS), |
| 50 | + KVM_ISA_EXT_ARR(ZFA), | |
| 51 | + KVM_ISA_EXT_ARR(ZFH), | |
| 52 | + KVM_ISA_EXT_ARR(ZFHMIN), | |
| 46 | 53 | KVM_ISA_EXT_ARR(ZICBOM), |
| 47 | 54 | KVM_ISA_EXT_ARR(ZICBOZ), |
| 48 | 55 | KVM_ISA_EXT_ARR(ZICNTR), |
| 49 | 56 | KVM_ISA_EXT_ARR(ZICOND), |
| 50 | 57 | KVM_ISA_EXT_ARR(ZICSR), |
| 51 | 58 | KVM_ISA_EXT_ARR(ZIFENCEI), |
| 59 | + KVM_ISA_EXT_ARR(ZIHINTNTL), | |
| 52 | 60 | KVM_ISA_EXT_ARR(ZIHINTPAUSE), |
| 53 | 61 | KVM_ISA_EXT_ARR(ZIHPM), |
| 62 | + KVM_ISA_EXT_ARR(ZKND), | |
| 63 | + KVM_ISA_EXT_ARR(ZKNE), | |
| 64 | + KVM_ISA_EXT_ARR(ZKNH), | |
| 65 | + KVM_ISA_EXT_ARR(ZKR), | |
| 66 | + KVM_ISA_EXT_ARR(ZKSED), | |
| 67 | + KVM_ISA_EXT_ARR(ZKSH), | |
| 68 | + KVM_ISA_EXT_ARR(ZKT), | |
| 69 | + KVM_ISA_EXT_ARR(ZVBB), | |
| 70 | + KVM_ISA_EXT_ARR(ZVBC), | |
| 71 | + KVM_ISA_EXT_ARR(ZVFH), | |
| 72 | + KVM_ISA_EXT_ARR(ZVFHMIN), | |
| 73 | + KVM_ISA_EXT_ARR(ZVKB), | |
| 74 | + KVM_ISA_EXT_ARR(ZVKG), | |
| 75 | + KVM_ISA_EXT_ARR(ZVKNED), | |
| 76 | + KVM_ISA_EXT_ARR(ZVKNHA), | |
| 77 | + KVM_ISA_EXT_ARR(ZVKNHB), | |
| 78 | + KVM_ISA_EXT_ARR(ZVKSED), | |
| 79 | + KVM_ISA_EXT_ARR(ZVKSH), | |
| 80 | + KVM_ISA_EXT_ARR(ZVKT), | |
| 54 | 81 | }; |
| 55 | 82 | |
| 56 | 83 | static unsigned long kvm_riscv_vcpu_base2isa_ext(unsigned long base_ext) |
| @@ -92,13 +119,40 @@ static bool kvm_riscv_vcpu_isa_disable_allowed(unsigned long ext) · 35 unmodified lines | ||
| 92 | 119 | case KVM_RISCV_ISA_EXT_SVNAPOT: |
| 93 | 120 | case KVM_RISCV_ISA_EXT_ZBA: |
| 94 | 121 | case KVM_RISCV_ISA_EXT_ZBB: |
| 122 | + case KVM_RISCV_ISA_EXT_ZBC: | |
| 123 | + case KVM_RISCV_ISA_EXT_ZBKB: | |
| 124 | + case KVM_RISCV_ISA_EXT_ZBKC: | |
| 125 | + case KVM_RISCV_ISA_EXT_ZBKX: | |
| 95 | 126 | case KVM_RISCV_ISA_EXT_ZBS: |
| 127 | + case KVM_RISCV_ISA_EXT_ZFA: | |
| 128 | + case KVM_RISCV_ISA_EXT_ZFH: | |
| 129 | + case KVM_RISCV_ISA_EXT_ZFHMIN: | |
| 96 | 130 | case KVM_RISCV_ISA_EXT_ZICNTR: |
| 97 | 131 | case KVM_RISCV_ISA_EXT_ZICOND: |
| 98 | 132 | case KVM_RISCV_ISA_EXT_ZICSR: |
| 99 | 133 | case KVM_RISCV_ISA_EXT_ZIFENCEI: |
| 134 | + case KVM_RISCV_ISA_EXT_ZIHINTNTL: | |
| 100 | 135 | case KVM_RISCV_ISA_EXT_ZIHINTPAUSE: |
| 101 | 136 | case KVM_RISCV_ISA_EXT_ZIHPM: |
| 137 | + case KVM_RISCV_ISA_EXT_ZKND: | |
| 138 | + case KVM_RISCV_ISA_EXT_ZKNE: | |
| 139 | + case KVM_RISCV_ISA_EXT_ZKNH: | |
| 140 | + case KVM_RISCV_ISA_EXT_ZKR: | |
| 141 | + case KVM_RISCV_ISA_EXT_ZKSED: | |
| 142 | + case KVM_RISCV_ISA_EXT_ZKSH: | |
| 143 | + case KVM_RISCV_ISA_EXT_ZKT: | |
| 144 | + case KVM_RISCV_ISA_EXT_ZVBB: | |
| 145 | + case KVM_RISCV_ISA_EXT_ZVBC: | |
| 146 | + case KVM_RISCV_ISA_EXT_ZVFH: | |
| 147 | + case KVM_RISCV_ISA_EXT_ZVFHMIN: | |
| 148 | + case KVM_RISCV_ISA_EXT_ZVKB: | |
| 149 | + case KVM_RISCV_ISA_EXT_ZVKG: | |
| 150 | + case KVM_RISCV_ISA_EXT_ZVKNED: | |
| 151 | + case KVM_RISCV_ISA_EXT_ZVKNHA: | |
| 152 | + case KVM_RISCV_ISA_EXT_ZVKNHB: | |
| 153 | + case KVM_RISCV_ISA_EXT_ZVKSED: | |
| 154 | + case KVM_RISCV_ISA_EXT_ZVKSH: | |
| 155 | + case KVM_RISCV_ISA_EXT_ZVKT: | |
| 102 | 156 | return false; |
| 103 | 157 | /* Extensions which can be disabled using Smstateen */ |
| 104 | 158 | case KVM_RISCV_ISA_EXT_SSAIA: |
| @@ -68,7 +68,7 @@ static inline void local_flush_tlb_range_asid(unsigned long start, · 67 unmodified lines | ||
| 68 | 68 | |
| 69 | 69 | void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) |
| 70 | 70 | { |
| 71 | − local_flush_tlb_range_asid(start, end, PAGE_SIZE, FLUSH_TLB_NO_ASID); | |
| 71 | + local_flush_tlb_range_asid(start, end - start, PAGE_SIZE, FLUSH_TLB_NO_ASID); | |
| 72 | 72 | } |
| 73 | 73 | |
| 74 | 74 | static void __ipi_flush_tlb_all(void *info) |
| @@ -676,8 +676,12 @@ static int handle_pqap(struct kvm_vcpu *vcpu) · 675 unmodified lines | ||
| 676 | 676 | if (vcpu->kvm->arch.crypto.pqap_hook) { |
| 677 | 677 | pqap_hook = *vcpu->kvm->arch.crypto.pqap_hook; |
| 678 | 678 | ret = pqap_hook(vcpu); |
| 679 | − if (!ret && vcpu->run->s.regs.gprs[1] & 0x00ff0000) | |
| 680 | − kvm_s390_set_psw_cc(vcpu, 3); | |
| 679 | + if (!ret) { | |
| 680 | + if (vcpu->run->s.regs.gprs[1] & 0x00ff0000) | |
| 681 | + kvm_s390_set_psw_cc(vcpu, 3); | |
| 682 | + else | |
| 683 | + kvm_s390_set_psw_cc(vcpu, 0); | |
| 684 | + } | |
| 681 | 685 | up_read(&vcpu->kvm->arch.crypto.pqap_hook_rwsem); |
| 682 | 686 | return ret; |
| 683 | 687 | } |
| @@ -1235,7 +1235,6 @@ static int acquire_gmap_shadow(struct kvm_vcpu *vcpu, · 1234 unmodified lines | ||
| 1235 | 1235 | gmap = gmap_shadow(vcpu->arch.gmap, asce, edat); |
| 1236 | 1236 | if (IS_ERR(gmap)) |
| 1237 | 1237 | return PTR_ERR(gmap); |
| 1238 | − gmap->private = vcpu->kvm; | |
| 1239 | 1238 | vcpu->kvm->stat.gmap_shadow_create++; |
| 1240 | 1239 | WRITE_ONCE(vsie_page->gmap, gmap); |
| 1241 | 1240 | return 0; |
| @@ -1691,6 +1691,7 @@ struct gmap *gmap_shadow(struct gmap *parent, unsigned long asce, · 1690 unmodified lines | ||
| 1691 | 1691 | return ERR_PTR(-ENOMEM); |
| 1692 | 1692 | new->mm = parent->mm; |
| 1693 | 1693 | new->parent = gmap_get(parent); |
| 1694 | + new->private = parent->private; | |
| 1694 | 1695 | new->orig_asce = asce; |
| 1695 | 1696 | new->edat_level = edat_level; |
| 1696 | 1697 | new->initialized = false; |
| @@ -10,13 +10,14 @@ enum cc_vendor { · 9 unmodified lines | ||
| 10 | 10 | CC_VENDOR_INTEL, |
| 11 | 11 | }; |
| 12 | 12 | |
| 13 | −extern enum cc_vendor cc_vendor; | |
| 14 | − | |
| 15 | 13 | #ifdef CONFIG_ARCH_HAS_CC_PLATFORM |
| 14 | +extern enum cc_vendor cc_vendor; | |
| 16 | 15 | void cc_set_mask(u64 mask); |
| 17 | 16 | u64 cc_mkenc(u64 val); |
| 18 | 17 | u64 cc_mkdec(u64 val); |
| 19 | 18 | #else |
| 19 | +#define cc_vendor (CC_VENDOR_NONE) | |
| 20 | + | |
| 20 | 21 | static inline u64 cc_mkenc(u64 val) |
| 21 | 22 | { |
| 22 | 23 | return val; |
| @@ -1145,6 +1145,8 @@ struct kvm_hv { · 1144 unmodified lines | ||
| 1145 | 1145 | unsigned int synic_auto_eoi_used; |
| 1146 | 1146 | |
| 1147 | 1147 | struct kvm_hv_syndbg hv_syndbg; |
| 1148 | + | |
| 1149 | + bool xsaves_xsavec_checked; | |
| 1148 | 1150 | }; |
| 1149 | 1151 | #endif |
| 1150 | 1152 | |
| @@ -434,7 +434,8 @@ static void __init sev_map_percpu_data(void) · 433 unmodified lines | ||
| 434 | 434 | { |
| 435 | 435 | int cpu; |
| 436 | 436 | |
| 437 | − if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) | |
| 437 | + if (cc_vendor != CC_VENDOR_AMD || | |
| 438 | + !cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) | |
| 438 | 439 | return; |
| 439 | 440 | |
| 440 | 441 | for_each_possible_cpu(cpu) { |
| @@ -1322,6 +1322,56 @@ static bool hv_check_msr_access(struct kvm_vcpu_hv *hv_vcpu, u32 msr) · 1321 unmodified lines | ||
| 1322 | 1322 | return false; |
| 1323 | 1323 | } |
| 1324 | 1324 | |
| 1325 | +#define KVM_HV_WIN2016_GUEST_ID 0x1040a00003839 | |
| 1326 | +#define KVM_HV_WIN2016_GUEST_ID_MASK (~GENMASK_ULL(23, 16)) /* mask out the service version */ | |
| 1327 | + | |
| 1328 | +/* | |
| 1329 | + * Hyper-V enabled Windows Server 2016 SMP VMs fail to boot in !XSAVES && XSAVEC | |
| 1330 | + * configuration. | |
| 1331 | + * Such configuration can result from, for example, AMD Erratum 1386 workaround. | |
| 1332 | + * | |
| 1333 | + * Print a notice so users aren't left wondering what's suddenly gone wrong. | |
| 1334 | + */ | |
| 1335 | +static void __kvm_hv_xsaves_xsavec_maybe_warn(struct kvm_vcpu *vcpu) | |
| 1336 | +{ | |
| 1337 | + struct kvm *kvm = vcpu->kvm; | |
| 1338 | + struct kvm_hv *hv = to_kvm_hv(kvm); | |
| 1339 | + | |
| 1340 | + /* Check again under the hv_lock. */ | |
| 1341 | + if (hv->xsaves_xsavec_checked) | |
| 1342 | + return; | |
| 1343 | + | |
| 1344 | + if ((hv->hv_guest_os_id & KVM_HV_WIN2016_GUEST_ID_MASK) != | |
| 1345 | + KVM_HV_WIN2016_GUEST_ID) | |
| 1346 | + return; | |
| 1347 | + | |
| 1348 | + hv->xsaves_xsavec_checked = true; | |
| 1349 | + | |
| 1350 | + /* UP configurations aren't affected */ | |
| 1351 | + if (atomic_read(&kvm->online_vcpus) < 2) | |
| 1352 | + return; | |
| 1353 | + | |
| 1354 | + if (guest_cpuid_has(vcpu, X86_FEATURE_XSAVES) || | |
| 1355 | + !guest_cpuid_has(vcpu, X86_FEATURE_XSAVEC)) | |
| 1356 | + return; | |
| 1357 | + | |
| 1358 | + pr_notice_ratelimited("Booting SMP Windows KVM VM with !XSAVES && XSAVEC. " | |
| 1359 | + "If it fails to boot try disabling XSAVEC in the VM config.\n"); | |
| 1360 | +} | |
| 1361 | + | |
| 1362 | +void kvm_hv_xsaves_xsavec_maybe_warn(struct kvm_vcpu *vcpu) | |
| 1363 | +{ | |
| 1364 | + struct kvm_hv *hv = to_kvm_hv(vcpu->kvm); | |
| 1365 | + | |
| 1366 | + if (!vcpu->arch.hyperv_enabled || | |
| 1367 | + hv->xsaves_xsavec_checked) | |
| 1368 | + return; | |
| 1369 | + | |
| 1370 | + mutex_lock(&hv->hv_lock); | |
| 1371 | + __kvm_hv_xsaves_xsavec_maybe_warn(vcpu); | |
| 1372 | + mutex_unlock(&hv->hv_lock); | |
| 1373 | +} | |
| 1374 | + | |
| 1325 | 1375 | static int kvm_hv_set_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data, |
| 1326 | 1376 | bool host) |
| 1327 | 1377 | { |
| @@ -182,6 +182,8 @@ void kvm_hv_setup_tsc_page(struct kvm *kvm, · 181 unmodified lines | ||
| 182 | 182 | struct pvclock_vcpu_time_info *hv_clock); |
| 183 | 183 | void kvm_hv_request_tsc_page_update(struct kvm *kvm); |
| 184 | 184 | |
| 185 | +void kvm_hv_xsaves_xsavec_maybe_warn(struct kvm_vcpu *vcpu); | |
| 186 | + | |
| 185 | 187 | void kvm_hv_init_vm(struct kvm *kvm); |
| 186 | 188 | void kvm_hv_destroy_vm(struct kvm *kvm); |
| 187 | 189 | int kvm_hv_vcpu_init(struct kvm_vcpu *vcpu); |
| @@ -267,6 +269,7 @@ int kvm_hv_vcpu_flush_tlb(struct kvm_vcpu *vcpu); · 79 unmodified lines | ||
| 267 | 269 | static inline void kvm_hv_setup_tsc_page(struct kvm *kvm, |
| 268 | 270 | struct pvclock_vcpu_time_info *hv_clock) {} |
| 269 | 271 | static inline void kvm_hv_request_tsc_page_update(struct kvm *kvm) {} |
| 272 | +static inline void kvm_hv_xsaves_xsavec_maybe_warn(struct kvm_vcpu *vcpu) {} | |
| 270 | 273 | static inline void kvm_hv_init_vm(struct kvm *kvm) {} |
| 271 | 274 | static inline void kvm_hv_destroy_vm(struct kvm *kvm) {} |
| 272 | 275 | static inline int kvm_hv_vcpu_init(struct kvm_vcpu *vcpu) |
| @@ -1782,6 +1782,10 @@ static int set_efer(struct kvm_vcpu *vcpu, struct msr_data *msr_info) · 1781 unmodified lines | ||
| 1782 | 1782 | if ((efer ^ old_efer) & KVM_MMU_EFER_ROLE_BITS) |
| 1783 | 1783 | kvm_mmu_reset_context(vcpu); |
| 1784 | 1784 | |
| 1785 | + if (!static_cpu_has(X86_FEATURE_XSAVES) && | |
| 1786 | + (efer & EFER_SVME)) | |
| 1787 | + kvm_hv_xsaves_xsavec_maybe_warn(vcpu); | |
| 1788 | + | |
| 1785 | 1789 | return 0; |
| 1786 | 1790 | } |
| 1787 | 1791 | |
| @@ -7016,6 +7020,9 @@ set_identity_unlock: · 5228 unmodified lines | ||
| 7016 | 7020 | r = -EEXIST; |
| 7017 | 7021 | if (kvm->arch.vpit) |
| 7018 | 7022 | goto create_pit_unlock; |
| 7023 | + r = -ENOENT; | |
| 7024 | + if (!pic_in_kernel(kvm)) | |
| 7025 | + goto create_pit_unlock; | |
| 7019 | 7026 | r = -ENOMEM; |
| 7020 | 7027 | kvm->arch.vpit = kvm_create_pit(kvm, u.pit_config.flags); |
| 7021 | 7028 | if (kvm->arch.vpit) |
| @@ -49,6 +49,7 @@ · 48 unmodified lines | ||
| 49 | 49 | #include "blk-pm.h" |
| 50 | 50 | #include "blk-cgroup.h" |
| 51 | 51 | #include "blk-throttle.h" |
| 52 | +#include "blk-ioprio.h" | |
| 52 | 53 | |
| 53 | 54 | struct dentry *blk_debugfs_root; |
| 54 | 55 | |
| @@ -833,6 +834,14 @@ end_io: · 778 unmodified lines | ||
| 833 | 834 | } |
| 834 | 835 | EXPORT_SYMBOL(submit_bio_noacct); |
| 835 | 836 | |
| 837 | +static void bio_set_ioprio(struct bio *bio) | |
| 838 | +{ | |
| 839 | + /* Nobody set ioprio so far? Initialize it based on task's nice value */ | |
| 840 | + if (IOPRIO_PRIO_CLASS(bio->bi_ioprio) == IOPRIO_CLASS_NONE) | |
| 841 | + bio->bi_ioprio = get_current_ioprio(); | |
| 842 | + blkcg_set_ioprio(bio); | |
| 843 | +} | |
| 844 | + | |
| 836 | 845 | /** |
| 837 | 846 | * submit_bio - submit a bio to the block device layer for I/O |
| 838 | 847 | * @bio: The &struct bio which describes the I/O |
| @@ -855,6 +864,7 @@ void submit_bio(struct bio *bio) · 16 unmodified lines | ||
| 855 | 864 | count_vm_events(PGPGOUT, bio_sectors(bio)); |
| 856 | 865 | } |
| 857 | 866 | |
| 867 | + bio_set_ioprio(bio); | |
| 858 | 868 | submit_bio_noacct(bio); |
| 859 | 869 | } |
| 860 | 870 | EXPORT_SYMBOL(submit_bio); |
| @@ -40,7 +40,6 @@ · 39 unmodified lines | ||
| 40 | 40 | #include "blk-stat.h" |
| 41 | 41 | #include "blk-mq-sched.h" |
| 42 | 42 | #include "blk-rq-qos.h" |
| 43 | −#include "blk-ioprio.h" | |
| 44 | 43 | |
| 45 | 44 | static DEFINE_PER_CPU(struct llist_head, blk_cpu_done); |
| 46 | 45 | static DEFINE_PER_CPU(call_single_data_t, blk_cpu_csd); |
| @@ -2944,14 +2943,6 @@ static bool blk_mq_use_cached_rq(struct request *rq, struct blk_plug *plug, · 2897 unmodified lines | ||
| 2944 | 2943 | return true; |
| 2945 | 2944 | } |
| 2946 | 2945 | |
| 2947 | −static void bio_set_ioprio(struct bio *bio) | |
| 2948 | −{ | |
| 2949 | − /* Nobody set ioprio so far? Initialize it based on task's nice value */ | |
| 2950 | − if (IOPRIO_PRIO_CLASS(bio->bi_ioprio) == IOPRIO_CLASS_NONE) | |
| 2951 | − bio->bi_ioprio = get_current_ioprio(); | |
| 2952 | − blkcg_set_ioprio(bio); | |
| 2953 | −} | |
| 2954 | − | |
| 2955 | 2946 | /** |
| 2956 | 2947 | * blk_mq_submit_bio - Create and send a request to block device. |
| 2957 | 2948 | * @bio: Bio pointer. |
| @@ -2976,7 +2967,6 @@ void blk_mq_submit_bio(struct bio *bio) · 18 unmodified lines | ||
| 2976 | 2967 | blk_status_t ret; |
| 2977 | 2968 | |
| 2978 | 2969 | bio = blk_queue_bounce(bio, q); |
| 2979 | − bio_set_ioprio(bio); | |
| 2980 | 2970 | |
| 2981 | 2971 | if (plug) { |
| 2982 | 2972 | rq = rq_list_peek(&plug->cached_rq); |
| @@ -91,13 +91,13 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg, · 90 unmodified lines | ||
| 91 | 91 | if (!(msg->msg_flags & MSG_MORE)) { |
| 92 | 92 | err = hash_alloc_result(sk, ctx); |
| 93 | 93 | if (err) |
| 94 | − goto unlock_free; | |
| 94 | + goto unlock_free_result; | |
| 95 | 95 | ahash_request_set_crypt(&ctx->req, NULL, |
| 96 | 96 | ctx->result, 0); |
| 97 | 97 | err = crypto_wait_req(crypto_ahash_final(&ctx->req), |
| 98 | 98 | &ctx->wait); |
| 99 | 99 | if (err) |
| 100 | − goto unlock_free; | |
| 100 | + goto unlock_free_result; | |
| 101 | 101 | } |
| 102 | 102 | goto done_more; |
| 103 | 103 | } |
| @@ -170,6 +170,7 @@ unlock: · 66 unmodified lines | ||
| 170 | 170 | |
| 171 | 171 | unlock_free: |
| 172 | 172 | af_alg_free_sg(&ctx->sgl); |
| 173 | +unlock_free_result: | |
| 173 | 174 | hash_free_result(sk, ctx); |
| 174 | 175 | ctx->more = false; |
| 175 | 176 | goto unlock; |
| @@ -148,6 +148,9 @@ static int crypto_cbc_create(struct crypto_template *tmpl, struct rtattr **tb) · 147 unmodified lines | ||
| 148 | 148 | if (!is_power_of_2(inst->alg.co.base.cra_blocksize)) |
| 149 | 149 | goto out_free_inst; |
| 150 | 150 | |
| 151 | + if (inst->alg.co.statesize) | |
| 152 | + goto out_free_inst; | |
| 153 | + | |
| 151 | 154 | inst->alg.encrypt = crypto_cbc_encrypt; |
| 152 | 155 | inst->alg.decrypt = crypto_cbc_decrypt; |
| 153 | 156 | |
| @@ -478,6 +478,16 @@ binder_enqueue_thread_work_ilocked(struct binder_thread *thread, · 477 unmodified lines | ||
| 478 | 478 | { |
| 479 | 479 | WARN_ON(!list_empty(&thread->waiting_thread_node)); |
| 480 | 480 | binder_enqueue_work_ilocked(work, &thread->todo); |
| 481 | + | |
| 482 | + /* (e)poll-based threads require an explicit wakeup signal when | |
| 483 | + * queuing their own work; they rely on these events to consume | |
| 484 | + * messages without I/O block. Without it, threads risk waiting | |
| 485 | + * indefinitely without handling the work. | |
| 486 | + */ | |
| 487 | + if (thread->looper & BINDER_LOOPER_STATE_POLL && | |
| 488 | + thread->pid == current->pid && !thread->process_todo) | |
| 489 | + wake_up_interruptible_sync(&thread->wait); | |
| 490 | + | |
| 481 | 491 | thread->process_todo = true; |
| 482 | 492 | } |
| 483 | 493 | |
| @@ -606,13 +606,13 @@ static const struct pci_device_id ahci_pci_tbl[] = { · 605 unmodified lines | ||
| 606 | 606 | { PCI_VDEVICE(PROMISE, 0x3781), board_ahci }, /* FastTrak TX8660 ahci-mode */ |
| 607 | 607 | |
| 608 | 608 | /* ASMedia */ |
| 609 | − { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */ | |
| 610 | − { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */ | |
| 609 | + { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci_43bit_dma }, /* ASM1060 */ | |
| 610 | + { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci_43bit_dma }, /* ASM1060 */ | |
| 611 | 611 | { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci_43bit_dma }, /* ASM1061 */ |
| 612 | 612 | { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci_43bit_dma }, /* ASM1061/1062 */ |
| 613 | − { PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci }, /* ASM1061R */ | |
| 614 | − { PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci }, /* ASM1062R */ | |
| 615 | − { PCI_VDEVICE(ASMEDIA, 0x0624), board_ahci }, /* ASM1062+JMB575 */ | |
| 613 | + { PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci_43bit_dma }, /* ASM1061R */ | |
| 614 | + { PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci_43bit_dma }, /* ASM1062R */ | |
| 615 | + { PCI_VDEVICE(ASMEDIA, 0x0624), board_ahci_43bit_dma }, /* ASM1062+JMB575 */ | |
| 616 | 616 | { PCI_VDEVICE(ASMEDIA, 0x1062), board_ahci }, /* ASM1062A */ |
| 617 | 617 | { PCI_VDEVICE(ASMEDIA, 0x1064), board_ahci }, /* ASM1064 */ |
| 618 | 618 | { PCI_VDEVICE(ASMEDIA, 0x1164), board_ahci }, /* ASM1164 */ |
| @@ -2930,6 +2930,8 @@ open_card_ubr0(struct idt77252_dev *card) · 2929 unmodified lines | ||
| 2930 | 2930 | vc->scq = alloc_scq(card, vc->class); |
| 2931 | 2931 | if (!vc->scq) { |
| 2932 | 2932 | printk("%s: can't get SCQ.\n", card->name); |
| 2933 | + kfree(card->vcs[0]); | |
| 2934 | + card->vcs[0] = NULL; | |
| 2933 | 2935 | return -ENOMEM; |
| 2934 | 2936 | } |
| 2935 | 2937 | |
| @@ -534,10 +534,16 @@ EXPORT_SYMBOL_GPL(sev_platform_init); · 533 unmodified lines | ||
| 534 | 534 | |
| 535 | 535 | static int __sev_platform_shutdown_locked(int *error) |
| 536 | 536 | { |
| 537 | − struct sev_device *sev = psp_master->sev_data; | |
| 537 | + struct psp_device *psp = psp_master; | |
| 538 | + struct sev_device *sev; | |
| 538 | 539 | int ret; |
| 539 | 540 | |
| 540 | − if (!sev || sev->state == SEV_STATE_UNINIT) | |
| 541 | + if (!psp || !psp->sev_data) | |
| 542 | + return 0; | |
| 543 | + | |
| 544 | + sev = psp->sev_data; | |
| 545 | + | |
| 546 | + if (sev->state == SEV_STATE_UNINIT) | |
| 541 | 547 | return 0; |
| 542 | 548 | |
| 543 | 549 | ret = __sev_do_cmd_locked(SEV_CMD_SHUTDOWN, NULL, error); |
| @@ -168,10 +168,7 @@ static vm_fault_t cma_heap_vm_fault(struct vm_fault *vmf) · 167 unmodified lines | ||
| 168 | 168 | if (vmf->pgoff > buffer->pagecount) |
| 169 | 169 | return VM_FAULT_SIGBUS; |
| 170 | 170 | |
| 171 | − vmf->page = buffer->pages[vmf->pgoff]; | |
| 172 | − get_page(vmf->page); | |
| 173 | − | |
| 174 | − return 0; | |
| 171 | + return vmf_insert_pfn(vma, vmf->address, page_to_pfn(buffer->pages[vmf->pgoff])); | |
| 175 | 172 | } |
| 176 | 173 | |
| 177 | 174 | static const struct vm_operations_struct dma_heap_vm_ops = { |
| @@ -185,6 +182,8 @@ static int cma_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) · 7 unmodified lines | ||
| 185 | 182 | if ((vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) == 0) |
| 186 | 183 | return -EINVAL; |
| 187 | 184 | |
| 185 | + vm_flags_set(vma, VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP); | |
| 186 | + | |
| 188 | 187 | vma->vm_ops = &dma_heap_vm_ops; |
| 189 | 188 | vma->vm_private_data = buffer; |
| 190 | 189 | |
| @@ -222,8 +222,14 @@ struct atdma_sg { · 221 unmodified lines | ||
| 222 | 222 | * @vd: pointer to the virtual dma descriptor. |
| 223 | 223 | * @atchan: pointer to the atmel dma channel. |
| 224 | 224 | * @total_len: total transaction byte count |
| 225 | − * @sg_len: number of sg entries. | |
| 225 | + * @sglen: number of sg entries. | |
| 226 | 226 | * @sg: array of sgs. |
| 227 | + * @boundary: number of transfers to perform before the automatic address increment operation | |
| 228 | + * @dst_hole: value to add to the destination address when the boundary has been reached | |
| 229 | + * @src_hole: value to add to the source address when the boundary has been reached | |
| 230 | + * @memset_buffer: buffer used for the memset operation | |
| 231 | + * @memset_paddr: physical address of the buffer used for the memset operation | |
| 232 | + * @memset_vaddr: virtual address of the buffer used for the memset operation | |
| 227 | 233 | */ |
| 228 | 234 | struct at_desc { |
| 229 | 235 | struct virt_dma_desc vd; |
| @@ -245,7 +251,10 @@ struct at_desc { · 15 unmodified lines | ||
| 245 | 251 | /*-- Channels --------------------------------------------------------*/ |
| 246 | 252 | |
| 247 | 253 | /** |
| 248 | − * atc_status - information bits stored in channel status flag | |
| 254 | + * enum atc_status - information bits stored in channel status flag | |
| 255 | + * | |
| 256 | + * @ATC_IS_PAUSED: If channel is pauses | |
| 257 | + * @ATC_IS_CYCLIC: If channel is cyclic | |
| 249 | 258 | * |
| 250 | 259 | * Manipulated with atomic operations. |
| 251 | 260 | */ |
| @@ -282,7 +291,6 @@ struct at_dma_chan { · 30 unmodified lines | ||
| 282 | 291 | u32 save_cfg; |
| 283 | 292 | u32 save_dscr; |
| 284 | 293 | struct dma_slave_config dma_sconfig; |
| 285 | − bool cyclic; | |
| 286 | 294 | struct at_desc *desc; |
| 287 | 295 | }; |
| 288 | 296 | |
| @@ -328,12 +336,12 @@ static inline u8 convert_buswidth(enum dma_slave_buswidth addr_width) · 39 unmodified lines | ||
| 328 | 336 | /** |
| 329 | 337 | * struct at_dma - internal representation of an Atmel HDMA Controller |
| 330 | 338 | * @dma_device: dmaengine dma_device object members |
| 331 | − * @atdma_devtype: identifier of DMA controller compatibility | |
| 332 | − * @ch_regs: memory mapped register base | |
| 339 | + * @regs: memory mapped register base | |
| 333 | 340 | * @clk: dma controller clock |
| 334 | 341 | * @save_imr: interrupt mask register that is saved on suspend/resume cycle |
| 335 | 342 | * @all_chan_mask: all channels availlable in a mask |
| 336 | 343 | * @lli_pool: hw lli table |
| 344 | + * @memset_pool: hw memset pool | |
| 337 | 345 | * @chan: channels table to store at_dma_chan structures |
| 338 | 346 | */ |
| 339 | 347 | struct at_dma { |
| @@ -626,6 +634,9 @@ static inline u32 atc_calc_bytes_left(u32 current_len, u32 ctrla) · 286 unmodified lines | ||
| 626 | 634 | |
| 627 | 635 | /** |
| 628 | 636 | * atc_get_llis_residue - Get residue for a hardware linked list transfer |
| 637 | + * @atchan: pointer to an atmel hdmac channel. | |
| 638 | + * @desc: pointer to the descriptor for which the residue is calculated. | |
| 639 | + * @residue: residue to be set to dma_tx_state. | |
| 629 | 640 | * |
| 630 | 641 | * Calculate the residue by removing the length of the Linked List Item (LLI) |
| 631 | 642 | * already transferred from the total length. To get the current LLI we can use |
| @@ -661,10 +672,8 @@ static inline u32 atc_calc_bytes_left(u32 current_len, u32 ctrla) · 29 unmodified lines | ||
| 661 | 672 | * two DSCR values are different, we read again the CTRLA then the DSCR till two |
| 662 | 673 | * consecutive read values from DSCR are equal or till the maximum trials is |
| 663 | 674 | * reach. This algorithm is very unlikely not to find a stable value for DSCR. |
| 664 | − * @atchan: pointer to an atmel hdmac channel. | |
| 665 | − * @desc: pointer to the descriptor for which the residue is calculated. | |
| 666 | − * @residue: residue to be set to dma_tx_state. | |
| 667 | − * Returns 0 on success, -errno otherwise. | |
| 675 | + * | |
| 676 | + * Returns: %0 on success, -errno otherwise. | |
| 668 | 677 | */ |
| 669 | 678 | static int atc_get_llis_residue(struct at_dma_chan *atchan, |
| 670 | 679 | struct at_desc *desc, u32 *residue) |
| @@ -731,7 +740,8 @@ static int atc_get_llis_residue(struct at_dma_chan *atchan, · 60 unmodified lines | ||
| 731 | 740 | * @chan: DMA channel |
| 732 | 741 | * @cookie: transaction identifier to check status of |
| 733 | 742 | * @residue: residue to be updated. |
| 734 | − * Return 0 on success, -errono otherwise. | |
| 743 | + * | |
| 744 | + * Return: %0 on success, -errno otherwise. | |
| 735 | 745 | */ |
| 736 | 746 | static int atc_get_residue(struct dma_chan *chan, dma_cookie_t cookie, |
| 737 | 747 | u32 *residue) |
| @@ -1710,7 +1720,7 @@ static void atc_issue_pending(struct dma_chan *chan) · 972 unmodified lines | ||
| 1710 | 1720 | * atc_alloc_chan_resources - allocate resources for DMA channel |
| 1711 | 1721 | * @chan: allocate descriptor resources for this channel |
| 1712 | 1722 | * |
| 1713 | − * return - the number of allocated descriptors | |
| 1723 | + * Return: the number of allocated descriptors | |
| 1714 | 1724 | */ |
| 1715 | 1725 | static int atc_alloc_chan_resources(struct dma_chan *chan) |
| 1716 | 1726 | { |
| @@ -38,15 +38,17 @@ static int dpaa2_qdma_alloc_chan_resources(struct dma_chan *chan) · 37 unmodified lines | ||
| 38 | 38 | if (!dpaa2_chan->fd_pool) |
| 39 | 39 | goto err; |
| 40 | 40 | |
| 41 | − dpaa2_chan->fl_pool = dma_pool_create("fl_pool", dev, | |
| 42 | − sizeof(struct dpaa2_fl_entry), | |
| 43 | − sizeof(struct dpaa2_fl_entry), 0); | |
| 41 | + dpaa2_chan->fl_pool = | |
| 42 | + dma_pool_create("fl_pool", dev, | |
| 43 | + sizeof(struct dpaa2_fl_entry) * 3, | |
| 44 | + sizeof(struct dpaa2_fl_entry), 0); | |
| 45 | + | |
| 44 | 46 | if (!dpaa2_chan->fl_pool) |
| 45 | 47 | goto err_fd; |
| 46 | 48 | |
| 47 | 49 | dpaa2_chan->sdd_pool = |
| 48 | 50 | dma_pool_create("sdd_pool", dev, |
| 49 | − sizeof(struct dpaa2_qdma_sd_d), | |
| 51 | + sizeof(struct dpaa2_qdma_sd_d) * 2, | |
| 50 | 52 | sizeof(struct dpaa2_qdma_sd_d), 0); |
| 51 | 53 | if (!dpaa2_chan->sdd_pool) |
| 52 | 54 | goto err_fl; |
| @@ -514,11 +514,11 @@ static struct fsl_qdma_queue · 513 unmodified lines | ||
| 514 | 514 | queue_temp = queue_head + i + (j * queue_num); |
| 515 | 515 | |
| 516 | 516 | queue_temp->cq = |
| 517 | − dma_alloc_coherent(&pdev->dev, | |
| 518 | − sizeof(struct fsl_qdma_format) * | |
| 519 | − queue_size[i], | |
| 520 | − &queue_temp->bus_addr, | |
| 521 | − GFP_KERNEL); | |
| 517 | + dmam_alloc_coherent(&pdev->dev, | |
| 518 | + sizeof(struct fsl_qdma_format) * | |
| 519 | + queue_size[i], | |
| 520 | + &queue_temp->bus_addr, | |
| 521 | + GFP_KERNEL); | |
| 522 | 522 | if (!queue_temp->cq) |
| 523 | 523 | return NULL; |
| 524 | 524 | queue_temp->block_base = fsl_qdma->block_base + |
| @@ -563,15 +563,14 @@ static struct fsl_qdma_queue · 38 unmodified lines | ||
| 563 | 563 | /* |
| 564 | 564 | * Buffer for queue command |
| 565 | 565 | */ |
| 566 | − status_head->cq = dma_alloc_coherent(&pdev->dev, | |
| 567 | − sizeof(struct fsl_qdma_format) * | |
| 568 | − status_size, | |
| 569 | − &status_head->bus_addr, | |
| 570 | − GFP_KERNEL); | |
| 571 | − if (!status_head->cq) { | |
| 572 | − devm_kfree(&pdev->dev, status_head); | |
| 566 | + status_head->cq = dmam_alloc_coherent(&pdev->dev, | |
| 567 | + sizeof(struct fsl_qdma_format) * | |
| 568 | + status_size, | |
| 569 | + &status_head->bus_addr, | |
| 570 | + GFP_KERNEL); | |
| 571 | + if (!status_head->cq) | |
| 573 | 572 | return NULL; |
| 574 | − } | |
| 573 | + | |
| 575 | 574 | status_head->n_cq = status_size; |
| 576 | 575 | status_head->virt_head = status_head->cq; |
| 577 | 576 | status_head->virt_tail = status_head->cq; |
| @@ -1268,8 +1267,6 @@ static void fsl_qdma_cleanup_vchan(struct dma_device *dmadev) · 690 unmodified lines | ||
| 1268 | 1267 | |
| 1269 | 1268 | static void fsl_qdma_remove(struct platform_device *pdev) |
| 1270 | 1269 | { |
| 1271 | − int i; | |
| 1272 | − struct fsl_qdma_queue *status; | |
| 1273 | 1270 | struct device_node *np = pdev->dev.of_node; |
| 1274 | 1271 | struct fsl_qdma_engine *fsl_qdma = platform_get_drvdata(pdev); |
| 1275 | 1272 | |
| @@ -1277,12 +1274,6 @@ static void fsl_qdma_remove(struct platform_device *pdev) · 1 unmodified line | ||
| 1277 | 1274 | fsl_qdma_cleanup_vchan(&fsl_qdma->dma_dev); |
| 1278 | 1275 | of_dma_controller_free(np); |
| 1279 | 1276 | dma_async_device_unregister(&fsl_qdma->dma_dev); |
| 1280 | − | |
| 1281 | − for (i = 0; i < fsl_qdma->block_number; i++) { | |
| 1282 | − status = fsl_qdma->status[i]; | |
| 1283 | − dma_free_coherent(&pdev->dev, sizeof(struct fsl_qdma_format) * | |
| 1284 | − status->n_cq, status->cq, status->bus_addr); | |
| 1285 | − } | |
| 1286 | 1277 | } |
| 1287 | 1278 | |
| 1288 | 1279 | static const struct of_device_id fsl_qdma_dt_ids[] = { |
| @@ -2404,6 +2404,11 @@ static int edma_probe(struct platform_device *pdev) · 2403 unmodified lines | ||
| 2404 | 2404 | if (irq > 0) { |
| 2405 | 2405 | irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s_ccint", |
| 2406 | 2406 | dev_name(dev)); |
| 2407 | + if (!irq_name) { | |
| 2408 | + ret = -ENOMEM; | |
| 2409 | + goto err_disable_pm; | |
| 2410 | + } | |
| 2411 | + | |
| 2407 | 2412 | ret = devm_request_irq(dev, irq, dma_irq_handler, 0, irq_name, |
| 2408 | 2413 | ecc); |
| 2409 | 2414 | if (ret) { |
| @@ -2420,6 +2425,11 @@ static int edma_probe(struct platform_device *pdev) · 10 unmodified lines | ||
| 2420 | 2425 | if (irq > 0) { |
| 2421 | 2426 | irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s_ccerrint", |
| 2422 | 2427 | dev_name(dev)); |
| 2428 | + if (!irq_name) { | |
| 2429 | + ret = -ENOMEM; | |
| 2430 | + goto err_disable_pm; | |
| 2431 | + } | |
| 2432 | + | |
| 2423 | 2433 | ret = devm_request_irq(dev, irq, dma_ccerr_handler, 0, irq_name, |
| 2424 | 2434 | ecc); |
| 2425 | 2435 | if (ret) { |
| @@ -3968,6 +3968,7 @@ static void udma_desc_pre_callback(struct virt_dma_chan *vc, · 3967 unmodified lines | ||
| 3968 | 3968 | { |
| 3969 | 3969 | struct udma_chan *uc = to_udma_chan(&vc->chan); |
| 3970 | 3970 | struct udma_desc *d; |
| 3971 | + u8 status; | |
| 3971 | 3972 | |
| 3972 | 3973 | if (!vd) |
| 3973 | 3974 | return; |
| @@ -3977,12 +3978,12 @@ static void udma_desc_pre_callback(struct virt_dma_chan *vc, · 3 unmodified lines | ||
| 3977 | 3978 | if (d->metadata_size) |
| 3978 | 3979 | udma_fetch_epib(uc, d); |
| 3979 | 3980 | |
| 3980 | − /* Provide residue information for the client */ | |
| 3981 | 3981 | if (result) { |
| 3982 | 3982 | void *desc_vaddr = udma_curr_cppi5_desc_vaddr(d, d->desc_idx); |
| 3983 | 3983 | |
| 3984 | 3984 | if (cppi5_desc_get_type(desc_vaddr) == |
| 3985 | 3985 | CPPI5_INFO0_DESC_TYPE_VAL_HOST) { |
| 3986 | + /* Provide residue information for the client */ | |
| 3986 | 3987 | result->residue = d->residue - |
| 3987 | 3988 | cppi5_hdesc_get_pktlen(desc_vaddr); |
| 3988 | 3989 | if (result->residue) |
| @@ -3991,7 +3992,12 @@ static void udma_desc_pre_callback(struct virt_dma_chan *vc, · 2 unmodified lines | ||
| 3991 | 3992 | result->result = DMA_TRANS_NOERROR; |
| 3992 | 3993 | } else { |
| 3993 | 3994 | result->residue = 0; |
| 3994 | − result->result = DMA_TRANS_NOERROR; | |
| 3995 | + /* Propagate TR Response errors to the client */ | |
| 3996 | + status = d->hwdesc[0].tr_resp_base->status; | |
| 3997 | + if (status) | |
| 3998 | + result->result = DMA_TRANS_ABORTED; | |
| 3999 | + else | |
| 4000 | + result->result = DMA_TRANS_NOERROR; | |
| 3995 | 4001 | } |
| 3996 | 4002 | } |
| 3997 | 4003 | } |
| @@ -141,11 +141,31 @@ static void amdgpu_amdkfd_reset_work(struct work_struct *work) · 140 unmodified lines | ||
| 141 | 141 | static const struct drm_client_funcs kfd_client_funcs = { |
| 142 | 142 | .unregister = drm_client_release, |
| 143 | 143 | }; |
| 144 | + | |
| 145 | +int amdgpu_amdkfd_drm_client_create(struct amdgpu_device *adev) | |
| 146 | +{ | |
| 147 | + int ret; | |
| 148 | + | |
| 149 | + if (!adev->kfd.init_complete) | |
| 150 | + return 0; | |
| 151 | + | |
| 152 | + ret = drm_client_init(&adev->ddev, &adev->kfd.client, "kfd", | |
| 153 | + &kfd_client_funcs); | |
| 154 | + if (ret) { | |
| 155 | + dev_err(adev->dev, "Failed to init DRM client: %d\n", | |
| 156 | + ret); | |
| 157 | + return ret; | |
| 158 | + } | |
| 159 | + | |
| 160 | + drm_client_register(&adev->kfd.client); | |
| 161 | + | |
| 162 | + return 0; | |
| 163 | +} | |
| 164 | + | |
| 144 | 165 | void amdgpu_amdkfd_device_init(struct amdgpu_device *adev) |
| 145 | 166 | { |
| 146 | 167 | int i; |
| 147 | 168 | int last_valid_bit; |
| 148 | − int ret; | |
| 149 | 169 | |
| 150 | 170 | amdgpu_amdkfd_gpuvm_init_mem_limits(); |
| 151 | 171 | |
| @@ -164,12 +184,6 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev) · 12 unmodified lines | ||
| 164 | 184 | .enable_mes = adev->enable_mes, |
| 165 | 185 | }; |
| 166 | 186 | |
| 167 | − ret = drm_client_init(&adev->ddev, &adev->kfd.client, "kfd", &kfd_client_funcs); | |
| 168 | − if (ret) { | |
| 169 | − dev_err(adev->dev, "Failed to init DRM client: %d\n", ret); | |
| 170 | − return; | |
| 171 | − } | |
| 172 | − | |
| 173 | 187 | /* this is going to have a few of the MSBs set that we need to |
| 174 | 188 | * clear |
| 175 | 189 | */ |
| @@ -208,10 +222,6 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev) · 32 unmodified lines | ||
| 208 | 222 | |
| 209 | 223 | adev->kfd.init_complete = kgd2kfd_device_init(adev->kfd.dev, |
| 210 | 224 | &gpu_resources); |
| 211 | − if (adev->kfd.init_complete) | |
| 212 | − drm_client_register(&adev->kfd.client); | |
| 213 | − else | |
| 214 | − drm_client_release(&adev->kfd.client); | |
| 215 | 225 | |
| 216 | 226 | amdgpu_amdkfd_total_mem_size += adev->gmc.real_vram_size; |
| 217 | 227 | |
| @@ -182,6 +182,8 @@ int amdgpu_queue_mask_bit_to_set_resource_bit(struct amdgpu_device *adev, · 181 unmodified lines | ||
| 182 | 182 | struct amdgpu_amdkfd_fence *amdgpu_amdkfd_fence_create(u64 context, |
| 183 | 183 | struct mm_struct *mm, |
| 184 | 184 | struct svm_range_bo *svm_bo); |
| 185 | + | |
| 186 | +int amdgpu_amdkfd_drm_client_create(struct amdgpu_device *adev); | |
| 185 | 187 | #if defined(CONFIG_DEBUG_FS) |
| 186 | 188 | int kfd_debugfs_kfd_mem_limits(struct seq_file *m, void *data); |
| 187 | 189 | #endif |
| @@ -301,7 +303,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(struct amdgpu_device *adev, · 113 unmodified lines | ||
| 301 | 303 | struct kgd_mem *mem, void *drm_priv); |
| 302 | 304 | int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu( |
| 303 | 305 | struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv); |
| 304 | −void amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv); | |
| 306 | +int amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv); | |
| 305 | 307 | int amdgpu_amdkfd_gpuvm_sync_memory( |
| 306 | 308 | struct amdgpu_device *adev, struct kgd_mem *mem, bool intr); |
| 307 | 309 | int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_mem *mem, |
| @@ -290,7 +290,7 @@ static int suspend_resume_compute_scheduler(struct amdgpu_device *adev, bool sus · 289 unmodified lines | ||
| 290 | 290 | for (i = 0; i < adev->gfx.num_compute_rings; i++) { |
| 291 | 291 | struct amdgpu_ring *ring = &adev->gfx.compute_ring[i]; |
| 292 | 292 | |
| 293 | − if (!(ring && drm_sched_wqueue_ready(&ring->sched))) | |
| 293 | + if (!amdgpu_ring_sched_ready(ring)) | |
| 294 | 294 | continue; |
| 295 | 295 | |
| 296 | 296 | /* stop secheduler and drain ring. */ |
| @@ -2085,21 +2085,35 @@ out: · 2084 unmodified lines | ||
| 2085 | 2085 | return ret; |
| 2086 | 2086 | } |
| 2087 | 2087 | |
| 2088 | −void amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv) | |
| 2088 | +int amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv) | |
| 2089 | 2089 | { |
| 2090 | 2090 | struct kfd_mem_attachment *entry; |
| 2091 | 2091 | struct amdgpu_vm *vm; |
| 2092 | + int ret; | |
| 2092 | 2093 | |
| 2093 | 2094 | vm = drm_priv_to_vm(drm_priv); |
| 2094 | 2095 | |
| 2095 | 2096 | mutex_lock(&mem->lock); |
| 2096 | 2097 | |
| 2098 | + ret = amdgpu_bo_reserve(mem->bo, true); | |
| 2099 | + if (ret) | |
| 2100 | + goto out; | |
| 2101 | + | |
| 2097 | 2102 | list_for_each_entry(entry, &mem->attachments, list) { |
| 2098 | − if (entry->bo_va->base.vm == vm) | |
| 2099 | − kfd_mem_dmaunmap_attachment(mem, entry); | |
| 2103 | + if (entry->bo_va->base.vm != vm) | |
| 2104 | + continue; | |
| 2105 | + if (entry->bo_va->base.bo->tbo.ttm && | |
| 2106 | + !entry->bo_va->base.bo->tbo.ttm->sg) | |
| 2107 | + continue; | |
| 2108 | + | |
| 2109 | + kfd_mem_dmaunmap_attachment(mem, entry); | |
| 2100 | 2110 | } |
| 2101 | 2111 | |
| 2112 | + amdgpu_bo_unreserve(mem->bo); | |
| 2113 | +out: | |
| 2102 | 2114 | mutex_unlock(&mem->lock); |
| 2115 | + | |
| 2116 | + return ret; | |
| 2103 | 2117 | } |
| 2104 | 2118 | |
| 2105 | 2119 | int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu( |
| @@ -1678,7 +1678,7 @@ static int amdgpu_debugfs_test_ib_show(struct seq_file *m, void *unused) · 1677 unmodified lines | ||
| 1678 | 1678 | for (i = 0; i < AMDGPU_MAX_RINGS; i++) { |
| 1679 | 1679 | struct amdgpu_ring *ring = adev->rings[i]; |
| 1680 | 1680 | |
| 1681 | − if (!ring || !drm_sched_wqueue_ready(&ring->sched)) | |
| 1681 | + if (!amdgpu_ring_sched_ready(ring)) | |
| 1682 | 1682 | continue; |
| 1683 | 1683 | drm_sched_wqueue_stop(&ring->sched); |
| 1684 | 1684 | } |
| @@ -1694,7 +1694,7 @@ static int amdgpu_debugfs_test_ib_show(struct seq_file *m, void *unused) · 9 unmodified lines | ||
| 1694 | 1694 | for (i = 0; i < AMDGPU_MAX_RINGS; i++) { |
| 1695 | 1695 | struct amdgpu_ring *ring = adev->rings[i]; |
| 1696 | 1696 | |
| 1697 | − if (!ring || !drm_sched_wqueue_ready(&ring->sched)) | |
| 1697 | + if (!amdgpu_ring_sched_ready(ring)) | |
| 1698 | 1698 | continue; |
| 1699 | 1699 | drm_sched_wqueue_start(&ring->sched); |
| 1700 | 1700 | } |
| @@ -1916,8 +1916,8 @@ static int amdgpu_debugfs_ib_preempt(void *data, u64 val) · 215 unmodified lines | ||
| 1916 | 1916 | |
| 1917 | 1917 | ring = adev->rings[val]; |
| 1918 | 1918 | |
| 1919 | − if (!ring || !ring->funcs->preempt_ib || | |
| 1920 | − !drm_sched_wqueue_ready(&ring->sched)) | |
| 1919 | + if (!amdgpu_ring_sched_ready(ring) || | |
| 1920 | + !ring->funcs->preempt_ib) | |
| 1921 | 1921 | return -EINVAL; |
| 1922 | 1922 | |
| 1923 | 1923 | /* the last preemption failed */ |
| @@ -4121,23 +4121,13 @@ int amdgpu_device_init(struct amdgpu_device *adev, · 4120 unmodified lines | ||
| 4121 | 4121 | } |
| 4122 | 4122 | } |
| 4123 | 4123 | } else { |
| 4124 | − switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) { | |
| 4125 | − case IP_VERSION(13, 0, 0): | |
| 4126 | − case IP_VERSION(13, 0, 7): | |
| 4127 | − case IP_VERSION(13, 0, 10): | |
| 4128 | − r = psp_gpu_reset(adev); | |
| 4129 | − break; | |
| 4130 | − default: | |
| 4131 | − tmp = amdgpu_reset_method; | |
| 4132 | − /* It should do a default reset when loading or reloading the driver, | |
| 4133 | − * regardless of the module parameter reset_method. | |
| 4134 | − */ | |
| 4135 | − amdgpu_reset_method = AMD_RESET_METHOD_NONE; | |
| 4136 | − r = amdgpu_asic_reset(adev); | |
| 4137 | − amdgpu_reset_method = tmp; | |
| 4138 | − break; | |
| 4139 | − } | |
| 4140 | − | |
| 4124 | + tmp = amdgpu_reset_method; | |
| 4125 | + /* It should do a default reset when loading or reloading the driver, | |
| 4126 | + * regardless of the module parameter reset_method. | |
| 4127 | + */ | |
| 4128 | + amdgpu_reset_method = AMD_RESET_METHOD_NONE; | |
| 4129 | + r = amdgpu_asic_reset(adev); | |
| 4130 | + amdgpu_reset_method = tmp; | |
| 4141 | 4131 | if (r) { |
| 4142 | 4132 | dev_err(adev->dev, "asic reset on init failed\n"); |
| 4143 | 4133 | goto failed; |
| @@ -5031,7 +5021,7 @@ bool amdgpu_device_has_job_running(struct amdgpu_device *adev) · 887 unmodified lines | ||
| 5031 | 5021 | for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { |
| 5032 | 5022 | struct amdgpu_ring *ring = adev->rings[i]; |
| 5033 | 5023 | |
| 5034 | − if (!ring || !drm_sched_wqueue_ready(&ring->sched)) | |
| 5024 | + if (!amdgpu_ring_sched_ready(ring)) | |
| 5035 | 5025 | continue; |
| 5036 | 5026 | |
| 5037 | 5027 | spin_lock(&ring->sched.job_list_lock); |
| @@ -5170,7 +5160,7 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev, · 132 unmodified lines | ||
| 5170 | 5160 | for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { |
| 5171 | 5161 | struct amdgpu_ring *ring = adev->rings[i]; |
| 5172 | 5162 | |
| 5173 | − if (!ring || !drm_sched_wqueue_ready(&ring->sched)) | |
| 5163 | + if (!amdgpu_ring_sched_ready(ring)) | |
| 5174 | 5164 | continue; |
| 5175 | 5165 | |
| 5176 | 5166 | /* Clear job fence from fence drv to avoid force_completion |
| @@ -5637,7 +5627,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, · 460 unmodified lines | ||
| 5637 | 5627 | for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { |
| 5638 | 5628 | struct amdgpu_ring *ring = tmp_adev->rings[i]; |
| 5639 | 5629 | |
| 5640 | − if (!ring || !drm_sched_wqueue_ready(&ring->sched)) | |
| 5630 | + if (!amdgpu_ring_sched_ready(ring)) | |
| 5641 | 5631 | continue; |
| 5642 | 5632 | |
| 5643 | 5633 | drm_sched_stop(&ring->sched, job ? &job->base : NULL); |
| @@ -5706,7 +5696,7 @@ skip_hw_reset: · 62 unmodified lines | ||
| 5706 | 5696 | for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { |
| 5707 | 5697 | struct amdgpu_ring *ring = tmp_adev->rings[i]; |
| 5708 | 5698 | |
| 5709 | − if (!ring || !drm_sched_wqueue_ready(&ring->sched)) | |
| 5699 | + if (!amdgpu_ring_sched_ready(ring)) | |
| 5710 | 5700 | continue; |
| 5711 | 5701 | |
| 5712 | 5702 | drm_sched_start(&ring->sched, true); |
| @@ -6061,7 +6051,7 @@ pci_ers_result_t amdgpu_pci_error_detected(struct pci_dev *pdev, pci_channel_sta · 348 unmodified lines | ||
| 6061 | 6051 | for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { |
| 6062 | 6052 | struct amdgpu_ring *ring = adev->rings[i]; |
| 6063 | 6053 | |
| 6064 | − if (!ring || !drm_sched_wqueue_ready(&ring->sched)) | |
| 6054 | + if (!amdgpu_ring_sched_ready(ring)) | |
| 6065 | 6055 | continue; |
| 6066 | 6056 | |
| 6067 | 6057 | drm_sched_stop(&ring->sched, NULL); |
| @@ -6189,7 +6179,7 @@ void amdgpu_pci_resume(struct pci_dev *pdev) · 121 unmodified lines | ||
| 6189 | 6179 | for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { |
| 6190 | 6180 | struct amdgpu_ring *ring = adev->rings[i]; |
| 6191 | 6181 | |
| 6192 | − if (!ring || !drm_sched_wqueue_ready(&ring->sched)) | |
| 6182 | + if (!amdgpu_ring_sched_ready(ring)) | |
| 6193 | 6183 | continue; |
| 6194 | 6184 | |
| 6195 | 6185 | drm_sched_start(&ring->sched, true); |
| @@ -2255,6 +2255,10 @@ retry_init: · 2254 unmodified lines | ||
| 2255 | 2255 | if (ret) |
| 2256 | 2256 | goto err_pci; |
| 2257 | 2257 | |
| 2258 | + ret = amdgpu_amdkfd_drm_client_create(adev); | |
| 2259 | + if (ret) | |
| 2260 | + goto err_pci; | |
| 2261 | + | |
| 2258 | 2262 | /* |
| 2259 | 2263 | * 1. don't init fbdev on hw without DCE |
| 2260 | 2264 | * 2. don't init fbdev if there are no connectors |
| @@ -635,6 +635,7 @@ int amdgpu_ring_test_helper(struct amdgpu_ring *ring) · 634 unmodified lines | ||
| 635 | 635 | ring->name); |
| 636 | 636 | |
| 637 | 637 | ring->sched.ready = !r; |
| 638 | + | |
| 638 | 639 | return r; |
| 639 | 640 | } |
| 640 | 641 | |
| @@ -717,3 +718,14 @@ void amdgpu_ring_ib_on_emit_de(struct amdgpu_ring *ring) · 76 unmodified lines | ||
| 717 | 718 | if (ring->is_sw_ring) |
| 718 | 719 | amdgpu_sw_ring_ib_mark_offset(ring, AMDGPU_MUX_OFFSET_TYPE_DE); |
| 719 | 720 | } |
| 721 | + | |
| 722 | +bool amdgpu_ring_sched_ready(struct amdgpu_ring *ring) | |
| 723 | +{ | |
| 724 | + if (!ring) | |
| 725 | + return false; | |
| 726 | + | |
| 727 | + if (ring->no_scheduler || !drm_sched_wqueue_ready(&ring->sched)) | |
| 728 | + return false; | |
| 729 | + | |
| 730 | + return true; | |
| 731 | +} | |
| @@ -450,5 +450,5 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, · 449 unmodified lines | ||
| 450 | 450 | int amdgpu_ib_pool_init(struct amdgpu_device *adev); |
| 451 | 451 | void amdgpu_ib_pool_fini(struct amdgpu_device *adev); |
| 452 | 452 | int amdgpu_ib_ring_tests(struct amdgpu_device *adev); |
| 453 | − | |
| 453 | +bool amdgpu_ring_sched_ready(struct amdgpu_ring *ring); | |
| 454 | 454 | #endif |
| @@ -204,6 +204,12 @@ static u32 cik_ih_get_wptr(struct amdgpu_device *adev, · 203 unmodified lines | ||
| 204 | 204 | tmp = RREG32(mmIH_RB_CNTL); |
| 205 | 205 | tmp |= IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK; |
| 206 | 206 | WREG32(mmIH_RB_CNTL, tmp); |
| 207 | + | |
| 208 | + /* Unset the CLEAR_OVERFLOW bit immediately so new overflows | |
| 209 | + * can be detected. | |
| 210 | + */ | |
| 211 | + tmp &= ~IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK; | |
| 212 | + WREG32(mmIH_RB_CNTL, tmp); | |
| 207 | 213 | } |
| 208 | 214 | return (wptr & ih->ptr_mask); |
| 209 | 215 | } |
| @@ -216,6 +216,11 @@ static u32 cz_ih_get_wptr(struct amdgpu_device *adev, · 215 unmodified lines | ||
| 216 | 216 | tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); |
| 217 | 217 | WREG32(mmIH_RB_CNTL, tmp); |
| 218 | 218 | |
| 219 | + /* Unset the CLEAR_OVERFLOW bit immediately so new overflows | |
| 220 | + * can be detected. | |
| 221 | + */ | |
| 222 | + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0); | |
| 223 | + WREG32(mmIH_RB_CNTL, tmp); | |
| 219 | 224 | |
| 220 | 225 | out: |
| 221 | 226 | return (wptr & ih->ptr_mask); |
| @@ -4027,8 +4027,6 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev) · 4026 unmodified lines | ||
| 4027 | 4027 | err = 0; |
| 4028 | 4028 | adev->gfx.mec2_fw = NULL; |
| 4029 | 4029 | } |
| 4030 | − amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2); | |
| 4031 | − amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2_JT); | |
| 4032 | 4030 | |
| 4033 | 4031 | gfx_v10_0_check_fw_write_wait(adev); |
| 4034 | 4032 | out: |
| @@ -107,23 +107,6 @@ static const struct soc15_reg_golden golden_settings_gc_11_0_1[] = · 106 unmodified lines | ||
| 107 | 107 | SOC15_REG_GOLDEN_VALUE(GC, 0, regTCP_CNTL2, 0xfcffffff, 0x0000000a) |
| 108 | 108 | }; |
| 109 | 109 | |
| 110 | −static const struct soc15_reg_golden golden_settings_gc_11_5_0[] = { | |
| 111 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regDB_DEBUG5, 0xffffffff, 0x00000800), | |
| 112 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regGB_ADDR_CONFIG, 0x0c1807ff, 0x00000242), | |
| 113 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regGCR_GENERAL_CNTL, 0x1ff1ffff, 0x00000500), | |
| 114 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regGL2A_ADDR_MATCH_MASK, 0xffffffff, 0xfffffff3), | |
| 115 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regGL2C_ADDR_MATCH_MASK, 0xffffffff, 0xfffffff3), | |
| 116 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regGL2C_CTRL, 0xffffffff, 0xf37fff3f), | |
| 117 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regGL2C_CTRL3, 0xfffffffb, 0x00f40188), | |
| 118 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regGL2C_CTRL4, 0xf0ffffff, 0x80009007), | |
| 119 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regPA_CL_ENHANCE, 0xf1ffffff, 0x00880007), | |
| 120 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regPC_CONFIG_CNTL_1, 0xffffffff, 0x00010000), | |
| 121 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regTA_CNTL_AUX, 0xf7f7ffff, 0x01030000), | |
| 122 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regTA_CNTL2, 0x007f0000, 0x00000000), | |
| 123 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regTCP_CNTL2, 0xffcfffff, 0x0000200a), | |
| 124 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regUTCL1_CTRL_2, 0xffffffff, 0x0000048f) | |
| 125 | −}; | |
| 126 | − | |
| 127 | 110 | #define DEFAULT_SH_MEM_CONFIG \ |
| 128 | 111 | ((SH_MEM_ADDRESS_MODE_64 << SH_MEM_CONFIG__ADDRESS_MODE__SHIFT) | \ |
| 129 | 112 | (SH_MEM_ALIGNMENT_MODE_UNALIGNED << SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | \ |
| @@ -304,11 +287,6 @@ static void gfx_v11_0_init_golden_registers(struct amdgpu_device *adev) · 174 unmodified lines | ||
| 304 | 287 | golden_settings_gc_11_0_1, |
| 305 | 288 | (const u32)ARRAY_SIZE(golden_settings_gc_11_0_1)); |
| 306 | 289 | break; |
| 307 | − case IP_VERSION(11, 5, 0): | |
| 308 | − soc15_program_register_sequence(adev, | |
| 309 | − golden_settings_gc_11_5_0, | |
| 310 | − (const u32)ARRAY_SIZE(golden_settings_gc_11_5_0)); | |
| 311 | − break; | |
| 312 | 290 | default: |
| 313 | 291 | break; |
| 314 | 292 | } |
| @@ -915,8 +915,8 @@ static int gmc_v6_0_hw_init(void *handle) · 914 unmodified lines | ||
| 915 | 915 | |
| 916 | 916 | if (amdgpu_emu_mode == 1) |
| 917 | 917 | return amdgpu_gmc_vram_checking(adev); |
| 918 | − else | |
| 919 | − return r; | |
| 918 | + | |
| 919 | + return 0; | |
| 920 | 920 | } |
| 921 | 921 | |
| 922 | 922 | static int gmc_v6_0_hw_fini(void *handle) |
| @@ -1099,8 +1099,8 @@ static int gmc_v7_0_hw_init(void *handle) · 1098 unmodified lines | ||
| 1099 | 1099 | |
| 1100 | 1100 | if (amdgpu_emu_mode == 1) |
| 1101 | 1101 | return amdgpu_gmc_vram_checking(adev); |
| 1102 | − else | |
| 1103 | − return r; | |
| 1102 | + | |
| 1103 | + return 0; | |
| 1104 | 1104 | } |
| 1105 | 1105 | |
| 1106 | 1106 | static int gmc_v7_0_hw_fini(void *handle) |
| @@ -1219,8 +1219,8 @@ static int gmc_v8_0_hw_init(void *handle) · 1218 unmodified lines | ||
| 1219 | 1219 | |
| 1220 | 1220 | if (amdgpu_emu_mode == 1) |
| 1221 | 1221 | return amdgpu_gmc_vram_checking(adev); |
| 1222 | − else | |
| 1223 | − return r; | |
| 1222 | + | |
| 1223 | + return 0; | |
| 1224 | 1224 | } |
| 1225 | 1225 | |
| 1226 | 1226 | static int gmc_v8_0_hw_fini(void *handle) |
| @@ -2341,8 +2341,8 @@ static int gmc_v9_0_hw_init(void *handle) · 2340 unmodified lines | ||
| 2341 | 2341 | |
| 2342 | 2342 | if (amdgpu_emu_mode == 1) |
| 2343 | 2343 | return amdgpu_gmc_vram_checking(adev); |
| 2344 | − else | |
| 2345 | − return r; | |
| 2344 | + | |
| 2345 | + return 0; | |
| 2346 | 2346 | } |
| 2347 | 2347 | |
| 2348 | 2348 | /** |
| @@ -215,6 +215,11 @@ static u32 iceland_ih_get_wptr(struct amdgpu_device *adev, · 214 unmodified lines | ||
| 215 | 215 | tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); |
| 216 | 216 | WREG32(mmIH_RB_CNTL, tmp); |
| 217 | 217 | |
| 218 | + /* Unset the CLEAR_OVERFLOW bit immediately so new overflows | |
| 219 | + * can be detected. | |
| 220 | + */ | |
| 221 | + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0); | |
| 222 | + WREG32(mmIH_RB_CNTL, tmp); | |
| 218 | 223 | |
| 219 | 224 | out: |
| 220 | 225 | return (wptr & ih->ptr_mask); |
| @@ -418,6 +418,12 @@ static u32 ih_v6_0_get_wptr(struct amdgpu_device *adev, · 417 unmodified lines | ||
| 418 | 418 | tmp = RREG32_NO_KIQ(ih_regs->ih_rb_cntl); |
| 419 | 419 | tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); |
| 420 | 420 | WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); |
| 421 | + | |
| 422 | + /* Unset the CLEAR_OVERFLOW bit immediately so new overflows | |
| 423 | + * can be detected. | |
| 424 | + */ | |
| 425 | + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0); | |
| 426 | + WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); | |
| 421 | 427 | out: |
| 422 | 428 | return (wptr & ih->ptr_mask); |
| 423 | 429 | } |
| @@ -418,6 +418,13 @@ static u32 ih_v6_1_get_wptr(struct amdgpu_device *adev, · 417 unmodified lines | ||
| 418 | 418 | tmp = RREG32_NO_KIQ(ih_regs->ih_rb_cntl); |
| 419 | 419 | tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); |
| 420 | 420 | WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); |
| 421 | + | |
| 422 | + /* Unset the CLEAR_OVERFLOW bit immediately so new overflows | |
| 423 | + * can be detected. | |
| 424 | + */ | |
| 425 | + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0); | |
| 426 | + WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); | |
| 427 | + | |
| 421 | 428 | out: |
| 422 | 429 | return (wptr & ih->ptr_mask); |
| 423 | 430 | } |
| @@ -442,6 +442,12 @@ static u32 navi10_ih_get_wptr(struct amdgpu_device *adev, · 441 unmodified lines | ||
| 442 | 442 | tmp = RREG32_NO_KIQ(ih_regs->ih_rb_cntl); |
| 443 | 443 | tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); |
| 444 | 444 | WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); |
| 445 | + | |
| 446 | + /* Unset the CLEAR_OVERFLOW bit immediately so new overflows | |
| 447 | + * can be detected. | |
| 448 | + */ | |
| 449 | + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0); | |
| 450 | + WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); | |
| 445 | 451 | out: |
| 446 | 452 | return (wptr & ih->ptr_mask); |
| 447 | 453 | } |
| @@ -119,6 +119,12 @@ static u32 si_ih_get_wptr(struct amdgpu_device *adev, · 118 unmodified lines | ||
| 119 | 119 | tmp = RREG32(IH_RB_CNTL); |
| 120 | 120 | tmp |= IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK; |
| 121 | 121 | WREG32(IH_RB_CNTL, tmp); |
| 122 | + | |
| 123 | + /* Unset the CLEAR_OVERFLOW bit immediately so new overflows | |
| 124 | + * can be detected. | |
| 125 | + */ | |
| 126 | + tmp &= ~IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK; | |
| 127 | + WREG32(IH_RB_CNTL, tmp); | |
| 122 | 128 | } |
| 123 | 129 | return (wptr & ih->ptr_mask); |
| 124 | 130 | } |
| @@ -219,6 +219,12 @@ static u32 tonga_ih_get_wptr(struct amdgpu_device *adev, · 218 unmodified lines | ||
| 219 | 219 | tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); |
| 220 | 220 | WREG32(mmIH_RB_CNTL, tmp); |
| 221 | 221 | |
| 222 | + /* Unset the CLEAR_OVERFLOW bit immediately so new overflows | |
| 223 | + * can be detected. | |
| 224 | + */ | |
| 225 | + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0); | |
| 226 | + WREG32(mmIH_RB_CNTL, tmp); | |
| 227 | + | |
| 222 | 228 | out: |
| 223 | 229 | return (wptr & ih->ptr_mask); |
| 224 | 230 | } |
| @@ -2017,22 +2017,6 @@ static int vcn_v4_0_set_powergating_state(void *handle, enum amd_powergating_sta · 2016 unmodified lines | ||
| 2017 | 2017 | return ret; |
| 2018 | 2018 | } |
| 2019 | 2019 | |
| 2020 | −/** | |
| 2021 | − * vcn_v4_0_set_interrupt_state - set VCN block interrupt state | |
| 2022 | − * | |
| 2023 | − * @adev: amdgpu_device pointer | |
| 2024 | − * @source: interrupt sources | |
| 2025 | − * @type: interrupt types | |
| 2026 | − * @state: interrupt states | |
| 2027 | − * | |
| 2028 | − * Set VCN block interrupt state | |
| 2029 | − */ | |
| 2030 | −static int vcn_v4_0_set_interrupt_state(struct amdgpu_device *adev, struct amdgpu_irq_src *source, | |
| 2031 | − unsigned type, enum amdgpu_interrupt_state state) | |
| 2032 | −{ | |
| 2033 | − return 0; | |
| 2034 | −} | |
| 2035 | − | |
| 2036 | 2020 | /** |
| 2037 | 2021 | * vcn_v4_0_set_ras_interrupt_state - set VCN block RAS interrupt state |
| 2038 | 2022 | * |
| @@ -2097,7 +2081,6 @@ static int vcn_v4_0_process_interrupt(struct amdgpu_device *adev, struct amdgpu_ · 58 unmodified lines | ||
| 2097 | 2081 | } |
| 2098 | 2082 | |
| 2099 | 2083 | static const struct amdgpu_irq_src_funcs vcn_v4_0_irq_funcs = { |
| 2100 | − .set = vcn_v4_0_set_interrupt_state, | |
| 2101 | 2084 | .process = vcn_v4_0_process_interrupt, |
| 2102 | 2085 | }; |
| 2103 | 2086 | |
| @@ -269,8 +269,6 @@ static int vcn_v4_0_5_hw_fini(void *handle) · 268 unmodified lines | ||
| 269 | 269 | vcn_v4_0_5_set_powergating_state(adev, AMD_PG_STATE_GATE); |
| 270 | 270 | } |
| 271 | 271 | } |
| 272 | − | |
| 273 | − amdgpu_irq_put(adev, &adev->vcn.inst[i].irq, 0); | |
| 274 | 272 | } |
| 275 | 273 | |
| 276 | 274 | return 0; |
| @@ -1668,22 +1666,6 @@ static int vcn_v4_0_5_set_powergating_state(void *handle, enum amd_powergating_s · 1391 unmodified lines | ||
| 1668 | 1666 | return ret; |
| 1669 | 1667 | } |
| 1670 | 1668 | |
| 1671 | −/** | |
| 1672 | − * vcn_v4_0_5_set_interrupt_state - set VCN block interrupt state | |
| 1673 | − * | |
| 1674 | − * @adev: amdgpu_device pointer | |
| 1675 | − * @source: interrupt sources | |
| 1676 | − * @type: interrupt types | |
| 1677 | − * @state: interrupt states | |
| 1678 | − * | |
| 1679 | − * Set VCN block interrupt state | |
| 1680 | − */ | |
| 1681 | −static int vcn_v4_0_5_set_interrupt_state(struct amdgpu_device *adev, struct amdgpu_irq_src *source, | |
| 1682 | − unsigned type, enum amdgpu_interrupt_state state) | |
| 1683 | −{ | |
| 1684 | − return 0; | |
| 1685 | −} | |
| 1686 | − | |
| 1687 | 1669 | /** |
| 1688 | 1670 | * vcn_v4_0_5_process_interrupt - process VCN block interrupt |
| 1689 | 1671 | * |
| @@ -1726,7 +1708,6 @@ static int vcn_v4_0_5_process_interrupt(struct amdgpu_device *adev, struct amdgp · 36 unmodified lines | ||
| 1726 | 1708 | } |
| 1727 | 1709 | |
| 1728 | 1710 | static const struct amdgpu_irq_src_funcs vcn_v4_0_5_irq_funcs = { |
| 1729 | − .set = vcn_v4_0_5_set_interrupt_state, | |
| 1730 | 1711 | .process = vcn_v4_0_5_process_interrupt, |
| 1731 | 1712 | }; |
| 1732 | 1713 | |
| @@ -373,6 +373,12 @@ static u32 vega10_ih_get_wptr(struct amdgpu_device *adev, · 372 unmodified lines | ||
| 373 | 373 | tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); |
| 374 | 374 | WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); |
| 375 | 375 | |
| 376 | + /* Unset the CLEAR_OVERFLOW bit immediately so new overflows | |
| 377 | + * can be detected. | |
| 378 | + */ | |
| 379 | + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0); | |
| 380 | + WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); | |
| 381 | + | |
| 376 | 382 | out: |
| 377 | 383 | return (wptr & ih->ptr_mask); |
| 378 | 384 | } |
| @@ -421,6 +421,12 @@ static u32 vega20_ih_get_wptr(struct amdgpu_device *adev, · 420 unmodified lines | ||
| 421 | 421 | tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); |
| 422 | 422 | WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); |
| 423 | 423 | |
| 424 | + /* Unset the CLEAR_OVERFLOW bit immediately so new overflows | |
| 425 | + * can be detected. | |
| 426 | + */ | |
| 427 | + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0); | |
| 428 | + WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); | |
| 429 | + | |
| 424 | 430 | out: |
| 425 | 431 | return (wptr & ih->ptr_mask); |
| 426 | 432 | } |
| @@ -674,7 +674,7 @@ static const uint32_t cwsr_trap_gfx9_hex[] = { · 673 unmodified lines | ||
| 674 | 674 | 0x86ea6a6a, 0x8f6e837a, |
| 675 | 675 | 0xb96ee0c2, 0xbf800002, |
| 676 | 676 | 0xb97a0002, 0xbf8a0000, |
| 677 | − 0xbe801f6c, 0xbf810000, | |
| 677 | + 0xbe801f6c, 0xbf9b0000, | |
| 678 | 678 | }; |
| 679 | 679 | |
| 680 | 680 | static const uint32_t cwsr_trap_nv1x_hex[] = { |
| @@ -1091,7 +1091,7 @@ static const uint32_t cwsr_trap_nv1x_hex[] = { · 410 unmodified lines | ||
| 1091 | 1091 | 0xb9eef807, 0x876dff6d, |
| 1092 | 1092 | 0x0000ffff, 0x87fe7e7e, |
| 1093 | 1093 | 0x87ea6a6a, 0xb9faf802, |
| 1094 | − 0xbe80226c, 0xbf810000, | |
| 1094 | + 0xbe80226c, 0xbf9b0000, | |
| 1095 | 1095 | 0xbf9f0000, 0xbf9f0000, |
| 1096 | 1096 | 0xbf9f0000, 0xbf9f0000, |
| 1097 | 1097 | 0xbf9f0000, 0x00000000, |
| @@ -1574,7 +1574,7 @@ static const uint32_t cwsr_trap_arcturus_hex[] = { · 476 unmodified lines | ||
| 1574 | 1574 | 0x86ea6a6a, 0x8f6e837a, |
| 1575 | 1575 | 0xb96ee0c2, 0xbf800002, |
| 1576 | 1576 | 0xb97a0002, 0xbf8a0000, |
| 1577 | − 0xbe801f6c, 0xbf810000, | |
| 1577 | + 0xbe801f6c, 0xbf9b0000, | |
| 1578 | 1578 | }; |
| 1579 | 1579 | |
| 1580 | 1580 | static const uint32_t cwsr_trap_aldebaran_hex[] = { |
| @@ -2065,7 +2065,7 @@ static const uint32_t cwsr_trap_aldebaran_hex[] = { · 484 unmodified lines | ||
| 2065 | 2065 | 0x86ea6a6a, 0x8f6e837a, |
| 2066 | 2066 | 0xb96ee0c2, 0xbf800002, |
| 2067 | 2067 | 0xb97a0002, 0xbf8a0000, |
| 2068 | − 0xbe801f6c, 0xbf810000, | |
| 2068 | + 0xbe801f6c, 0xbf9b0000, | |
| 2069 | 2069 | }; |
| 2070 | 2070 | |
| 2071 | 2071 | static const uint32_t cwsr_trap_gfx10_hex[] = { |
| @@ -2500,7 +2500,7 @@ static const uint32_t cwsr_trap_gfx10_hex[] = { · 428 unmodified lines | ||
| 2500 | 2500 | 0x876dff6d, 0x0000ffff, |
| 2501 | 2501 | 0x87fe7e7e, 0x87ea6a6a, |
| 2502 | 2502 | 0xb9faf802, 0xbe80226c, |
| 2503 | − 0xbf810000, 0xbf9f0000, | |
| 2503 | + 0xbf9b0000, 0xbf9f0000, | |
| 2504 | 2504 | 0xbf9f0000, 0xbf9f0000, |
| 2505 | 2505 | 0xbf9f0000, 0xbf9f0000, |
| 2506 | 2506 | }; |
| @@ -2944,7 +2944,7 @@ static const uint32_t cwsr_trap_gfx11_hex[] = { · 437 unmodified lines | ||
| 2944 | 2944 | 0xb8eef802, 0xbf0d866e, |
| 2945 | 2945 | 0xbfa20002, 0xb97af802, |
| 2946 | 2946 | 0xbe80486c, 0xb97af802, |
| 2947 | − 0xbe804a6c, 0xbfb00000, | |
| 2947 | + 0xbe804a6c, 0xbfb10000, | |
| 2948 | 2948 | 0xbf9f0000, 0xbf9f0000, |
| 2949 | 2949 | 0xbf9f0000, 0xbf9f0000, |
| 2950 | 2950 | 0xbf9f0000, 0x00000000, |
| @@ -3436,5 +3436,5 @@ static const uint32_t cwsr_trap_gfx9_4_3_hex[] = { · 485 unmodified lines | ||
| 3436 | 3436 | 0x86ea6a6a, 0x8f6e837a, |
| 3437 | 3437 | 0xb96ee0c2, 0xbf800002, |
| 3438 | 3438 | 0xb97a0002, 0xbf8a0000, |
| 3439 | − 0xbe801f6c, 0xbf810000, | |
| 3439 | + 0xbe801f6c, 0xbf9b0000, | |
| 3440 | 3440 | }; |
| @@ -1104,7 +1104,7 @@ L_RETURN_WITHOUT_PRIV: · 1103 unmodified lines | ||
| 1104 | 1104 | s_rfe_b64 s_restore_pc_lo //Return to the main shader program and resume execution |
| 1105 | 1105 | |
| 1106 | 1106 | L_END_PGM: |
| 1107 | − s_endpgm | |
| 1107 | + s_endpgm_saved | |
| 1108 | 1108 | end |
| 1109 | 1109 | |
| 1110 | 1110 | function write_hwreg_to_mem(s, s_rsrc, s_mem_offset) |
| @@ -921,7 +921,7 @@ L_RESTORE: · 920 unmodified lines | ||
| 921 | 921 | /* the END */ |
| 922 | 922 | /**************************************************************************/ |
| 923 | 923 | L_END_PGM: |
| 924 | − s_endpgm | |
| 924 | + s_endpgm_saved | |
| 925 | 925 | |
| 926 | 926 | end |
| 927 | 927 | |
| @@ -1442,7 +1442,9 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep, · 1441 unmodified lines | ||
| 1442 | 1442 | kfd_flush_tlb(peer_pdd, TLB_FLUSH_HEAVYWEIGHT); |
| 1443 | 1443 | |
| 1444 | 1444 | /* Remove dma mapping after tlb flush to avoid IO_PAGE_FAULT */ |
| 1445 | − amdgpu_amdkfd_gpuvm_dmaunmap_mem(mem, peer_pdd->drm_priv); | |
| 1445 | + err = amdgpu_amdkfd_gpuvm_dmaunmap_mem(mem, peer_pdd->drm_priv); | |
| 1446 | + if (err) | |
| 1447 | + goto sync_memory_failed; | |
| 1446 | 1448 | } |
| 1447 | 1449 | |
| 1448 | 1450 | mutex_unlock(&p->mutex); |
| @@ -574,7 +574,7 @@ svm_migrate_copy_to_ram(struct amdgpu_device *adev, struct svm_range *prange, · 573 unmodified lines | ||
| 574 | 574 | pr_debug("svms 0x%p [0x%lx 0x%lx]\n", prange->svms, prange->start, |
| 575 | 575 | prange->last); |
| 576 | 576 | |
| 577 | − addr = prange->start << PAGE_SHIFT; | |
| 577 | + addr = migrate->start; | |
| 578 | 578 | |
| 579 | 579 | src = (uint64_t *)(scratch + npages); |
| 580 | 580 | dst = scratch; |
| @@ -1488,10 +1488,15 @@ void kfd_dec_compute_active(struct kfd_node *dev); · 1487 unmodified lines | ||
| 1488 | 1488 | |
| 1489 | 1489 | /* Cgroup Support */ |
| 1490 | 1490 | /* Check with device cgroup if @kfd device is accessible */ |
| 1491 | −static inline int kfd_devcgroup_check_permission(struct kfd_node *kfd) | |
| 1491 | +static inline int kfd_devcgroup_check_permission(struct kfd_node *node) | |
| 1492 | 1492 | { |
| 1493 | 1493 | #if defined(CONFIG_CGROUP_DEVICE) || defined(CONFIG_CGROUP_BPF) |
| 1494 | − struct drm_device *ddev = adev_to_drm(kfd->adev); | |
| 1494 | + struct drm_device *ddev; | |
| 1495 | + | |
| 1496 | + if (node->xcp) | |
| 1497 | + ddev = node->xcp->ddev; | |
| 1498 | + else | |
| 1499 | + ddev = adev_to_drm(node->adev); | |
| 1495 | 1500 | |
| 1496 | 1501 | return devcgroup_check_permission(DEVCG_DEV_CHAR, DRM_MAJOR, |
| 1497 | 1502 | ddev->render->index, |
| @@ -9187,6 +9187,10 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) · 9186 unmodified lines | ||
| 9187 | 9187 | * To fix this, DC should permit updating only stream properties. |
| 9188 | 9188 | */ |
| 9189 | 9189 | dummy_updates = kzalloc(sizeof(struct dc_surface_update) * MAX_SURFACES, GFP_ATOMIC); |
| 9190 | + if (!dummy_updates) { | |
| 9191 | + DRM_ERROR("Failed to allocate memory for dummy_updates.\n"); | |
| 9192 | + continue; | |
| 9193 | + } | |
| 9190 | 9194 | for (j = 0; j < status->plane_count; j++) |
| 9191 | 9195 | dummy_updates[j].surface = status->plane_states[0]; |
| 9192 | 9196 | |
| @@ -437,32 +437,32 @@ static struct wm_table ddr5_wm_table = { · 436 unmodified lines | ||
| 437 | 437 | .wm_inst = WM_A, |
| 438 | 438 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 439 | 439 | .pstate_latency_us = 11.72, |
| 440 | − .sr_exit_time_us = 14.0, | |
| 441 | − .sr_enter_plus_exit_time_us = 16.0, | |
| 440 | + .sr_exit_time_us = 28.0, | |
| 441 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 442 | 442 | .valid = true, |
| 443 | 443 | }, |
| 444 | 444 | { |
| 445 | 445 | .wm_inst = WM_B, |
| 446 | 446 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 447 | 447 | .pstate_latency_us = 11.72, |
| 448 | − .sr_exit_time_us = 14.0, | |
| 449 | − .sr_enter_plus_exit_time_us = 16.0, | |
| 448 | + .sr_exit_time_us = 28.0, | |
| 449 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 450 | 450 | .valid = true, |
| 451 | 451 | }, |
| 452 | 452 | { |
| 453 | 453 | .wm_inst = WM_C, |
| 454 | 454 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 455 | 455 | .pstate_latency_us = 11.72, |
| 456 | − .sr_exit_time_us = 14.0, | |
| 457 | − .sr_enter_plus_exit_time_us = 16.0, | |
| 456 | + .sr_exit_time_us = 28.0, | |
| 457 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 458 | 458 | .valid = true, |
| 459 | 459 | }, |
| 460 | 460 | { |
| 461 | 461 | .wm_inst = WM_D, |
| 462 | 462 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 463 | 463 | .pstate_latency_us = 11.72, |
| 464 | − .sr_exit_time_us = 14.0, | |
| 465 | − .sr_enter_plus_exit_time_us = 16.0, | |
| 464 | + .sr_exit_time_us = 28.0, | |
| 465 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 466 | 466 | .valid = true, |
| 467 | 467 | }, |
| 468 | 468 | } |
| @@ -474,32 +474,32 @@ static struct wm_table lpddr5_wm_table = { · 5 unmodified lines | ||
| 474 | 474 | .wm_inst = WM_A, |
| 475 | 475 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 476 | 476 | .pstate_latency_us = 11.65333, |
| 477 | − .sr_exit_time_us = 14.0, | |
| 478 | − .sr_enter_plus_exit_time_us = 16.0, | |
| 477 | + .sr_exit_time_us = 28.0, | |
| 478 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 479 | 479 | .valid = true, |
| 480 | 480 | }, |
| 481 | 481 | { |
| 482 | 482 | .wm_inst = WM_B, |
| 483 | 483 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 484 | 484 | .pstate_latency_us = 11.65333, |
| 485 | − .sr_exit_time_us = 14.0, | |
| 486 | − .sr_enter_plus_exit_time_us = 16.0, | |
| 485 | + .sr_exit_time_us = 28.0, | |
| 486 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 487 | 487 | .valid = true, |
| 488 | 488 | }, |
| 489 | 489 | { |
| 490 | 490 | .wm_inst = WM_C, |
| 491 | 491 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 492 | 492 | .pstate_latency_us = 11.65333, |
| 493 | − .sr_exit_time_us = 14.0, | |
| 494 | − .sr_enter_plus_exit_time_us = 16.0, | |
| 493 | + .sr_exit_time_us = 28.0, | |
| 494 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 495 | 495 | .valid = true, |
| 496 | 496 | }, |
| 497 | 497 | { |
| 498 | 498 | .wm_inst = WM_D, |
| 499 | 499 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 500 | 500 | .pstate_latency_us = 11.65333, |
| 501 | − .sr_exit_time_us = 14.0, | |
| 502 | − .sr_enter_plus_exit_time_us = 16.0, | |
| 501 | + .sr_exit_time_us = 28.0, | |
| 502 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 503 | 503 | .valid = true, |
| 504 | 504 | }, |
| 505 | 505 | } |
| @@ -203,12 +203,12 @@ void dcn32_link_encoder_construct( · 202 unmodified lines | ||
| 203 | 203 | enc10->base.hpd_source = init_data->hpd_source; |
| 204 | 204 | enc10->base.connector = init_data->connector; |
| 205 | 205 | |
| 206 | − if (enc10->base.connector.id == CONNECTOR_ID_USBC) | |
| 207 | − enc10->base.features.flags.bits.DP_IS_USB_C = 1; | |
| 208 | 206 | |
| 209 | 207 | enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; |
| 210 | 208 | |
| 211 | 209 | enc10->base.features = *enc_features; |
| 210 | + if (enc10->base.connector.id == CONNECTOR_ID_USBC) | |
| 211 | + enc10->base.features.flags.bits.DP_IS_USB_C = 1; | |
| 212 | 212 | |
| 213 | 213 | enc10->base.transmitter = init_data->transmitter; |
| 214 | 214 | |
| @@ -184,8 +184,6 @@ void dcn35_link_encoder_construct( · 183 unmodified lines | ||
| 184 | 184 | enc10->base.hpd_source = init_data->hpd_source; |
| 185 | 185 | enc10->base.connector = init_data->connector; |
| 186 | 186 | |
| 187 | − if (enc10->base.connector.id == CONNECTOR_ID_USBC) | |
| 188 | − enc10->base.features.flags.bits.DP_IS_USB_C = 1; | |
| 189 | 187 | |
| 190 | 188 | enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; |
| 191 | 189 | |
| @@ -240,6 +238,8 @@ void dcn35_link_encoder_construct( · 48 unmodified lines | ||
| 240 | 238 | } |
| 241 | 239 | |
| 242 | 240 | enc10->base.features.flags.bits.HDMI_6GB_EN = 1; |
| 241 | + if (enc10->base.connector.id == CONNECTOR_ID_USBC) | |
| 242 | + enc10->base.features.flags.bits.DP_IS_USB_C = 1; | |
| 243 | 243 | |
| 244 | 244 | if (bp_funcs->get_connector_speed_cap_info) |
| 245 | 245 | result = bp_funcs->get_connector_speed_cap_info(enc10->base.ctx->dc_bios, |
| @@ -1112,7 +1112,7 @@ struct pipe_slice_table { · 1111 unmodified lines | ||
| 1112 | 1112 | struct pipe_ctx *pri_pipe; |
| 1113 | 1113 | struct dc_plane_state *plane; |
| 1114 | 1114 | int slice_count; |
| 1115 | − } mpc_combines[MAX_SURFACES]; | |
| 1115 | + } mpc_combines[MAX_PLANES]; | |
| 1116 | 1116 | int mpc_combine_count; |
| 1117 | 1117 | }; |
| 1118 | 1118 | |
| @@ -2753,7 +2753,7 @@ static int build_synthetic_soc_states(bool disable_dc_mode_overwrite, struct clk · 1634 unmodified lines | ||
| 2753 | 2753 | struct _vcs_dpi_voltage_scaling_st entry = {0}; |
| 2754 | 2754 | struct clk_limit_table_entry max_clk_data = {0}; |
| 2755 | 2755 | |
| 2756 | − unsigned int min_dcfclk_mhz = 199, min_fclk_mhz = 299; | |
| 2756 | + unsigned int min_dcfclk_mhz = 399, min_fclk_mhz = 599; | |
| 2757 | 2757 | |
| 2758 | 2758 | static const unsigned int num_dcfclk_stas = 5; |
| 2759 | 2759 | unsigned int dcfclk_sta_targets[DC__VOLTAGE_STATES] = {199, 615, 906, 1324, 1564}; |
| @@ -164,8 +164,8 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc = { · 163 unmodified lines | ||
| 164 | 164 | }, |
| 165 | 165 | }, |
| 166 | 166 | .num_states = 5, |
| 167 | − .sr_exit_time_us = 14.0, | |
| 168 | − .sr_enter_plus_exit_time_us = 16.0, | |
| 167 | + .sr_exit_time_us = 28.0, | |
| 168 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 169 | 169 | .sr_exit_z8_time_us = 210.0, |
| 170 | 170 | .sr_enter_plus_exit_z8_time_us = 320.0, |
| 171 | 171 | .fclk_change_latency_us = 24.0, |
| @@ -341,9 +341,6 @@ void dml2_init_soc_states(struct dml2_context *dml2, const struct dc *in_dc, · 340 unmodified lines | ||
| 341 | 341 | break; |
| 342 | 342 | } |
| 343 | 343 | |
| 344 | − if (dml2->config.bbox_overrides.clks_table.num_states) | |
| 345 | − p->in_states->num_states = dml2->config.bbox_overrides.clks_table.num_states; | |
| 346 | − | |
| 347 | 344 | /* Override from passed values, if available */ |
| 348 | 345 | for (i = 0; i < p->in_states->num_states; i++) { |
| 349 | 346 | if (dml2->config.bbox_overrides.sr_exit_latency_us) { |
| @@ -400,6 +397,7 @@ void dml2_init_soc_states(struct dml2_context *dml2, const struct dc *in_dc, · 50 unmodified lines | ||
| 400 | 397 | } |
| 401 | 398 | /* Copy clocks tables entries, if available */ |
| 402 | 399 | if (dml2->config.bbox_overrides.clks_table.num_states) { |
| 400 | + p->in_states->num_states = dml2->config.bbox_overrides.clks_table.num_states; | |
| 403 | 401 | |
| 404 | 402 | for (i = 0; i < dml2->config.bbox_overrides.clks_table.num_entries_per_clk.num_dcfclk_levels; i++) { |
| 405 | 403 | p->in_states->state_array[i].dcfclk_mhz = dml2->config.bbox_overrides.clks_table.clk_entries[i].dcfclk_mhz; |
| @@ -793,35 +791,28 @@ static void populate_dml_surface_cfg_from_plane_state(enum dml_project_id dml2_p · 387 unmodified lines | ||
| 793 | 791 | } |
| 794 | 792 | } |
| 795 | 793 | |
| 796 | −/*TODO no support for mpc combine, need rework - should calculate scaling params based on plane+stream*/ | |
| 797 | −static struct scaler_data get_scaler_data_for_plane(const struct dc_plane_state *in, const struct dc_state *context) | |
| 794 | +static struct scaler_data get_scaler_data_for_plane(const struct dc_plane_state *in, struct dc_state *context) | |
| 798 | 795 | { |
| 799 | 796 | int i; |
| 800 | − struct scaler_data data = { 0 }; | |
| 797 | + struct pipe_ctx *temp_pipe = &context->res_ctx.temp_pipe; | |
| 798 | + | |
| 799 | + memset(temp_pipe, 0, sizeof(struct pipe_ctx)); | |
| 801 | 800 | |
| 802 | 801 | for (i = 0; i < MAX_PIPES; i++) { |
| 803 | 802 | const struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; |
| 804 | 803 | |
| 805 | 804 | if (pipe->plane_state == in && !pipe->prev_odm_pipe) { |
| 806 | − const struct pipe_ctx *next_pipe = pipe->next_odm_pipe; | |
| 807 | − | |
| 808 | − data = context->res_ctx.pipe_ctx[i].plane_res.scl_data; | |
| 809 | − while (next_pipe) { | |
| 810 | − data.h_active += next_pipe->plane_res.scl_data.h_active; | |
| 811 | − data.recout.width += next_pipe->plane_res.scl_data.recout.width; | |
| 812 | − if (in->rotation == ROTATION_ANGLE_0 || in->rotation == ROTATION_ANGLE_180) { | |
| 813 | − data.viewport.width += next_pipe->plane_res.scl_data.viewport.width; | |
| 814 | − } else { | |
| 815 | − data.viewport.height += next_pipe->plane_res.scl_data.viewport.height; | |
| 816 | − } | |
| 817 | − next_pipe = next_pipe->next_odm_pipe; | |
| 818 | − } | |
| 805 | + temp_pipe->stream = pipe->stream; | |
| 806 | + temp_pipe->plane_state = pipe->plane_state; | |
| 807 | + temp_pipe->plane_res.scl_data.taps = pipe->plane_res.scl_data.taps; | |
| 808 | + | |
| 809 | + resource_build_scaling_params(temp_pipe); | |
| 819 | 810 | break; |
| 820 | 811 | } |
| 821 | 812 | } |
| 822 | 813 | |
| 823 | 814 | ASSERT(i < MAX_PIPES); |
| 824 | − return data; | |
| 815 | + return temp_pipe->plane_res.scl_data; | |
| 825 | 816 | } |
| 826 | 817 | |
| 827 | 818 | static void populate_dummy_dml_plane_cfg(struct dml_plane_cfg_st *out, unsigned int location, const struct dc_stream_state *in) |
| @@ -866,7 +857,7 @@ static void populate_dummy_dml_plane_cfg(struct dml_plane_cfg_st *out, unsigned · 38 unmodified lines | ||
| 866 | 857 | out->ScalerEnabled[location] = false; |
| 867 | 858 | } |
| 868 | 859 | |
| 869 | −static void populate_dml_plane_cfg_from_plane_state(struct dml_plane_cfg_st *out, unsigned int location, const struct dc_plane_state *in, const struct dc_state *context) | |
| 860 | +static void populate_dml_plane_cfg_from_plane_state(struct dml_plane_cfg_st *out, unsigned int location, const struct dc_plane_state *in, struct dc_state *context) | |
| 870 | 861 | { |
| 871 | 862 | const struct scaler_data scaler_data = get_scaler_data_for_plane(in, context); |
| 872 | 863 | |
| @@ -1183,9 +1183,9 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) · 1182 unmodified lines | ||
| 1183 | 1183 | dto_params.timing = &pipe_ctx->stream->timing; |
| 1184 | 1184 | dp_hpo_inst = pipe_ctx->stream_res.hpo_dp_stream_enc->inst; |
| 1185 | 1185 | if (dccg) { |
| 1186 | − dccg->funcs->set_dtbclk_dto(dccg, &dto_params); | |
| 1187 | 1186 | dccg->funcs->disable_symclk32_se(dccg, dp_hpo_inst); |
| 1188 | 1187 | dccg->funcs->set_dpstreamclk(dccg, REFCLK, tg->inst, dp_hpo_inst); |
| 1188 | + dccg->funcs->set_dtbclk_dto(dccg, &dto_params); | |
| 1189 | 1189 | } |
| 1190 | 1190 | } else if (dccg && dccg->funcs->disable_symclk_se) { |
| 1191 | 1191 | dccg->funcs->disable_symclk_se(dccg, stream_enc->stream_enc_inst, |
| @@ -2790,18 +2790,17 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) · 2789 unmodified lines | ||
| 2790 | 2790 | } |
| 2791 | 2791 | |
| 2792 | 2792 | if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { |
| 2793 | − dp_hpo_inst = pipe_ctx->stream_res.hpo_dp_stream_enc->inst; | |
| 2794 | − dccg->funcs->set_dpstreamclk(dccg, DTBCLK0, tg->inst, dp_hpo_inst); | |
| 2795 | − | |
| 2796 | − phyd32clk = get_phyd32clk_src(link); | |
| 2797 | − dccg->funcs->enable_symclk32_se(dccg, dp_hpo_inst, phyd32clk); | |
| 2798 | − | |
| 2799 | 2793 | dto_params.otg_inst = tg->inst; |
| 2800 | 2794 | dto_params.pixclk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10; |
| 2801 | 2795 | dto_params.num_odm_segments = get_odm_segment_count(pipe_ctx); |
| 2802 | 2796 | dto_params.timing = &pipe_ctx->stream->timing; |
| 2803 | 2797 | dto_params.ref_dtbclk_khz = dc->clk_mgr->funcs->get_dtb_ref_clk_frequency(dc->clk_mgr); |
| 2804 | 2798 | dccg->funcs->set_dtbclk_dto(dccg, &dto_params); |
| 2799 | + dp_hpo_inst = pipe_ctx->stream_res.hpo_dp_stream_enc->inst; | |
| 2800 | + dccg->funcs->set_dpstreamclk(dccg, DTBCLK0, tg->inst, dp_hpo_inst); | |
| 2801 | + | |
| 2802 | + phyd32clk = get_phyd32clk_src(link); | |
| 2803 | + dccg->funcs->enable_symclk32_se(dccg, dp_hpo_inst, phyd32clk); | |
| 2805 | 2804 | } else { |
| 2806 | 2805 | if (dccg->funcs->enable_symclk_se) |
| 2807 | 2806 | dccg->funcs->enable_symclk_se(dccg, stream_enc->stream_enc_inst, |
| @@ -469,6 +469,8 @@ struct resource_context { · 468 unmodified lines | ||
| 469 | 469 | unsigned int hpo_dp_link_enc_to_link_idx[MAX_HPO_DP2_LINK_ENCODERS]; |
| 470 | 470 | int hpo_dp_link_enc_ref_cnts[MAX_HPO_DP2_LINK_ENCODERS]; |
| 471 | 471 | bool is_mpc_3dlut_acquired[MAX_PIPES]; |
| 472 | + /* solely used for build scalar data in dml2 */ | |
| 473 | + struct pipe_ctx temp_pipe; | |
| 472 | 474 | }; |
| 473 | 475 | |
| 474 | 476 | struct dce_bw_output { |
| @@ -196,7 +196,7 @@ static int get_host_router_total_dp_tunnel_bw(const struct dc *dc, uint8_t hr_in · 195 unmodified lines | ||
| 196 | 196 | struct dc_link *link_dpia_primary, *link_dpia_secondary; |
| 197 | 197 | int total_bw = 0; |
| 198 | 198 | |
| 199 | − for (uint8_t i = 0; i < MAX_PIPES * 2; ++i) { | |
| 199 | + for (uint8_t i = 0; i < (MAX_PIPES * 2) - 1; ++i) { | |
| 200 | 200 | |
| 201 | 201 | if (!dc->links[i] || dc->links[i]->ep_type != DISPLAY_ENDPOINT_USB4_DPIA) |
| 202 | 202 | continue; |
| @@ -734,7 +734,7 @@ static int smu_early_init(void *handle) · 733 unmodified lines | ||
| 734 | 734 | smu->adev = adev; |
| 735 | 735 | smu->pm_enabled = !!amdgpu_dpm; |
| 736 | 736 | smu->is_apu = false; |
| 737 | − smu->smu_baco.state = SMU_BACO_STATE_NONE; | |
| 737 | + smu->smu_baco.state = SMU_BACO_STATE_EXIT; | |
| 738 | 738 | smu->smu_baco.platform_support = false; |
| 739 | 739 | smu->user_dpm_profile.fan_mode = -1; |
| 740 | 740 | |
| @@ -1954,31 +1954,10 @@ static int smu_smc_hw_cleanup(struct smu_context *smu) · 1213 unmodified lines | ||
| 1954 | 1954 | return 0; |
| 1955 | 1955 | } |
| 1956 | 1956 | |
| 1957 | −static int smu_reset_mp1_state(struct smu_context *smu) | |
| 1958 | −{ | |
| 1959 | − struct amdgpu_device *adev = smu->adev; | |
| 1960 | − int ret = 0; | |
| 1961 | − | |
| 1962 | − if ((!adev->in_runpm) && (!adev->in_suspend) && | |
| 1963 | − (!amdgpu_in_reset(adev))) | |
| 1964 | − switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) { | |
| 1965 | − case IP_VERSION(13, 0, 0): | |
| 1966 | − case IP_VERSION(13, 0, 7): | |
| 1967 | − case IP_VERSION(13, 0, 10): | |
| 1968 | − ret = smu_set_mp1_state(smu, PP_MP1_STATE_UNLOAD); | |
| 1969 | − break; | |
| 1970 | − default: | |
| 1971 | − break; | |
| 1972 | − } | |
| 1973 | − | |
| 1974 | − return ret; | |
| 1975 | −} | |
| 1976 | − | |
| 1977 | 1957 | static int smu_hw_fini(void *handle) |
| 1978 | 1958 | { |
| 1979 | 1959 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 1980 | 1960 | struct smu_context *smu = adev->powerplay.pp_handle; |
| 1981 | − int ret; | |
| 1982 | 1961 | |
| 1983 | 1962 | if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) |
| 1984 | 1963 | return 0; |
| @@ -1996,15 +1975,7 @@ static int smu_hw_fini(void *handle) · 11 unmodified lines | ||
| 1996 | 1975 | |
| 1997 | 1976 | adev->pm.dpm_enabled = false; |
| 1998 | 1977 | |
| 1999 | − ret = smu_smc_hw_cleanup(smu); | |
| 2000 | − if (ret) | |
| 2001 | − return ret; | |
| 2002 | − | |
| 2003 | − ret = smu_reset_mp1_state(smu); | |
| 2004 | − if (ret) | |
| 2005 | − return ret; | |
| 2006 | − | |
| 2007 | − return 0; | |
| 1978 | + return smu_smc_hw_cleanup(smu); | |
| 2008 | 1979 | } |
| 2009 | 1980 | |
| 2010 | 1981 | static void smu_late_fini(void *handle) |
| @@ -424,7 +424,6 @@ enum smu_reset_mode { · 423 unmodified lines | ||
| 424 | 424 | enum smu_baco_state { |
| 425 | 425 | SMU_BACO_STATE_ENTER = 0, |
| 426 | 426 | SMU_BACO_STATE_EXIT, |
| 427 | − SMU_BACO_STATE_NONE, | |
| 428 | 427 | }; |
| 429 | 428 | |
| 430 | 429 | struct smu_baco_context { |
| @@ -2748,13 +2748,7 @@ static int smu_v13_0_0_set_mp1_state(struct smu_context *smu, · 2747 unmodified lines | ||
| 2748 | 2748 | |
| 2749 | 2749 | switch (mp1_state) { |
| 2750 | 2750 | case PP_MP1_STATE_UNLOAD: |
| 2751 | − ret = smu_cmn_send_smc_msg_with_param(smu, | |
| 2752 | − SMU_MSG_PrepareMp1ForUnload, | |
| 2753 | − 0x55, NULL); | |
| 2754 | − | |
| 2755 | − if (!ret && smu->smu_baco.state == SMU_BACO_STATE_EXIT) | |
| 2756 | − ret = smu_v13_0_disable_pmfw_state(smu); | |
| 2757 | − | |
| 2751 | + ret = smu_cmn_set_mp1_state(smu, mp1_state); | |
| 2758 | 2752 | break; |
| 2759 | 2753 | default: |
| 2760 | 2754 | /* Ignore others */ |
| @@ -2950,7 +2944,7 @@ static bool smu_v13_0_0_wbrf_support_check(struct smu_context *smu) · 189 unmodified lines | ||
| 2950 | 2944 | { |
| 2951 | 2945 | struct amdgpu_device *adev = smu->adev; |
| 2952 | 2946 | |
| 2953 | − switch (adev->ip_versions[MP1_HWIP][0]) { | |
| 2947 | + switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) { | |
| 2954 | 2948 | case IP_VERSION(13, 0, 0): |
| 2955 | 2949 | return smu->smc_fw_version >= 0x004e6300; |
| 2956 | 2950 | case IP_VERSION(13, 0, 10): |
| @@ -2505,13 +2505,7 @@ static int smu_v13_0_7_set_mp1_state(struct smu_context *smu, · 2504 unmodified lines | ||
| 2505 | 2505 | |
| 2506 | 2506 | switch (mp1_state) { |
| 2507 | 2507 | case PP_MP1_STATE_UNLOAD: |
| 2508 | − ret = smu_cmn_send_smc_msg_with_param(smu, | |
| 2509 | − SMU_MSG_PrepareMp1ForUnload, | |
| 2510 | − 0x55, NULL); | |
| 2511 | − | |
| 2512 | − if (!ret && smu->smu_baco.state == SMU_BACO_STATE_EXIT) | |
| 2513 | − ret = smu_v13_0_disable_pmfw_state(smu); | |
| 2514 | − | |
| 2508 | + ret = smu_cmn_set_mp1_state(smu, mp1_state); | |
| 2515 | 2509 | break; |
| 2516 | 2510 | default: |
| 2517 | 2511 | /* Ignore others */ |
| @@ -103,6 +103,7 @@ nouveau_fence_context_kill(struct nouveau_fence_chan *fctx, int error) · 102 unmodified lines | ||
| 103 | 103 | void |
| 104 | 104 | nouveau_fence_context_del(struct nouveau_fence_chan *fctx) |
| 105 | 105 | { |
| 106 | + cancel_work_sync(&fctx->uevent_work); | |
| 106 | 107 | nouveau_fence_context_kill(fctx, 0); |
| 107 | 108 | nvif_event_dtor(&fctx->event); |
| 108 | 109 | fctx->dead = 1; |
| @@ -145,12 +146,13 @@ nouveau_fence_update(struct nouveau_channel *chan, struct nouveau_fence_chan *fc · 36 unmodified lines | ||
| 145 | 146 | return drop; |
| 146 | 147 | } |
| 147 | 148 | |
| 148 | −static int | |
| 149 | −nouveau_fence_wait_uevent_handler(struct nvif_event *event, void *repv, u32 repc) | |
| 149 | +static void | |
| 150 | +nouveau_fence_uevent_work(struct work_struct *work) | |
| 150 | 151 | { |
| 151 | − struct nouveau_fence_chan *fctx = container_of(event, typeof(*fctx), event); | |
| 152 | + struct nouveau_fence_chan *fctx = container_of(work, struct nouveau_fence_chan, | |
| 153 | + uevent_work); | |
| 152 | 154 | unsigned long flags; |
| 153 | − int ret = NVIF_EVENT_KEEP; | |
| 155 | + int drop = 0; | |
| 154 | 156 | |
| 155 | 157 | spin_lock_irqsave(&fctx->lock, flags); |
| 156 | 158 | if (!list_empty(&fctx->pending)) { |
| @@ -160,11 +162,20 @@ nouveau_fence_wait_uevent_handler(struct nvif_event *event, void *repv, u32 repc · 3 unmodified lines | ||
| 160 | 162 | fence = list_entry(fctx->pending.next, typeof(*fence), head); |
| 161 | 163 | chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock)); |
| 162 | 164 | if (nouveau_fence_update(chan, fctx)) |
| 163 | − ret = NVIF_EVENT_DROP; | |
| 165 | + drop = 1; | |
| 164 | 166 | } |
| 167 | + if (drop) | |
| 168 | + nvif_event_block(&fctx->event); | |
| 169 | + | |
| 165 | 170 | spin_unlock_irqrestore(&fctx->lock, flags); |
| 171 | +} | |
| 166 | 172 | |
| 167 | − return ret; | |
| 173 | +static int | |
| 174 | +nouveau_fence_wait_uevent_handler(struct nvif_event *event, void *repv, u32 repc) | |
| 175 | +{ | |
| 176 | + struct nouveau_fence_chan *fctx = container_of(event, typeof(*fctx), event); | |
| 177 | + schedule_work(&fctx->uevent_work); | |
| 178 | + return NVIF_EVENT_KEEP; | |
| 168 | 179 | } |
| 169 | 180 | |
| 170 | 181 | void |
| @@ -178,6 +189,7 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha · 7 unmodified lines | ||
| 178 | 189 | } args; |
| 179 | 190 | int ret; |
| 180 | 191 | |
| 192 | + INIT_WORK(&fctx->uevent_work, nouveau_fence_uevent_work); | |
| 181 | 193 | INIT_LIST_HEAD(&fctx->flip); |
| 182 | 194 | INIT_LIST_HEAD(&fctx->pending); |
| 183 | 195 | spin_lock_init(&fctx->lock); |
| @@ -44,6 +44,7 @@ struct nouveau_fence_chan { · 43 unmodified lines | ||
| 44 | 44 | u32 context; |
| 45 | 45 | char name[32]; |
| 46 | 46 | |
| 47 | + struct work_struct uevent_work; | |
| 47 | 48 | struct nvif_event event; |
| 48 | 49 | int notify_ref, dead, killed; |
| 49 | 50 | }; |
| @@ -1078,7 +1078,6 @@ r535_gsp_rpc_set_registry(struct nvkm_gsp *gsp) · 1077 unmodified lines | ||
| 1078 | 1078 | if (IS_ERR(rpc)) |
| 1079 | 1079 | return PTR_ERR(rpc); |
| 1080 | 1080 | |
| 1081 | − rpc->size = sizeof(*rpc); | |
| 1082 | 1081 | rpc->numEntries = NV_GSP_REG_NUM_ENTRIES; |
| 1083 | 1082 | |
| 1084 | 1083 | str_offset = offsetof(typeof(*rpc), entries[NV_GSP_REG_NUM_ENTRIES]); |
| @@ -1094,6 +1093,7 @@ r535_gsp_rpc_set_registry(struct nvkm_gsp *gsp) · 9 unmodified lines | ||
| 1094 | 1093 | strings += name_len; |
| 1095 | 1094 | str_offset += name_len; |
| 1096 | 1095 | } |
| 1096 | + rpc->size = str_offset; | |
| 1097 | 1097 | |
| 1098 | 1098 | return nvkm_gsp_rpc_wr(gsp, rpc, false); |
| 1099 | 1099 | } |
| @@ -960,7 +960,8 @@ int host1x_client_iommu_attach(struct host1x_client *client) · 959 unmodified lines | ||
| 960 | 960 | * not the shared IOMMU domain, don't try to attach it to a different |
| 961 | 961 | * domain. This allows using the IOMMU-backed DMA API. |
| 962 | 962 | */ |
| 963 | − if (domain && domain != tegra->domain) | |
| 963 | + if (domain && domain->type != IOMMU_DOMAIN_IDENTITY && | |
| 964 | + domain != tegra->domain) | |
| 964 | 965 | return 0; |
| 965 | 966 | |
| 966 | 967 | if (tegra->domain) { |
| @@ -94,6 +94,7 @@ static int virtio_gpu_probe(struct virtio_device *vdev) · 93 unmodified lines | ||
| 94 | 94 | goto err_free; |
| 95 | 95 | } |
| 96 | 96 | |
| 97 | + dma_set_max_seg_size(dev->dev, dma_max_mapping_size(dev->dev) ?: UINT_MAX); | |
| 97 | 98 | ret = virtio_gpu_init(vdev, dev); |
| 98 | 99 | if (ret) |
| 99 | 100 | goto err_free; |
| @@ -50,8 +50,8 @@ · 49 unmodified lines | ||
| 50 | 50 | |
| 51 | 51 | #define HOST2GUC_SELF_CFG_REQUEST_MSG_LEN (GUC_HXG_REQUEST_MSG_MIN_LEN + 3u) |
| 52 | 52 | #define HOST2GUC_SELF_CFG_REQUEST_MSG_0_MBZ GUC_HXG_REQUEST_MSG_0_DATA0 |
| 53 | −#define HOST2GUC_SELF_CFG_REQUEST_MSG_1_KLV_KEY (0xffff << 16) | |
| 54 | −#define HOST2GUC_SELF_CFG_REQUEST_MSG_1_KLV_LEN (0xffff << 0) | |
| 53 | +#define HOST2GUC_SELF_CFG_REQUEST_MSG_1_KLV_KEY (0xffffu << 16) | |
| 54 | +#define HOST2GUC_SELF_CFG_REQUEST_MSG_1_KLV_LEN (0xffffu << 0) | |
| 55 | 55 | #define HOST2GUC_SELF_CFG_REQUEST_MSG_2_VALUE32 GUC_HXG_REQUEST_MSG_n_DATAn |
| 56 | 56 | #define HOST2GUC_SELF_CFG_REQUEST_MSG_3_VALUE64 GUC_HXG_REQUEST_MSG_n_DATAn |
| 57 | 57 | |
| @@ -242,8 +242,8 @@ struct slpc_shared_data { · 241 unmodified lines | ||
| 242 | 242 | (HOST2GUC_PC_SLPC_REQUEST_REQUEST_MSG_MIN_LEN + \ |
| 243 | 243 | HOST2GUC_PC_SLPC_EVENT_MAX_INPUT_ARGS) |
| 244 | 244 | #define HOST2GUC_PC_SLPC_REQUEST_MSG_0_MBZ GUC_HXG_REQUEST_MSG_0_DATA0 |
| 245 | −#define HOST2GUC_PC_SLPC_REQUEST_MSG_1_EVENT_ID (0xff << 8) | |
| 246 | −#define HOST2GUC_PC_SLPC_REQUEST_MSG_1_EVENT_ARGC (0xff << 0) | |
| 245 | +#define HOST2GUC_PC_SLPC_REQUEST_MSG_1_EVENT_ID (0xffu << 8) | |
| 246 | +#define HOST2GUC_PC_SLPC_REQUEST_MSG_1_EVENT_ARGC (0xffu << 0) | |
| 247 | 247 | #define HOST2GUC_PC_SLPC_REQUEST_MSG_N_EVENT_DATA_N GUC_HXG_REQUEST_MSG_n_DATAn |
| 248 | 248 | |
| 249 | 249 | #endif |
| @@ -82,11 +82,11 @@ static_assert(sizeof(struct guc_ct_buffer_desc) == 64); · 81 unmodified lines | ||
| 82 | 82 | #define GUC_CTB_HDR_LEN 1u |
| 83 | 83 | #define GUC_CTB_MSG_MIN_LEN GUC_CTB_HDR_LEN |
| 84 | 84 | #define GUC_CTB_MSG_MAX_LEN 256u |
| 85 | −#define GUC_CTB_MSG_0_FENCE (0xffff << 16) | |
| 86 | −#define GUC_CTB_MSG_0_FORMAT (0xf << 12) | |
| 85 | +#define GUC_CTB_MSG_0_FENCE (0xffffu << 16) | |
| 86 | +#define GUC_CTB_MSG_0_FORMAT (0xfu << 12) | |
| 87 | 87 | #define GUC_CTB_FORMAT_HXG 0u |
| 88 | −#define GUC_CTB_MSG_0_RESERVED (0xf << 8) | |
| 89 | −#define GUC_CTB_MSG_0_NUM_DWORDS (0xff << 0) | |
| 88 | +#define GUC_CTB_MSG_0_RESERVED (0xfu << 8) | |
| 89 | +#define GUC_CTB_MSG_0_NUM_DWORDS (0xffu << 0) | |
| 90 | 90 | |
| 91 | 91 | /** |
| 92 | 92 | * DOC: CTB HXG Message |
| @@ -31,9 +31,9 @@ · 30 unmodified lines | ||
| 31 | 31 | */ |
| 32 | 32 | |
| 33 | 33 | #define GUC_KLV_LEN_MIN 1u |
| 34 | −#define GUC_KLV_0_KEY (0xffff << 16) | |
| 35 | −#define GUC_KLV_0_LEN (0xffff << 0) | |
| 36 | −#define GUC_KLV_n_VALUE (0xffffffff << 0) | |
| 34 | +#define GUC_KLV_0_KEY (0xffffu << 16) | |
| 35 | +#define GUC_KLV_0_LEN (0xffffu << 0) | |
| 36 | +#define GUC_KLV_n_VALUE (0xffffffffu << 0) | |
| 37 | 37 | |
| 38 | 38 | /** |
| 39 | 39 | * DOC: GuC Self Config KLVs |
| @@ -40,18 +40,18 @@ · 39 unmodified lines | ||
| 40 | 40 | */ |
| 41 | 41 | |
| 42 | 42 | #define GUC_HXG_MSG_MIN_LEN 1u |
| 43 | −#define GUC_HXG_MSG_0_ORIGIN (0x1 << 31) | |
| 43 | +#define GUC_HXG_MSG_0_ORIGIN (0x1u << 31) | |
| 44 | 44 | #define GUC_HXG_ORIGIN_HOST 0u |
| 45 | 45 | #define GUC_HXG_ORIGIN_GUC 1u |
| 46 | −#define GUC_HXG_MSG_0_TYPE (0x7 << 28) | |
| 46 | +#define GUC_HXG_MSG_0_TYPE (0x7u << 28) | |
| 47 | 47 | #define GUC_HXG_TYPE_REQUEST 0u |
| 48 | 48 | #define GUC_HXG_TYPE_EVENT 1u |
| 49 | 49 | #define GUC_HXG_TYPE_NO_RESPONSE_BUSY 3u |
| 50 | 50 | #define GUC_HXG_TYPE_NO_RESPONSE_RETRY 5u |
| 51 | 51 | #define GUC_HXG_TYPE_RESPONSE_FAILURE 6u |
| 52 | 52 | #define GUC_HXG_TYPE_RESPONSE_SUCCESS 7u |
| 53 | −#define GUC_HXG_MSG_0_AUX (0xfffffff << 0) | |
| 54 | −#define GUC_HXG_MSG_n_PAYLOAD (0xffffffff << 0) | |
| 53 | +#define GUC_HXG_MSG_0_AUX (0xfffffffu << 0) | |
| 54 | +#define GUC_HXG_MSG_n_PAYLOAD (0xffffffffu << 0) | |
| 55 | 55 | |
| 56 | 56 | /** |
| 57 | 57 | * DOC: HXG Request |
| @@ -85,8 +85,8 @@ · 27 unmodified lines | ||
| 85 | 85 | */ |
| 86 | 86 | |
| 87 | 87 | #define GUC_HXG_REQUEST_MSG_MIN_LEN GUC_HXG_MSG_MIN_LEN |
| 88 | −#define GUC_HXG_REQUEST_MSG_0_DATA0 (0xfff << 16) | |
| 89 | −#define GUC_HXG_REQUEST_MSG_0_ACTION (0xffff << 0) | |
| 88 | +#define GUC_HXG_REQUEST_MSG_0_DATA0 (0xfffu << 16) | |
| 89 | +#define GUC_HXG_REQUEST_MSG_0_ACTION (0xffffu << 0) | |
| 90 | 90 | #define GUC_HXG_REQUEST_MSG_n_DATAn GUC_HXG_MSG_n_PAYLOAD |
| 91 | 91 | |
| 92 | 92 | /** |
| @@ -117,8 +117,8 @@ · 24 unmodified lines | ||
| 117 | 117 | */ |
| 118 | 118 | |
| 119 | 119 | #define GUC_HXG_EVENT_MSG_MIN_LEN GUC_HXG_MSG_MIN_LEN |
| 120 | −#define GUC_HXG_EVENT_MSG_0_DATA0 (0xfff << 16) | |
| 121 | −#define GUC_HXG_EVENT_MSG_0_ACTION (0xffff << 0) | |
| 120 | +#define GUC_HXG_EVENT_MSG_0_DATA0 (0xfffu << 16) | |
| 121 | +#define GUC_HXG_EVENT_MSG_0_ACTION (0xffffu << 0) | |
| 122 | 122 | #define GUC_HXG_EVENT_MSG_n_DATAn GUC_HXG_MSG_n_PAYLOAD |
| 123 | 123 | |
| 124 | 124 | /** |
| @@ -188,8 +188,8 @@ · 63 unmodified lines | ||
| 188 | 188 | */ |
| 189 | 189 | |
| 190 | 190 | #define GUC_HXG_FAILURE_MSG_LEN GUC_HXG_MSG_MIN_LEN |
| 191 | −#define GUC_HXG_FAILURE_MSG_0_HINT (0xfff << 16) | |
| 192 | −#define GUC_HXG_FAILURE_MSG_0_ERROR (0xffff << 0) | |
| 191 | +#define GUC_HXG_FAILURE_MSG_0_HINT (0xfffu << 16) | |
| 192 | +#define GUC_HXG_FAILURE_MSG_0_ERROR (0xffffu << 0) | |
| 193 | 193 | |
| 194 | 194 | /** |
| 195 | 195 | * DOC: HXG Response |
| @@ -111,7 +111,7 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file) · 110 unmodified lines | ||
| 111 | 111 | u64 addresses[XE_HW_ENGINE_MAX_INSTANCE]; |
| 112 | 112 | struct drm_gpuvm_exec vm_exec = {.extra.fn = xe_exec_fn}; |
| 113 | 113 | struct drm_exec *exec = &vm_exec.exec; |
| 114 | − u32 i, num_syncs = 0; | |
| 114 | + u32 i, num_syncs = 0, num_ufence = 0; | |
| 115 | 115 | struct xe_sched_job *job; |
| 116 | 116 | struct dma_fence *rebind_fence; |
| 117 | 117 | struct xe_vm *vm; |
| @@ -157,6 +157,14 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file) · 39 unmodified lines | ||
| 157 | 157 | SYNC_PARSE_FLAG_LR_MODE : 0)); |
| 158 | 158 | if (err) |
| 159 | 159 | goto err_syncs; |
| 160 | + | |
| 161 | + if (xe_sync_is_ufence(&syncs[i])) | |
| 162 | + num_ufence++; | |
| 163 | + } | |
| 164 | + | |
| 165 | + if (XE_IOCTL_DBG(xe, num_ufence > 1)) { | |
| 166 | + err = -EINVAL; | |
| 167 | + goto err_syncs; | |
| 160 | 168 | } |
| 161 | 169 | |
| 162 | 170 | if (xe_exec_queue_is_parallel(q)) { |
| @@ -480,7 +480,7 @@ static bool xe_gt_mcr_get_nonterminated_steering(struct xe_gt *gt, · 479 unmodified lines | ||
| 480 | 480 | * to synchronize with external clients (e.g., firmware), so a semaphore |
| 481 | 481 | * register will also need to be taken. |
| 482 | 482 | */ |
| 483 | −static void mcr_lock(struct xe_gt *gt) | |
| 483 | +static void mcr_lock(struct xe_gt *gt) __acquires(>->mcr_lock) | |
| 484 | 484 | { |
| 485 | 485 | struct xe_device *xe = gt_to_xe(gt); |
| 486 | 486 | int ret = 0; |
| @@ -500,7 +500,7 @@ static void mcr_lock(struct xe_gt *gt) · 13 unmodified lines | ||
| 500 | 500 | drm_WARN_ON_ONCE(&xe->drm, ret == -ETIMEDOUT); |
| 501 | 501 | } |
| 502 | 502 | |
| 503 | −static void mcr_unlock(struct xe_gt *gt) | |
| 503 | +static void mcr_unlock(struct xe_gt *gt) __releases(>->mcr_lock) | |
| 504 | 504 | { |
| 505 | 505 | /* Release hardware semaphore - this is done by writing 1 to the register */ |
| 506 | 506 | if (GRAPHICS_VERx100(gt_to_xe(gt)) >= 1270) |
| @@ -165,7 +165,8 @@ retry_userptr: · 164 unmodified lines | ||
| 165 | 165 | goto unlock_vm; |
| 166 | 166 | } |
| 167 | 167 | |
| 168 | − if (!xe_vma_is_userptr(vma) || !xe_vma_userptr_check_repin(vma)) { | |
| 168 | + if (!xe_vma_is_userptr(vma) || | |
| 169 | + !xe_vma_userptr_check_repin(to_userptr_vma(vma))) { | |
| 169 | 170 | downgrade_write(&vm->lock); |
| 170 | 171 | write_locked = false; |
| 171 | 172 | } |
| @@ -181,11 +182,13 @@ retry_userptr: · 9 unmodified lines | ||
| 181 | 182 | /* TODO: Validate fault */ |
| 182 | 183 | |
| 183 | 184 | if (xe_vma_is_userptr(vma) && write_locked) { |
| 185 | + struct xe_userptr_vma *uvma = to_userptr_vma(vma); | |
| 186 | + | |
| 184 | 187 | spin_lock(&vm->userptr.invalidated_lock); |
| 185 | − list_del_init(&vma->userptr.invalidate_link); | |
| 188 | + list_del_init(&uvma->userptr.invalidate_link); | |
| 186 | 189 | spin_unlock(&vm->userptr.invalidated_lock); |
| 187 | 190 | |
| 188 | − ret = xe_vma_userptr_pin_pages(vma); | |
| 191 | + ret = xe_vma_userptr_pin_pages(uvma); | |
| 189 | 192 | if (ret) |
| 190 | 193 | goto unlock_vm; |
| 191 | 194 | |
| @@ -220,7 +223,7 @@ retry_userptr: · 28 unmodified lines | ||
| 220 | 223 | dma_fence_put(fence); |
| 221 | 224 | |
| 222 | 225 | if (xe_vma_is_userptr(vma)) |
| 223 | − ret = xe_vma_userptr_check_repin(vma); | |
| 226 | + ret = xe_vma_userptr_check_repin(to_userptr_vma(vma)); | |
| 224 | 227 | vma->usm.tile_invalidated &= ~BIT(tile->id); |
| 225 | 228 | |
| 226 | 229 | unlock_dma_resv: |
| @@ -963,7 +963,9 @@ void xe_guc_pc_fini(struct xe_guc_pc *pc) · 962 unmodified lines | ||
| 963 | 963 | struct xe_device *xe = pc_to_xe(pc); |
| 964 | 964 | |
| 965 | 965 | if (xe->info.skip_guc_pc) { |
| 966 | + xe_device_mem_access_get(xe); | |
| 966 | 967 | xe_gt_idle_disable_c6(pc_to_gt(pc)); |
| 968 | + xe_device_mem_access_put(xe); | |
| 967 | 969 | return; |
| 968 | 970 | } |
| 969 | 971 | |
| @@ -217,13 +217,13 @@ struct xe_hw_fence *xe_hw_fence_create(struct xe_hw_fence_ctx *ctx, · 216 unmodified lines | ||
| 217 | 217 | if (!fence) |
| 218 | 218 | return ERR_PTR(-ENOMEM); |
| 219 | 219 | |
| 220 | − dma_fence_init(&fence->dma, &xe_hw_fence_ops, &ctx->irq->lock, | |
| 221 | − ctx->dma_fence_ctx, ctx->next_seqno++); | |
| 222 | − | |
| 223 | 220 | fence->ctx = ctx; |
| 224 | 221 | fence->seqno_map = seqno_map; |
| 225 | 222 | INIT_LIST_HEAD(&fence->irq_link); |
| 226 | 223 | |
| 224 | + dma_fence_init(&fence->dma, &xe_hw_fence_ops, &ctx->irq->lock, | |
| 225 | + ctx->dma_fence_ctx, ctx->next_seqno++); | |
| 226 | + | |
| 227 | 227 | trace_xe_hw_fence_create(fence); |
| 228 | 228 | |
| 229 | 229 | return fence; |
| @@ -21,10 +21,10 @@ · 20 unmodified lines | ||
| 21 | 21 | #include "xe_map.h" |
| 22 | 22 | #include "xe_vm.h" |
| 23 | 23 | |
| 24 | −#define CTX_VALID (1 << 0) | |
| 25 | −#define CTX_PRIVILEGE (1 << 8) | |
| 26 | −#define CTX_ADDRESSING_MODE_SHIFT 3 | |
| 27 | −#define LEGACY_64B_CONTEXT 3 | |
| 24 | +#define LRC_VALID (1 << 0) | |
| 25 | +#define LRC_PRIVILEGE (1 << 8) | |
| 26 | +#define LRC_ADDRESSING_MODE_SHIFT 3 | |
| 27 | +#define LRC_LEGACY_64B_CONTEXT 3 | |
| 28 | 28 | |
| 29 | 29 | #define ENGINE_CLASS_SHIFT 61 |
| 30 | 30 | #define ENGINE_INSTANCE_SHIFT 48 |
| @@ -762,15 +762,15 @@ int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, · 731 unmodified lines | ||
| 762 | 762 | (q->usm.acc_notify << ACC_NOTIFY_S) | |
| 763 | 763 | q->usm.acc_trigger); |
| 764 | 764 | |
| 765 | − lrc->desc = CTX_VALID; | |
| 766 | − lrc->desc |= LEGACY_64B_CONTEXT << CTX_ADDRESSING_MODE_SHIFT; | |
| 765 | + lrc->desc = LRC_VALID; | |
| 766 | + lrc->desc |= LRC_LEGACY_64B_CONTEXT << LRC_ADDRESSING_MODE_SHIFT; | |
| 767 | 767 | /* TODO: Priority */ |
| 768 | 768 | |
| 769 | 769 | /* While this appears to have something about privileged batches or |
| 770 | 770 | * some such, it really just means PPGTT mode. |
| 771 | 771 | */ |
| 772 | 772 | if (vm) |
| 773 | − lrc->desc |= CTX_PRIVILEGE; | |
| 773 | + lrc->desc |= LRC_PRIVILEGE; | |
| 774 | 774 | |
| 775 | 775 | if (GRAPHICS_VERx100(xe) < 1250) { |
| 776 | 776 | lrc->desc |= (u64)hwe->instance << ENGINE_INSTANCE_SHIFT; |
| @@ -618,8 +618,8 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma, · 617 unmodified lines | ||
| 618 | 618 | |
| 619 | 619 | if (!xe_vma_is_null(vma)) { |
| 620 | 620 | if (xe_vma_is_userptr(vma)) |
| 621 | − xe_res_first_sg(vma->userptr.sg, 0, xe_vma_size(vma), | |
| 622 | − &curs); | |
| 621 | + xe_res_first_sg(to_userptr_vma(vma)->userptr.sg, 0, | |
| 622 | + xe_vma_size(vma), &curs); | |
| 623 | 623 | else if (xe_bo_is_vram(bo) || xe_bo_is_stolen(bo)) |
| 624 | 624 | xe_res_first(bo->ttm.resource, xe_vma_bo_offset(vma), |
| 625 | 625 | xe_vma_size(vma), &curs); |
| @@ -906,17 +906,17 @@ static void xe_vm_dbg_print_entries(struct xe_device *xe, · 280 unmodified lines | ||
| 906 | 906 | |
| 907 | 907 | #ifdef CONFIG_DRM_XE_USERPTR_INVAL_INJECT |
| 908 | 908 | |
| 909 | −static int xe_pt_userptr_inject_eagain(struct xe_vma *vma) | |
| 909 | +static int xe_pt_userptr_inject_eagain(struct xe_userptr_vma *uvma) | |
| 910 | 910 | { |
| 911 | − u32 divisor = vma->userptr.divisor ? vma->userptr.divisor : 2; | |
| 911 | + u32 divisor = uvma->userptr.divisor ? uvma->userptr.divisor : 2; | |
| 912 | 912 | static u32 count; |
| 913 | 913 | |
| 914 | 914 | if (count++ % divisor == divisor - 1) { |
| 915 | − struct xe_vm *vm = xe_vma_vm(vma); | |
| 915 | + struct xe_vm *vm = xe_vma_vm(&uvma->vma); | |
| 916 | 916 | |
| 917 | − vma->userptr.divisor = divisor << 1; | |
| 917 | + uvma->userptr.divisor = divisor << 1; | |
| 918 | 918 | spin_lock(&vm->userptr.invalidated_lock); |
| 919 | − list_move_tail(&vma->userptr.invalidate_link, | |
| 919 | + list_move_tail(&uvma->userptr.invalidate_link, | |
| 920 | 920 | &vm->userptr.invalidated); |
| 921 | 921 | spin_unlock(&vm->userptr.invalidated_lock); |
| 922 | 922 | return true; |
| @@ -927,7 +927,7 @@ static int xe_pt_userptr_inject_eagain(struct xe_vma *vma) · 4 unmodified lines | ||
| 927 | 927 | |
| 928 | 928 | #else |
| 929 | 929 | |
| 930 | −static bool xe_pt_userptr_inject_eagain(struct xe_vma *vma) | |
| 930 | +static bool xe_pt_userptr_inject_eagain(struct xe_userptr_vma *uvma) | |
| 931 | 931 | { |
| 932 | 932 | return false; |
| 933 | 933 | } |
| @@ -1000,9 +1000,9 @@ static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update) · 66 unmodified lines | ||
| 1000 | 1000 | { |
| 1001 | 1001 | struct xe_pt_migrate_pt_update *userptr_update = |
| 1002 | 1002 | container_of(pt_update, typeof(*userptr_update), base); |
| 1003 | − struct xe_vma *vma = pt_update->vma; | |
| 1004 | − unsigned long notifier_seq = vma->userptr.notifier_seq; | |
| 1005 | − struct xe_vm *vm = xe_vma_vm(vma); | |
| 1003 | + struct xe_userptr_vma *uvma = to_userptr_vma(pt_update->vma); | |
| 1004 | + unsigned long notifier_seq = uvma->userptr.notifier_seq; | |
| 1005 | + struct xe_vm *vm = xe_vma_vm(&uvma->vma); | |
| 1006 | 1006 | int err = xe_pt_vm_dependencies(pt_update->job, |
| 1007 | 1007 | &vm->rftree[pt_update->tile_id], |
| 1008 | 1008 | pt_update->start, |
| @@ -1023,7 +1023,7 @@ static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update) · 14 unmodified lines | ||
| 1023 | 1023 | */ |
| 1024 | 1024 | do { |
| 1025 | 1025 | down_read(&vm->userptr.notifier_lock); |
| 1026 | − if (!mmu_interval_read_retry(&vma->userptr.notifier, | |
| 1026 | + if (!mmu_interval_read_retry(&uvma->userptr.notifier, | |
| 1027 | 1027 | notifier_seq)) |
| 1028 | 1028 | break; |
| 1029 | 1029 | |
| @@ -1032,11 +1032,11 @@ static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update) · 2 unmodified lines | ||
| 1032 | 1032 | if (userptr_update->bind) |
| 1033 | 1033 | return -EAGAIN; |
| 1034 | 1034 | |
| 1035 | − notifier_seq = mmu_interval_read_begin(&vma->userptr.notifier); | |
| 1035 | + notifier_seq = mmu_interval_read_begin(&uvma->userptr.notifier); | |
| 1036 | 1036 | } while (true); |
| 1037 | 1037 | |
| 1038 | 1038 | /* Inject errors to test_whether they are handled correctly */ |
| 1039 | − if (userptr_update->bind && xe_pt_userptr_inject_eagain(vma)) { | |
| 1039 | + if (userptr_update->bind && xe_pt_userptr_inject_eagain(uvma)) { | |
| 1040 | 1040 | up_read(&vm->userptr.notifier_lock); |
| 1041 | 1041 | return -EAGAIN; |
| 1042 | 1042 | } |
| @@ -1297,7 +1297,7 @@ __xe_pt_bind_vma(struct xe_tile *tile, struct xe_vma *vma, struct xe_exec_queue · 254 unmodified lines | ||
| 1297 | 1297 | vma->tile_present |= BIT(tile->id); |
| 1298 | 1298 | |
| 1299 | 1299 | if (bind_pt_update.locked) { |
| 1300 | − vma->userptr.initial_bind = true; | |
| 1300 | + to_userptr_vma(vma)->userptr.initial_bind = true; | |
| 1301 | 1301 | up_read(&vm->userptr.notifier_lock); |
| 1302 | 1302 | xe_bo_put_commit(&deferred); |
| 1303 | 1303 | } |
| @@ -1642,7 +1642,7 @@ __xe_pt_unbind_vma(struct xe_tile *tile, struct xe_vma *vma, struct xe_exec_queu · 338 unmodified lines | ||
| 1642 | 1642 | |
| 1643 | 1643 | if (!vma->tile_present) { |
| 1644 | 1644 | spin_lock(&vm->userptr.invalidated_lock); |
| 1645 | − list_del_init(&vma->userptr.invalidate_link); | |
| 1645 | + list_del_init(&to_userptr_vma(vma)->userptr.invalidate_link); | |
| 1646 | 1646 | spin_unlock(&vm->userptr.invalidated_lock); |
| 1647 | 1647 | } |
| 1648 | 1648 | up_read(&vm->userptr.notifier_lock); |
| @@ -459,21 +459,21 @@ static size_t calc_topo_query_size(struct xe_device *xe) · 458 unmodified lines | ||
| 459 | 459 | sizeof_field(struct xe_gt, fuse_topo.eu_mask_per_dss)); |
| 460 | 460 | } |
| 461 | 461 | |
| 462 | −static void __user *copy_mask(void __user *ptr, | |
| 463 | − struct drm_xe_query_topology_mask *topo, | |
| 464 | − void *mask, size_t mask_size) | |
| 462 | +static int copy_mask(void __user **ptr, | |
| 463 | + struct drm_xe_query_topology_mask *topo, | |
| 464 | + void *mask, size_t mask_size) | |
| 465 | 465 | { |
| 466 | 466 | topo->num_bytes = mask_size; |
| 467 | 467 | |
| 468 | − if (copy_to_user(ptr, topo, sizeof(*topo))) | |
| 469 | − return ERR_PTR(-EFAULT); | |
| 470 | − ptr += sizeof(topo); | |
| 468 | + if (copy_to_user(*ptr, topo, sizeof(*topo))) | |
| 469 | + return -EFAULT; | |
| 470 | + *ptr += sizeof(topo); | |
| 471 | 471 | |
| 472 | − if (copy_to_user(ptr, mask, mask_size)) | |
| 473 | − return ERR_PTR(-EFAULT); | |
| 474 | − ptr += mask_size; | |
| 472 | + if (copy_to_user(*ptr, mask, mask_size)) | |
| 473 | + return -EFAULT; | |
| 474 | + *ptr += mask_size; | |
| 475 | 475 | |
| 476 | − return ptr; | |
| 476 | + return 0; | |
| 477 | 477 | } |
| 478 | 478 | |
| 479 | 479 | static int query_gt_topology(struct xe_device *xe, |
| @@ -493,28 +493,28 @@ static int query_gt_topology(struct xe_device *xe, · 13 unmodified lines | ||
| 493 | 493 | } |
| 494 | 494 | |
| 495 | 495 | for_each_gt(gt, xe, id) { |
| 496 | + int err; | |
| 497 | + | |
| 496 | 498 | topo.gt_id = id; |
| 497 | 499 | |
| 498 | 500 | topo.type = DRM_XE_TOPO_DSS_GEOMETRY; |
| 499 | − query_ptr = copy_mask(query_ptr, &topo, | |
| 500 | − gt->fuse_topo.g_dss_mask, | |
| 501 | − sizeof(gt->fuse_topo.g_dss_mask)); | |
| 502 | − if (IS_ERR(query_ptr)) | |
| 503 | − return PTR_ERR(query_ptr); | |
| 501 | + err = copy_mask(&query_ptr, &topo, gt->fuse_topo.g_dss_mask, | |
| 502 | + sizeof(gt->fuse_topo.g_dss_mask)); | |
| 503 | + if (err) | |
| 504 | + return err; | |
| 504 | 505 | |
| 505 | 506 | topo.type = DRM_XE_TOPO_DSS_COMPUTE; |
| 506 | − query_ptr = copy_mask(query_ptr, &topo, | |
| 507 | − gt->fuse_topo.c_dss_mask, | |
| 508 | − sizeof(gt->fuse_topo.c_dss_mask)); | |
| 509 | − if (IS_ERR(query_ptr)) | |
| 510 | − return PTR_ERR(query_ptr); | |
| 507 | + err = copy_mask(&query_ptr, &topo, gt->fuse_topo.c_dss_mask, | |
| 508 | + sizeof(gt->fuse_topo.c_dss_mask)); | |
| 509 | + if (err) | |
| 510 | + return err; | |
| 511 | 511 | |
| 512 | 512 | topo.type = DRM_XE_TOPO_EU_PER_DSS; |
| 513 | − query_ptr = copy_mask(query_ptr, &topo, | |
| 514 | − gt->fuse_topo.eu_mask_per_dss, | |
| 515 | − sizeof(gt->fuse_topo.eu_mask_per_dss)); | |
| 516 | − if (IS_ERR(query_ptr)) | |
| 517 | − return PTR_ERR(query_ptr); | |
| 513 | + err = copy_mask(&query_ptr, &topo, | |
| 514 | + gt->fuse_topo.eu_mask_per_dss, | |
| 515 | + sizeof(gt->fuse_topo.eu_mask_per_dss)); | |
| 516 | + if (err) | |
| 517 | + return err; | |
| 518 | 518 | } |
| 519 | 519 | |
| 520 | 520 | return 0; |
| @@ -33,4 +33,9 @@ struct dma_fence * · 32 unmodified lines | ||
| 33 | 33 | xe_sync_in_fence_get(struct xe_sync_entry *sync, int num_sync, |
| 34 | 34 | struct xe_exec_queue *q, struct xe_vm *vm); |
| 35 | 35 | |
| 36 | +static inline bool xe_sync_is_ufence(struct xe_sync_entry *sync) | |
| 37 | +{ | |
| 38 | + return !!sync->ufence; | |
| 39 | +} | |
| 40 | + | |
| 36 | 41 | #endif |
| @@ -46,7 +46,7 @@ static struct drm_gem_object *xe_vm_obj(struct xe_vm *vm) · 45 unmodified lines | ||
| 46 | 46 | |
| 47 | 47 | /** |
| 48 | 48 | * xe_vma_userptr_check_repin() - Advisory check for repin needed |
| 49 | − * @vma: The userptr vma | |
| 49 | + * @uvma: The userptr vma | |
| 50 | 50 | * |
| 51 | 51 | * Check if the userptr vma has been invalidated since last successful |
| 52 | 52 | * repin. The check is advisory only and can the function can be called |
| @@ -56,15 +56,17 @@ static struct drm_gem_object *xe_vm_obj(struct xe_vm *vm) · 3 unmodified lines | ||
| 56 | 56 | * |
| 57 | 57 | * Return: 0 if userptr vma is valid, -EAGAIN otherwise; repin recommended. |
| 58 | 58 | */ |
| 59 | −int xe_vma_userptr_check_repin(struct xe_vma *vma) | |
| 59 | +int xe_vma_userptr_check_repin(struct xe_userptr_vma *uvma) | |
| 60 | 60 | { |
| 61 | − return mmu_interval_check_retry(&vma->userptr.notifier, | |
| 62 | − vma->userptr.notifier_seq) ? | |
| 61 | + return mmu_interval_check_retry(&uvma->userptr.notifier, | |
| 62 | + uvma->userptr.notifier_seq) ? | |
| 63 | 63 | -EAGAIN : 0; |
| 64 | 64 | } |
| 65 | 65 | |
| 66 | −int xe_vma_userptr_pin_pages(struct xe_vma *vma) | |
| 66 | +int xe_vma_userptr_pin_pages(struct xe_userptr_vma *uvma) | |
| 67 | 67 | { |
| 68 | + struct xe_userptr *userptr = &uvma->userptr; | |
| 69 | + struct xe_vma *vma = &uvma->vma; | |
| 68 | 70 | struct xe_vm *vm = xe_vma_vm(vma); |
| 69 | 71 | struct xe_device *xe = vm->xe; |
| 70 | 72 | const unsigned long num_pages = xe_vma_size(vma) >> PAGE_SHIFT; |
| @@ -80,30 +82,30 @@ retry: · 9 unmodified lines | ||
| 80 | 82 | if (vma->gpuva.flags & XE_VMA_DESTROYED) |
| 81 | 83 | return 0; |
| 82 | 84 | |
| 83 | − notifier_seq = mmu_interval_read_begin(&vma->userptr.notifier); | |
| 84 | − if (notifier_seq == vma->userptr.notifier_seq) | |
| 85 | + notifier_seq = mmu_interval_read_begin(&userptr->notifier); | |
| 86 | + if (notifier_seq == userptr->notifier_seq) | |
| 85 | 87 | return 0; |
| 86 | 88 | |
| 87 | 89 | pages = kvmalloc_array(num_pages, sizeof(*pages), GFP_KERNEL); |
| 88 | 90 | if (!pages) |
| 89 | 91 | return -ENOMEM; |
| 90 | 92 | |
| 91 | − if (vma->userptr.sg) { | |
| 93 | + if (userptr->sg) { | |
| 92 | 94 | dma_unmap_sgtable(xe->drm.dev, |
| 93 | − vma->userptr.sg, | |
| 95 | + userptr->sg, | |
| 94 | 96 | read_only ? DMA_TO_DEVICE : |
| 95 | 97 | DMA_BIDIRECTIONAL, 0); |
| 96 | − sg_free_table(vma->userptr.sg); | |
| 97 | − vma->userptr.sg = NULL; | |
| 98 | + sg_free_table(userptr->sg); | |
| 99 | + userptr->sg = NULL; | |
| 98 | 100 | } |
| 99 | 101 | |
| 100 | 102 | pinned = ret = 0; |
| 101 | 103 | if (in_kthread) { |
| 102 | − if (!mmget_not_zero(vma->userptr.notifier.mm)) { | |
| 104 | + if (!mmget_not_zero(userptr->notifier.mm)) { | |
| 103 | 105 | ret = -EFAULT; |
| 104 | 106 | goto mm_closed; |
| 105 | 107 | } |
| 106 | − kthread_use_mm(vma->userptr.notifier.mm); | |
| 108 | + kthread_use_mm(userptr->notifier.mm); | |
| 107 | 109 | } |
| 108 | 110 | |
| 109 | 111 | while (pinned < num_pages) { |
| @@ -123,32 +125,32 @@ retry: · 13 unmodified lines | ||
| 123 | 125 | } |
| 124 | 126 | |
| 125 | 127 | if (in_kthread) { |
| 126 | − kthread_unuse_mm(vma->userptr.notifier.mm); | |
| 127 | − mmput(vma->userptr.notifier.mm); | |
| 128 | + kthread_unuse_mm(userptr->notifier.mm); | |
| 129 | + mmput(userptr->notifier.mm); | |
| 128 | 130 | } |
| 129 | 131 | mm_closed: |
| 130 | 132 | if (ret) |
| 131 | 133 | goto out; |
| 132 | 134 | |
| 133 | − ret = sg_alloc_table_from_pages_segment(&vma->userptr.sgt, pages, | |
| 135 | + ret = sg_alloc_table_from_pages_segment(&userptr->sgt, pages, | |
| 134 | 136 | pinned, 0, |
| 135 | 137 | (u64)pinned << PAGE_SHIFT, |
| 136 | 138 | xe_sg_segment_size(xe->drm.dev), |
| 137 | 139 | GFP_KERNEL); |
| 138 | 140 | if (ret) { |
| 139 | − vma->userptr.sg = NULL; | |
| 141 | + userptr->sg = NULL; | |
| 140 | 142 | goto out; |
| 141 | 143 | } |
| 142 | − vma->userptr.sg = &vma->userptr.sgt; | |
| 144 | + userptr->sg = &userptr->sgt; | |
| 143 | 145 | |
| 144 | − ret = dma_map_sgtable(xe->drm.dev, vma->userptr.sg, | |
| 146 | + ret = dma_map_sgtable(xe->drm.dev, userptr->sg, | |
| 145 | 147 | read_only ? DMA_TO_DEVICE : |
| 146 | 148 | DMA_BIDIRECTIONAL, |
| 147 | 149 | DMA_ATTR_SKIP_CPU_SYNC | |
| 148 | 150 | DMA_ATTR_NO_KERNEL_MAPPING); |
| 149 | 151 | if (ret) { |
| 150 | − sg_free_table(vma->userptr.sg); | |
| 151 | − vma->userptr.sg = NULL; | |
| 152 | + sg_free_table(userptr->sg); | |
| 153 | + userptr->sg = NULL; | |
| 152 | 154 | goto out; |
| 153 | 155 | } |
| 154 | 156 | |
| @@ -167,8 +169,8 @@ out: · 12 unmodified lines | ||
| 167 | 169 | kvfree(pages); |
| 168 | 170 | |
| 169 | 171 | if (!(ret < 0)) { |
| 170 | − vma->userptr.notifier_seq = notifier_seq; | |
| 171 | − if (xe_vma_userptr_check_repin(vma) == -EAGAIN) | |
| 172 | + userptr->notifier_seq = notifier_seq; | |
| 173 | + if (xe_vma_userptr_check_repin(uvma) == -EAGAIN) | |
| 172 | 174 | goto retry; |
| 173 | 175 | } |
| 174 | 176 | |
| @@ -635,7 +637,9 @@ static bool vma_userptr_invalidate(struct mmu_interval_notifier *mni, · 460 unmodified lines | ||
| 635 | 637 | const struct mmu_notifier_range *range, |
| 636 | 638 | unsigned long cur_seq) |
| 637 | 639 | { |
| 638 | − struct xe_vma *vma = container_of(mni, struct xe_vma, userptr.notifier); | |
| 640 | + struct xe_userptr *userptr = container_of(mni, typeof(*userptr), notifier); | |
| 641 | + struct xe_userptr_vma *uvma = container_of(userptr, typeof(*uvma), userptr); | |
| 642 | + struct xe_vma *vma = &uvma->vma; | |
| 639 | 643 | struct xe_vm *vm = xe_vma_vm(vma); |
| 640 | 644 | struct dma_resv_iter cursor; |
| 641 | 645 | struct dma_fence *fence; |
| @@ -651,7 +655,7 @@ static bool vma_userptr_invalidate(struct mmu_interval_notifier *mni, · 9 unmodified lines | ||
| 651 | 655 | mmu_interval_set_seq(mni, cur_seq); |
| 652 | 656 | |
| 653 | 657 | /* No need to stop gpu access if the userptr is not yet bound. */ |
| 654 | − if (!vma->userptr.initial_bind) { | |
| 658 | + if (!userptr->initial_bind) { | |
| 655 | 659 | up_write(&vm->userptr.notifier_lock); |
| 656 | 660 | return true; |
| 657 | 661 | } |
| @@ -663,7 +667,7 @@ static bool vma_userptr_invalidate(struct mmu_interval_notifier *mni, · 5 unmodified lines | ||
| 663 | 667 | if (!xe_vm_in_fault_mode(vm) && |
| 664 | 668 | !(vma->gpuva.flags & XE_VMA_DESTROYED) && vma->tile_present) { |
| 665 | 669 | spin_lock(&vm->userptr.invalidated_lock); |
| 666 | − list_move_tail(&vma->userptr.invalidate_link, | |
| 670 | + list_move_tail(&userptr->invalidate_link, | |
| 667 | 671 | &vm->userptr.invalidated); |
| 668 | 672 | spin_unlock(&vm->userptr.invalidated_lock); |
| 669 | 673 | } |
| @@ -703,7 +707,7 @@ static const struct mmu_interval_notifier_ops vma_userptr_notifier_ops = { · 33 unmodified lines | ||
| 703 | 707 | |
| 704 | 708 | int xe_vm_userptr_pin(struct xe_vm *vm) |
| 705 | 709 | { |
| 706 | − struct xe_vma *vma, *next; | |
| 710 | + struct xe_userptr_vma *uvma, *next; | |
| 707 | 711 | int err = 0; |
| 708 | 712 | LIST_HEAD(tmp_evict); |
| 709 | 713 | |
| @@ -711,22 +715,23 @@ int xe_vm_userptr_pin(struct xe_vm *vm) · 1 unmodified line | ||
| 711 | 715 | |
| 712 | 716 | /* Collect invalidated userptrs */ |
| 713 | 717 | spin_lock(&vm->userptr.invalidated_lock); |
| 714 | − list_for_each_entry_safe(vma, next, &vm->userptr.invalidated, | |
| 718 | + list_for_each_entry_safe(uvma, next, &vm->userptr.invalidated, | |
| 715 | 719 | userptr.invalidate_link) { |
| 716 | − list_del_init(&vma->userptr.invalidate_link); | |
| 717 | − list_move_tail(&vma->combined_links.userptr, | |
| 720 | + list_del_init(&uvma->userptr.invalidate_link); | |
| 721 | + list_move_tail(&uvma->userptr.repin_link, | |
| 718 | 722 | &vm->userptr.repin_list); |
| 719 | 723 | } |
| 720 | 724 | spin_unlock(&vm->userptr.invalidated_lock); |
| 721 | 725 | |
| 722 | 726 | /* Pin and move to temporary list */ |
| 723 | − list_for_each_entry_safe(vma, next, &vm->userptr.repin_list, | |
| 724 | − combined_links.userptr) { | |
| 725 | − err = xe_vma_userptr_pin_pages(vma); | |
| 727 | + list_for_each_entry_safe(uvma, next, &vm->userptr.repin_list, | |
| 728 | + userptr.repin_link) { | |
| 729 | + err = xe_vma_userptr_pin_pages(uvma); | |
| 726 | 730 | if (err < 0) |
| 727 | 731 | return err; |
| 728 | 732 | |
| 729 | − list_move_tail(&vma->combined_links.userptr, &vm->rebind_list); | |
| 733 | + list_del_init(&uvma->userptr.repin_link); | |
| 734 | + list_move_tail(&uvma->vma.combined_links.rebind, &vm->rebind_list); | |
| 730 | 735 | } |
| 731 | 736 | |
| 732 | 737 | return 0; |
| @@ -782,6 +787,14 @@ struct dma_fence *xe_vm_rebind(struct xe_vm *vm, bool rebind_worker) · 49 unmodified lines | ||
| 782 | 787 | return fence; |
| 783 | 788 | } |
| 784 | 789 | |
| 790 | +static void xe_vma_free(struct xe_vma *vma) | |
| 791 | +{ | |
| 792 | + if (xe_vma_is_userptr(vma)) | |
| 793 | + kfree(to_userptr_vma(vma)); | |
| 794 | + else | |
| 795 | + kfree(vma); | |
| 796 | +} | |
| 797 | + | |
| 785 | 798 | #define VMA_CREATE_FLAG_READ_ONLY BIT(0) |
| 786 | 799 | #define VMA_CREATE_FLAG_IS_NULL BIT(1) |
| 787 | 800 | |
| @@ -800,14 +813,26 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm, · 12 unmodified lines | ||
| 800 | 813 | xe_assert(vm->xe, start < end); |
| 801 | 814 | xe_assert(vm->xe, end < vm->size); |
| 802 | 815 | |
| 803 | − if (!bo && !is_null) /* userptr */ | |
| 816 | + /* | |
| 817 | + * Allocate and ensure that the xe_vma_is_userptr() return | |
| 818 | + * matches what was allocated. | |
| 819 | + */ | |
| 820 | + if (!bo && !is_null) { | |
| 821 | + struct xe_userptr_vma *uvma = kzalloc(sizeof(*uvma), GFP_KERNEL); | |
| 822 | + | |
| 823 | + if (!uvma) | |
| 824 | + return ERR_PTR(-ENOMEM); | |
| 825 | + | |
| 826 | + vma = &uvma->vma; | |
| 827 | + } else { | |
| 804 | 828 | vma = kzalloc(sizeof(*vma), GFP_KERNEL); |
| 805 | − else | |
| 806 | − vma = kzalloc(sizeof(*vma) - sizeof(struct xe_userptr), | |
| 807 | − GFP_KERNEL); | |
| 808 | − if (!vma) { | |
| 809 | − vma = ERR_PTR(-ENOMEM); | |
| 810 | − return vma; | |
| 829 | + if (!vma) | |
| 830 | + return ERR_PTR(-ENOMEM); | |
| 831 | + | |
| 832 | + if (is_null) | |
| 833 | + vma->gpuva.flags |= DRM_GPUVA_SPARSE; | |
| 834 | + if (bo) | |
| 835 | + vma->gpuva.gem.obj = &bo->ttm.base; | |
| 811 | 836 | } |
| 812 | 837 | |
| 813 | 838 | INIT_LIST_HEAD(&vma->combined_links.rebind); |
| @@ -818,8 +843,6 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm, · 4 unmodified lines | ||
| 818 | 843 | vma->gpuva.va.range = end - start + 1; |
| 819 | 844 | if (read_only) |
| 820 | 845 | vma->gpuva.flags |= XE_VMA_READ_ONLY; |
| 821 | − if (is_null) | |
| 822 | − vma->gpuva.flags |= DRM_GPUVA_SPARSE; | |
| 823 | 846 | |
| 824 | 847 | for_each_tile(tile, vm->xe, id) |
| 825 | 848 | vma->tile_mask |= 0x1 << id; |
| @@ -836,35 +859,35 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm, · 10 unmodified lines | ||
| 836 | 859 | |
| 837 | 860 | vm_bo = drm_gpuvm_bo_obtain(vma->gpuva.vm, &bo->ttm.base); |
| 838 | 861 | if (IS_ERR(vm_bo)) { |
| 839 | − kfree(vma); | |
| 862 | + xe_vma_free(vma); | |
| 840 | 863 | return ERR_CAST(vm_bo); |
| 841 | 864 | } |
| 842 | 865 | |
| 843 | 866 | drm_gpuvm_bo_extobj_add(vm_bo); |
| 844 | 867 | drm_gem_object_get(&bo->ttm.base); |
| 845 | − vma->gpuva.gem.obj = &bo->ttm.base; | |
| 846 | 868 | vma->gpuva.gem.offset = bo_offset_or_userptr; |
| 847 | 869 | drm_gpuva_link(&vma->gpuva, vm_bo); |
| 848 | 870 | drm_gpuvm_bo_put(vm_bo); |
| 849 | 871 | } else /* userptr or null */ { |
| 850 | 872 | if (!is_null) { |
| 873 | + struct xe_userptr *userptr = &to_userptr_vma(vma)->userptr; | |
| 851 | 874 | u64 size = end - start + 1; |
| 852 | 875 | int err; |
| 853 | 876 | |
| 854 | − INIT_LIST_HEAD(&vma->userptr.invalidate_link); | |
| 877 | + INIT_LIST_HEAD(&userptr->invalidate_link); | |
| 878 | + INIT_LIST_HEAD(&userptr->repin_link); | |
| 855 | 879 | vma->gpuva.gem.offset = bo_offset_or_userptr; |
| 856 | 880 | |
| 857 | − err = mmu_interval_notifier_insert(&vma->userptr.notifier, | |
| 881 | + err = mmu_interval_notifier_insert(&userptr->notifier, | |
| 858 | 882 | current->mm, |
| 859 | 883 | xe_vma_userptr(vma), size, |
| 860 | 884 | &vma_userptr_notifier_ops); |
| 861 | 885 | if (err) { |
| 862 | − kfree(vma); | |
| 863 | − vma = ERR_PTR(err); | |
| 864 | − return vma; | |
| 886 | + xe_vma_free(vma); | |
| 887 | + return ERR_PTR(err); | |
| 865 | 888 | } |
| 866 | 889 | |
| 867 | − vma->userptr.notifier_seq = LONG_MAX; | |
| 890 | + userptr->notifier_seq = LONG_MAX; | |
| 868 | 891 | } |
| 869 | 892 | |
| 870 | 893 | xe_vm_get(vm); |
| @@ -880,13 +903,15 @@ static void xe_vma_destroy_late(struct xe_vma *vma) · 9 unmodified lines | ||
| 880 | 903 | bool read_only = xe_vma_read_only(vma); |
| 881 | 904 | |
| 882 | 905 | if (xe_vma_is_userptr(vma)) { |
| 883 | − if (vma->userptr.sg) { | |
| 906 | + struct xe_userptr *userptr = &to_userptr_vma(vma)->userptr; | |
| 907 | + | |
| 908 | + if (userptr->sg) { | |
| 884 | 909 | dma_unmap_sgtable(xe->drm.dev, |
| 885 | − vma->userptr.sg, | |
| 910 | + userptr->sg, | |
| 886 | 911 | read_only ? DMA_TO_DEVICE : |
| 887 | 912 | DMA_BIDIRECTIONAL, 0); |
| 888 | − sg_free_table(vma->userptr.sg); | |
| 889 | − vma->userptr.sg = NULL; | |
| 913 | + sg_free_table(userptr->sg); | |
| 914 | + userptr->sg = NULL; | |
| 890 | 915 | } |
| 891 | 916 | |
| 892 | 917 | /* |
| @@ -894,7 +919,7 @@ static void xe_vma_destroy_late(struct xe_vma *vma) · 1 unmodified line | ||
| 894 | 919 | * the notifer until we're sure the GPU is not accessing |
| 895 | 920 | * them anymore |
| 896 | 921 | */ |
| 897 | − mmu_interval_notifier_remove(&vma->userptr.notifier); | |
| 922 | + mmu_interval_notifier_remove(&userptr->notifier); | |
| 898 | 923 | xe_vm_put(vm); |
| 899 | 924 | } else if (xe_vma_is_null(vma)) { |
| 900 | 925 | xe_vm_put(vm); |
| @@ -902,7 +927,7 @@ static void xe_vma_destroy_late(struct xe_vma *vma) · 1 unmodified line | ||
| 902 | 927 | xe_bo_put(xe_vma_bo(vma)); |
| 903 | 928 | } |
| 904 | 929 | |
| 905 | − kfree(vma); | |
| 930 | + xe_vma_free(vma); | |
| 906 | 931 | } |
| 907 | 932 | |
| 908 | 933 | static void vma_destroy_work_func(struct work_struct *w) |
| @@ -933,7 +958,7 @@ static void xe_vma_destroy(struct xe_vma *vma, struct dma_fence *fence) · 24 unmodified lines | ||
| 933 | 958 | xe_assert(vm->xe, vma->gpuva.flags & XE_VMA_DESTROYED); |
| 934 | 959 | |
| 935 | 960 | spin_lock(&vm->userptr.invalidated_lock); |
| 936 | − list_del(&vma->userptr.invalidate_link); | |
| 961 | + list_del(&to_userptr_vma(vma)->userptr.invalidate_link); | |
| 937 | 962 | spin_unlock(&vm->userptr.invalidated_lock); |
| 938 | 963 | } else if (!xe_vma_is_null(vma)) { |
| 939 | 964 | xe_bo_assert_held(xe_vma_bo(vma)); |
| @@ -2150,7 +2175,7 @@ static struct xe_vma *new_vma(struct xe_vm *vm, struct drm_gpuva_op_map *op, · 1210 unmodified lines | ||
| 2150 | 2175 | drm_exec_fini(&exec); |
| 2151 | 2176 | |
| 2152 | 2177 | if (xe_vma_is_userptr(vma)) { |
| 2153 | − err = xe_vma_userptr_pin_pages(vma); | |
| 2178 | + err = xe_vma_userptr_pin_pages(to_userptr_vma(vma)); | |
| 2154 | 2179 | if (err) { |
| 2155 | 2180 | prep_vma_destroy(vm, vma, false); |
| 2156 | 2181 | xe_vma_destroy_unlocked(vma); |
| @@ -2507,7 +2532,7 @@ retry_userptr: · 350 unmodified lines | ||
| 2507 | 2532 | |
| 2508 | 2533 | if (err == -EAGAIN && xe_vma_is_userptr(vma)) { |
| 2509 | 2534 | lockdep_assert_held_write(&vm->lock); |
| 2510 | − err = xe_vma_userptr_pin_pages(vma); | |
| 2535 | + err = xe_vma_userptr_pin_pages(to_userptr_vma(vma)); | |
| 2511 | 2536 | if (!err) |
| 2512 | 2537 | goto retry_userptr; |
| 2513 | 2538 | |
| @@ -2851,7 +2876,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file) · 337 unmodified lines | ||
| 2851 | 2876 | struct drm_gpuva_ops **ops = NULL; |
| 2852 | 2877 | struct xe_vm *vm; |
| 2853 | 2878 | struct xe_exec_queue *q = NULL; |
| 2854 | − u32 num_syncs; | |
| 2879 | + u32 num_syncs, num_ufence = 0; | |
| 2855 | 2880 | struct xe_sync_entry *syncs = NULL; |
| 2856 | 2881 | struct drm_xe_vm_bind_op *bind_ops; |
| 2857 | 2882 | LIST_HEAD(ops_list); |
| @@ -2988,6 +3013,14 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file) · 130 unmodified lines | ||
| 2988 | 3013 | SYNC_PARSE_FLAG_DISALLOW_USER_FENCE : 0)); |
| 2989 | 3014 | if (err) |
| 2990 | 3015 | goto free_syncs; |
| 3016 | + | |
| 3017 | + if (xe_sync_is_ufence(&syncs[num_syncs])) | |
| 3018 | + num_ufence++; | |
| 3019 | + } | |
| 3020 | + | |
| 3021 | + if (XE_IOCTL_DBG(xe, num_ufence > 1)) { | |
| 3022 | + err = -EINVAL; | |
| 3023 | + goto free_syncs; | |
| 2991 | 3024 | } |
| 2992 | 3025 | |
| 2993 | 3026 | if (!args->num_binds) { |
| @@ -3130,8 +3163,8 @@ int xe_vm_invalidate_vma(struct xe_vma *vma) · 136 unmodified lines | ||
| 3130 | 3163 | if (IS_ENABLED(CONFIG_PROVE_LOCKING)) { |
| 3131 | 3164 | if (xe_vma_is_userptr(vma)) { |
| 3132 | 3165 | WARN_ON_ONCE(!mmu_interval_check_retry |
| 3133 | − (&vma->userptr.notifier, | |
| 3134 | − vma->userptr.notifier_seq)); | |
| 3166 | + (&to_userptr_vma(vma)->userptr.notifier, | |
| 3167 | + to_userptr_vma(vma)->userptr.notifier_seq)); | |
| 3135 | 3168 | WARN_ON_ONCE(!dma_resv_test_signaled(xe_vm_resv(xe_vma_vm(vma)), |
| 3136 | 3169 | DMA_RESV_USAGE_BOOKKEEP)); |
| 3137 | 3170 | |
| @@ -3192,11 +3225,11 @@ int xe_analyze_vm(struct drm_printer *p, struct xe_vm *vm, int gt_id) · 54 unmodified lines | ||
| 3192 | 3225 | if (is_null) { |
| 3193 | 3226 | addr = 0; |
| 3194 | 3227 | } else if (is_userptr) { |
| 3228 | + struct sg_table *sg = to_userptr_vma(vma)->userptr.sg; | |
| 3195 | 3229 | struct xe_res_cursor cur; |
| 3196 | 3230 | |
| 3197 | − if (vma->userptr.sg) { | |
| 3198 | − xe_res_first_sg(vma->userptr.sg, 0, XE_PAGE_SIZE, | |
| 3199 | − &cur); | |
| 3231 | + if (sg) { | |
| 3232 | + xe_res_first_sg(sg, 0, XE_PAGE_SIZE, &cur); | |
| 3200 | 3233 | addr = xe_res_dma(&cur); |
| 3201 | 3234 | } else { |
| 3202 | 3235 | addr = 0; |
| @@ -160,6 +160,18 @@ static inline bool xe_vma_is_userptr(struct xe_vma *vma) · 159 unmodified lines | ||
| 160 | 160 | return xe_vma_has_no_bo(vma) && !xe_vma_is_null(vma); |
| 161 | 161 | } |
| 162 | 162 | |
| 163 | +/** | |
| 164 | + * to_userptr_vma() - Return a pointer to an embedding userptr vma | |
| 165 | + * @vma: Pointer to the embedded struct xe_vma | |
| 166 | + * | |
| 167 | + * Return: Pointer to the embedding userptr vma | |
| 168 | + */ | |
| 169 | +static inline struct xe_userptr_vma *to_userptr_vma(struct xe_vma *vma) | |
| 170 | +{ | |
| 171 | + xe_assert(xe_vma_vm(vma)->xe, xe_vma_is_userptr(vma)); | |
| 172 | + return container_of(vma, struct xe_userptr_vma, vma); | |
| 173 | +} | |
| 174 | + | |
| 163 | 175 | u64 xe_vm_pdp4_descriptor(struct xe_vm *vm, struct xe_tile *tile); |
| 164 | 176 | |
| 165 | 177 | int xe_vm_create_ioctl(struct drm_device *dev, void *data, |
| @@ -224,9 +236,9 @@ static inline void xe_vm_reactivate_rebind(struct xe_vm *vm) · 58 unmodified lines | ||
| 224 | 236 | } |
| 225 | 237 | } |
| 226 | 238 | |
| 227 | −int xe_vma_userptr_pin_pages(struct xe_vma *vma); | |
| 239 | +int xe_vma_userptr_pin_pages(struct xe_userptr_vma *uvma); | |
| 228 | 240 | |
| 229 | −int xe_vma_userptr_check_repin(struct xe_vma *vma); | |
| 241 | +int xe_vma_userptr_check_repin(struct xe_userptr_vma *uvma); | |
| 230 | 242 | |
| 231 | 243 | bool xe_vm_validate_should_retry(struct drm_exec *exec, int err, ktime_t *end); |
| 232 | 244 | |
| @@ -37,6 +37,8 @@ struct xe_vm; · 36 unmodified lines | ||
| 37 | 37 | struct xe_userptr { |
| 38 | 38 | /** @invalidate_link: Link for the vm::userptr.invalidated list */ |
| 39 | 39 | struct list_head invalidate_link; |
| 40 | + /** @userptr: link into VM repin list if userptr. */ | |
| 41 | + struct list_head repin_link; | |
| 40 | 42 | /** |
| 41 | 43 | * @notifier: MMU notifier for user pointer (invalidation call back) |
| 42 | 44 | */ |
| @@ -68,8 +70,6 @@ struct xe_vma { · 25 unmodified lines | ||
| 68 | 70 | * resv. |
| 69 | 71 | */ |
| 70 | 72 | union { |
| 71 | − /** @userptr: link into VM repin list if userptr. */ | |
| 72 | − struct list_head userptr; | |
| 73 | 73 | /** @rebind: link into VM if this VMA needs rebinding. */ |
| 74 | 74 | struct list_head rebind; |
| 75 | 75 | /** @destroy: link to contested list when VM is being closed. */ |
| @@ -105,11 +105,15 @@ struct xe_vma { · 29 unmodified lines | ||
| 105 | 105 | * @pat_index: The pat index to use when encoding the PTEs for this vma. |
| 106 | 106 | */ |
| 107 | 107 | u16 pat_index; |
| 108 | +}; | |
| 108 | 109 | |
| 109 | − /** | |
| 110 | − * @userptr: user pointer state, only allocated for VMAs that are | |
| 111 | − * user pointers | |
| 112 | − */ | |
| 110 | +/** | |
| 111 | + * struct xe_userptr_vma - A userptr vma subclass | |
| 112 | + * @vma: The vma. | |
| 113 | + * @userptr: Additional userptr information. | |
| 114 | + */ | |
| 115 | +struct xe_userptr_vma { | |
| 116 | + struct xe_vma vma; | |
| 113 | 117 | struct xe_userptr userptr; |
| 114 | 118 | }; |
| 115 | 119 | |
| @@ -146,7 +146,7 @@ static int waterforce_get_status(struct waterforce_data *priv) · 145 unmodified lines | ||
| 146 | 146 | /* Send command for getting status */ |
| 147 | 147 | ret = waterforce_write_expanded(priv, get_status_cmd, GET_STATUS_CMD_LENGTH); |
| 148 | 148 | if (ret < 0) |
| 149 | − return ret; | |
| 149 | + goto unlock_and_return; | |
| 150 | 150 | |
| 151 | 151 | ret = wait_for_completion_interruptible_timeout(&priv->status_report_received, |
| 152 | 152 | msecs_to_jiffies(STATUS_VALIDITY)); |
| @@ -126,6 +126,21 @@ static const struct regulator_desc __maybe_unused mp2975_reg_desc[] = { · 125 unmodified lines | ||
| 126 | 126 | |
| 127 | 127 | #define to_mp2975_data(x) container_of(x, struct mp2975_data, info) |
| 128 | 128 | |
| 129 | +static int mp2975_read_byte_data(struct i2c_client *client, int page, int reg) | |
| 130 | +{ | |
| 131 | + switch (reg) { | |
| 132 | + case PMBUS_VOUT_MODE: | |
| 133 | + /* | |
| 134 | + * Report direct format as configured by MFR_DC_LOOP_CTRL. | |
| 135 | + * Unlike on MP2971/MP2973 the reported VOUT_MODE isn't automatically | |
| 136 | + * internally updated, but always reads as PB_VOUT_MODE_VID. | |
| 137 | + */ | |
| 138 | + return PB_VOUT_MODE_DIRECT; | |
| 139 | + default: | |
| 140 | + return -ENODATA; | |
| 141 | + } | |
| 142 | +} | |
| 143 | + | |
| 129 | 144 | static int |
| 130 | 145 | mp2975_read_word_helper(struct i2c_client *client, int page, int phase, u8 reg, |
| 131 | 146 | u16 mask) |
| @@ -869,6 +884,7 @@ static struct pmbus_driver_info mp2975_info = { · 737 unmodified lines | ||
| 869 | 884 | PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | |
| 870 | 885 | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_POUT | |
| 871 | 886 | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT | PMBUS_PHASE_VIRTUAL, |
| 887 | + .read_byte_data = mp2975_read_byte_data, | |
| 872 | 888 | .read_word_data = mp2975_read_word_data, |
| 873 | 889 | #if IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR) |
| 874 | 890 | .num_regulators = 1, |
| @@ -294,6 +294,7 @@ static const struct xpad_device { · 293 unmodified lines | ||
| 294 | 294 | { 0x1689, 0xfd00, "Razer Onza Tournament Edition", 0, XTYPE_XBOX360 }, |
| 295 | 295 | { 0x1689, 0xfd01, "Razer Onza Classic Edition", 0, XTYPE_XBOX360 }, |
| 296 | 296 | { 0x1689, 0xfe00, "Razer Sabertooth", 0, XTYPE_XBOX360 }, |
| 297 | + { 0x17ef, 0x6182, "Lenovo Legion Controller for Windows", 0, XTYPE_XBOX360 }, | |
| 297 | 298 | { 0x1949, 0x041a, "Amazon Game Controller", 0, XTYPE_XBOX360 }, |
| 298 | 299 | { 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 }, |
| 299 | 300 | { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, |
| @@ -491,6 +492,7 @@ static const struct usb_device_id xpad_table[] = { · 191 unmodified lines | ||
| 491 | 492 | XPAD_XBOX360_VENDOR(0x15e4), /* Numark Xbox 360 controllers */ |
| 492 | 493 | XPAD_XBOX360_VENDOR(0x162e), /* Joytech Xbox 360 controllers */ |
| 493 | 494 | XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */ |
| 495 | + XPAD_XBOX360_VENDOR(0x17ef), /* Lenovo */ | |
| 494 | 496 | XPAD_XBOX360_VENDOR(0x1949), /* Amazon controllers */ |
| 495 | 497 | XPAD_XBOX360_VENDOR(0x1bad), /* Harmonix Rock Band guitar and drums */ |
| 496 | 498 | XPAD_XBOX360_VENDOR(0x20d6), /* PowerA controllers */ |
| @@ -811,7 +811,6 @@ static int atkbd_probe(struct atkbd *atkbd) · 810 unmodified lines | ||
| 811 | 811 | { |
| 812 | 812 | struct ps2dev *ps2dev = &atkbd->ps2dev; |
| 813 | 813 | unsigned char param[2]; |
| 814 | − bool skip_getid; | |
| 815 | 814 | |
| 816 | 815 | /* |
| 817 | 816 | * Some systems, where the bit-twiddling when testing the io-lines of the |
| @@ -825,6 +824,11 @@ static int atkbd_probe(struct atkbd *atkbd) · 7 unmodified lines | ||
| 825 | 824 | "keyboard reset failed on %s\n", |
| 826 | 825 | ps2dev->serio->phys); |
| 827 | 826 | |
| 827 | + if (atkbd_skip_getid(atkbd)) { | |
| 828 | + atkbd->id = 0xab83; | |
| 829 | + goto deactivate_kbd; | |
| 830 | + } | |
| 831 | + | |
| 828 | 832 | /* |
| 829 | 833 | * Then we check the keyboard ID. We should get 0xab83 under normal conditions. |
| 830 | 834 | * Some keyboards report different values, but the first byte is always 0xab or |
| @@ -833,18 +837,17 @@ static int atkbd_probe(struct atkbd *atkbd) · 2 unmodified lines | ||
| 833 | 837 | */ |
| 834 | 838 | |
| 835 | 839 | param[0] = param[1] = 0xa5; /* initialize with invalid values */ |
| 836 | − skip_getid = atkbd_skip_getid(atkbd); | |
| 837 | − if (skip_getid || ps2_command(ps2dev, param, ATKBD_CMD_GETID)) { | |
| 840 | + if (ps2_command(ps2dev, param, ATKBD_CMD_GETID)) { | |
| 838 | 841 | |
| 839 | 842 | /* |
| 840 | − * If the get ID command was skipped or failed, we check if we can at least set | |
| 843 | + * If the get ID command failed, we check if we can at least set | |
| 841 | 844 | * the LEDs on the keyboard. This should work on every keyboard out there. |
| 842 | 845 | * It also turns the LEDs off, which we want anyway. |
| 843 | 846 | */ |
| 844 | 847 | param[0] = 0; |
| 845 | 848 | if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS)) |
| 846 | 849 | return -1; |
| 847 | − atkbd->id = skip_getid ? 0xab83 : 0xabba; | |
| 850 | + atkbd->id = 0xabba; | |
| 848 | 851 | return 0; |
| 849 | 852 | } |
| 850 | 853 | |
| @@ -860,6 +863,7 @@ static int atkbd_probe(struct atkbd *atkbd) · 9 unmodified lines | ||
| 860 | 863 | return -1; |
| 861 | 864 | } |
| 862 | 865 | |
| 866 | +deactivate_kbd: | |
| 863 | 867 | /* |
| 864 | 868 | * Make sure nothing is coming from the keyboard and disturbs our |
| 865 | 869 | * internal state. |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | * Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch) |
| 20 | 20 | */ |
| 21 | 21 | |
| 22 | +#include "linux/usb.h" | |
| 22 | 23 | #include <linux/kernel.h> |
| 23 | 24 | #include <linux/errno.h> |
| 24 | 25 | #include <linux/slab.h> |
| @@ -193,6 +194,8 @@ enum tp_type { · 168 unmodified lines | ||
| 193 | 194 | |
| 194 | 195 | /* list of device capability bits */ |
| 195 | 196 | #define HAS_INTEGRATED_BUTTON 1 |
| 197 | +/* maximum number of supported endpoints (currently trackpad and button) */ | |
| 198 | +#define MAX_ENDPOINTS 2 | |
| 196 | 199 | |
| 197 | 200 | /* trackpad finger data block size */ |
| 198 | 201 | #define FSIZE_TYPE1 (14 * sizeof(__le16)) |
| @@ -891,6 +894,18 @@ static int bcm5974_resume(struct usb_interface *iface) · 692 unmodified lines | ||
| 891 | 894 | return error; |
| 892 | 895 | } |
| 893 | 896 | |
| 897 | +static bool bcm5974_check_endpoints(struct usb_interface *iface, | |
| 898 | + const struct bcm5974_config *cfg) | |
| 899 | +{ | |
| 900 | + u8 ep_addr[MAX_ENDPOINTS + 1] = {0}; | |
| 901 | + | |
| 902 | + ep_addr[0] = cfg->tp_ep; | |
| 903 | + if (cfg->tp_type == TYPE1) | |
| 904 | + ep_addr[1] = cfg->bt_ep; | |
| 905 | + | |
| 906 | + return usb_check_int_endpoints(iface, ep_addr); | |
| 907 | +} | |
| 908 | + | |
| 894 | 909 | static int bcm5974_probe(struct usb_interface *iface, |
| 895 | 910 | const struct usb_device_id *id) |
| 896 | 911 | { |
| @@ -903,6 +918,11 @@ static int bcm5974_probe(struct usb_interface *iface, · 6 unmodified lines | ||
| 903 | 918 | /* find the product index */ |
| 904 | 919 | cfg = bcm5974_get_config(udev); |
| 905 | 920 | |
| 921 | + if (!bcm5974_check_endpoints(iface, cfg)) { | |
| 922 | + dev_err(&iface->dev, "Unexpected non-int endpoint\n"); | |
| 923 | + return -ENODEV; | |
| 924 | + } | |
| 925 | + | |
| 906 | 926 | /* allocate memory for our device state and initialize it */ |
| 907 | 927 | dev = kzalloc(sizeof(struct bcm5974), GFP_KERNEL); |
| 908 | 928 | input_dev = input_allocate_device(); |
| @@ -634,6 +634,14 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { · 633 unmodified lines | ||
| 634 | 634 | }, |
| 635 | 635 | .driver_data = (void *)(SERIO_QUIRK_NOAUX) |
| 636 | 636 | }, |
| 637 | + { | |
| 638 | + /* Fujitsu Lifebook U728 */ | |
| 639 | + .matches = { | |
| 640 | + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | |
| 641 | + DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U728"), | |
| 642 | + }, | |
| 643 | + .driver_data = (void *)(SERIO_QUIRK_NOAUX) | |
| 644 | + }, | |
| 637 | 645 | { |
| 638 | 646 | /* Gigabyte M912 */ |
| 639 | 647 | .matches = { |
| @@ -1208,6 +1216,12 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { · 568 unmodified lines | ||
| 1208 | 1216 | SERIO_QUIRK_RESET_ALWAYS | SERIO_QUIRK_NOLOOP | |
| 1209 | 1217 | SERIO_QUIRK_NOPNP) |
| 1210 | 1218 | }, |
| 1219 | + { | |
| 1220 | + .matches = { | |
| 1221 | + DMI_MATCH(DMI_BOARD_NAME, "NS5x_7xPU"), | |
| 1222 | + }, | |
| 1223 | + .driver_data = (void *)(SERIO_QUIRK_NOAUX) | |
| 1224 | + }, | |
| 1211 | 1225 | { |
| 1212 | 1226 | .matches = { |
| 1213 | 1227 | DMI_MATCH(DMI_BOARD_NAME, "NJ50_70CU"), |
| @@ -884,7 +884,8 @@ static int goodix_add_acpi_gpio_mappings(struct goodix_ts_data *ts) · 883 unmodified lines | ||
| 884 | 884 | } |
| 885 | 885 | } |
| 886 | 886 | |
| 887 | − if (ts->gpio_count == 2 && ts->gpio_int_idx == 0) { | |
| 887 | + /* Some devices with gpio_int_idx 0 list a third unused GPIO */ | |
| 888 | + if ((ts->gpio_count == 2 || ts->gpio_count == 3) && ts->gpio_int_idx == 0) { | |
| 888 | 889 | ts->irq_pin_access_method = IRQ_PIN_ACCESS_ACPI_GPIO; |
| 889 | 890 | gpio_mapping = acpi_goodix_int_first_gpios; |
| 890 | 891 | } else if (ts->gpio_count == 2 && ts->gpio_int_idx == 1) { |
| @@ -1799,7 +1799,7 @@ iommu_group_alloc_default_domain(struct iommu_group *group, int req_type) · 1798 unmodified lines | ||
| 1799 | 1799 | * domain. Do not use in new drivers. |
| 1800 | 1800 | */ |
| 1801 | 1801 | if (ops->default_domain) { |
| 1802 | − if (req_type) | |
| 1802 | + if (req_type != ops->default_domain->type) | |
| 1803 | 1803 | return ERR_PTR(-EINVAL); |
| 1804 | 1804 | return ops->default_domain; |
| 1805 | 1805 | } |
| @@ -1871,10 +1871,18 @@ static int iommu_get_def_domain_type(struct iommu_group *group, · 65 unmodified lines | ||
| 1871 | 1871 | const struct iommu_ops *ops = dev_iommu_ops(dev); |
| 1872 | 1872 | int type; |
| 1873 | 1873 | |
| 1874 | − if (!ops->def_domain_type) | |
| 1875 | − return cur_type; | |
| 1876 | − | |
| 1877 | − type = ops->def_domain_type(dev); | |
| 1874 | + if (ops->default_domain) { | |
| 1875 | + /* | |
| 1876 | + * Drivers that declare a global static default_domain will | |
| 1877 | + * always choose that. | |
| 1878 | + */ | |
| 1879 | + type = ops->default_domain->type; | |
| 1880 | + } else { | |
| 1881 | + if (ops->def_domain_type) | |
| 1882 | + type = ops->def_domain_type(dev); | |
| 1883 | + else | |
| 1884 | + return cur_type; | |
| 1885 | + } | |
| 1878 | 1886 | if (!type || cur_type == type) |
| 1879 | 1887 | return cur_type; |
| 1880 | 1888 | if (!cur_type) |
| @@ -22,6 +22,8 @@ · 21 unmodified lines | ||
| 22 | 22 | #include "dm-ima.h" |
| 23 | 23 | |
| 24 | 24 | #define DM_RESERVED_MAX_IOS 1024 |
| 25 | +#define DM_MAX_TARGETS 1048576 | |
| 26 | +#define DM_MAX_TARGET_PARAMS 1024 | |
| 25 | 27 | |
| 26 | 28 | struct dm_io; |
| 27 | 29 | |
| @@ -73,10 +73,8 @@ struct dm_crypt_io { · 72 unmodified lines | ||
| 73 | 73 | struct bio *base_bio; |
| 74 | 74 | u8 *integrity_metadata; |
| 75 | 75 | bool integrity_metadata_from_pool:1; |
| 76 | − bool in_tasklet:1; | |
| 77 | 76 | |
| 78 | 77 | struct work_struct work; |
| 79 | − struct tasklet_struct tasklet; | |
| 80 | 78 | |
| 81 | 79 | struct convert_context ctx; |
| 82 | 80 | |
| @@ -1762,7 +1760,6 @@ static void crypt_io_init(struct dm_crypt_io *io, struct crypt_config *cc, · 1679 unmodified lines | ||
| 1762 | 1760 | io->ctx.r.req = NULL; |
| 1763 | 1761 | io->integrity_metadata = NULL; |
| 1764 | 1762 | io->integrity_metadata_from_pool = false; |
| 1765 | − io->in_tasklet = false; | |
| 1766 | 1763 | atomic_set(&io->io_pending, 0); |
| 1767 | 1764 | } |
| 1768 | 1765 | |
| @@ -1771,13 +1768,6 @@ static void crypt_inc_pending(struct dm_crypt_io *io) · 2 unmodified lines | ||
| 1771 | 1768 | atomic_inc(&io->io_pending); |
| 1772 | 1769 | } |
| 1773 | 1770 | |
| 1774 | −static void kcryptd_io_bio_endio(struct work_struct *work) | |
| 1775 | −{ | |
| 1776 | − struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work); | |
| 1777 | − | |
| 1778 | − bio_endio(io->base_bio); | |
| 1779 | −} | |
| 1780 | − | |
| 1781 | 1771 | /* |
| 1782 | 1772 | * One of the bios was finished. Check for completion of |
| 1783 | 1773 | * the whole request and correctly clean up the buffer. |
| @@ -1801,20 +1791,6 @@ static void crypt_dec_pending(struct dm_crypt_io *io) · 17 unmodified lines | ||
| 1801 | 1791 | |
| 1802 | 1792 | base_bio->bi_status = error; |
| 1803 | 1793 | |
| 1804 | − /* | |
| 1805 | − * If we are running this function from our tasklet, | |
| 1806 | − * we can't call bio_endio() here, because it will call | |
| 1807 | − * clone_endio() from dm.c, which in turn will | |
| 1808 | − * free the current struct dm_crypt_io structure with | |
| 1809 | − * our tasklet. In this case we need to delay bio_endio() | |
| 1810 | − * execution to after the tasklet is done and dequeued. | |
| 1811 | − */ | |
| 1812 | − if (io->in_tasklet) { | |
| 1813 | − INIT_WORK(&io->work, kcryptd_io_bio_endio); | |
| 1814 | − queue_work(cc->io_queue, &io->work); | |
| 1815 | − return; | |
| 1816 | − } | |
| 1817 | − | |
| 1818 | 1794 | bio_endio(base_bio); |
| 1819 | 1795 | } |
| 1820 | 1796 | |
| @@ -2246,11 +2222,6 @@ static void kcryptd_crypt(struct work_struct *work) · 425 unmodified lines | ||
| 2246 | 2222 | kcryptd_crypt_write_convert(io); |
| 2247 | 2223 | } |
| 2248 | 2224 | |
| 2249 | −static void kcryptd_crypt_tasklet(unsigned long work) | |
| 2250 | −{ | |
| 2251 | − kcryptd_crypt((struct work_struct *)work); | |
| 2252 | −} | |
| 2253 | − | |
| 2254 | 2225 | static void kcryptd_queue_crypt(struct dm_crypt_io *io) |
| 2255 | 2226 | { |
| 2256 | 2227 | struct crypt_config *cc = io->cc; |
| @@ -2262,15 +2233,10 @@ static void kcryptd_queue_crypt(struct dm_crypt_io *io) · 5 unmodified lines | ||
| 2262 | 2233 | * irqs_disabled(): the kernel may run some IO completion from the idle thread, but |
| 2263 | 2234 | * it is being executed with irqs disabled. |
| 2264 | 2235 | */ |
| 2265 | − if (in_hardirq() || irqs_disabled()) { | |
| 2266 | − io->in_tasklet = true; | |
| 2267 | − tasklet_init(&io->tasklet, kcryptd_crypt_tasklet, (unsigned long)&io->work); | |
| 2268 | − tasklet_schedule(&io->tasklet); | |
| 2236 | + if (!(in_hardirq() || irqs_disabled())) { | |
| 2237 | + kcryptd_crypt(&io->work); | |
| 2269 | 2238 | return; |
| 2270 | 2239 | } |
| 2271 | − | |
| 2272 | − kcryptd_crypt(&io->work); | |
| 2273 | − return; | |
| 2274 | 2240 | } |
| 2275 | 2241 | |
| 2276 | 2242 | INIT_WORK(&io->work, kcryptd_crypt); |
| @@ -1941,7 +1941,8 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern · 1940 unmodified lines | ||
| 1941 | 1941 | minimum_data_size - sizeof(param_kernel->version))) |
| 1942 | 1942 | return -EFAULT; |
| 1943 | 1943 | |
| 1944 | − if (param_kernel->data_size < minimum_data_size) { | |
| 1944 | + if (unlikely(param_kernel->data_size < minimum_data_size) || | |
| 1945 | + unlikely(param_kernel->data_size > DM_MAX_TARGETS * DM_MAX_TARGET_PARAMS)) { | |
| 1945 | 1946 | DMERR("Invalid data size in the ioctl structure: %u", |
| 1946 | 1947 | param_kernel->data_size); |
| 1947 | 1948 | return -EINVAL; |
| @@ -66,6 +66,9 @@ struct dm_stats_last_position { · 65 unmodified lines | ||
| 66 | 66 | unsigned int last_rw; |
| 67 | 67 | }; |
| 68 | 68 | |
| 69 | +#define DM_STAT_MAX_ENTRIES 8388608 | |
| 70 | +#define DM_STAT_MAX_HISTOGRAM_ENTRIES 134217728 | |
| 71 | + | |
| 69 | 72 | /* |
| 70 | 73 | * A typo on the command line could possibly make the kernel run out of memory |
| 71 | 74 | * and crash. To prevent the crash we account all used memory. We fail if we |
| @@ -285,6 +288,9 @@ static int dm_stats_create(struct dm_stats *stats, sector_t start, sector_t end, · 213 unmodified lines | ||
| 285 | 288 | if (n_entries != (size_t)n_entries || !(size_t)(n_entries + 1)) |
| 286 | 289 | return -EOVERFLOW; |
| 287 | 290 | |
| 291 | + if (n_entries > DM_STAT_MAX_ENTRIES) | |
| 292 | + return -EOVERFLOW; | |
| 293 | + | |
| 288 | 294 | shared_alloc_size = struct_size(s, stat_shared, n_entries); |
| 289 | 295 | if ((shared_alloc_size - sizeof(struct dm_stat)) / sizeof(struct dm_stat_shared) != n_entries) |
| 290 | 296 | return -EOVERFLOW; |
| @@ -297,6 +303,9 @@ static int dm_stats_create(struct dm_stats *stats, sector_t start, sector_t end, · 6 unmodified lines | ||
| 297 | 303 | if (histogram_alloc_size / (n_histogram_entries + 1) != (size_t)n_entries * sizeof(unsigned long long)) |
| 298 | 304 | return -EOVERFLOW; |
| 299 | 305 | |
| 306 | + if ((n_histogram_entries + 1) * (size_t)n_entries > DM_STAT_MAX_HISTOGRAM_ENTRIES) | |
| 307 | + return -EOVERFLOW; | |
| 308 | + | |
| 300 | 309 | if (!check_shared_memory(shared_alloc_size + histogram_alloc_size + |
| 301 | 310 | num_possible_cpus() * (percpu_alloc_size + histogram_alloc_size))) |
| 302 | 311 | return -ENOMEM; |
| @@ -129,7 +129,12 @@ static int alloc_targets(struct dm_table *t, unsigned int num) · 128 unmodified lines | ||
| 129 | 129 | int dm_table_create(struct dm_table **result, blk_mode_t mode, |
| 130 | 130 | unsigned int num_targets, struct mapped_device *md) |
| 131 | 131 | { |
| 132 | − struct dm_table *t = kzalloc(sizeof(*t), GFP_KERNEL); | |
| 132 | + struct dm_table *t; | |
| 133 | + | |
| 134 | + if (num_targets > DM_MAX_TARGETS) | |
| 135 | + return -EOVERFLOW; | |
| 136 | + | |
| 137 | + t = kzalloc(sizeof(*t), GFP_KERNEL); | |
| 133 | 138 | |
| 134 | 139 | if (!t) |
| 135 | 140 | return -ENOMEM; |
| @@ -144,7 +149,7 @@ int dm_table_create(struct dm_table **result, blk_mode_t mode, · 8 unmodified lines | ||
| 144 | 149 | |
| 145 | 150 | if (!num_targets) { |
| 146 | 151 | kfree(t); |
| 147 | − return -ENOMEM; | |
| 152 | + return -EOVERFLOW; | |
| 148 | 153 | } |
| 149 | 154 | |
| 150 | 155 | if (alloc_targets(t, num_targets)) { |
| @@ -645,23 +645,6 @@ static void verity_work(struct work_struct *w) · 644 unmodified lines | ||
| 645 | 645 | verity_finish_io(io, errno_to_blk_status(verity_verify_io(io))); |
| 646 | 646 | } |
| 647 | 647 | |
| 648 | −static void verity_tasklet(unsigned long data) | |
| 649 | −{ | |
| 650 | − struct dm_verity_io *io = (struct dm_verity_io *)data; | |
| 651 | − int err; | |
| 652 | − | |
| 653 | − io->in_tasklet = true; | |
| 654 | − err = verity_verify_io(io); | |
| 655 | − if (err == -EAGAIN || err == -ENOMEM) { | |
| 656 | − /* fallback to retrying with work-queue */ | |
| 657 | − INIT_WORK(&io->work, verity_work); | |
| 658 | − queue_work(io->v->verify_wq, &io->work); | |
| 659 | − return; | |
| 660 | − } | |
| 661 | − | |
| 662 | − verity_finish_io(io, errno_to_blk_status(err)); | |
| 663 | −} | |
| 664 | − | |
| 665 | 648 | static void verity_end_io(struct bio *bio) |
| 666 | 649 | { |
| 667 | 650 | struct dm_verity_io *io = bio->bi_private; |
| @@ -674,13 +657,8 @@ static void verity_end_io(struct bio *bio) · 6 unmodified lines | ||
| 674 | 657 | return; |
| 675 | 658 | } |
| 676 | 659 | |
| 677 | − if (static_branch_unlikely(&use_tasklet_enabled) && io->v->use_tasklet) { | |
| 678 | − tasklet_init(&io->tasklet, verity_tasklet, (unsigned long)io); | |
| 679 | − tasklet_schedule(&io->tasklet); | |
| 680 | − } else { | |
| 681 | − INIT_WORK(&io->work, verity_work); | |
| 682 | − queue_work(io->v->verify_wq, &io->work); | |
| 683 | − } | |
| 660 | + INIT_WORK(&io->work, verity_work); | |
| 661 | + queue_work(io->v->verify_wq, &io->work); | |
| 684 | 662 | } |
| 685 | 663 | |
| 686 | 664 | /* |
| @@ -83,7 +83,6 @@ struct dm_verity_io { · 82 unmodified lines | ||
| 83 | 83 | struct bvec_iter iter; |
| 84 | 84 | |
| 85 | 85 | struct work_struct work; |
| 86 | − struct tasklet_struct tasklet; | |
| 87 | 86 | |
| 88 | 87 | /* |
| 89 | 88 | * Three variably-size fields follow this struct: |
| @@ -299,7 +299,7 @@ static int persistent_memory_claim(struct dm_writecache *wc) · 298 unmodified lines | ||
| 299 | 299 | long i; |
| 300 | 300 | |
| 301 | 301 | wc->memory_map = NULL; |
| 302 | − pages = kvmalloc_array(p, sizeof(struct page *), GFP_KERNEL); | |
| 302 | + pages = vmalloc_array(p, sizeof(struct page *)); | |
| 303 | 303 | if (!pages) { |
| 304 | 304 | r = -ENOMEM; |
| 305 | 305 | goto err2; |
| @@ -330,7 +330,7 @@ static int persistent_memory_claim(struct dm_writecache *wc) · 24 unmodified lines | ||
| 330 | 330 | r = -ENOMEM; |
| 331 | 331 | goto err3; |
| 332 | 332 | } |
| 333 | − kvfree(pages); | |
| 333 | + vfree(pages); | |
| 334 | 334 | wc->memory_vmapped = true; |
| 335 | 335 | } |
| 336 | 336 | |
| @@ -341,7 +341,7 @@ static int persistent_memory_claim(struct dm_writecache *wc) · 4 unmodified lines | ||
| 341 | 341 | |
| 342 | 342 | return 0; |
| 343 | 343 | err3: |
| 344 | − kvfree(pages); | |
| 344 | + vfree(pages); | |
| 345 | 345 | err2: |
| 346 | 346 | dax_read_unlock(id); |
| 347 | 347 | err1: |
| @@ -962,7 +962,7 @@ static int writecache_alloc_entries(struct dm_writecache *wc) · 614 unmodified lines | ||
| 962 | 962 | |
| 963 | 963 | if (wc->entries) |
| 964 | 964 | return 0; |
| 965 | − wc->entries = vmalloc(array_size(sizeof(struct wc_entry), wc->n_blocks)); | |
| 965 | + wc->entries = vmalloc_array(wc->n_blocks, sizeof(struct wc_entry)); | |
| 966 | 966 | if (!wc->entries) |
| 967 | 967 | return -ENOMEM; |
| 968 | 968 | for (b = 0; b < wc->n_blocks; b++) { |
| @@ -2191,7 +2191,7 @@ static int fastrpc_cb_remove(struct platform_device *pdev) · 2190 unmodified lines | ||
| 2191 | 2191 | int i; |
| 2192 | 2192 | |
| 2193 | 2193 | spin_lock_irqsave(&cctx->lock, flags); |
| 2194 | − for (i = 1; i < FASTRPC_MAX_SESSIONS; i++) { | |
| 2194 | + for (i = 0; i < FASTRPC_MAX_SESSIONS; i++) { | |
| 2195 | 2195 | if (cctx->session[i].sid == sess->sid) { |
| 2196 | 2196 | cctx->session[i].valid = false; |
| 2197 | 2197 | cctx->sesscount--; |
| @@ -140,7 +140,6 @@ static int __init open_dice_probe(struct platform_device *pdev) · 139 unmodified lines | ||
| 140 | 140 | return -ENOMEM; |
| 141 | 141 | |
| 142 | 142 | *drvdata = (struct open_dice_drvdata){ |
| 143 | − .lock = __MUTEX_INITIALIZER(drvdata->lock), | |
| 144 | 143 | .rmem = rmem, |
| 145 | 144 | .misc = (struct miscdevice){ |
| 146 | 145 | .parent = dev, |
| @@ -150,6 +149,7 @@ static int __init open_dice_probe(struct platform_device *pdev) · 3 unmodified lines | ||
| 150 | 149 | .mode = 0600, |
| 151 | 150 | }, |
| 152 | 151 | }; |
| 152 | + mutex_init(&drvdata->lock); | |
| 153 | 153 | |
| 154 | 154 | /* Index overflow check not needed, misc_register() will fail. */ |
| 155 | 155 | snprintf(drvdata->name, sizeof(drvdata->name), DRIVER_NAME"%u", dev_idx++); |
| @@ -993,7 +993,7 @@ int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic) · 992 unmodified lines | ||
| 993 | 993 | return 0; |
| 994 | 994 | |
| 995 | 995 | err_exit_hwts_rx: |
| 996 | − aq_ring_free(&aq_ptp->hwts_rx); | |
| 996 | + aq_ring_hwts_rx_free(&aq_ptp->hwts_rx); | |
| 997 | 997 | err_exit_ptp_rx: |
| 998 | 998 | aq_ring_free(&aq_ptp->ptp_rx); |
| 999 | 999 | err_exit_ptp_tx: |
| @@ -1011,7 +1011,7 @@ void aq_ptp_ring_free(struct aq_nic_s *aq_nic) · 11 unmodified lines | ||
| 1011 | 1011 | |
| 1012 | 1012 | aq_ring_free(&aq_ptp->ptp_tx); |
| 1013 | 1013 | aq_ring_free(&aq_ptp->ptp_rx); |
| 1014 | − aq_ring_free(&aq_ptp->hwts_rx); | |
| 1014 | + aq_ring_hwts_rx_free(&aq_ptp->hwts_rx); | |
| 1015 | 1015 | |
| 1016 | 1016 | aq_ptp_skb_ring_release(&aq_ptp->skb_ring); |
| 1017 | 1017 | } |
| @@ -919,6 +919,19 @@ void aq_ring_free(struct aq_ring_s *self) · 918 unmodified lines | ||
| 919 | 919 | } |
| 920 | 920 | } |
| 921 | 921 | |
| 922 | +void aq_ring_hwts_rx_free(struct aq_ring_s *self) | |
| 923 | +{ | |
| 924 | + if (!self) | |
| 925 | + return; | |
| 926 | + | |
| 927 | + if (self->dx_ring) { | |
| 928 | + dma_free_coherent(aq_nic_get_dev(self->aq_nic), | |
| 929 | + self->size * self->dx_size + AQ_CFG_RXDS_DEF, | |
| 930 | + self->dx_ring, self->dx_ring_pa); | |
| 931 | + self->dx_ring = NULL; | |
| 932 | + } | |
| 933 | +} | |
| 934 | + | |
| 922 | 935 | unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data) |
| 923 | 936 | { |
| 924 | 937 | unsigned int count; |
| @@ -210,6 +210,7 @@ int aq_ring_rx_fill(struct aq_ring_s *self); · 209 unmodified lines | ||
| 210 | 210 | int aq_ring_hwts_rx_alloc(struct aq_ring_s *self, |
| 211 | 211 | struct aq_nic_s *aq_nic, unsigned int idx, |
| 212 | 212 | unsigned int size, unsigned int dx_size); |
| 213 | +void aq_ring_hwts_rx_free(struct aq_ring_s *self); | |
| 213 | 214 | void aq_ring_hwts_rx_clean(struct aq_ring_s *self, struct aq_nic_s *aq_nic); |
| 214 | 215 | |
| 215 | 216 | unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data); |
| @@ -721,17 +721,25 @@ static void tsnep_xdp_xmit_flush(struct tsnep_tx *tx) · 720 unmodified lines | ||
| 721 | 721 | |
| 722 | 722 | static bool tsnep_xdp_xmit_back(struct tsnep_adapter *adapter, |
| 723 | 723 | struct xdp_buff *xdp, |
| 724 | − struct netdev_queue *tx_nq, struct tsnep_tx *tx) | |
| 724 | + struct netdev_queue *tx_nq, struct tsnep_tx *tx, | |
| 725 | + bool zc) | |
| 725 | 726 | { |
| 726 | 727 | struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp); |
| 727 | 728 | bool xmit; |
| 729 | + u32 type; | |
| 728 | 730 | |
| 729 | 731 | if (unlikely(!xdpf)) |
| 730 | 732 | return false; |
| 731 | 733 | |
| 734 | + /* no page pool for zero copy */ | |
| 735 | + if (zc) | |
| 736 | + type = TSNEP_TX_TYPE_XDP_NDO; | |
| 737 | + else | |
| 738 | + type = TSNEP_TX_TYPE_XDP_TX; | |
| 739 | + | |
| 732 | 740 | __netif_tx_lock(tx_nq, smp_processor_id()); |
| 733 | 741 | |
| 734 | − xmit = tsnep_xdp_xmit_frame_ring(xdpf, tx, TSNEP_TX_TYPE_XDP_TX); | |
| 742 | + xmit = tsnep_xdp_xmit_frame_ring(xdpf, tx, type); | |
| 735 | 743 | |
| 736 | 744 | /* Avoid transmit queue timeout since we share it with the slow path */ |
| 737 | 745 | if (xmit) |
| @@ -1283,7 +1291,7 @@ static bool tsnep_xdp_run_prog(struct tsnep_rx *rx, struct bpf_prog *prog, · 545 unmodified lines | ||
| 1283 | 1291 | case XDP_PASS: |
| 1284 | 1292 | return false; |
| 1285 | 1293 | case XDP_TX: |
| 1286 | − if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx)) | |
| 1294 | + if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx, false)) | |
| 1287 | 1295 | goto out_failure; |
| 1288 | 1296 | *status |= TSNEP_XDP_TX; |
| 1289 | 1297 | return true; |
| @@ -1333,7 +1341,7 @@ static bool tsnep_xdp_run_prog_zc(struct tsnep_rx *rx, struct bpf_prog *prog, · 43 unmodified lines | ||
| 1333 | 1341 | case XDP_PASS: |
| 1334 | 1342 | return false; |
| 1335 | 1343 | case XDP_TX: |
| 1336 | − if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx)) | |
| 1344 | + if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx, true)) | |
| 1337 | 1345 | goto out_failure; |
| 1338 | 1346 | *status |= TSNEP_XDP_TX; |
| 1339 | 1347 | return true; |
| @@ -43,7 +43,7 @@ · 42 unmodified lines | ||
| 43 | 43 | #define I40E_LLDP_TLV_SUBTYPE_SHIFT 0 |
| 44 | 44 | #define I40E_LLDP_TLV_SUBTYPE_MASK (0xFF << I40E_LLDP_TLV_SUBTYPE_SHIFT) |
| 45 | 45 | #define I40E_LLDP_TLV_OUI_SHIFT 8 |
| 46 | −#define I40E_LLDP_TLV_OUI_MASK (0xFFFFFF << I40E_LLDP_TLV_OUI_SHIFT) | |
| 46 | +#define I40E_LLDP_TLV_OUI_MASK (0xFFFFFFU << I40E_LLDP_TLV_OUI_SHIFT) | |
| 47 | 47 | |
| 48 | 48 | /* Defines for IEEE ETS TLV */ |
| 49 | 49 | #define I40E_IEEE_ETS_MAXTC_SHIFT 0 |
| @@ -24,7 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | #define rd64(a, reg) readq((a)->hw_addr + (reg)) |
| 25 | 25 | |
| 26 | 26 | #define ice_flush(a) rd32((a), GLGEN_STAT) |
| 27 | −#define ICE_M(m, s) ((m) << (s)) | |
| 27 | +#define ICE_M(m, s) ((m ## U) << (s)) | |
| 28 | 28 | |
| 29 | 29 | struct ice_dma_mem { |
| 30 | 30 | void *va; |
| @@ -1072,7 +1072,7 @@ struct ice_aq_get_set_rss_lut_params { · 1071 unmodified lines | ||
| 1072 | 1072 | #define ICE_OROM_VER_BUILD_SHIFT 8 |
| 1073 | 1073 | #define ICE_OROM_VER_BUILD_MASK (0xffff << ICE_OROM_VER_BUILD_SHIFT) |
| 1074 | 1074 | #define ICE_OROM_VER_SHIFT 24 |
| 1075 | −#define ICE_OROM_VER_MASK (0xff << ICE_OROM_VER_SHIFT) | |
| 1075 | +#define ICE_OROM_VER_MASK (0xffU << ICE_OROM_VER_SHIFT) | |
| 1076 | 1076 | #define ICE_SR_PFA_PTR 0x40 |
| 1077 | 1077 | #define ICE_SR_1ST_NVM_BANK_PTR 0x42 |
| 1078 | 1078 | #define ICE_SR_NVM_BANK_SIZE 0x43 |
| @@ -1850,8 +1850,8 @@ void npc_mcam_rsrcs_deinit(struct rvu *rvu) · 1849 unmodified lines | ||
| 1850 | 1850 | { |
| 1851 | 1851 | struct npc_mcam *mcam = &rvu->hw->mcam; |
| 1852 | 1852 | |
| 1853 | − kfree(mcam->bmap); | |
| 1854 | − kfree(mcam->bmap_reverse); | |
| 1853 | + bitmap_free(mcam->bmap); | |
| 1854 | + bitmap_free(mcam->bmap_reverse); | |
| 1855 | 1855 | kfree(mcam->entry2pfvf_map); |
| 1856 | 1856 | kfree(mcam->cntr2pfvf_map); |
| 1857 | 1857 | kfree(mcam->entry2cntr_map); |
| @@ -1904,21 +1904,20 @@ int npc_mcam_rsrcs_init(struct rvu *rvu, int blkaddr) · 46 unmodified lines | ||
| 1904 | 1904 | mcam->pf_offset = mcam->nixlf_offset + nixlf_count; |
| 1905 | 1905 | |
| 1906 | 1906 | /* Allocate bitmaps for managing MCAM entries */ |
| 1907 | − mcam->bmap = kmalloc_array(BITS_TO_LONGS(mcam->bmap_entries), | |
| 1908 | − sizeof(long), GFP_KERNEL); | |
| 1907 | + mcam->bmap = bitmap_zalloc(mcam->bmap_entries, GFP_KERNEL); | |
| 1909 | 1908 | if (!mcam->bmap) |
| 1910 | 1909 | return -ENOMEM; |
| 1911 | 1910 | |
| 1912 | − mcam->bmap_reverse = kmalloc_array(BITS_TO_LONGS(mcam->bmap_entries), | |
| 1913 | − sizeof(long), GFP_KERNEL); | |
| 1911 | + mcam->bmap_reverse = bitmap_zalloc(mcam->bmap_entries, GFP_KERNEL); | |
| 1914 | 1912 | if (!mcam->bmap_reverse) |
| 1915 | 1913 | goto free_bmap; |
| 1916 | 1914 | |
| 1917 | 1915 | mcam->bmap_fcnt = mcam->bmap_entries; |
| 1918 | 1916 | |
| 1919 | 1917 | /* Alloc memory for saving entry to RVU PFFUNC allocation mapping */ |
| 1920 | − mcam->entry2pfvf_map = kmalloc_array(mcam->bmap_entries, | |
| 1921 | − sizeof(u16), GFP_KERNEL); | |
| 1918 | + mcam->entry2pfvf_map = kcalloc(mcam->bmap_entries, sizeof(u16), | |
| 1919 | + GFP_KERNEL); | |
| 1920 | + | |
| 1922 | 1921 | if (!mcam->entry2pfvf_map) |
| 1923 | 1922 | goto free_bmap_reverse; |
| 1924 | 1923 | |
| @@ -1941,21 +1940,21 @@ int npc_mcam_rsrcs_init(struct rvu *rvu, int blkaddr) · 16 unmodified lines | ||
| 1941 | 1940 | if (err) |
| 1942 | 1941 | goto free_entry_map; |
| 1943 | 1942 | |
| 1944 | − mcam->cntr2pfvf_map = kmalloc_array(mcam->counters.max, | |
| 1945 | − sizeof(u16), GFP_KERNEL); | |
| 1943 | + mcam->cntr2pfvf_map = kcalloc(mcam->counters.max, sizeof(u16), | |
| 1944 | + GFP_KERNEL); | |
| 1946 | 1945 | if (!mcam->cntr2pfvf_map) |
| 1947 | 1946 | goto free_cntr_bmap; |
| 1948 | 1947 | |
| 1949 | 1948 | /* Alloc memory for MCAM entry to counter mapping and for tracking |
| 1950 | 1949 | * counter's reference count. |
| 1951 | 1950 | */ |
| 1952 | − mcam->entry2cntr_map = kmalloc_array(mcam->bmap_entries, | |
| 1953 | − sizeof(u16), GFP_KERNEL); | |
| 1951 | + mcam->entry2cntr_map = kcalloc(mcam->bmap_entries, sizeof(u16), | |
| 1952 | + GFP_KERNEL); | |
| 1954 | 1953 | if (!mcam->entry2cntr_map) |
| 1955 | 1954 | goto free_cntr_map; |
| 1956 | 1955 | |
| 1957 | − mcam->cntr_refcnt = kmalloc_array(mcam->counters.max, | |
| 1958 | − sizeof(u16), GFP_KERNEL); | |
| 1956 | + mcam->cntr_refcnt = kcalloc(mcam->counters.max, sizeof(u16), | |
| 1957 | + GFP_KERNEL); | |
| 1959 | 1958 | if (!mcam->cntr_refcnt) |
| 1960 | 1959 | goto free_entry_cntr_map; |
| 1961 | 1960 | |
| @@ -1988,9 +1987,9 @@ free_cntr_bmap: · 26 unmodified lines | ||
| 1988 | 1987 | free_entry_map: |
| 1989 | 1988 | kfree(mcam->entry2pfvf_map); |
| 1990 | 1989 | free_bmap_reverse: |
| 1991 | − kfree(mcam->bmap_reverse); | |
| 1990 | + bitmap_free(mcam->bmap_reverse); | |
| 1992 | 1991 | free_bmap: |
| 1993 | − kfree(mcam->bmap); | |
| 1992 | + bitmap_free(mcam->bmap); | |
| 1994 | 1993 | |
| 1995 | 1994 | return -ENOMEM; |
| 1996 | 1995 | } |
| @@ -951,8 +951,11 @@ int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura) · 950 unmodified lines | ||
| 951 | 951 | if (pfvf->ptp && qidx < pfvf->hw.tx_queues) { |
| 952 | 952 | err = qmem_alloc(pfvf->dev, &sq->timestamps, qset->sqe_cnt, |
| 953 | 953 | sizeof(*sq->timestamps)); |
| 954 | − if (err) | |
| 954 | + if (err) { | |
| 955 | + kfree(sq->sg); | |
| 956 | + sq->sg = NULL; | |
| 955 | 957 | return err; |
| 958 | + } | |
| 956 | 959 | } |
| 957 | 960 | |
| 958 | 961 | sq->head = 0; |
| @@ -968,7 +971,14 @@ int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura) · 9 unmodified lines | ||
| 968 | 971 | sq->stats.bytes = 0; |
| 969 | 972 | sq->stats.pkts = 0; |
| 970 | 973 | |
| 971 | − return pfvf->hw_ops->sq_aq_init(pfvf, qidx, sqb_aura); | |
| 974 | + err = pfvf->hw_ops->sq_aq_init(pfvf, qidx, sqb_aura); | |
| 975 | + if (err) { | |
| 976 | + kfree(sq->sg); | |
| 977 | + sq->sg = NULL; | |
| 978 | + return err; | |
| 979 | + } | |
| 980 | + | |
| 981 | + return 0; | |
| 972 | 982 | |
| 973 | 983 | } |
| 974 | 984 | |
| @@ -1084,7 +1084,7 @@ nfp_tunnel_add_shared_mac(struct nfp_app *app, struct net_device *netdev, · 1083 unmodified lines | ||
| 1084 | 1084 | u16 nfp_mac_idx = 0; |
| 1085 | 1085 | |
| 1086 | 1086 | entry = nfp_tunnel_lookup_offloaded_macs(app, netdev->dev_addr); |
| 1087 | − if (entry && nfp_tunnel_is_mac_idx_global(entry->index)) { | |
| 1087 | + if (entry && (nfp_tunnel_is_mac_idx_global(entry->index) || netif_is_lag_port(netdev))) { | |
| 1088 | 1088 | if (entry->bridge_count || |
| 1089 | 1089 | !nfp_flower_is_supported_bridge(netdev)) { |
| 1090 | 1090 | nfp_tunnel_offloaded_macs_inc_ref_and_link(entry, |
| @@ -2776,6 +2776,7 @@ static void nfp_net_netdev_init(struct nfp_net *nn) · 2775 unmodified lines | ||
| 2776 | 2776 | case NFP_NFD_VER_NFD3: |
| 2777 | 2777 | netdev->netdev_ops = &nfp_nfd3_netdev_ops; |
| 2778 | 2778 | netdev->xdp_features |= NETDEV_XDP_ACT_XSK_ZEROCOPY; |
| 2779 | + netdev->xdp_features |= NETDEV_XDP_ACT_REDIRECT; | |
| 2779 | 2780 | break; |
| 2780 | 2781 | case NFP_NFD_VER_NFDK: |
| 2781 | 2782 | netdev->netdev_ops = &nfp_nfdk_netdev_ops; |
| @@ -537,11 +537,13 @@ static int enable_bars(struct nfp6000_pcie *nfp, u16 interface) · 536 unmodified lines | ||
| 537 | 537 | const u32 barcfg_msix_general = |
| 538 | 538 | NFP_PCIE_BAR_PCIE2CPP_MapType( |
| 539 | 539 | NFP_PCIE_BAR_PCIE2CPP_MapType_GENERAL) | |
| 540 | − NFP_PCIE_BAR_PCIE2CPP_LengthSelect_32BIT; | |
| 540 | + NFP_PCIE_BAR_PCIE2CPP_LengthSelect( | |
| 541 | + NFP_PCIE_BAR_PCIE2CPP_LengthSelect_32BIT); | |
| 541 | 542 | const u32 barcfg_msix_xpb = |
| 542 | 543 | NFP_PCIE_BAR_PCIE2CPP_MapType( |
| 543 | 544 | NFP_PCIE_BAR_PCIE2CPP_MapType_BULK) | |
| 544 | − NFP_PCIE_BAR_PCIE2CPP_LengthSelect_32BIT | | |
| 545 | + NFP_PCIE_BAR_PCIE2CPP_LengthSelect( | |
| 546 | + NFP_PCIE_BAR_PCIE2CPP_LengthSelect_32BIT) | | |
| 545 | 547 | NFP_PCIE_BAR_PCIE2CPP_Target_BaseAddress( |
| 546 | 548 | NFP_CPP_TARGET_ISLAND_XPB); |
| 547 | 549 | const u32 barcfg_explicit[4] = { |
| @@ -59,28 +59,51 @@ · 58 unmodified lines | ||
| 59 | 59 | #undef FRAME_FILTER_DEBUG |
| 60 | 60 | /* #define FRAME_FILTER_DEBUG */ |
| 61 | 61 | |
| 62 | +struct stmmac_q_tx_stats { | |
| 63 | + u64_stats_t tx_bytes; | |
| 64 | + u64_stats_t tx_set_ic_bit; | |
| 65 | + u64_stats_t tx_tso_frames; | |
| 66 | + u64_stats_t tx_tso_nfrags; | |
| 67 | +}; | |
| 68 | + | |
| 69 | +struct stmmac_napi_tx_stats { | |
| 70 | + u64_stats_t tx_packets; | |
| 71 | + u64_stats_t tx_pkt_n; | |
| 72 | + u64_stats_t poll; | |
| 73 | + u64_stats_t tx_clean; | |
| 74 | + u64_stats_t tx_set_ic_bit; | |
| 75 | +}; | |
| 76 | + | |
| 62 | 77 | struct stmmac_txq_stats { |
| 63 | − u64 tx_bytes; | |
| 64 | − u64 tx_packets; | |
| 65 | − u64 tx_pkt_n; | |
| 66 | − u64 tx_normal_irq_n; | |
| 67 | − u64 napi_poll; | |
| 68 | − u64 tx_clean; | |
| 69 | − u64 tx_set_ic_bit; | |
| 70 | − u64 tx_tso_frames; | |
| 71 | − u64 tx_tso_nfrags; | |
| 72 | − struct u64_stats_sync syncp; | |
| 78 | + /* Updates protected by tx queue lock. */ | |
| 79 | + struct u64_stats_sync q_syncp; | |
| 80 | + struct stmmac_q_tx_stats q; | |
| 81 | + | |
| 82 | + /* Updates protected by NAPI poll logic. */ | |
| 83 | + struct u64_stats_sync napi_syncp; | |
| 84 | + struct stmmac_napi_tx_stats napi; | |
| 73 | 85 | } ____cacheline_aligned_in_smp; |
| 74 | 86 | |
| 87 | +struct stmmac_napi_rx_stats { | |
| 88 | + u64_stats_t rx_bytes; | |
| 89 | + u64_stats_t rx_packets; | |
| 90 | + u64_stats_t rx_pkt_n; | |
| 91 | + u64_stats_t poll; | |
| 92 | +}; | |
| 93 | + | |
| 75 | 94 | struct stmmac_rxq_stats { |
| 76 | − u64 rx_bytes; | |
| 77 | − u64 rx_packets; | |
| 78 | − u64 rx_pkt_n; | |
| 79 | − u64 rx_normal_irq_n; | |
| 80 | − u64 napi_poll; | |
| 81 | − struct u64_stats_sync syncp; | |
| 95 | + /* Updates protected by NAPI poll logic. */ | |
| 96 | + struct u64_stats_sync napi_syncp; | |
| 97 | + struct stmmac_napi_rx_stats napi; | |
| 82 | 98 | } ____cacheline_aligned_in_smp; |
| 83 | 99 | |
| 100 | +/* Updates on each CPU protected by not allowing nested irqs. */ | |
| 101 | +struct stmmac_pcpu_stats { | |
| 102 | + struct u64_stats_sync syncp; | |
| 103 | + u64_stats_t rx_normal_irq_n[MTL_MAX_TX_QUEUES]; | |
| 104 | + u64_stats_t tx_normal_irq_n[MTL_MAX_RX_QUEUES]; | |
| 105 | +}; | |
| 106 | + | |
| 84 | 107 | /* Extra statistic and debug information exposed by ethtool */ |
| 85 | 108 | struct stmmac_extra_stats { |
| 86 | 109 | /* Transmit errors */ |
| @@ -207,6 +230,7 @@ struct stmmac_extra_stats { · 120 unmodified lines | ||
| 207 | 230 | /* per queue statistics */ |
| 208 | 231 | struct stmmac_txq_stats txq_stats[MTL_MAX_TX_QUEUES]; |
| 209 | 232 | struct stmmac_rxq_stats rxq_stats[MTL_MAX_RX_QUEUES]; |
| 233 | + struct stmmac_pcpu_stats __percpu *pcpu_stats; | |
| 210 | 234 | unsigned long rx_dropped; |
| 211 | 235 | unsigned long rx_errors; |
| 212 | 236 | unsigned long tx_dropped; |
| @@ -218,6 +242,7 @@ struct stmmac_safety_stats { · 5 unmodified lines | ||
| 218 | 242 | unsigned long mac_errors[32]; |
| 219 | 243 | unsigned long mtl_errors[32]; |
| 220 | 244 | unsigned long dma_errors[32]; |
| 245 | + unsigned long dma_dpp_errors[32]; | |
| 221 | 246 | }; |
| 222 | 247 | |
| 223 | 248 | /* Number of fields in Safety Stats */ |
| @@ -441,8 +441,7 @@ static int sun8i_dwmac_dma_interrupt(struct stmmac_priv *priv, · 440 unmodified lines | ||
| 441 | 441 | struct stmmac_extra_stats *x, u32 chan, |
| 442 | 442 | u32 dir) |
| 443 | 443 | { |
| 444 | − struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan]; | |
| 445 | − struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan]; | |
| 444 | + struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats); | |
| 446 | 445 | int ret = 0; |
| 447 | 446 | u32 v; |
| 448 | 447 | |
| @@ -455,9 +454,9 @@ static int sun8i_dwmac_dma_interrupt(struct stmmac_priv *priv, · 6 unmodified lines | ||
| 455 | 454 | |
| 456 | 455 | if (v & EMAC_TX_INT) { |
| 457 | 456 | ret |= handle_tx; |
| 458 | − u64_stats_update_begin(&txq_stats->syncp); | |
| 459 | − txq_stats->tx_normal_irq_n++; | |
| 460 | − u64_stats_update_end(&txq_stats->syncp); | |
| 457 | + u64_stats_update_begin(&stats->syncp); | |
| 458 | + u64_stats_inc(&stats->tx_normal_irq_n[chan]); | |
| 459 | + u64_stats_update_end(&stats->syncp); | |
| 461 | 460 | } |
| 462 | 461 | |
| 463 | 462 | if (v & EMAC_TX_DMA_STOP_INT) |
| @@ -479,9 +478,9 @@ static int sun8i_dwmac_dma_interrupt(struct stmmac_priv *priv, · 15 unmodified lines | ||
| 479 | 478 | |
| 480 | 479 | if (v & EMAC_RX_INT) { |
| 481 | 480 | ret |= handle_rx; |
| 482 | − u64_stats_update_begin(&rxq_stats->syncp); | |
| 483 | − rxq_stats->rx_normal_irq_n++; | |
| 484 | − u64_stats_update_end(&rxq_stats->syncp); | |
| 481 | + u64_stats_update_begin(&stats->syncp); | |
| 482 | + u64_stats_inc(&stats->rx_normal_irq_n[chan]); | |
| 483 | + u64_stats_update_end(&stats->syncp); | |
| 485 | 484 | } |
| 486 | 485 | |
| 487 | 486 | if (v & EMAC_RX_BUF_UA_INT) |
| @@ -171,8 +171,7 @@ int dwmac4_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr, · 170 unmodified lines | ||
| 171 | 171 | const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; |
| 172 | 172 | u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(dwmac4_addrs, chan)); |
| 173 | 173 | u32 intr_en = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); |
| 174 | − struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan]; | |
| 175 | − struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan]; | |
| 174 | + struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats); | |
| 176 | 175 | int ret = 0; |
| 177 | 176 | |
| 178 | 177 | if (dir == DMA_DIR_RX) |
| @@ -201,15 +200,15 @@ int dwmac4_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr, · 22 unmodified lines | ||
| 201 | 200 | } |
| 202 | 201 | /* TX/RX NORMAL interrupts */ |
| 203 | 202 | if (likely(intr_status & DMA_CHAN_STATUS_RI)) { |
| 204 | − u64_stats_update_begin(&rxq_stats->syncp); | |
| 205 | − rxq_stats->rx_normal_irq_n++; | |
| 206 | − u64_stats_update_end(&rxq_stats->syncp); | |
| 203 | + u64_stats_update_begin(&stats->syncp); | |
| 204 | + u64_stats_inc(&stats->rx_normal_irq_n[chan]); | |
| 205 | + u64_stats_update_end(&stats->syncp); | |
| 207 | 206 | ret |= handle_rx; |
| 208 | 207 | } |
| 209 | 208 | if (likely(intr_status & DMA_CHAN_STATUS_TI)) { |
| 210 | − u64_stats_update_begin(&txq_stats->syncp); | |
| 211 | − txq_stats->tx_normal_irq_n++; | |
| 212 | − u64_stats_update_end(&txq_stats->syncp); | |
| 209 | + u64_stats_update_begin(&stats->syncp); | |
| 210 | + u64_stats_inc(&stats->tx_normal_irq_n[chan]); | |
| 211 | + u64_stats_update_end(&stats->syncp); | |
| 213 | 212 | ret |= handle_tx; |
| 214 | 213 | } |
| 215 | 214 | |
| @@ -162,8 +162,7 @@ static void show_rx_process_state(unsigned int status) · 161 unmodified lines | ||
| 162 | 162 | int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr, |
| 163 | 163 | struct stmmac_extra_stats *x, u32 chan, u32 dir) |
| 164 | 164 | { |
| 165 | − struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan]; | |
| 166 | − struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan]; | |
| 165 | + struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats); | |
| 167 | 166 | int ret = 0; |
| 168 | 167 | /* read the status register (CSR5) */ |
| 169 | 168 | u32 intr_status = readl(ioaddr + DMA_STATUS); |
| @@ -215,16 +214,16 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr, · 45 unmodified lines | ||
| 215 | 214 | u32 value = readl(ioaddr + DMA_INTR_ENA); |
| 216 | 215 | /* to schedule NAPI on real RIE event. */ |
| 217 | 216 | if (likely(value & DMA_INTR_ENA_RIE)) { |
| 218 | − u64_stats_update_begin(&rxq_stats->syncp); | |
| 219 | − rxq_stats->rx_normal_irq_n++; | |
| 220 | − u64_stats_update_end(&rxq_stats->syncp); | |
| 217 | + u64_stats_update_begin(&stats->syncp); | |
| 218 | + u64_stats_inc(&stats->rx_normal_irq_n[chan]); | |
| 219 | + u64_stats_update_end(&stats->syncp); | |
| 221 | 220 | ret |= handle_rx; |
| 222 | 221 | } |
| 223 | 222 | } |
| 224 | 223 | if (likely(intr_status & DMA_STATUS_TI)) { |
| 225 | − u64_stats_update_begin(&txq_stats->syncp); | |
| 226 | − txq_stats->tx_normal_irq_n++; | |
| 227 | − u64_stats_update_end(&txq_stats->syncp); | |
| 224 | + u64_stats_update_begin(&stats->syncp); | |
| 225 | + u64_stats_inc(&stats->tx_normal_irq_n[chan]); | |
| 226 | + u64_stats_update_end(&stats->syncp); | |
| 228 | 227 | ret |= handle_tx; |
| 229 | 228 | } |
| 230 | 229 | if (unlikely(intr_status & DMA_STATUS_ERI)) |
| @@ -303,6 +303,8 @@ · 302 unmodified lines | ||
| 303 | 303 | #define XGMAC_RXCEIE BIT(4) |
| 304 | 304 | #define XGMAC_TXCEIE BIT(0) |
| 305 | 305 | #define XGMAC_MTL_ECC_INT_STATUS 0x000010cc |
| 306 | +#define XGMAC_MTL_DPP_CONTROL 0x000010e0 | |
| 307 | +#define XGMAC_DPP_DISABLE BIT(0) | |
| 306 | 308 | #define XGMAC_MTL_TXQ_OPMODE(x) (0x00001100 + (0x80 * (x))) |
| 307 | 309 | #define XGMAC_TQS GENMASK(25, 16) |
| 308 | 310 | #define XGMAC_TQS_SHIFT 16 |
| @@ -385,6 +387,7 @@ · 76 unmodified lines | ||
| 385 | 387 | #define XGMAC_DCEIE BIT(1) |
| 386 | 388 | #define XGMAC_TCEIE BIT(0) |
| 387 | 389 | #define XGMAC_DMA_ECC_INT_STATUS 0x0000306c |
| 390 | +#define XGMAC_DMA_DPP_INT_STATUS 0x00003074 | |
| 388 | 391 | #define XGMAC_DMA_CH_CONTROL(x) (0x00003100 + (0x80 * (x))) |
| 389 | 392 | #define XGMAC_SPH BIT(24) |
| 390 | 393 | #define XGMAC_PBLx8 BIT(16) |
| @@ -830,6 +830,43 @@ static const struct dwxgmac3_error_desc dwxgmac3_dma_errors[32]= { · 829 unmodified lines | ||
| 830 | 830 | { false, "UNKNOWN", "Unknown Error" }, /* 31 */ |
| 831 | 831 | }; |
| 832 | 832 | |
| 833 | +static const char * const dpp_rx_err = "Read Rx Descriptor Parity checker Error"; | |
| 834 | +static const char * const dpp_tx_err = "Read Tx Descriptor Parity checker Error"; | |
| 835 | +static const struct dwxgmac3_error_desc dwxgmac3_dma_dpp_errors[32] = { | |
| 836 | + { true, "TDPES0", dpp_tx_err }, | |
| 837 | + { true, "TDPES1", dpp_tx_err }, | |
| 838 | + { true, "TDPES2", dpp_tx_err }, | |
| 839 | + { true, "TDPES3", dpp_tx_err }, | |
| 840 | + { true, "TDPES4", dpp_tx_err }, | |
| 841 | + { true, "TDPES5", dpp_tx_err }, | |
| 842 | + { true, "TDPES6", dpp_tx_err }, | |
| 843 | + { true, "TDPES7", dpp_tx_err }, | |
| 844 | + { true, "TDPES8", dpp_tx_err }, | |
| 845 | + { true, "TDPES9", dpp_tx_err }, | |
| 846 | + { true, "TDPES10", dpp_tx_err }, | |
| 847 | + { true, "TDPES11", dpp_tx_err }, | |
| 848 | + { true, "TDPES12", dpp_tx_err }, | |
| 849 | + { true, "TDPES13", dpp_tx_err }, | |
| 850 | + { true, "TDPES14", dpp_tx_err }, | |
| 851 | + { true, "TDPES15", dpp_tx_err }, | |
| 852 | + { true, "RDPES0", dpp_rx_err }, | |
| 853 | + { true, "RDPES1", dpp_rx_err }, | |
| 854 | + { true, "RDPES2", dpp_rx_err }, | |
| 855 | + { true, "RDPES3", dpp_rx_err }, | |
| 856 | + { true, "RDPES4", dpp_rx_err }, | |
| 857 | + { true, "RDPES5", dpp_rx_err }, | |
| 858 | + { true, "RDPES6", dpp_rx_err }, | |
| 859 | + { true, "RDPES7", dpp_rx_err }, | |
| 860 | + { true, "RDPES8", dpp_rx_err }, | |
| 861 | + { true, "RDPES9", dpp_rx_err }, | |
| 862 | + { true, "RDPES10", dpp_rx_err }, | |
| 863 | + { true, "RDPES11", dpp_rx_err }, | |
| 864 | + { true, "RDPES12", dpp_rx_err }, | |
| 865 | + { true, "RDPES13", dpp_rx_err }, | |
| 866 | + { true, "RDPES14", dpp_rx_err }, | |
| 867 | + { true, "RDPES15", dpp_rx_err }, | |
| 868 | +}; | |
| 869 | + | |
| 833 | 870 | static void dwxgmac3_handle_dma_err(struct net_device *ndev, |
| 834 | 871 | void __iomem *ioaddr, bool correctable, |
| 835 | 872 | struct stmmac_safety_stats *stats) |
| @@ -841,6 +878,13 @@ static void dwxgmac3_handle_dma_err(struct net_device *ndev, · 5 unmodified lines | ||
| 841 | 878 | |
| 842 | 879 | dwxgmac3_log_error(ndev, value, correctable, "DMA", |
| 843 | 880 | dwxgmac3_dma_errors, STAT_OFF(dma_errors), stats); |
| 881 | + | |
| 882 | + value = readl(ioaddr + XGMAC_DMA_DPP_INT_STATUS); | |
| 883 | + writel(value, ioaddr + XGMAC_DMA_DPP_INT_STATUS); | |
| 884 | + | |
| 885 | + dwxgmac3_log_error(ndev, value, false, "DMA_DPP", | |
| 886 | + dwxgmac3_dma_dpp_errors, | |
| 887 | + STAT_OFF(dma_dpp_errors), stats); | |
| 844 | 888 | } |
| 845 | 889 | |
| 846 | 890 | static int |
| @@ -881,6 +925,12 @@ dwxgmac3_safety_feat_config(void __iomem *ioaddr, unsigned int asp, · 34 unmodified lines | ||
| 881 | 925 | value |= XGMAC_TMOUTEN; /* FSM Timeout Feature */ |
| 882 | 926 | writel(value, ioaddr + XGMAC_MAC_FSM_CONTROL); |
| 883 | 927 | |
| 928 | + /* 5. Enable Data Path Parity Protection */ | |
| 929 | + value = readl(ioaddr + XGMAC_MTL_DPP_CONTROL); | |
| 930 | + /* already enabled by default, explicit enable it again */ | |
| 931 | + value &= ~XGMAC_DPP_DISABLE; | |
| 932 | + writel(value, ioaddr + XGMAC_MTL_DPP_CONTROL); | |
| 933 | + | |
| 884 | 934 | return 0; |
| 885 | 935 | } |
| 886 | 936 | |
| @@ -914,7 +964,11 @@ static int dwxgmac3_safety_feat_irq_status(struct net_device *ndev, · 27 unmodified lines | ||
| 914 | 964 | ret |= !corr; |
| 915 | 965 | } |
| 916 | 966 | |
| 917 | − err = dma & (XGMAC_DEUIS | XGMAC_DECIS); | |
| 967 | + /* DMA_DPP_Interrupt_Status is indicated by MCSIS bit in | |
| 968 | + * DMA_Safety_Interrupt_Status, so we handle DMA Data Path | |
| 969 | + * Parity Errors here | |
| 970 | + */ | |
| 971 | + err = dma & (XGMAC_DEUIS | XGMAC_DECIS | XGMAC_MCSIS); | |
| 918 | 972 | corr = dma & XGMAC_DECIS; |
| 919 | 973 | if (err) { |
| 920 | 974 | dwxgmac3_handle_dma_err(ndev, ioaddr, corr, stats); |
| @@ -930,6 +984,7 @@ static const struct dwxgmac3_error { · 9 unmodified lines | ||
| 930 | 984 | { dwxgmac3_mac_errors }, |
| 931 | 985 | { dwxgmac3_mtl_errors }, |
| 932 | 986 | { dwxgmac3_dma_errors }, |
| 987 | + { dwxgmac3_dma_dpp_errors }, | |
| 933 | 988 | }; |
| 934 | 989 | |
| 935 | 990 | static int dwxgmac3_safety_feat_dump(struct stmmac_safety_stats *stats, |
| @@ -337,8 +337,7 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv, · 336 unmodified lines | ||
| 337 | 337 | struct stmmac_extra_stats *x, u32 chan, |
| 338 | 338 | u32 dir) |
| 339 | 339 | { |
| 340 | − struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan]; | |
| 341 | − struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan]; | |
| 340 | + struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats); | |
| 342 | 341 | u32 intr_status = readl(ioaddr + XGMAC_DMA_CH_STATUS(chan)); |
| 343 | 342 | u32 intr_en = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan)); |
| 344 | 343 | int ret = 0; |
| @@ -367,15 +366,15 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv, · 22 unmodified lines | ||
| 367 | 366 | /* TX/RX NORMAL interrupts */ |
| 368 | 367 | if (likely(intr_status & XGMAC_NIS)) { |
| 369 | 368 | if (likely(intr_status & XGMAC_RI)) { |
| 370 | − u64_stats_update_begin(&rxq_stats->syncp); | |
| 371 | − rxq_stats->rx_normal_irq_n++; | |
| 372 | − u64_stats_update_end(&rxq_stats->syncp); | |
| 369 | + u64_stats_update_begin(&stats->syncp); | |
| 370 | + u64_stats_inc(&stats->rx_normal_irq_n[chan]); | |
| 371 | + u64_stats_update_end(&stats->syncp); | |
| 373 | 372 | ret |= handle_rx; |
| 374 | 373 | } |
| 375 | 374 | if (likely(intr_status & (XGMAC_TI | XGMAC_TBU))) { |
| 376 | − u64_stats_update_begin(&txq_stats->syncp); | |
| 377 | − txq_stats->tx_normal_irq_n++; | |
| 378 | − u64_stats_update_end(&txq_stats->syncp); | |
| 375 | + u64_stats_update_begin(&stats->syncp); | |
| 376 | + u64_stats_inc(&stats->tx_normal_irq_n[chan]); | |
| 377 | + u64_stats_update_end(&stats->syncp); | |
| 379 | 378 | ret |= handle_tx; |
| 380 | 379 | } |
| 381 | 380 | } |
| @@ -549,44 +549,79 @@ stmmac_set_pauseparam(struct net_device *netdev, · 548 unmodified lines | ||
| 549 | 549 | } |
| 550 | 550 | } |
| 551 | 551 | |
| 552 | +static u64 stmmac_get_rx_normal_irq_n(struct stmmac_priv *priv, int q) | |
| 553 | +{ | |
| 554 | + u64 total; | |
| 555 | + int cpu; | |
| 556 | + | |
| 557 | + total = 0; | |
| 558 | + for_each_possible_cpu(cpu) { | |
| 559 | + struct stmmac_pcpu_stats *pcpu; | |
| 560 | + unsigned int start; | |
| 561 | + u64 irq_n; | |
| 562 | + | |
| 563 | + pcpu = per_cpu_ptr(priv->xstats.pcpu_stats, cpu); | |
| 564 | + do { | |
| 565 | + start = u64_stats_fetch_begin(&pcpu->syncp); | |
| 566 | + irq_n = u64_stats_read(&pcpu->rx_normal_irq_n[q]); | |
| 567 | + } while (u64_stats_fetch_retry(&pcpu->syncp, start)); | |
| 568 | + total += irq_n; | |
| 569 | + } | |
| 570 | + return total; | |
| 571 | +} | |
| 572 | + | |
| 573 | +static u64 stmmac_get_tx_normal_irq_n(struct stmmac_priv *priv, int q) | |
| 574 | +{ | |
| 575 | + u64 total; | |
| 576 | + int cpu; | |
| 577 | + | |
| 578 | + total = 0; | |
| 579 | + for_each_possible_cpu(cpu) { | |
| 580 | + struct stmmac_pcpu_stats *pcpu; | |
| 581 | + unsigned int start; | |
| 582 | + u64 irq_n; | |
| 583 | + | |
| 584 | + pcpu = per_cpu_ptr(priv->xstats.pcpu_stats, cpu); | |
| 585 | + do { | |
| 586 | + start = u64_stats_fetch_begin(&pcpu->syncp); | |
| 587 | + irq_n = u64_stats_read(&pcpu->tx_normal_irq_n[q]); | |
| 588 | + } while (u64_stats_fetch_retry(&pcpu->syncp, start)); | |
| 589 | + total += irq_n; | |
| 590 | + } | |
| 591 | + return total; | |
| 592 | +} | |
| 593 | + | |
| 552 | 594 | static void stmmac_get_per_qstats(struct stmmac_priv *priv, u64 *data) |
| 553 | 595 | { |
| 554 | 596 | u32 tx_cnt = priv->plat->tx_queues_to_use; |
| 555 | 597 | u32 rx_cnt = priv->plat->rx_queues_to_use; |
| 556 | 598 | unsigned int start; |
| 557 | − int q, stat; | |
| 558 | − char *p; | |
| 599 | + int q; | |
| 559 | 600 | |
| 560 | 601 | for (q = 0; q < tx_cnt; q++) { |
| 561 | 602 | struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[q]; |
| 562 | − struct stmmac_txq_stats snapshot; | |
| 603 | + u64 pkt_n; | |
| 563 | 604 | |
| 564 | 605 | do { |
| 565 | − start = u64_stats_fetch_begin(&txq_stats->syncp); | |
| 566 | − snapshot = *txq_stats; | |
| 567 | − } while (u64_stats_fetch_retry(&txq_stats->syncp, start)); | |
| 606 | + start = u64_stats_fetch_begin(&txq_stats->napi_syncp); | |
| 607 | + pkt_n = u64_stats_read(&txq_stats->napi.tx_pkt_n); | |
| 608 | + } while (u64_stats_fetch_retry(&txq_stats->napi_syncp, start)); | |
| 568 | 609 | |
| 569 | − p = (char *)&snapshot + offsetof(struct stmmac_txq_stats, tx_pkt_n); | |
| 570 | − for (stat = 0; stat < STMMAC_TXQ_STATS; stat++) { | |
| 571 | − *data++ = (*(u64 *)p); | |
| 572 | − p += sizeof(u64); | |
| 573 | − } | |
| 610 | + *data++ = pkt_n; | |
| 611 | + *data++ = stmmac_get_tx_normal_irq_n(priv, q); | |
| 574 | 612 | } |
| 575 | 613 | |
| 576 | 614 | for (q = 0; q < rx_cnt; q++) { |
| 577 | 615 | struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[q]; |
| 578 | − struct stmmac_rxq_stats snapshot; | |
| 616 | + u64 pkt_n; | |
| 579 | 617 | |
| 580 | 618 | do { |
| 581 | − start = u64_stats_fetch_begin(&rxq_stats->syncp); | |
| 582 | − snapshot = *rxq_stats; | |
| 583 | − } while (u64_stats_fetch_retry(&rxq_stats->syncp, start)); | |
| 619 | + start = u64_stats_fetch_begin(&rxq_stats->napi_syncp); | |
| 620 | + pkt_n = u64_stats_read(&rxq_stats->napi.rx_pkt_n); | |
| 621 | + } while (u64_stats_fetch_retry(&rxq_stats->napi_syncp, start)); | |
| 584 | 622 | |
| 585 | − p = (char *)&snapshot + offsetof(struct stmmac_rxq_stats, rx_pkt_n); | |
| 586 | − for (stat = 0; stat < STMMAC_RXQ_STATS; stat++) { | |
| 587 | − *data++ = (*(u64 *)p); | |
| 588 | − p += sizeof(u64); | |
| 589 | − } | |
| 623 | + *data++ = pkt_n; | |
| 624 | + *data++ = stmmac_get_rx_normal_irq_n(priv, q); | |
| 590 | 625 | } |
| 591 | 626 | } |
| 592 | 627 | |
| @@ -645,39 +680,49 @@ static void stmmac_get_ethtool_stats(struct net_device *dev, · 52 unmodified lines | ||
| 645 | 680 | pos = j; |
| 646 | 681 | for (i = 0; i < rx_queues_count; i++) { |
| 647 | 682 | struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[i]; |
| 648 | − struct stmmac_rxq_stats snapshot; | |
| 683 | + struct stmmac_napi_rx_stats snapshot; | |
| 684 | + u64 n_irq; | |
| 649 | 685 | |
| 650 | 686 | j = pos; |
| 651 | 687 | do { |
| 652 | − start = u64_stats_fetch_begin(&rxq_stats->syncp); | |
| 653 | − snapshot = *rxq_stats; | |
| 654 | − } while (u64_stats_fetch_retry(&rxq_stats->syncp, start)); | |
| 655 | − | |
| 656 | − data[j++] += snapshot.rx_pkt_n; | |
| 657 | − data[j++] += snapshot.rx_normal_irq_n; | |
| 658 | − normal_irq_n += snapshot.rx_normal_irq_n; | |
| 659 | − napi_poll += snapshot.napi_poll; | |
| 688 | + start = u64_stats_fetch_begin(&rxq_stats->napi_syncp); | |
| 689 | + snapshot = rxq_stats->napi; | |
| 690 | + } while (u64_stats_fetch_retry(&rxq_stats->napi_syncp, start)); | |
| 691 | + | |
| 692 | + data[j++] += u64_stats_read(&snapshot.rx_pkt_n); | |
| 693 | + n_irq = stmmac_get_rx_normal_irq_n(priv, i); | |
| 694 | + data[j++] += n_irq; | |
| 695 | + normal_irq_n += n_irq; | |
| 696 | + napi_poll += u64_stats_read(&snapshot.poll); | |
| 660 | 697 | } |
| 661 | 698 | |
| 662 | 699 | pos = j; |
| 663 | 700 | for (i = 0; i < tx_queues_count; i++) { |
| 664 | 701 | struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[i]; |
| 665 | − struct stmmac_txq_stats snapshot; | |
| 702 | + struct stmmac_napi_tx_stats napi_snapshot; | |
| 703 | + struct stmmac_q_tx_stats q_snapshot; | |
| 704 | + u64 n_irq; | |
| 666 | 705 | |
| 667 | 706 | j = pos; |
| 668 | 707 | do { |
| 669 | − start = u64_stats_fetch_begin(&txq_stats->syncp); | |
| 670 | − snapshot = *txq_stats; | |
| 671 | − } while (u64_stats_fetch_retry(&txq_stats->syncp, start)); | |
| 672 | − | |
| 673 | − data[j++] += snapshot.tx_pkt_n; | |
| 674 | − data[j++] += snapshot.tx_normal_irq_n; | |
| 675 | − normal_irq_n += snapshot.tx_normal_irq_n; | |
| 676 | − data[j++] += snapshot.tx_clean; | |
| 677 | − data[j++] += snapshot.tx_set_ic_bit; | |
| 678 | − data[j++] += snapshot.tx_tso_frames; | |
| 679 | − data[j++] += snapshot.tx_tso_nfrags; | |
| 680 | − napi_poll += snapshot.napi_poll; | |
| 708 | + start = u64_stats_fetch_begin(&txq_stats->q_syncp); | |
| 709 | + q_snapshot = txq_stats->q; | |
| 710 | + } while (u64_stats_fetch_retry(&txq_stats->q_syncp, start)); | |
| 711 | + do { | |
| 712 | + start = u64_stats_fetch_begin(&txq_stats->napi_syncp); | |
| 713 | + napi_snapshot = txq_stats->napi; | |
| 714 | + } while (u64_stats_fetch_retry(&txq_stats->napi_syncp, start)); | |
| 715 | + | |
| 716 | + data[j++] += u64_stats_read(&napi_snapshot.tx_pkt_n); | |
| 717 | + n_irq = stmmac_get_tx_normal_irq_n(priv, i); | |
| 718 | + data[j++] += n_irq; | |
| 719 | + normal_irq_n += n_irq; | |
| 720 | + data[j++] += u64_stats_read(&napi_snapshot.tx_clean); | |
| 721 | + data[j++] += u64_stats_read(&q_snapshot.tx_set_ic_bit) + | |
| 722 | + u64_stats_read(&napi_snapshot.tx_set_ic_bit); | |
| 723 | + data[j++] += u64_stats_read(&q_snapshot.tx_tso_frames); | |
| 724 | + data[j++] += u64_stats_read(&q_snapshot.tx_tso_nfrags); | |
| 725 | + napi_poll += u64_stats_read(&napi_snapshot.poll); | |
| 681 | 726 | } |
| 682 | 727 | normal_irq_n += priv->xstats.rx_early_irq; |
| 683 | 728 | data[j++] = normal_irq_n; |
| @@ -2482,7 +2482,6 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget) · 2481 unmodified lines | ||
| 2482 | 2482 | struct xdp_desc xdp_desc; |
| 2483 | 2483 | bool work_done = true; |
| 2484 | 2484 | u32 tx_set_ic_bit = 0; |
| 2485 | − unsigned long flags; | |
| 2486 | 2485 | |
| 2487 | 2486 | /* Avoids TX time-out as we are sharing with slow path */ |
| 2488 | 2487 | txq_trans_cond_update(nq); |
| @@ -2573,9 +2572,9 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget) · 84 unmodified lines | ||
| 2573 | 2572 | tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, priv->dma_conf.dma_tx_size); |
| 2574 | 2573 | entry = tx_q->cur_tx; |
| 2575 | 2574 | } |
| 2576 | − flags = u64_stats_update_begin_irqsave(&txq_stats->syncp); | |
| 2577 | − txq_stats->tx_set_ic_bit += tx_set_ic_bit; | |
| 2578 | − u64_stats_update_end_irqrestore(&txq_stats->syncp, flags); | |
| 2575 | + u64_stats_update_begin(&txq_stats->napi_syncp); | |
| 2576 | + u64_stats_add(&txq_stats->napi.tx_set_ic_bit, tx_set_ic_bit); | |
| 2577 | + u64_stats_update_end(&txq_stats->napi_syncp); | |
| 2579 | 2578 | |
| 2580 | 2579 | if (tx_desc) { |
| 2581 | 2580 | stmmac_flush_tx_descriptors(priv, queue); |
| @@ -2623,7 +2622,6 @@ static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue, · 41 unmodified lines | ||
| 2623 | 2622 | unsigned int bytes_compl = 0, pkts_compl = 0; |
| 2624 | 2623 | unsigned int entry, xmits = 0, count = 0; |
| 2625 | 2624 | u32 tx_packets = 0, tx_errors = 0; |
| 2626 | − unsigned long flags; | |
| 2627 | 2625 | |
| 2628 | 2626 | __netif_tx_lock_bh(netdev_get_tx_queue(priv->dev, queue)); |
| 2629 | 2627 | |
| @@ -2789,11 +2787,11 @@ static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue, · 159 unmodified lines | ||
| 2789 | 2787 | if (tx_q->dirty_tx != tx_q->cur_tx) |
| 2790 | 2788 | *pending_packets = true; |
| 2791 | 2789 | |
| 2792 | − flags = u64_stats_update_begin_irqsave(&txq_stats->syncp); | |
| 2793 | − txq_stats->tx_packets += tx_packets; | |
| 2794 | − txq_stats->tx_pkt_n += tx_packets; | |
| 2795 | − txq_stats->tx_clean++; | |
| 2796 | − u64_stats_update_end_irqrestore(&txq_stats->syncp, flags); | |
| 2790 | + u64_stats_update_begin(&txq_stats->napi_syncp); | |
| 2791 | + u64_stats_add(&txq_stats->napi.tx_packets, tx_packets); | |
| 2792 | + u64_stats_add(&txq_stats->napi.tx_pkt_n, tx_packets); | |
| 2793 | + u64_stats_inc(&txq_stats->napi.tx_clean); | |
| 2794 | + u64_stats_update_end(&txq_stats->napi_syncp); | |
| 2797 | 2795 | |
| 2798 | 2796 | priv->xstats.tx_errors += tx_errors; |
| 2799 | 2797 | |
| @@ -4220,7 +4218,6 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) · 1420 unmodified lines | ||
| 4220 | 4218 | struct stmmac_tx_queue *tx_q; |
| 4221 | 4219 | bool has_vlan, set_ic; |
| 4222 | 4220 | u8 proto_hdr_len, hdr; |
| 4223 | − unsigned long flags; | |
| 4224 | 4221 | u32 pay_len, mss; |
| 4225 | 4222 | dma_addr_t des; |
| 4226 | 4223 | int i; |
| @@ -4385,13 +4382,13 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) · 158 unmodified lines | ||
| 4385 | 4382 | netif_tx_stop_queue(netdev_get_tx_queue(priv->dev, queue)); |
| 4386 | 4383 | } |
| 4387 | 4384 | |
| 4388 | − flags = u64_stats_update_begin_irqsave(&txq_stats->syncp); | |
| 4389 | − txq_stats->tx_bytes += skb->len; | |
| 4390 | − txq_stats->tx_tso_frames++; | |
| 4391 | − txq_stats->tx_tso_nfrags += nfrags; | |
| 4385 | + u64_stats_update_begin(&txq_stats->q_syncp); | |
| 4386 | + u64_stats_add(&txq_stats->q.tx_bytes, skb->len); | |
| 4387 | + u64_stats_inc(&txq_stats->q.tx_tso_frames); | |
| 4388 | + u64_stats_add(&txq_stats->q.tx_tso_nfrags, nfrags); | |
| 4392 | 4389 | if (set_ic) |
| 4393 | − txq_stats->tx_set_ic_bit++; | |
| 4394 | − u64_stats_update_end_irqrestore(&txq_stats->syncp, flags); | |
| 4390 | + u64_stats_inc(&txq_stats->q.tx_set_ic_bit); | |
| 4391 | + u64_stats_update_end(&txq_stats->q_syncp); | |
| 4395 | 4392 | |
| 4396 | 4393 | if (priv->sarc_type) |
| 4397 | 4394 | stmmac_set_desc_sarc(priv, first, priv->sarc_type); |
| @@ -4490,7 +4487,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) · 92 unmodified lines | ||
| 4490 | 4487 | struct stmmac_tx_queue *tx_q; |
| 4491 | 4488 | bool has_vlan, set_ic; |
| 4492 | 4489 | int entry, first_tx; |
| 4493 | − unsigned long flags; | |
| 4494 | 4490 | dma_addr_t des; |
| 4495 | 4491 | |
| 4496 | 4492 | tx_q = &priv->dma_conf.tx_queue[queue]; |
| @@ -4667,11 +4663,11 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) · 170 unmodified lines | ||
| 4667 | 4663 | netif_tx_stop_queue(netdev_get_tx_queue(priv->dev, queue)); |
| 4668 | 4664 | } |
| 4669 | 4665 | |
| 4670 | − flags = u64_stats_update_begin_irqsave(&txq_stats->syncp); | |
| 4671 | − txq_stats->tx_bytes += skb->len; | |
| 4666 | + u64_stats_update_begin(&txq_stats->q_syncp); | |
| 4667 | + u64_stats_add(&txq_stats->q.tx_bytes, skb->len); | |
| 4672 | 4668 | if (set_ic) |
| 4673 | − txq_stats->tx_set_ic_bit++; | |
| 4674 | − u64_stats_update_end_irqrestore(&txq_stats->syncp, flags); | |
| 4669 | + u64_stats_inc(&txq_stats->q.tx_set_ic_bit); | |
| 4670 | + u64_stats_update_end(&txq_stats->q_syncp); | |
| 4675 | 4671 | |
| 4676 | 4672 | if (priv->sarc_type) |
| 4677 | 4673 | stmmac_set_desc_sarc(priv, first, priv->sarc_type); |
| @@ -4943,12 +4939,11 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue, · 265 unmodified lines | ||
| 4943 | 4939 | set_ic = false; |
| 4944 | 4940 | |
| 4945 | 4941 | if (set_ic) { |
| 4946 | − unsigned long flags; | |
| 4947 | 4942 | tx_q->tx_count_frames = 0; |
| 4948 | 4943 | stmmac_set_tx_ic(priv, tx_desc); |
| 4949 | − flags = u64_stats_update_begin_irqsave(&txq_stats->syncp); | |
| 4950 | − txq_stats->tx_set_ic_bit++; | |
| 4951 | − u64_stats_update_end_irqrestore(&txq_stats->syncp, flags); | |
| 4944 | + u64_stats_update_begin(&txq_stats->q_syncp); | |
| 4945 | + u64_stats_inc(&txq_stats->q.tx_set_ic_bit); | |
| 4946 | + u64_stats_update_end(&txq_stats->q_syncp); | |
| 4952 | 4947 | } |
| 4953 | 4948 | |
| 4954 | 4949 | stmmac_enable_dma_transmission(priv, priv->ioaddr); |
| @@ -5098,7 +5093,6 @@ static void stmmac_dispatch_skb_zc(struct stmmac_priv *priv, u32 queue, · 143 unmodified lines | ||
| 5098 | 5093 | unsigned int len = xdp->data_end - xdp->data; |
| 5099 | 5094 | enum pkt_hash_types hash_type; |
| 5100 | 5095 | int coe = priv->hw->rx_csum; |
| 5101 | − unsigned long flags; | |
| 5102 | 5096 | struct sk_buff *skb; |
| 5103 | 5097 | u32 hash; |
| 5104 | 5098 | |
| @@ -5128,10 +5122,10 @@ static void stmmac_dispatch_skb_zc(struct stmmac_priv *priv, u32 queue, · 23 unmodified lines | ||
| 5128 | 5122 | skb_record_rx_queue(skb, queue); |
| 5129 | 5123 | napi_gro_receive(&ch->rxtx_napi, skb); |
| 5130 | 5124 | |
| 5131 | − flags = u64_stats_update_begin_irqsave(&rxq_stats->syncp); | |
| 5132 | − rxq_stats->rx_pkt_n++; | |
| 5133 | − rxq_stats->rx_bytes += len; | |
| 5134 | − u64_stats_update_end_irqrestore(&rxq_stats->syncp, flags); | |
| 5125 | + u64_stats_update_begin(&rxq_stats->napi_syncp); | |
| 5126 | + u64_stats_inc(&rxq_stats->napi.rx_pkt_n); | |
| 5127 | + u64_stats_add(&rxq_stats->napi.rx_bytes, len); | |
| 5128 | + u64_stats_update_end(&rxq_stats->napi_syncp); | |
| 5135 | 5129 | } |
| 5136 | 5130 | |
| 5137 | 5131 | static bool stmmac_rx_refill_zc(struct stmmac_priv *priv, u32 queue, u32 budget) |
| @@ -5213,7 +5207,6 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue) · 75 unmodified lines | ||
| 5213 | 5207 | unsigned int desc_size; |
| 5214 | 5208 | struct bpf_prog *prog; |
| 5215 | 5209 | bool failure = false; |
| 5216 | − unsigned long flags; | |
| 5217 | 5210 | int xdp_status = 0; |
| 5218 | 5211 | int status = 0; |
| 5219 | 5212 | |
| @@ -5368,9 +5361,9 @@ read_again: · 148 unmodified lines | ||
| 5368 | 5361 | |
| 5369 | 5362 | stmmac_finalize_xdp_rx(priv, xdp_status); |
| 5370 | 5363 | |
| 5371 | − flags = u64_stats_update_begin_irqsave(&rxq_stats->syncp); | |
| 5372 | − rxq_stats->rx_pkt_n += count; | |
| 5373 | − u64_stats_update_end_irqrestore(&rxq_stats->syncp, flags); | |
| 5364 | + u64_stats_update_begin(&rxq_stats->napi_syncp); | |
| 5365 | + u64_stats_add(&rxq_stats->napi.rx_pkt_n, count); | |
| 5366 | + u64_stats_update_end(&rxq_stats->napi_syncp); | |
| 5374 | 5367 | |
| 5375 | 5368 | priv->xstats.rx_dropped += rx_dropped; |
| 5376 | 5369 | priv->xstats.rx_errors += rx_errors; |
| @@ -5408,7 +5401,6 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) · 31 unmodified lines | ||
| 5408 | 5401 | unsigned int desc_size; |
| 5409 | 5402 | struct sk_buff *skb = NULL; |
| 5410 | 5403 | struct stmmac_xdp_buff ctx; |
| 5411 | − unsigned long flags; | |
| 5412 | 5404 | int xdp_status = 0; |
| 5413 | 5405 | int buf_sz; |
| 5414 | 5406 | |
| @@ -5668,11 +5660,11 @@ drain_data: · 253 unmodified lines | ||
| 5668 | 5660 | |
| 5669 | 5661 | stmmac_rx_refill(priv, queue); |
| 5670 | 5662 | |
| 5671 | − flags = u64_stats_update_begin_irqsave(&rxq_stats->syncp); | |
| 5672 | − rxq_stats->rx_packets += rx_packets; | |
| 5673 | − rxq_stats->rx_bytes += rx_bytes; | |
| 5674 | − rxq_stats->rx_pkt_n += count; | |
| 5675 | − u64_stats_update_end_irqrestore(&rxq_stats->syncp, flags); | |
| 5663 | + u64_stats_update_begin(&rxq_stats->napi_syncp); | |
| 5664 | + u64_stats_add(&rxq_stats->napi.rx_packets, rx_packets); | |
| 5665 | + u64_stats_add(&rxq_stats->napi.rx_bytes, rx_bytes); | |
| 5666 | + u64_stats_add(&rxq_stats->napi.rx_pkt_n, count); | |
| 5667 | + u64_stats_update_end(&rxq_stats->napi_syncp); | |
| 5676 | 5668 | |
| 5677 | 5669 | priv->xstats.rx_dropped += rx_dropped; |
| 5678 | 5670 | priv->xstats.rx_errors += rx_errors; |
| @@ -5687,13 +5679,12 @@ static int stmmac_napi_poll_rx(struct napi_struct *napi, int budget) · 8 unmodified lines | ||
| 5687 | 5679 | struct stmmac_priv *priv = ch->priv_data; |
| 5688 | 5680 | struct stmmac_rxq_stats *rxq_stats; |
| 5689 | 5681 | u32 chan = ch->index; |
| 5690 | − unsigned long flags; | |
| 5691 | 5682 | int work_done; |
| 5692 | 5683 | |
| 5693 | 5684 | rxq_stats = &priv->xstats.rxq_stats[chan]; |
| 5694 | − flags = u64_stats_update_begin_irqsave(&rxq_stats->syncp); | |
| 5695 | − rxq_stats->napi_poll++; | |
| 5696 | − u64_stats_update_end_irqrestore(&rxq_stats->syncp, flags); | |
| 5685 | + u64_stats_update_begin(&rxq_stats->napi_syncp); | |
| 5686 | + u64_stats_inc(&rxq_stats->napi.poll); | |
| 5687 | + u64_stats_update_end(&rxq_stats->napi_syncp); | |
| 5697 | 5688 | |
| 5698 | 5689 | work_done = stmmac_rx(priv, budget, chan); |
| 5699 | 5690 | if (work_done < budget && napi_complete_done(napi, work_done)) { |
| @@ -5715,13 +5706,12 @@ static int stmmac_napi_poll_tx(struct napi_struct *napi, int budget) · 15 unmodified lines | ||
| 5715 | 5706 | struct stmmac_txq_stats *txq_stats; |
| 5716 | 5707 | bool pending_packets = false; |
| 5717 | 5708 | u32 chan = ch->index; |
| 5718 | − unsigned long flags; | |
| 5719 | 5709 | int work_done; |
| 5720 | 5710 | |
| 5721 | 5711 | txq_stats = &priv->xstats.txq_stats[chan]; |
| 5722 | − flags = u64_stats_update_begin_irqsave(&txq_stats->syncp); | |
| 5723 | − txq_stats->napi_poll++; | |
| 5724 | − u64_stats_update_end_irqrestore(&txq_stats->syncp, flags); | |
| 5712 | + u64_stats_update_begin(&txq_stats->napi_syncp); | |
| 5713 | + u64_stats_inc(&txq_stats->napi.poll); | |
| 5714 | + u64_stats_update_end(&txq_stats->napi_syncp); | |
| 5725 | 5715 | |
| 5726 | 5716 | work_done = stmmac_tx_clean(priv, budget, chan, &pending_packets); |
| 5727 | 5717 | work_done = min(work_done, budget); |
| @@ -5751,17 +5741,16 @@ static int stmmac_napi_poll_rxtx(struct napi_struct *napi, int budget) · 23 unmodified lines | ||
| 5751 | 5741 | struct stmmac_rxq_stats *rxq_stats; |
| 5752 | 5742 | struct stmmac_txq_stats *txq_stats; |
| 5753 | 5743 | u32 chan = ch->index; |
| 5754 | − unsigned long flags; | |
| 5755 | 5744 | |
| 5756 | 5745 | rxq_stats = &priv->xstats.rxq_stats[chan]; |
| 5757 | − flags = u64_stats_update_begin_irqsave(&rxq_stats->syncp); | |
| 5758 | − rxq_stats->napi_poll++; | |
| 5759 | − u64_stats_update_end_irqrestore(&rxq_stats->syncp, flags); | |
| 5746 | + u64_stats_update_begin(&rxq_stats->napi_syncp); | |
| 5747 | + u64_stats_inc(&rxq_stats->napi.poll); | |
| 5748 | + u64_stats_update_end(&rxq_stats->napi_syncp); | |
| 5760 | 5749 | |
| 5761 | 5750 | txq_stats = &priv->xstats.txq_stats[chan]; |
| 5762 | − flags = u64_stats_update_begin_irqsave(&txq_stats->syncp); | |
| 5763 | − txq_stats->napi_poll++; | |
| 5764 | − u64_stats_update_end_irqrestore(&txq_stats->syncp, flags); | |
| 5751 | + u64_stats_update_begin(&txq_stats->napi_syncp); | |
| 5752 | + u64_stats_inc(&txq_stats->napi.poll); | |
| 5753 | + u64_stats_update_end(&txq_stats->napi_syncp); | |
| 5765 | 5754 | |
| 5766 | 5755 | tx_done = stmmac_tx_clean(priv, budget, chan, &tx_pending_packets); |
| 5767 | 5756 | tx_done = min(tx_done, budget); |
| @@ -7087,10 +7076,13 @@ static void stmmac_get_stats64(struct net_device *dev, struct rtnl_link_stats64 · 1319 unmodified lines | ||
| 7087 | 7076 | u64 tx_bytes; |
| 7088 | 7077 | |
| 7089 | 7078 | do { |
| 7090 | − start = u64_stats_fetch_begin(&txq_stats->syncp); | |
| 7091 | − tx_packets = txq_stats->tx_packets; | |
| 7092 | − tx_bytes = txq_stats->tx_bytes; | |
| 7093 | − } while (u64_stats_fetch_retry(&txq_stats->syncp, start)); | |
| 7079 | + start = u64_stats_fetch_begin(&txq_stats->q_syncp); | |
| 7080 | + tx_bytes = u64_stats_read(&txq_stats->q.tx_bytes); | |
| 7081 | + } while (u64_stats_fetch_retry(&txq_stats->q_syncp, start)); | |
| 7082 | + do { | |
| 7083 | + start = u64_stats_fetch_begin(&txq_stats->napi_syncp); | |
| 7084 | + tx_packets = u64_stats_read(&txq_stats->napi.tx_packets); | |
| 7085 | + } while (u64_stats_fetch_retry(&txq_stats->napi_syncp, start)); | |
| 7094 | 7086 | |
| 7095 | 7087 | stats->tx_packets += tx_packets; |
| 7096 | 7088 | stats->tx_bytes += tx_bytes; |
| @@ -7102,10 +7094,10 @@ static void stmmac_get_stats64(struct net_device *dev, struct rtnl_link_stats64 · 5 unmodified lines | ||
| 7102 | 7094 | u64 rx_bytes; |
| 7103 | 7095 | |
| 7104 | 7096 | do { |
| 7105 | − start = u64_stats_fetch_begin(&rxq_stats->syncp); | |
| 7106 | − rx_packets = rxq_stats->rx_packets; | |
| 7107 | − rx_bytes = rxq_stats->rx_bytes; | |
| 7108 | − } while (u64_stats_fetch_retry(&rxq_stats->syncp, start)); | |
| 7097 | + start = u64_stats_fetch_begin(&rxq_stats->napi_syncp); | |
| 7098 | + rx_packets = u64_stats_read(&rxq_stats->napi.rx_packets); | |
| 7099 | + rx_bytes = u64_stats_read(&rxq_stats->napi.rx_bytes); | |
| 7100 | + } while (u64_stats_fetch_retry(&rxq_stats->napi_syncp, start)); | |
| 7109 | 7101 | |
| 7110 | 7102 | stats->rx_packets += rx_packets; |
| 7111 | 7103 | stats->rx_bytes += rx_bytes; |
| @@ -7499,9 +7491,16 @@ int stmmac_dvr_probe(struct device *device, · 387 unmodified lines | ||
| 7499 | 7491 | priv->dev = ndev; |
| 7500 | 7492 | |
| 7501 | 7493 | for (i = 0; i < MTL_MAX_RX_QUEUES; i++) |
| 7502 | − u64_stats_init(&priv->xstats.rxq_stats[i].syncp); | |
| 7503 | − for (i = 0; i < MTL_MAX_TX_QUEUES; i++) | |
| 7504 | − u64_stats_init(&priv->xstats.txq_stats[i].syncp); | |
| 7494 | + u64_stats_init(&priv->xstats.rxq_stats[i].napi_syncp); | |
| 7495 | + for (i = 0; i < MTL_MAX_TX_QUEUES; i++) { | |
| 7496 | + u64_stats_init(&priv->xstats.txq_stats[i].q_syncp); | |
| 7497 | + u64_stats_init(&priv->xstats.txq_stats[i].napi_syncp); | |
| 7498 | + } | |
| 7499 | + | |
| 7500 | + priv->xstats.pcpu_stats = | |
| 7501 | + devm_netdev_alloc_pcpu_stats(device, struct stmmac_pcpu_stats); | |
| 7502 | + if (!priv->xstats.pcpu_stats) | |
| 7503 | + return -ENOMEM; | |
| 7505 | 7504 | |
| 7506 | 7505 | stmmac_set_ethtool_ops(ndev); |
| 7507 | 7506 | priv->pause = pause; |
| @@ -631,6 +631,8 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv) · 630 unmodified lines | ||
| 631 | 631 | } |
| 632 | 632 | } |
| 633 | 633 | |
| 634 | + phy->mac_managed_pm = true; | |
| 635 | + | |
| 634 | 636 | slave->phy = phy; |
| 635 | 637 | |
| 636 | 638 | phy_attached_info(slave->phy); |
| @@ -773,6 +773,9 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv) · 772 unmodified lines | ||
| 773 | 773 | slave->slave_num); |
| 774 | 774 | return; |
| 775 | 775 | } |
| 776 | + | |
| 777 | + phy->mac_managed_pm = true; | |
| 778 | + | |
| 776 | 779 | slave->phy = phy; |
| 777 | 780 | |
| 778 | 781 | phy_attached_info(slave->phy); |
| @@ -42,6 +42,10 @@ · 41 unmodified lines | ||
| 42 | 42 | #define LINKCHANGE_INT (2 * HZ) |
| 43 | 43 | #define VF_TAKEOVER_INT (HZ / 10) |
| 44 | 44 | |
| 45 | +/* Macros to define the context of vf registration */ | |
| 46 | +#define VF_REG_IN_PROBE 1 | |
| 47 | +#define VF_REG_IN_NOTIFIER 2 | |
| 48 | + | |
| 45 | 49 | static unsigned int ring_size __ro_after_init = 128; |
| 46 | 50 | module_param(ring_size, uint, 0444); |
| 47 | 51 | MODULE_PARM_DESC(ring_size, "Ring buffer size (# of 4K pages)"); |
| @@ -2185,7 +2189,7 @@ static rx_handler_result_t netvsc_vf_handle_frame(struct sk_buff **pskb) · 2137 unmodified lines | ||
| 2185 | 2189 | } |
| 2186 | 2190 | |
| 2187 | 2191 | static int netvsc_vf_join(struct net_device *vf_netdev, |
| 2188 | − struct net_device *ndev) | |
| 2192 | + struct net_device *ndev, int context) | |
| 2189 | 2193 | { |
| 2190 | 2194 | struct net_device_context *ndev_ctx = netdev_priv(ndev); |
| 2191 | 2195 | int ret; |
| @@ -2208,7 +2212,11 @@ static int netvsc_vf_join(struct net_device *vf_netdev, · 16 unmodified lines | ||
| 2208 | 2212 | goto upper_link_failed; |
| 2209 | 2213 | } |
| 2210 | 2214 | |
| 2211 | − schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT); | |
| 2215 | + /* If this registration is called from probe context vf_takeover | |
| 2216 | + * is taken care of later in probe itself. | |
| 2217 | + */ | |
| 2218 | + if (context == VF_REG_IN_NOTIFIER) | |
| 2219 | + schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT); | |
| 2212 | 2220 | |
| 2213 | 2221 | call_netdevice_notifiers(NETDEV_JOIN, vf_netdev); |
| 2214 | 2222 | |
| @@ -2346,7 +2354,7 @@ static int netvsc_prepare_bonding(struct net_device *vf_netdev) · 131 unmodified lines | ||
| 2346 | 2354 | return NOTIFY_DONE; |
| 2347 | 2355 | } |
| 2348 | 2356 | |
| 2349 | −static int netvsc_register_vf(struct net_device *vf_netdev) | |
| 2357 | +static int netvsc_register_vf(struct net_device *vf_netdev, int context) | |
| 2350 | 2358 | { |
| 2351 | 2359 | struct net_device_context *net_device_ctx; |
| 2352 | 2360 | struct netvsc_device *netvsc_dev; |
| @@ -2386,7 +2394,7 @@ static int netvsc_register_vf(struct net_device *vf_netdev) · 33 unmodified lines | ||
| 2386 | 2394 | |
| 2387 | 2395 | netdev_info(ndev, "VF registering: %s\n", vf_netdev->name); |
| 2388 | 2396 | |
| 2389 | − if (netvsc_vf_join(vf_netdev, ndev) != 0) | |
| 2397 | + if (netvsc_vf_join(vf_netdev, ndev, context) != 0) | |
| 2390 | 2398 | return NOTIFY_DONE; |
| 2391 | 2399 | |
| 2392 | 2400 | dev_hold(vf_netdev); |
| @@ -2484,10 +2492,31 @@ static int netvsc_unregister_vf(struct net_device *vf_netdev) · 91 unmodified lines | ||
| 2484 | 2492 | return NOTIFY_OK; |
| 2485 | 2493 | } |
| 2486 | 2494 | |
| 2495 | +static int check_dev_is_matching_vf(struct net_device *event_ndev) | |
| 2496 | +{ | |
| 2497 | + /* Skip NetVSC interfaces */ | |
| 2498 | + if (event_ndev->netdev_ops == &device_ops) | |
| 2499 | + return -ENODEV; | |
| 2500 | + | |
| 2501 | + /* Avoid non-Ethernet type devices */ | |
| 2502 | + if (event_ndev->type != ARPHRD_ETHER) | |
| 2503 | + return -ENODEV; | |
| 2504 | + | |
| 2505 | + /* Avoid Vlan dev with same MAC registering as VF */ | |
| 2506 | + if (is_vlan_dev(event_ndev)) | |
| 2507 | + return -ENODEV; | |
| 2508 | + | |
| 2509 | + /* Avoid Bonding master dev with same MAC registering as VF */ | |
| 2510 | + if (netif_is_bond_master(event_ndev)) | |
| 2511 | + return -ENODEV; | |
| 2512 | + | |
| 2513 | + return 0; | |
| 2514 | +} | |
| 2515 | + | |
| 2487 | 2516 | static int netvsc_probe(struct hv_device *dev, |
| 2488 | 2517 | const struct hv_vmbus_device_id *dev_id) |
| 2489 | 2518 | { |
| 2490 | − struct net_device *net = NULL; | |
| 2519 | + struct net_device *net = NULL, *vf_netdev; | |
| 2491 | 2520 | struct net_device_context *net_device_ctx; |
| 2492 | 2521 | struct netvsc_device_info *device_info = NULL; |
| 2493 | 2522 | struct netvsc_device *nvdev; |
| @@ -2599,6 +2628,30 @@ static int netvsc_probe(struct hv_device *dev, · 105 unmodified lines | ||
| 2599 | 2628 | } |
| 2600 | 2629 | |
| 2601 | 2630 | list_add(&net_device_ctx->list, &netvsc_dev_list); |
| 2631 | + | |
| 2632 | + /* When the hv_netvsc driver is unloaded and reloaded, the | |
| 2633 | + * NET_DEVICE_REGISTER for the vf device is replayed before probe | |
| 2634 | + * is complete. This is because register_netdevice_notifier() gets | |
| 2635 | + * registered before vmbus_driver_register() so that callback func | |
| 2636 | + * is set before probe and we don't miss events like NETDEV_POST_INIT | |
| 2637 | + * So, in this section we try to register the matching vf device that | |
| 2638 | + * is present as a netdevice, knowing that its register call is not | |
| 2639 | + * processed in the netvsc_netdev_notifier(as probing is progress and | |
| 2640 | + * get_netvsc_byslot fails). | |
| 2641 | + */ | |
| 2642 | + for_each_netdev(dev_net(net), vf_netdev) { | |
| 2643 | + ret = check_dev_is_matching_vf(vf_netdev); | |
| 2644 | + if (ret != 0) | |
| 2645 | + continue; | |
| 2646 | + | |
| 2647 | + if (net != get_netvsc_byslot(vf_netdev)) | |
| 2648 | + continue; | |
| 2649 | + | |
| 2650 | + netvsc_prepare_bonding(vf_netdev); | |
| 2651 | + netvsc_register_vf(vf_netdev, VF_REG_IN_PROBE); | |
| 2652 | + __netvsc_vf_setup(net, vf_netdev); | |
| 2653 | + break; | |
| 2654 | + } | |
| 2602 | 2655 | rtnl_unlock(); |
| 2603 | 2656 | |
| 2604 | 2657 | netvsc_devinfo_put(device_info); |
| @@ -2754,28 +2807,17 @@ static int netvsc_netdev_event(struct notifier_block *this, · 149 unmodified lines | ||
| 2754 | 2807 | unsigned long event, void *ptr) |
| 2755 | 2808 | { |
| 2756 | 2809 | struct net_device *event_dev = netdev_notifier_info_to_dev(ptr); |
| 2810 | + int ret = 0; | |
| 2757 | 2811 | |
| 2758 | − /* Skip our own events */ | |
| 2759 | − if (event_dev->netdev_ops == &device_ops) | |
| 2760 | − return NOTIFY_DONE; | |
| 2761 | − | |
| 2762 | − /* Avoid non-Ethernet type devices */ | |
| 2763 | − if (event_dev->type != ARPHRD_ETHER) | |
| 2764 | − return NOTIFY_DONE; | |
| 2765 | − | |
| 2766 | − /* Avoid Vlan dev with same MAC registering as VF */ | |
| 2767 | − if (is_vlan_dev(event_dev)) | |
| 2768 | − return NOTIFY_DONE; | |
| 2769 | − | |
| 2770 | − /* Avoid Bonding master dev with same MAC registering as VF */ | |
| 2771 | − if (netif_is_bond_master(event_dev)) | |
| 2812 | + ret = check_dev_is_matching_vf(event_dev); | |
| 2813 | + if (ret != 0) | |
| 2772 | 2814 | return NOTIFY_DONE; |
| 2773 | 2815 | |
| 2774 | 2816 | switch (event) { |
| 2775 | 2817 | case NETDEV_POST_INIT: |
| 2776 | 2818 | return netvsc_prepare_bonding(event_dev); |
| 2777 | 2819 | case NETDEV_REGISTER: |
| 2778 | − return netvsc_register_vf(event_dev); | |
| 2820 | + return netvsc_register_vf(event_dev, VF_REG_IN_NOTIFIER); | |
| 2779 | 2821 | case NETDEV_UNREGISTER: |
| 2780 | 2822 | return netvsc_unregister_vf(event_dev); |
| 2781 | 2823 | case NETDEV_UP: |
| @@ -835,14 +835,14 @@ static void nsim_dev_trap_report_work(struct work_struct *work) · 834 unmodified lines | ||
| 835 | 835 | trap_report_dw.work); |
| 836 | 836 | nsim_dev = nsim_trap_data->nsim_dev; |
| 837 | 837 | |
| 838 | − /* For each running port and enabled packet trap, generate a UDP | |
| 839 | − * packet with a random 5-tuple and report it. | |
| 840 | − */ | |
| 841 | 838 | if (!devl_trylock(priv_to_devlink(nsim_dev))) { |
| 842 | − schedule_delayed_work(&nsim_dev->trap_data->trap_report_dw, 0); | |
| 839 | + schedule_delayed_work(&nsim_dev->trap_data->trap_report_dw, 1); | |
| 843 | 840 | return; |
| 844 | 841 | } |
| 845 | 842 | |
| 843 | + /* For each running port and enabled packet trap, generate a UDP | |
| 844 | + * packet with a random 5-tuple and report it. | |
| 845 | + */ | |
| 846 | 846 | list_for_each_entry(nsim_dev_port, &nsim_dev->port_list, list) { |
| 847 | 847 | if (!netif_running(nsim_dev_port->ns->netdev)) |
| 848 | 848 | continue; |
| @@ -460,6 +460,10 @@ ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg) · 459 unmodified lines | ||
| 460 | 460 | case PPPIOCSMRU: |
| 461 | 461 | if (get_user(val, p)) |
| 462 | 462 | break; |
| 463 | + if (val > U16_MAX) { | |
| 464 | + err = -EINVAL; | |
| 465 | + break; | |
| 466 | + } | |
| 463 | 467 | if (val < PPP_MRU) |
| 464 | 468 | val = PPP_MRU; |
| 465 | 469 | ap->mru = val; |
| @@ -1803,5 +1803,6 @@ static struct usb_driver ar5523_driver = { · 1802 unmodified lines | ||
| 1803 | 1803 | |
| 1804 | 1804 | module_usb_driver(ar5523_driver); |
| 1805 | 1805 | |
| 1806 | +MODULE_DESCRIPTION("Atheros AR5523 wireless driver"); | |
| 1806 | 1807 | MODULE_LICENSE("Dual BSD/GPL"); |
| 1807 | 1808 | MODULE_FIRMWARE(AR5523_FIRMWARE_FILE); |
| @@ -1685,6 +1685,7 @@ static struct platform_driver wcn36xx_driver = { · 1684 unmodified lines | ||
| 1685 | 1685 | |
| 1686 | 1686 | module_platform_driver(wcn36xx_driver); |
| 1687 | 1687 | |
| 1688 | +MODULE_DESCRIPTION("Qualcomm Atheros WCN3660/3680 wireless driver"); | |
| 1688 | 1689 | MODULE_LICENSE("Dual BSD/GPL"); |
| 1689 | 1690 | MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com"); |
| 1690 | 1691 | MODULE_FIRMWARE(WLAN_NV_FILE); |
| @@ -20,6 +20,7 @@ static void __exit brcmf_bca_exit(void) · 19 unmodified lines | ||
| 20 | 20 | brcmf_fwvid_unregister_vendor(BRCMF_FWVENDOR_BCA, THIS_MODULE); |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | +MODULE_DESCRIPTION("Broadcom FullMAC WLAN driver plugin for Broadcom AP chipsets"); | |
| 23 | 24 | MODULE_LICENSE("Dual BSD/GPL"); |
| 24 | 25 | MODULE_IMPORT_NS(BRCMFMAC); |
| 25 | 26 | |
| @@ -3765,8 +3765,10 @@ static int brcmf_internal_escan_add_info(struct cfg80211_scan_request *req, · 3764 unmodified lines | ||
| 3765 | 3765 | if (req->channels[i] == chan) |
| 3766 | 3766 | break; |
| 3767 | 3767 | } |
| 3768 | − if (i == req->n_channels) | |
| 3769 | − req->channels[req->n_channels++] = chan; | |
| 3768 | + if (i == req->n_channels) { | |
| 3769 | + req->n_channels++; | |
| 3770 | + req->channels[i] = chan; | |
| 3771 | + } | |
| 3770 | 3772 | |
| 3771 | 3773 | for (i = 0; i < req->n_ssids; i++) { |
| 3772 | 3774 | if (req->ssids[i].ssid_len == ssid_len && |
| @@ -20,6 +20,7 @@ static void __exit brcmf_cyw_exit(void) · 19 unmodified lines | ||
| 20 | 20 | brcmf_fwvid_unregister_vendor(BRCMF_FWVENDOR_CYW, THIS_MODULE); |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | +MODULE_DESCRIPTION("Broadcom FullMAC WLAN driver plugin for Cypress/Infineon chipsets"); | |
| 23 | 24 | MODULE_LICENSE("Dual BSD/GPL"); |
| 24 | 25 | MODULE_IMPORT_NS(BRCMFMAC); |
| 25 | 26 | |
| @@ -20,6 +20,7 @@ static void __exit brcmf_wcc_exit(void) · 19 unmodified lines | ||
| 20 | 20 | brcmf_fwvid_unregister_vendor(BRCMF_FWVENDOR_WCC, THIS_MODULE); |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | +MODULE_DESCRIPTION("Broadcom FullMAC WLAN driver plugin for Broadcom mobility chipsets"); | |
| 23 | 24 | MODULE_LICENSE("Dual BSD/GPL"); |
| 24 | 25 | MODULE_IMPORT_NS(BRCMFMAC); |
| 25 | 26 | |
| @@ -537,7 +537,7 @@ enum iwl_fw_dbg_config_cmd_type { · 536 unmodified lines | ||
| 537 | 537 | }; /* LDBG_CFG_CMD_TYPE_API_E_VER_1 */ |
| 538 | 538 | |
| 539 | 539 | /* this token disables debug asserts in the firmware */ |
| 540 | −#define IWL_FW_DBG_CONFIG_TOKEN 0x00011301 | |
| 540 | +#define IWL_FW_DBG_CONFIG_TOKEN 0x00010001 | |
| 541 | 541 | |
| 542 | 542 | /** |
| 543 | 543 | * struct iwl_fw_dbg_config_cmd - configure FW debug |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause |
| 2 | 2 | /* |
| 3 | − * Copyright (C) 2005-2014, 2018-2023 Intel Corporation | |
| 3 | + * Copyright (C) 2005-2014, 2018-2024 Intel Corporation | |
| 4 | 4 | * Copyright (C) 2013-2015 Intel Mobile Communications GmbH |
| 5 | 5 | * Copyright (C) 2015-2017 Intel Deutschland GmbH |
| 6 | 6 | */ |
| @@ -19,7 +19,6 @@ · 12 unmodified lines | ||
| 19 | 19 | * @fwrt_ptr: pointer to the buffer coming from fwrt |
| 20 | 20 | * @trans_ptr: pointer to struct %iwl_trans_dump_data which contains the |
| 21 | 21 | * transport's data. |
| 22 | − * @trans_len: length of the valid data in trans_ptr | |
| 23 | 22 | * @fwrt_len: length of the valid data in fwrt_ptr |
| 24 | 23 | */ |
| 25 | 24 | struct iwl_fw_dump_ptrs { |
| @@ -128,6 +128,7 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv) · 127 unmodified lines | ||
| 128 | 128 | kfree(drv->fw.ucode_capa.cmd_versions); |
| 129 | 129 | kfree(drv->fw.phy_integration_ver); |
| 130 | 130 | kfree(drv->trans->dbg.pc_data); |
| 131 | + drv->trans->dbg.pc_data = NULL; | |
| 131 | 132 | |
| 132 | 133 | for (i = 0; i < IWL_UCODE_TYPE_MAX; i++) |
| 133 | 134 | iwl_free_fw_img(drv, drv->fw.img + i); |
| @@ -668,7 +668,6 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = { · 667 unmodified lines | ||
| 668 | 668 | .has_eht = true, |
| 669 | 669 | .eht_cap_elem = { |
| 670 | 670 | .mac_cap_info[0] = |
| 671 | − IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | | |
| 672 | 671 | IEEE80211_EHT_MAC_CAP0_OM_CONTROL | |
| 673 | 672 | IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 | |
| 674 | 673 | IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2 | |
| @@ -793,7 +792,6 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = { · 118 unmodified lines | ||
| 793 | 792 | .has_eht = true, |
| 794 | 793 | .eht_cap_elem = { |
| 795 | 794 | .mac_cap_info[0] = |
| 796 | − IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | | |
| 797 | 795 | IEEE80211_EHT_MAC_CAP0_OM_CONTROL | |
| 798 | 796 | IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 | |
| 799 | 797 | IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2, |
| @@ -1020,8 +1018,7 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans, · 220 unmodified lines | ||
| 1020 | 1018 | if (CSR_HW_REV_TYPE(trans->hw_rev) == IWL_CFG_MAC_TYPE_GL && |
| 1021 | 1019 | iftype_data->eht_cap.has_eht) { |
| 1022 | 1020 | iftype_data->eht_cap.eht_cap_elem.mac_cap_info[0] &= |
| 1023 | − ~(IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | | |
| 1024 | − IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 | | |
| 1021 | + ~(IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 | | |
| 1025 | 1022 | IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2); |
| 1026 | 1023 | iftype_data->eht_cap.eht_cap_elem.phy_cap_info[3] &= |
| 1027 | 1024 | ~(IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO | |
| @@ -1600,7 +1600,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, · 1599 unmodified lines | ||
| 1600 | 1600 | */ |
| 1601 | 1601 | if (vif->type == NL80211_IFTYPE_AP || |
| 1602 | 1602 | vif->type == NL80211_IFTYPE_ADHOC) { |
| 1603 | − iwl_mvm_vif_dbgfs_add_link(mvm, vif); | |
| 1603 | + if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) | |
| 1604 | + iwl_mvm_vif_dbgfs_add_link(mvm, vif); | |
| 1604 | 1605 | ret = 0; |
| 1605 | 1606 | goto out; |
| 1606 | 1607 | } |
| @@ -1640,7 +1641,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, · 33 unmodified lines | ||
| 1640 | 1641 | iwl_mvm_chandef_get_primary_80(&vif->bss_conf.chandef); |
| 1641 | 1642 | } |
| 1642 | 1643 | |
| 1643 | − iwl_mvm_vif_dbgfs_add_link(mvm, vif); | |
| 1644 | + if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) | |
| 1645 | + iwl_mvm_vif_dbgfs_add_link(mvm, vif); | |
| 1644 | 1646 | |
| 1645 | 1647 | if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && |
| 1646 | 1648 | vif->type == NL80211_IFTYPE_STATION && !vif->p2p && |
| @@ -81,7 +81,8 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw, · 80 unmodified lines | ||
| 81 | 81 | ieee80211_hw_set(mvm->hw, RX_INCLUDES_FCS); |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | − iwl_mvm_vif_dbgfs_add_link(mvm, vif); | |
| 84 | + if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) | |
| 85 | + iwl_mvm_vif_dbgfs_add_link(mvm, vif); | |
| 85 | 86 | |
| 86 | 87 | if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && |
| 87 | 88 | vif->type == NL80211_IFTYPE_STATION && !vif->p2p && |
| @@ -437,6 +438,9 @@ __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm, · 349 unmodified lines | ||
| 437 | 438 | mvmvif->ap_ibss_active = false; |
| 438 | 439 | } |
| 439 | 440 | |
| 441 | + iwl_mvm_link_changed(mvm, vif, link_conf, | |
| 442 | + LINK_CONTEXT_MODIFY_ACTIVE, false); | |
| 443 | + | |
| 440 | 444 | if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) { |
| 441 | 445 | int ret = iwl_mvm_esr_mode_inactive(mvm, vif); |
| 442 | 446 | |
| @@ -448,9 +452,6 @@ __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm, · 5 unmodified lines | ||
| 448 | 452 | if (vif->type == NL80211_IFTYPE_MONITOR) |
| 449 | 453 | iwl_mvm_mld_rm_snif_sta(mvm, vif); |
| 450 | 454 | |
| 451 | − iwl_mvm_link_changed(mvm, vif, link_conf, | |
| 452 | − LINK_CONTEXT_MODIFY_ACTIVE, false); | |
| 453 | − | |
| 454 | 455 | if (switching_chanctx) |
| 455 | 456 | return; |
| 456 | 457 | mvmvif->link[link_id]->phy_ctxt = NULL; |
| @@ -700,6 +700,7 @@ static struct spi_driver p54spi_driver = { · 699 unmodified lines | ||
| 700 | 700 | |
| 701 | 701 | module_spi_driver(p54spi_driver); |
| 702 | 702 | |
| 703 | +MODULE_DESCRIPTION("Prism54 SPI wireless driver"); | |
| 703 | 704 | MODULE_LICENSE("GPL"); |
| 704 | 705 | MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>"); |
| 705 | 706 | MODULE_ALIAS("spi:cx3110x"); |
| @@ -728,6 +728,7 @@ const struct ieee80211_ops mt7603_ops = { · 727 unmodified lines | ||
| 728 | 728 | .set_sar_specs = mt7603_set_sar_specs, |
| 729 | 729 | }; |
| 730 | 730 | |
| 731 | +MODULE_DESCRIPTION("MediaTek MT7603E and MT76x8 wireless driver"); | |
| 731 | 732 | MODULE_LICENSE("Dual BSD/GPL"); |
| 732 | 733 | |
| 733 | 734 | static int __init mt7603_init(void) |
| @@ -1375,4 +1375,5 @@ const struct ieee80211_ops mt7615_ops = { · 1374 unmodified lines | ||
| 1375 | 1375 | }; |
| 1376 | 1376 | EXPORT_SYMBOL_GPL(mt7615_ops); |
| 1377 | 1377 | |
| 1378 | +MODULE_DESCRIPTION("MediaTek MT7615E and MT7663E wireless driver"); | |
| 1378 | 1379 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -270,4 +270,5 @@ static void __exit mt7615_exit(void) · 269 unmodified lines | ||
| 270 | 270 | |
| 271 | 271 | module_init(mt7615_init); |
| 272 | 272 | module_exit(mt7615_exit); |
| 273 | +MODULE_DESCRIPTION("MediaTek MT7615E MMIO helpers"); | |
| 273 | 274 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -253,4 +253,5 @@ module_sdio_driver(mt7663s_driver); · 252 unmodified lines | ||
| 253 | 253 | |
| 254 | 254 | MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); |
| 255 | 255 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| 256 | +MODULE_DESCRIPTION("MediaTek MT7663S (SDIO) wireless driver"); | |
| 256 | 257 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -281,4 +281,5 @@ module_usb_driver(mt7663u_driver); · 280 unmodified lines | ||
| 281 | 281 | |
| 282 | 282 | MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); |
| 283 | 283 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| 284 | +MODULE_DESCRIPTION("MediaTek MT7663U (USB) wireless driver"); | |
| 284 | 285 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -349,4 +349,5 @@ EXPORT_SYMBOL_GPL(mt7663_usb_sdio_register_device); · 348 unmodified lines | ||
| 349 | 349 | |
| 350 | 350 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| 351 | 351 | MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); |
| 352 | +MODULE_DESCRIPTION("MediaTek MT7663 SDIO/USB helpers"); | |
| 352 | 353 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -3160,4 +3160,5 @@ exit: · 3159 unmodified lines | ||
| 3160 | 3160 | EXPORT_SYMBOL_GPL(mt76_connac2_mcu_fill_message); |
| 3161 | 3161 | |
| 3162 | 3162 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| 3163 | +MODULE_DESCRIPTION("MediaTek MT76x connac layer helpers"); | |
| 3163 | 3164 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -342,4 +342,5 @@ int mt76x0_eeprom_init(struct mt76x02_dev *dev) · 341 unmodified lines | ||
| 342 | 342 | return 0; |
| 343 | 343 | } |
| 344 | 344 | |
| 345 | +MODULE_DESCRIPTION("MediaTek MT76x EEPROM helpers"); | |
| 345 | 346 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -302,6 +302,7 @@ static const struct pci_device_id mt76x0e_device_table[] = { · 301 unmodified lines | ||
| 302 | 302 | MODULE_DEVICE_TABLE(pci, mt76x0e_device_table); |
| 303 | 303 | MODULE_FIRMWARE(MT7610E_FIRMWARE); |
| 304 | 304 | MODULE_FIRMWARE(MT7650E_FIRMWARE); |
| 305 | +MODULE_DESCRIPTION("MediaTek MT76x0E (PCIe) wireless driver"); | |
| 305 | 306 | MODULE_LICENSE("Dual BSD/GPL"); |
| 306 | 307 | |
| 307 | 308 | static struct pci_driver mt76x0e_driver = { |
| @@ -336,6 +336,7 @@ err: · 335 unmodified lines | ||
| 336 | 336 | MODULE_DEVICE_TABLE(usb, mt76x0_device_table); |
| 337 | 337 | MODULE_FIRMWARE(MT7610E_FIRMWARE); |
| 338 | 338 | MODULE_FIRMWARE(MT7610U_FIRMWARE); |
| 339 | +MODULE_DESCRIPTION("MediaTek MT76x0U (USB) wireless driver"); | |
| 339 | 340 | MODULE_LICENSE("GPL"); |
| 340 | 341 | |
| 341 | 342 | static struct usb_driver mt76x0_driver = { |
| @@ -293,4 +293,5 @@ void mt76x02u_init_mcu(struct mt76_dev *dev) · 292 unmodified lines | ||
| 293 | 293 | EXPORT_SYMBOL_GPL(mt76x02u_init_mcu); |
| 294 | 294 | |
| 295 | 295 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>"); |
| 296 | +MODULE_DESCRIPTION("MediaTek MT76x02 MCU helpers"); | |
| 296 | 297 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -696,4 +696,5 @@ void mt76x02_config_mac_addr_list(struct mt76x02_dev *dev) · 695 unmodified lines | ||
| 696 | 696 | } |
| 697 | 697 | EXPORT_SYMBOL_GPL(mt76x02_config_mac_addr_list); |
| 698 | 698 | |
| 699 | +MODULE_DESCRIPTION("MediaTek MT76x02 helpers"); | |
| 699 | 700 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -506,4 +506,5 @@ int mt76x2_eeprom_init(struct mt76x02_dev *dev) · 505 unmodified lines | ||
| 506 | 506 | } |
| 507 | 507 | EXPORT_SYMBOL_GPL(mt76x2_eeprom_init); |
| 508 | 508 | |
| 509 | +MODULE_DESCRIPTION("MediaTek MT76x2 EEPROM helpers"); | |
| 509 | 510 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -165,6 +165,7 @@ mt76x2e_resume(struct pci_dev *pdev) · 164 unmodified lines | ||
| 165 | 165 | MODULE_DEVICE_TABLE(pci, mt76x2e_device_table); |
| 166 | 166 | MODULE_FIRMWARE(MT7662_FIRMWARE); |
| 167 | 167 | MODULE_FIRMWARE(MT7662_ROM_PATCH); |
| 168 | +MODULE_DESCRIPTION("MediaTek MT76x2E (PCIe) wireless driver"); | |
| 168 | 169 | MODULE_LICENSE("Dual BSD/GPL"); |
| 169 | 170 | |
| 170 | 171 | static struct pci_driver mt76pci_driver = { |
| @@ -147,4 +147,5 @@ static struct usb_driver mt76x2u_driver = { · 146 unmodified lines | ||
| 147 | 147 | module_usb_driver(mt76x2u_driver); |
| 148 | 148 | |
| 149 | 149 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>"); |
| 150 | +MODULE_DESCRIPTION("MediaTek MT76x2U (USB) wireless driver"); | |
| 150 | 151 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -958,4 +958,5 @@ static void __exit mt7915_exit(void) · 957 unmodified lines | ||
| 958 | 958 | |
| 959 | 959 | module_init(mt7915_init); |
| 960 | 960 | module_exit(mt7915_exit); |
| 961 | +MODULE_DESCRIPTION("MediaTek MT7915E MMIO helpers"); | |
| 961 | 962 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -1418,5 +1418,6 @@ const struct ieee80211_ops mt7921_ops = { · 1417 unmodified lines | ||
| 1418 | 1418 | }; |
| 1419 | 1419 | EXPORT_SYMBOL_GPL(mt7921_ops); |
| 1420 | 1420 | |
| 1421 | +MODULE_DESCRIPTION("MediaTek MT7921 core driver"); | |
| 1421 | 1422 | MODULE_LICENSE("Dual BSD/GPL"); |
| 1422 | 1423 | MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); |
| @@ -544,4 +544,5 @@ MODULE_FIRMWARE(MT7922_FIRMWARE_WM); · 543 unmodified lines | ||
| 544 | 544 | MODULE_FIRMWARE(MT7922_ROM_PATCH); |
| 545 | 545 | MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); |
| 546 | 546 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| 547 | +MODULE_DESCRIPTION("MediaTek MT7921E (PCIe) wireless driver"); | |
| 547 | 548 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -323,5 +323,6 @@ static struct sdio_driver mt7921s_driver = { · 322 unmodified lines | ||
| 323 | 323 | .drv.pm = pm_sleep_ptr(&mt7921s_pm_ops), |
| 324 | 324 | }; |
| 325 | 325 | module_sdio_driver(mt7921s_driver); |
| 326 | +MODULE_DESCRIPTION("MediaTek MT7921S (SDIO) wireless driver"); | |
| 326 | 327 | MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); |
| 327 | 328 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -336,5 +336,6 @@ static struct usb_driver mt7921u_driver = { · 335 unmodified lines | ||
| 336 | 336 | }; |
| 337 | 337 | module_usb_driver(mt7921u_driver); |
| 338 | 338 | |
| 339 | +MODULE_DESCRIPTION("MediaTek MT7921U (USB) wireless driver"); | |
| 339 | 340 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| 340 | 341 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -1450,4 +1450,5 @@ const struct ieee80211_ops mt7925_ops = { · 1449 unmodified lines | ||
| 1450 | 1450 | EXPORT_SYMBOL_GPL(mt7925_ops); |
| 1451 | 1451 | |
| 1452 | 1452 | MODULE_AUTHOR("Deren Wu <deren.wu@mediatek.com>"); |
| 1453 | +MODULE_DESCRIPTION("MediaTek MT7925 core driver"); | |
| 1453 | 1454 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -583,4 +583,5 @@ MODULE_FIRMWARE(MT7925_FIRMWARE_WM); · 582 unmodified lines | ||
| 583 | 583 | MODULE_FIRMWARE(MT7925_ROM_PATCH); |
| 584 | 584 | MODULE_AUTHOR("Deren Wu <deren.wu@mediatek.com>"); |
| 585 | 585 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| 586 | +MODULE_DESCRIPTION("MediaTek MT7925E (PCIe) wireless driver"); | |
| 586 | 587 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -329,4 +329,5 @@ static struct usb_driver mt7925u_driver = { · 328 unmodified lines | ||
| 329 | 329 | module_usb_driver(mt7925u_driver); |
| 330 | 330 | |
| 331 | 331 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| 332 | +MODULE_DESCRIPTION("MediaTek MT7925U (USB) wireless driver"); | |
| 332 | 333 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -862,5 +862,6 @@ int mt792x_load_firmware(struct mt792x_dev *dev) · 861 unmodified lines | ||
| 862 | 862 | } |
| 863 | 863 | EXPORT_SYMBOL_GPL(mt792x_load_firmware); |
| 864 | 864 | |
| 865 | +MODULE_DESCRIPTION("MediaTek MT792x core driver"); | |
| 865 | 866 | MODULE_LICENSE("Dual BSD/GPL"); |
| 866 | 867 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| @@ -314,5 +314,6 @@ void mt792xu_disconnect(struct usb_interface *usb_intf) · 313 unmodified lines | ||
| 314 | 314 | } |
| 315 | 315 | EXPORT_SYMBOL_GPL(mt792xu_disconnect); |
| 316 | 316 | |
| 317 | +MODULE_DESCRIPTION("MediaTek MT792x USB helpers"); | |
| 317 | 318 | MODULE_LICENSE("Dual BSD/GPL"); |
| 318 | 319 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| @@ -4477,7 +4477,8 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy) · 4476 unmodified lines | ||
| 4477 | 4477 | |
| 4478 | 4478 | skb_put_data(skb, &req, sizeof(req)); |
| 4479 | 4479 | /* cck and ofdm */ |
| 4480 | − skb_put_data(skb, &la.cck, sizeof(la.cck) + sizeof(la.ofdm)); | |
| 4480 | + skb_put_data(skb, &la.cck, sizeof(la.cck)); | |
| 4481 | + skb_put_data(skb, &la.ofdm, sizeof(la.ofdm)); | |
| 4481 | 4482 | /* ht20 */ |
| 4482 | 4483 | skb_put_data(skb, &la.mcs[0], 8); |
| 4483 | 4484 | /* ht40 */ |
| @@ -650,4 +650,5 @@ static void __exit mt7996_exit(void) · 649 unmodified lines | ||
| 650 | 650 | |
| 651 | 651 | module_init(mt7996_init); |
| 652 | 652 | module_exit(mt7996_exit); |
| 653 | +MODULE_DESCRIPTION("MediaTek MT7996 MMIO helpers"); | |
| 653 | 654 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -672,4 +672,5 @@ EXPORT_SYMBOL_GPL(mt76s_init); · 671 unmodified lines | ||
| 672 | 672 | |
| 673 | 673 | MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); |
| 674 | 674 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| 675 | +MODULE_DESCRIPTION("MediaTek MT76x SDIO helpers"); | |
| 675 | 676 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -1128,4 +1128,5 @@ int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf) · 1127 unmodified lines | ||
| 1128 | 1128 | EXPORT_SYMBOL_GPL(mt76u_init); |
| 1129 | 1129 | |
| 1130 | 1130 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>"); |
| 1131 | +MODULE_DESCRIPTION("MediaTek MT76x USB helpers"); | |
| 1131 | 1132 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -138,4 +138,5 @@ int __mt76_worker_fn(void *ptr) · 137 unmodified lines | ||
| 138 | 138 | } |
| 139 | 139 | EXPORT_SYMBOL_GPL(__mt76_worker_fn); |
| 140 | 140 | |
| 141 | +MODULE_DESCRIPTION("MediaTek MT76x helpers"); | |
| 141 | 142 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -1010,5 +1010,6 @@ error: · 1009 unmodified lines | ||
| 1010 | 1010 | return ERR_PTR(ret); |
| 1011 | 1011 | } |
| 1012 | 1012 | |
| 1013 | +MODULE_DESCRIPTION("Atmel WILC1000 core wireless driver"); | |
| 1013 | 1014 | MODULE_LICENSE("GPL"); |
| 1014 | 1015 | MODULE_FIRMWARE(WILC1000_FW(WILC1000_API_VER)); |
| @@ -984,4 +984,5 @@ static struct sdio_driver wilc_sdio_driver = { · 983 unmodified lines | ||
| 984 | 984 | module_driver(wilc_sdio_driver, |
| 985 | 985 | sdio_register_driver, |
| 986 | 986 | sdio_unregister_driver); |
| 987 | +MODULE_DESCRIPTION("Atmel WILC1000 SDIO wireless driver"); | |
| 987 | 988 | MODULE_LICENSE("GPL"); |
| @@ -273,6 +273,7 @@ static struct spi_driver wilc_spi_driver = { · 272 unmodified lines | ||
| 273 | 273 | .remove = wilc_bus_remove, |
| 274 | 274 | }; |
| 275 | 275 | module_spi_driver(wilc_spi_driver); |
| 276 | +MODULE_DESCRIPTION("Atmel WILC1000 SPI wireless driver"); | |
| 276 | 277 | MODULE_LICENSE("GPL"); |
| 277 | 278 | |
| 278 | 279 | static int wilc_spi_tx(struct wilc *wilc, u8 *b, u32 len) |
| @@ -343,5 +343,6 @@ static void __exit wl1251_sdio_exit(void) · 342 unmodified lines | ||
| 343 | 343 | module_init(wl1251_sdio_init); |
| 344 | 344 | module_exit(wl1251_sdio_exit); |
| 345 | 345 | |
| 346 | +MODULE_DESCRIPTION("TI WL1251 SDIO helpers"); | |
| 346 | 347 | MODULE_LICENSE("GPL"); |
| 347 | 348 | MODULE_AUTHOR("Kalle Valo <kvalo@adurom.com>"); |
| @@ -342,6 +342,7 @@ static struct spi_driver wl1251_spi_driver = { · 341 unmodified lines | ||
| 342 | 342 | |
| 343 | 343 | module_spi_driver(wl1251_spi_driver); |
| 344 | 344 | |
| 345 | +MODULE_DESCRIPTION("TI WL1251 SPI helpers"); | |
| 345 | 346 | MODULE_LICENSE("GPL"); |
| 346 | 347 | MODULE_AUTHOR("Kalle Valo <kvalo@adurom.com>"); |
| 347 | 348 | MODULE_ALIAS("spi:wl1251"); |
| @@ -1955,6 +1955,7 @@ module_param_named(tcxo, tcxo_param, charp, 0); · 1954 unmodified lines | ||
| 1955 | 1955 | MODULE_PARM_DESC(tcxo, |
| 1956 | 1956 | "TCXO clock: 19.2, 26, 38.4, 52, 16.368, 32.736, 16.8, 33.6"); |
| 1957 | 1957 | |
| 1958 | +MODULE_DESCRIPTION("TI WL12xx wireless driver"); | |
| 1958 | 1959 | MODULE_LICENSE("GPL v2"); |
| 1959 | 1960 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); |
| 1960 | 1961 | MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE); |
| @@ -2086,6 +2086,7 @@ module_param_named(num_rx_desc, num_rx_desc_param, int, 0400); · 2085 unmodified lines | ||
| 2086 | 2086 | MODULE_PARM_DESC(num_rx_desc_param, |
| 2087 | 2087 | "Number of Rx descriptors: u8 (default is 32)"); |
| 2088 | 2088 | |
| 2089 | +MODULE_DESCRIPTION("TI WiLink 8 wireless driver"); | |
| 2089 | 2090 | MODULE_LICENSE("GPL v2"); |
| 2090 | 2091 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); |
| 2091 | 2092 | MODULE_FIRMWARE(WL18XX_FW_NAME); |
| @@ -6793,6 +6793,7 @@ MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery"); · 6792 unmodified lines | ||
| 6793 | 6793 | module_param(no_recovery, int, 0600); |
| 6794 | 6794 | MODULE_PARM_DESC(no_recovery, "Prevent HW recovery. FW will remain stuck."); |
| 6795 | 6795 | |
| 6796 | +MODULE_DESCRIPTION("TI WLAN core driver"); | |
| 6796 | 6797 | MODULE_LICENSE("GPL"); |
| 6797 | 6798 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); |
| 6798 | 6799 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); |
| @@ -447,6 +447,7 @@ module_sdio_driver(wl1271_sdio_driver); · 446 unmodified lines | ||
| 447 | 447 | module_param(dump, bool, 0600); |
| 448 | 448 | MODULE_PARM_DESC(dump, "Enable sdio read/write dumps."); |
| 449 | 449 | |
| 450 | +MODULE_DESCRIPTION("TI WLAN SDIO helpers"); | |
| 450 | 451 | MODULE_LICENSE("GPL"); |
| 451 | 452 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); |
| 452 | 453 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); |
| @@ -562,6 +562,7 @@ static struct spi_driver wl1271_spi_driver = { · 561 unmodified lines | ||
| 562 | 562 | }; |
| 563 | 563 | |
| 564 | 564 | module_spi_driver(wl1271_spi_driver); |
| 565 | +MODULE_DESCRIPTION("TI WLAN SPI helpers"); | |
| 565 | 566 | MODULE_LICENSE("GPL"); |
| 566 | 567 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); |
| 567 | 568 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); |
| @@ -471,4 +471,5 @@ int nvme_auth_generate_key(u8 *secret, struct nvme_dhchap_key **ret_key) · 470 unmodified lines | ||
| 471 | 471 | } |
| 472 | 472 | EXPORT_SYMBOL_GPL(nvme_auth_generate_key); |
| 473 | 473 | |
| 474 | +MODULE_DESCRIPTION("NVMe Authentication framework"); | |
| 474 | 475 | MODULE_LICENSE("GPL v2"); |
| @@ -181,5 +181,6 @@ static void __exit nvme_keyring_exit(void) · 180 unmodified lines | ||
| 181 | 181 | |
| 182 | 182 | MODULE_LICENSE("GPL v2"); |
| 183 | 183 | MODULE_AUTHOR("Hannes Reinecke <hare@suse.de>"); |
| 184 | +MODULE_DESCRIPTION("NVMe Keyring implementation"); | |
| 184 | 185 | module_init(nvme_keyring_init); |
| 185 | 186 | module_exit(nvme_keyring_exit); |
| @@ -797,6 +797,7 @@ static int apple_nvme_init_request(struct blk_mq_tag_set *set, · 796 unmodified lines | ||
| 797 | 797 | |
| 798 | 798 | static void apple_nvme_disable(struct apple_nvme *anv, bool shutdown) |
| 799 | 799 | { |
| 800 | + enum nvme_ctrl_state state = nvme_ctrl_state(&anv->ctrl); | |
| 800 | 801 | u32 csts = readl(anv->mmio_nvme + NVME_REG_CSTS); |
| 801 | 802 | bool dead = false, freeze = false; |
| 802 | 803 | unsigned long flags; |
| @@ -808,8 +809,8 @@ static void apple_nvme_disable(struct apple_nvme *anv, bool shutdown) · 5 unmodified lines | ||
| 808 | 809 | if (csts & NVME_CSTS_CFS) |
| 809 | 810 | dead = true; |
| 810 | 811 | |
| 811 | − if (anv->ctrl.state == NVME_CTRL_LIVE || | |
| 812 | − anv->ctrl.state == NVME_CTRL_RESETTING) { | |
| 812 | + if (state == NVME_CTRL_LIVE || | |
| 813 | + state == NVME_CTRL_RESETTING) { | |
| 813 | 814 | freeze = true; |
| 814 | 815 | nvme_start_freeze(&anv->ctrl); |
| 815 | 816 | } |
| @@ -881,7 +882,7 @@ static enum blk_eh_timer_return apple_nvme_timeout(struct request *req) · 65 unmodified lines | ||
| 881 | 882 | unsigned long flags; |
| 882 | 883 | u32 csts = readl(anv->mmio_nvme + NVME_REG_CSTS); |
| 883 | 884 | |
| 884 | − if (anv->ctrl.state != NVME_CTRL_LIVE) { | |
| 885 | + if (nvme_ctrl_state(&anv->ctrl) != NVME_CTRL_LIVE) { | |
| 885 | 886 | /* |
| 886 | 887 | * From rdma.c: |
| 887 | 888 | * If we are resetting, connecting or deleting we should |
| @@ -985,10 +986,10 @@ static void apple_nvme_reset_work(struct work_struct *work) · 97 unmodified lines | ||
| 985 | 986 | u32 boot_status, aqa; |
| 986 | 987 | struct apple_nvme *anv = |
| 987 | 988 | container_of(work, struct apple_nvme, ctrl.reset_work); |
| 989 | + enum nvme_ctrl_state state = nvme_ctrl_state(&anv->ctrl); | |
| 988 | 990 | |
| 989 | − if (anv->ctrl.state != NVME_CTRL_RESETTING) { | |
| 990 | − dev_warn(anv->dev, "ctrl state %d is not RESETTING\n", | |
| 991 | − anv->ctrl.state); | |
| 991 | + if (state != NVME_CTRL_RESETTING) { | |
| 992 | + dev_warn(anv->dev, "ctrl state %d is not RESETTING\n", state); | |
| 992 | 993 | ret = -ENODEV; |
| 993 | 994 | goto out; |
| 994 | 995 | } |
| @@ -48,11 +48,6 @@ struct nvme_dhchap_queue_context { · 47 unmodified lines | ||
| 48 | 48 | |
| 49 | 49 | static struct workqueue_struct *nvme_auth_wq; |
| 50 | 50 | |
| 51 | −#define nvme_auth_flags_from_qid(qid) \ | |
| 52 | − (qid == 0) ? 0 : BLK_MQ_REQ_NOWAIT | BLK_MQ_REQ_RESERVED | |
| 53 | −#define nvme_auth_queue_from_qid(ctrl, qid) \ | |
| 54 | − (qid == 0) ? (ctrl)->fabrics_q : (ctrl)->connect_q | |
| 55 | − | |
| 56 | 51 | static inline int ctrl_max_dhchaps(struct nvme_ctrl *ctrl) |
| 57 | 52 | { |
| 58 | 53 | return ctrl->opts->nr_io_queues + ctrl->opts->nr_write_queues + |
| @@ -63,10 +58,15 @@ static int nvme_auth_submit(struct nvme_ctrl *ctrl, int qid, · 4 unmodified lines | ||
| 63 | 58 | void *data, size_t data_len, bool auth_send) |
| 64 | 59 | { |
| 65 | 60 | struct nvme_command cmd = {}; |
| 66 | − blk_mq_req_flags_t flags = nvme_auth_flags_from_qid(qid); | |
| 67 | − struct request_queue *q = nvme_auth_queue_from_qid(ctrl, qid); | |
| 61 | + nvme_submit_flags_t flags = NVME_SUBMIT_RETRY; | |
| 62 | + struct request_queue *q = ctrl->fabrics_q; | |
| 68 | 63 | int ret; |
| 69 | 64 | |
| 65 | + if (qid != 0) { | |
| 66 | + flags |= NVME_SUBMIT_NOWAIT | NVME_SUBMIT_RESERVED; | |
| 67 | + q = ctrl->connect_q; | |
| 68 | + } | |
| 69 | + | |
| 70 | 70 | cmd.auth_common.opcode = nvme_fabrics_command; |
| 71 | 71 | cmd.auth_common.secp = NVME_AUTH_DHCHAP_PROTOCOL_IDENTIFIER; |
| 72 | 72 | cmd.auth_common.spsp0 = 0x01; |
| @@ -80,8 +80,7 @@ static int nvme_auth_submit(struct nvme_ctrl *ctrl, int qid, · 7 unmodified lines | ||
| 80 | 80 | } |
| 81 | 81 | |
| 82 | 82 | ret = __nvme_submit_sync_cmd(q, &cmd, NULL, data, data_len, |
| 83 | − qid == 0 ? NVME_QID_ANY : qid, | |
| 84 | − 0, flags); | |
| 83 | + qid == 0 ? NVME_QID_ANY : qid, flags); | |
| 85 | 84 | if (ret > 0) |
| 86 | 85 | dev_warn(ctrl->device, |
| 87 | 86 | "qid %d auth_send failed with status %d\n", qid, ret); |
| @@ -897,7 +896,7 @@ static void nvme_ctrl_auth_work(struct work_struct *work) · 809 unmodified lines | ||
| 897 | 896 | * If the ctrl is no connected, bail as reconnect will handle |
| 898 | 897 | * authentication. |
| 899 | 898 | */ |
| 900 | − if (ctrl->state != NVME_CTRL_LIVE) | |
| 899 | + if (nvme_ctrl_state(ctrl) != NVME_CTRL_LIVE) | |
| 901 | 900 | return; |
| 902 | 901 | |
| 903 | 902 | /* Authenticate admin queue first */ |
| @@ -171,15 +171,15 @@ static const char * const nvme_statuses[] = { · 170 unmodified lines | ||
| 171 | 171 | [NVME_SC_HOST_ABORTED_CMD] = "Host Aborted Command", |
| 172 | 172 | }; |
| 173 | 173 | |
| 174 | −const unsigned char *nvme_get_error_status_str(u16 status) | |
| 174 | +const char *nvme_get_error_status_str(u16 status) | |
| 175 | 175 | { |
| 176 | 176 | status &= 0x7ff; |
| 177 | 177 | if (status < ARRAY_SIZE(nvme_statuses) && nvme_statuses[status]) |
| 178 | − return nvme_statuses[status & 0x7ff]; | |
| 178 | + return nvme_statuses[status]; | |
| 179 | 179 | return "Unknown"; |
| 180 | 180 | } |
| 181 | 181 | |
| 182 | −const unsigned char *nvme_get_opcode_str(u8 opcode) | |
| 182 | +const char *nvme_get_opcode_str(u8 opcode) | |
| 183 | 183 | { |
| 184 | 184 | if (opcode < ARRAY_SIZE(nvme_ops) && nvme_ops[opcode]) |
| 185 | 185 | return nvme_ops[opcode]; |
| @@ -187,7 +187,7 @@ const unsigned char *nvme_get_opcode_str(u8 opcode) · 1 unmodified line | ||
| 187 | 187 | } |
| 188 | 188 | EXPORT_SYMBOL_GPL(nvme_get_opcode_str); |
| 189 | 189 | |
| 190 | −const unsigned char *nvme_get_admin_opcode_str(u8 opcode) | |
| 190 | +const char *nvme_get_admin_opcode_str(u8 opcode) | |
| 191 | 191 | { |
| 192 | 192 | if (opcode < ARRAY_SIZE(nvme_admin_ops) && nvme_admin_ops[opcode]) |
| 193 | 193 | return nvme_admin_ops[opcode]; |
| @@ -195,7 +195,7 @@ const unsigned char *nvme_get_admin_opcode_str(u8 opcode) · 1 unmodified line | ||
| 195 | 195 | } |
| 196 | 196 | EXPORT_SYMBOL_GPL(nvme_get_admin_opcode_str); |
| 197 | 197 | |
| 198 | −const unsigned char *nvme_get_fabrics_opcode_str(u8 opcode) { | |
| 198 | +const char *nvme_get_fabrics_opcode_str(u8 opcode) { | |
| 199 | 199 | if (opcode < ARRAY_SIZE(nvme_fabrics_ops) && nvme_fabrics_ops[opcode]) |
| 200 | 200 | return nvme_fabrics_ops[opcode]; |
| 201 | 201 | return "Unknown"; |
| @@ -338,6 +338,30 @@ static void nvme_log_error(struct request *req) · 337 unmodified lines | ||
| 338 | 338 | nr->status & NVME_SC_DNR ? "DNR " : ""); |
| 339 | 339 | } |
| 340 | 340 | |
| 341 | +static void nvme_log_err_passthru(struct request *req) | |
| 342 | +{ | |
| 343 | + struct nvme_ns *ns = req->q->queuedata; | |
| 344 | + struct nvme_request *nr = nvme_req(req); | |
| 345 | + | |
| 346 | + pr_err_ratelimited("%s: %s(0x%x), %s (sct 0x%x / sc 0x%x) %s%s" | |
| 347 | + "cdw10=0x%x cdw11=0x%x cdw12=0x%x cdw13=0x%x cdw14=0x%x cdw15=0x%x\n", | |
| 348 | + ns ? ns->disk->disk_name : dev_name(nr->ctrl->device), | |
| 349 | + ns ? nvme_get_opcode_str(nr->cmd->common.opcode) : | |
| 350 | + nvme_get_admin_opcode_str(nr->cmd->common.opcode), | |
| 351 | + nr->cmd->common.opcode, | |
| 352 | + nvme_get_error_status_str(nr->status), | |
| 353 | + nr->status >> 8 & 7, /* Status Code Type */ | |
| 354 | + nr->status & 0xff, /* Status Code */ | |
| 355 | + nr->status & NVME_SC_MORE ? "MORE " : "", | |
| 356 | + nr->status & NVME_SC_DNR ? "DNR " : "", | |
| 357 | + nr->cmd->common.cdw10, | |
| 358 | + nr->cmd->common.cdw11, | |
| 359 | + nr->cmd->common.cdw12, | |
| 360 | + nr->cmd->common.cdw13, | |
| 361 | + nr->cmd->common.cdw14, | |
| 362 | + nr->cmd->common.cdw14); | |
| 363 | +} | |
| 364 | + | |
| 341 | 365 | enum nvme_disposition { |
| 342 | 366 | COMPLETE, |
| 343 | 367 | RETRY, |
| @@ -385,8 +409,12 @@ static inline void nvme_end_req(struct request *req) · 41 unmodified lines | ||
| 385 | 409 | { |
| 386 | 410 | blk_status_t status = nvme_error_status(nvme_req(req)->status); |
| 387 | 411 | |
| 388 | − if (unlikely(nvme_req(req)->status && !(req->rq_flags & RQF_QUIET))) | |
| 389 | − nvme_log_error(req); | |
| 412 | + if (unlikely(nvme_req(req)->status && !(req->rq_flags & RQF_QUIET))) { | |
| 413 | + if (blk_rq_is_passthrough(req)) | |
| 414 | + nvme_log_err_passthru(req); | |
| 415 | + else | |
| 416 | + nvme_log_error(req); | |
| 417 | + } | |
| 390 | 418 | nvme_end_req_zoned(req); |
| 391 | 419 | nvme_trace_bio_complete(req); |
| 392 | 420 | if (req->cmd_flags & REQ_NVME_MPATH) |
| @@ -679,10 +707,21 @@ static inline void nvme_clear_nvme_request(struct request *req) · 286 unmodified lines | ||
| 679 | 707 | /* initialize a passthrough request */ |
| 680 | 708 | void nvme_init_request(struct request *req, struct nvme_command *cmd) |
| 681 | 709 | { |
| 682 | − if (req->q->queuedata) | |
| 710 | + struct nvme_request *nr = nvme_req(req); | |
| 711 | + bool logging_enabled; | |
| 712 | + | |
| 713 | + if (req->q->queuedata) { | |
| 714 | + struct nvme_ns *ns = req->q->disk->private_data; | |
| 715 | + | |
| 716 | + logging_enabled = ns->passthru_err_log_enabled; | |
| 683 | 717 | req->timeout = NVME_IO_TIMEOUT; |
| 684 | − else /* no queuedata implies admin queue */ | |
| 718 | + } else { /* no queuedata implies admin queue */ | |
| 719 | + logging_enabled = nr->ctrl->passthru_err_log_enabled; | |
| 685 | 720 | req->timeout = NVME_ADMIN_TIMEOUT; |
| 721 | + } | |
| 722 | + | |
| 723 | + if (!logging_enabled) | |
| 724 | + req->rq_flags |= RQF_QUIET; | |
| 686 | 725 | |
| 687 | 726 | /* passthru commands should let the driver set the SGL flags */ |
| 688 | 727 | cmd->common.flags &= ~NVME_CMD_SGL_ALL; |
| @@ -691,8 +730,7 @@ void nvme_init_request(struct request *req, struct nvme_command *cmd) · 2 unmodified lines | ||
| 691 | 730 | if (req->mq_hctx->type == HCTX_TYPE_POLL) |
| 692 | 731 | req->cmd_flags |= REQ_POLLED; |
| 693 | 732 | nvme_clear_nvme_request(req); |
| 694 | − req->rq_flags |= RQF_QUIET; | |
| 695 | − memcpy(nvme_req(req)->cmd, cmd, sizeof(*cmd)); | |
| 733 | + memcpy(nr->cmd, cmd, sizeof(*cmd)); | |
| 696 | 734 | } |
| 697 | 735 | EXPORT_SYMBOL_GPL(nvme_init_request); |
| 698 | 736 | |
| @@ -721,7 +759,7 @@ blk_status_t nvme_fail_nonready_command(struct nvme_ctrl *ctrl, · 22 unmodified lines | ||
| 721 | 759 | EXPORT_SYMBOL_GPL(nvme_fail_nonready_command); |
| 722 | 760 | |
| 723 | 761 | bool __nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq, |
| 724 | − bool queue_live) | |
| 762 | + bool queue_live, enum nvme_ctrl_state state) | |
| 725 | 763 | { |
| 726 | 764 | struct nvme_request *req = nvme_req(rq); |
| 727 | 765 | |
| @@ -742,7 +780,7 @@ bool __nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq, · 14 unmodified lines | ||
| 742 | 780 | * command, which is require to set the queue live in the |
| 743 | 781 | * appropinquate states. |
| 744 | 782 | */ |
| 745 | − switch (nvme_ctrl_state(ctrl)) { | |
| 783 | + switch (state) { | |
| 746 | 784 | case NVME_CTRL_CONNECTING: |
| 747 | 785 | if (blk_rq_is_passthrough(rq) && nvme_is_fabrics(req->cmd) && |
| 748 | 786 | (req->cmd->fabrics.fctype == nvme_fabrics_type_connect || |
| @@ -1051,20 +1089,27 @@ EXPORT_SYMBOL_NS_GPL(nvme_execute_rq, NVME_TARGET_PASSTHRU); · 302 unmodified lines | ||
| 1051 | 1089 | */ |
| 1052 | 1090 | int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, |
| 1053 | 1091 | union nvme_result *result, void *buffer, unsigned bufflen, |
| 1054 | − int qid, int at_head, blk_mq_req_flags_t flags) | |
| 1092 | + int qid, nvme_submit_flags_t flags) | |
| 1055 | 1093 | { |
| 1056 | 1094 | struct request *req; |
| 1057 | 1095 | int ret; |
| 1096 | + blk_mq_req_flags_t blk_flags = 0; | |
| 1058 | 1097 | |
| 1098 | + if (flags & NVME_SUBMIT_NOWAIT) | |
| 1099 | + blk_flags |= BLK_MQ_REQ_NOWAIT; | |
| 1100 | + if (flags & NVME_SUBMIT_RESERVED) | |
| 1101 | + blk_flags |= BLK_MQ_REQ_RESERVED; | |
| 1059 | 1102 | if (qid == NVME_QID_ANY) |
| 1060 | − req = blk_mq_alloc_request(q, nvme_req_op(cmd), flags); | |
| 1103 | + req = blk_mq_alloc_request(q, nvme_req_op(cmd), blk_flags); | |
| 1061 | 1104 | else |
| 1062 | − req = blk_mq_alloc_request_hctx(q, nvme_req_op(cmd), flags, | |
| 1105 | + req = blk_mq_alloc_request_hctx(q, nvme_req_op(cmd), blk_flags, | |
| 1063 | 1106 | qid - 1); |
| 1064 | 1107 | |
| 1065 | 1108 | if (IS_ERR(req)) |
| 1066 | 1109 | return PTR_ERR(req); |
| 1067 | 1110 | nvme_init_request(req, cmd); |
| 1111 | + if (flags & NVME_SUBMIT_RETRY) | |
| 1112 | + req->cmd_flags &= ~REQ_FAILFAST_DRIVER; | |
| 1068 | 1113 | |
| 1069 | 1114 | if (buffer && bufflen) { |
| 1070 | 1115 | ret = blk_rq_map_kern(q, req, buffer, bufflen, GFP_KERNEL); |
| @@ -1072,7 +1117,7 @@ int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, · 1 unmodified line | ||
| 1072 | 1117 | goto out; |
| 1073 | 1118 | } |
| 1074 | 1119 | |
| 1075 | − ret = nvme_execute_rq(req, at_head); | |
| 1120 | + ret = nvme_execute_rq(req, flags & NVME_SUBMIT_AT_HEAD); | |
| 1076 | 1121 | if (result && ret >= 0) |
| 1077 | 1122 | *result = nvme_req(req)->result; |
| 1078 | 1123 | out: |
| @@ -1085,7 +1130,7 @@ int nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, · 6 unmodified lines | ||
| 1085 | 1130 | void *buffer, unsigned bufflen) |
| 1086 | 1131 | { |
| 1087 | 1132 | return __nvme_submit_sync_cmd(q, cmd, NULL, buffer, bufflen, |
| 1088 | − NVME_QID_ANY, 0, 0); | |
| 1133 | + NVME_QID_ANY, 0); | |
| 1089 | 1134 | } |
| 1090 | 1135 | EXPORT_SYMBOL_GPL(nvme_submit_sync_cmd); |
| 1091 | 1136 | |
| @@ -1560,7 +1605,7 @@ static int nvme_features(struct nvme_ctrl *dev, u8 op, unsigned int fid, · 468 unmodified lines | ||
| 1560 | 1605 | c.features.dword11 = cpu_to_le32(dword11); |
| 1561 | 1606 | |
| 1562 | 1607 | ret = __nvme_submit_sync_cmd(dev->admin_q, &c, &res, |
| 1563 | − buffer, buflen, NVME_QID_ANY, 0, 0); | |
| 1608 | + buffer, buflen, NVME_QID_ANY, 0); | |
| 1564 | 1609 | if (ret >= 0 && result) |
| 1565 | 1610 | *result = le32_to_cpu(res.u32); |
| 1566 | 1611 | return ret; |
| @@ -2172,7 +2217,7 @@ static int nvme_sec_submit(void *data, u16 spsp, u8 secp, void *buffer, size_t l · 605 unmodified lines | ||
| 2172 | 2217 | cmd.common.cdw11 = cpu_to_le32(len); |
| 2173 | 2218 | |
| 2174 | 2219 | return __nvme_submit_sync_cmd(ctrl->admin_q, &cmd, NULL, buffer, len, |
| 2175 | − NVME_QID_ANY, 1, 0); | |
| 2220 | + NVME_QID_ANY, NVME_SUBMIT_AT_HEAD); | |
| 2176 | 2221 | } |
| 2177 | 2222 | |
| 2178 | 2223 | static void nvme_configure_opal(struct nvme_ctrl *ctrl, bool was_suspended) |
| @@ -3651,6 +3696,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info) · 1472 unmodified lines | ||
| 3651 | 3696 | |
| 3652 | 3697 | ns->disk = disk; |
| 3653 | 3698 | ns->queue = disk->queue; |
| 3699 | + ns->passthru_err_log_enabled = false; | |
| 3654 | 3700 | |
| 3655 | 3701 | if (ctrl->opts && ctrl->opts->data_digest) |
| 3656 | 3702 | blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, ns->queue); |
| @@ -3714,6 +3760,13 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info) · 57 unmodified lines | ||
| 3714 | 3760 | nvme_mpath_add_disk(ns, info->anagrpid); |
| 3715 | 3761 | nvme_fault_inject_init(&ns->fault_inject, ns->disk->disk_name); |
| 3716 | 3762 | |
| 3763 | + /* | |
| 3764 | + * Set ns->disk->device->driver_data to ns so we can access | |
| 3765 | + * ns->logging_enabled in nvme_passthru_err_log_enabled_store() and | |
| 3766 | + * nvme_passthru_err_log_enabled_show(). | |
| 3767 | + */ | |
| 3768 | + dev_set_drvdata(disk_to_dev(ns->disk), ns); | |
| 3769 | + | |
| 3717 | 3770 | return; |
| 3718 | 3771 | |
| 3719 | 3772 | out_cleanup_ns_from_list: |
| @@ -4514,6 +4567,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev, · 794 unmodified lines | ||
| 4514 | 4567 | int ret; |
| 4515 | 4568 | |
| 4516 | 4569 | WRITE_ONCE(ctrl->state, NVME_CTRL_NEW); |
| 4570 | + ctrl->passthru_err_log_enabled = false; | |
| 4517 | 4571 | clear_bit(NVME_CTRL_FAILFAST_EXPIRED, &ctrl->flags); |
| 4518 | 4572 | spin_lock_init(&ctrl->lock); |
| 4519 | 4573 | mutex_init(&ctrl->scan_lock); |
| @@ -4851,5 +4905,6 @@ static void __exit nvme_core_exit(void) · 331 unmodified lines | ||
| 4851 | 4905 | |
| 4852 | 4906 | MODULE_LICENSE("GPL"); |
| 4853 | 4907 | MODULE_VERSION("1.0"); |
| 4908 | +MODULE_DESCRIPTION("NVMe host core framework"); | |
| 4854 | 4909 | module_init(nvme_core_init); |
| 4855 | 4910 | module_exit(nvme_core_exit); |
| @@ -180,7 +180,7 @@ int nvmf_reg_read32(struct nvme_ctrl *ctrl, u32 off, u32 *val) · 179 unmodified lines | ||
| 180 | 180 | cmd.prop_get.offset = cpu_to_le32(off); |
| 181 | 181 | |
| 182 | 182 | ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, &res, NULL, 0, |
| 183 | − NVME_QID_ANY, 0, 0); | |
| 183 | + NVME_QID_ANY, 0); | |
| 184 | 184 | |
| 185 | 185 | if (ret >= 0) |
| 186 | 186 | *val = le64_to_cpu(res.u64); |
| @@ -226,7 +226,7 @@ int nvmf_reg_read64(struct nvme_ctrl *ctrl, u32 off, u64 *val) · 39 unmodified lines | ||
| 226 | 226 | cmd.prop_get.offset = cpu_to_le32(off); |
| 227 | 227 | |
| 228 | 228 | ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, &res, NULL, 0, |
| 229 | − NVME_QID_ANY, 0, 0); | |
| 229 | + NVME_QID_ANY, 0); | |
| 230 | 230 | |
| 231 | 231 | if (ret >= 0) |
| 232 | 232 | *val = le64_to_cpu(res.u64); |
| @@ -271,7 +271,7 @@ int nvmf_reg_write32(struct nvme_ctrl *ctrl, u32 off, u32 val) · 38 unmodified lines | ||
| 271 | 271 | cmd.prop_set.value = cpu_to_le64(val); |
| 272 | 272 | |
| 273 | 273 | ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, NULL, NULL, 0, |
| 274 | − NVME_QID_ANY, 0, 0); | |
| 274 | + NVME_QID_ANY, 0); | |
| 275 | 275 | if (unlikely(ret)) |
| 276 | 276 | dev_err(ctrl->device, |
| 277 | 277 | "Property Set error: %d, offset %#x\n", |
| @@ -450,8 +450,10 @@ int nvmf_connect_admin_queue(struct nvme_ctrl *ctrl) · 172 unmodified lines | ||
| 450 | 450 | return -ENOMEM; |
| 451 | 451 | |
| 452 | 452 | ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, &res, |
| 453 | − data, sizeof(*data), NVME_QID_ANY, 1, | |
| 454 | − BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT); | |
| 453 | + data, sizeof(*data), NVME_QID_ANY, | |
| 454 | + NVME_SUBMIT_AT_HEAD | | |
| 455 | + NVME_SUBMIT_NOWAIT | | |
| 456 | + NVME_SUBMIT_RESERVED); | |
| 455 | 457 | if (ret) { |
| 456 | 458 | nvmf_log_connect_error(ctrl, ret, le32_to_cpu(res.u32), |
| 457 | 459 | &cmd, data); |
| @@ -525,8 +527,10 @@ int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid) · 67 unmodified lines | ||
| 525 | 527 | return -ENOMEM; |
| 526 | 528 | |
| 527 | 529 | ret = __nvme_submit_sync_cmd(ctrl->connect_q, &cmd, &res, |
| 528 | − data, sizeof(*data), qid, 1, | |
| 529 | − BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT); | |
| 530 | + data, sizeof(*data), qid, | |
| 531 | + NVME_SUBMIT_AT_HEAD | | |
| 532 | + NVME_SUBMIT_RESERVED | | |
| 533 | + NVME_SUBMIT_NOWAIT); | |
| 530 | 534 | if (ret) { |
| 531 | 535 | nvmf_log_connect_error(ctrl, ret, le32_to_cpu(res.u32), |
| 532 | 536 | &cmd, data); |
| @@ -1488,6 +1492,7 @@ static void __exit nvmf_exit(void) · 955 unmodified lines | ||
| 1488 | 1492 | } |
| 1489 | 1493 | |
| 1490 | 1494 | MODULE_LICENSE("GPL v2"); |
| 1495 | +MODULE_DESCRIPTION("NVMe host fabrics library"); | |
| 1491 | 1496 | |
| 1492 | 1497 | module_init(nvmf_init); |
| 1493 | 1498 | module_exit(nvmf_exit); |
| @@ -185,9 +185,11 @@ static inline bool · 184 unmodified lines | ||
| 185 | 185 | nvmf_ctlr_matches_baseopts(struct nvme_ctrl *ctrl, |
| 186 | 186 | struct nvmf_ctrl_options *opts) |
| 187 | 187 | { |
| 188 | − if (ctrl->state == NVME_CTRL_DELETING || | |
| 189 | − ctrl->state == NVME_CTRL_DELETING_NOIO || | |
| 190 | − ctrl->state == NVME_CTRL_DEAD || | |
| 188 | + enum nvme_ctrl_state state = nvme_ctrl_state(ctrl); | |
| 189 | + | |
| 190 | + if (state == NVME_CTRL_DELETING || | |
| 191 | + state == NVME_CTRL_DELETING_NOIO || | |
| 192 | + state == NVME_CTRL_DEAD || | |
| 191 | 193 | strcmp(opts->subsysnqn, ctrl->opts->subsysnqn) || |
| 192 | 194 | strcmp(opts->host->nqn, ctrl->opts->host->nqn) || |
| 193 | 195 | !uuid_equal(&opts->host->id, &ctrl->opts->host->id)) |
| @@ -221,11 +221,6 @@ static LIST_HEAD(nvme_fc_lport_list); · 220 unmodified lines | ||
| 221 | 221 | static DEFINE_IDA(nvme_fc_local_port_cnt); |
| 222 | 222 | static DEFINE_IDA(nvme_fc_ctrl_cnt); |
| 223 | 223 | |
| 224 | −static struct workqueue_struct *nvme_fc_wq; | |
| 225 | − | |
| 226 | −static bool nvme_fc_waiting_to_unload; | |
| 227 | −static DECLARE_COMPLETION(nvme_fc_unload_proceed); | |
| 228 | − | |
| 229 | 224 | /* |
| 230 | 225 | * These items are short-term. They will eventually be moved into |
| 231 | 226 | * a generic FC class. See comments in module init. |
| @@ -255,8 +250,6 @@ nvme_fc_free_lport(struct kref *ref) · 23 unmodified lines | ||
| 255 | 250 | /* remove from transport list */ |
| 256 | 251 | spin_lock_irqsave(&nvme_fc_lock, flags); |
| 257 | 252 | list_del(&lport->port_list); |
| 258 | − if (nvme_fc_waiting_to_unload && list_empty(&nvme_fc_lport_list)) | |
| 259 | − complete(&nvme_fc_unload_proceed); | |
| 260 | 253 | spin_unlock_irqrestore(&nvme_fc_lock, flags); |
| 261 | 254 | |
| 262 | 255 | ida_free(&nvme_fc_local_port_cnt, lport->localport.port_num); |
| @@ -2574,6 +2567,7 @@ static enum blk_eh_timer_return nvme_fc_timeout(struct request *rq) · 2311 unmodified lines | ||
| 2574 | 2567 | { |
| 2575 | 2568 | struct nvme_fc_fcp_op *op = blk_mq_rq_to_pdu(rq); |
| 2576 | 2569 | struct nvme_fc_ctrl *ctrl = op->ctrl; |
| 2570 | + u16 qnum = op->queue->qnum; | |
| 2577 | 2571 | struct nvme_fc_cmd_iu *cmdiu = &op->cmd_iu; |
| 2578 | 2572 | struct nvme_command *sqe = &cmdiu->sqe; |
| 2579 | 2573 | |
| @@ -2582,10 +2576,11 @@ static enum blk_eh_timer_return nvme_fc_timeout(struct request *rq) · 2 unmodified lines | ||
| 2582 | 2576 | * will detect the aborted io and will fail the connection. |
| 2583 | 2577 | */ |
| 2584 | 2578 | dev_info(ctrl->ctrl.device, |
| 2585 | − "NVME-FC{%d.%d}: io timeout: opcode %d fctype %d w10/11: " | |
| 2579 | + "NVME-FC{%d.%d}: io timeout: opcode %d fctype %d (%s) w10/11: " | |
| 2586 | 2580 | "x%08x/x%08x\n", |
| 2587 | − ctrl->cnum, op->queue->qnum, sqe->common.opcode, | |
| 2588 | − sqe->connect.fctype, sqe->common.cdw10, sqe->common.cdw11); | |
| 2581 | + ctrl->cnum, qnum, sqe->common.opcode, sqe->fabrics.fctype, | |
| 2582 | + nvme_fabrics_opcode_str(qnum, sqe), | |
| 2583 | + sqe->common.cdw10, sqe->common.cdw11); | |
| 2589 | 2584 | if (__nvme_fc_abort_op(ctrl, op)) |
| 2590 | 2585 | nvme_fc_error_recovery(ctrl, "io timeout abort failed"); |
| 2591 | 2586 | |
| @@ -3575,8 +3570,8 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts, · 983 unmodified lines | ||
| 3575 | 3570 | flush_delayed_work(&ctrl->connect_work); |
| 3576 | 3571 | |
| 3577 | 3572 | dev_info(ctrl->ctrl.device, |
| 3578 | − "NVME-FC{%d}: new ctrl: NQN \"%s\"\n", | |
| 3579 | − ctrl->cnum, nvmf_ctrl_subsysnqn(&ctrl->ctrl)); | |
| 3573 | + "NVME-FC{%d}: new ctrl: NQN \"%s\", hostnqn: %s\n", | |
| 3574 | + ctrl->cnum, nvmf_ctrl_subsysnqn(&ctrl->ctrl), opts->host->nqn); | |
| 3580 | 3575 | |
| 3581 | 3576 | return &ctrl->ctrl; |
| 3582 | 3577 | |
| @@ -3894,10 +3889,6 @@ static int __init nvme_fc_init_module(void) · 311 unmodified lines | ||
| 3894 | 3889 | { |
| 3895 | 3890 | int ret; |
| 3896 | 3891 | |
| 3897 | − nvme_fc_wq = alloc_workqueue("nvme_fc_wq", WQ_MEM_RECLAIM, 0); | |
| 3898 | − if (!nvme_fc_wq) | |
| 3899 | − return -ENOMEM; | |
| 3900 | − | |
| 3901 | 3892 | /* |
| 3902 | 3893 | * NOTE: |
| 3903 | 3894 | * It is expected that in the future the kernel will combine |
| @@ -3915,7 +3906,7 @@ static int __init nvme_fc_init_module(void) · 11 unmodified lines | ||
| 3915 | 3906 | ret = class_register(&fc_class); |
| 3916 | 3907 | if (ret) { |
| 3917 | 3908 | pr_err("couldn't register class fc\n"); |
| 3918 | − goto out_destroy_wq; | |
| 3909 | + return ret; | |
| 3919 | 3910 | } |
| 3920 | 3911 | |
| 3921 | 3912 | /* |
| @@ -3939,8 +3930,6 @@ out_destroy_device: · 17 unmodified lines | ||
| 3939 | 3930 | device_destroy(&fc_class, MKDEV(0, 0)); |
| 3940 | 3931 | out_destroy_class: |
| 3941 | 3932 | class_unregister(&fc_class); |
| 3942 | −out_destroy_wq: | |
| 3943 | − destroy_workqueue(nvme_fc_wq); | |
| 3944 | 3933 | |
| 3945 | 3934 | return ret; |
| 3946 | 3935 | } |
| @@ -3960,48 +3949,27 @@ nvme_fc_delete_controllers(struct nvme_fc_rport *rport) · 13 unmodified lines | ||
| 3960 | 3949 | spin_unlock(&rport->lock); |
| 3961 | 3950 | } |
| 3962 | 3951 | |
| 3963 | −static void | |
| 3964 | −nvme_fc_cleanup_for_unload(void) | |
| 3952 | +static void __exit nvme_fc_exit_module(void) | |
| 3965 | 3953 | { |
| 3966 | 3954 | struct nvme_fc_lport *lport; |
| 3967 | 3955 | struct nvme_fc_rport *rport; |
| 3968 | − | |
| 3969 | − list_for_each_entry(lport, &nvme_fc_lport_list, port_list) { | |
| 3970 | − list_for_each_entry(rport, &lport->endp_list, endp_list) { | |
| 3971 | − nvme_fc_delete_controllers(rport); | |
| 3972 | − } | |
| 3973 | − } | |
| 3974 | −} | |
| 3975 | − | |
| 3976 | −static void __exit nvme_fc_exit_module(void) | |
| 3977 | −{ | |
| 3978 | 3956 | unsigned long flags; |
| 3979 | − bool need_cleanup = false; | |
| 3980 | 3957 | |
| 3981 | 3958 | spin_lock_irqsave(&nvme_fc_lock, flags); |
| 3982 | − nvme_fc_waiting_to_unload = true; | |
| 3983 | − if (!list_empty(&nvme_fc_lport_list)) { | |
| 3984 | − need_cleanup = true; | |
| 3985 | − nvme_fc_cleanup_for_unload(); | |
| 3986 | − } | |
| 3959 | + list_for_each_entry(lport, &nvme_fc_lport_list, port_list) | |
| 3960 | + list_for_each_entry(rport, &lport->endp_list, endp_list) | |
| 3961 | + nvme_fc_delete_controllers(rport); | |
| 3987 | 3962 | spin_unlock_irqrestore(&nvme_fc_lock, flags); |
| 3988 | − if (need_cleanup) { | |
| 3989 | − pr_info("%s: waiting for ctlr deletes\n", __func__); | |
| 3990 | − wait_for_completion(&nvme_fc_unload_proceed); | |
| 3991 | − pr_info("%s: ctrl deletes complete\n", __func__); | |
| 3992 | − } | |
| 3963 | + flush_workqueue(nvme_delete_wq); | |
| 3993 | 3964 | |
| 3994 | 3965 | nvmf_unregister_transport(&nvme_fc_transport); |
| 3995 | 3966 | |
| 3996 | − ida_destroy(&nvme_fc_local_port_cnt); | |
| 3997 | − ida_destroy(&nvme_fc_ctrl_cnt); | |
| 3998 | − | |
| 3999 | 3967 | device_destroy(&fc_class, MKDEV(0, 0)); |
| 4000 | 3968 | class_unregister(&fc_class); |
| 4001 | − destroy_workqueue(nvme_fc_wq); | |
| 4002 | 3969 | } |
| 4003 | 3970 | |
| 4004 | 3971 | module_init(nvme_fc_init_module); |
| 4005 | 3972 | module_exit(nvme_fc_exit_module); |
| 4006 | 3973 | |
| 3974 | +MODULE_DESCRIPTION("NVMe host FC transport driver"); | |
| 4007 | 3975 | MODULE_LICENSE("GPL v2"); |
| @@ -156,7 +156,7 @@ void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl) · 155 unmodified lines | ||
| 156 | 156 | if (!ns->head->disk) |
| 157 | 157 | continue; |
| 158 | 158 | kblockd_schedule_work(&ns->head->requeue_work); |
| 159 | − if (ctrl->state == NVME_CTRL_LIVE) | |
| 159 | + if (nvme_ctrl_state(ns->ctrl) == NVME_CTRL_LIVE) | |
| 160 | 160 | disk_uevent(ns->head->disk, KOBJ_CHANGE); |
| 161 | 161 | } |
| 162 | 162 | up_read(&ctrl->namespaces_rwsem); |
| @@ -223,13 +223,14 @@ void nvme_mpath_revalidate_paths(struct nvme_ns *ns) · 60 unmodified lines | ||
| 223 | 223 | |
| 224 | 224 | static bool nvme_path_is_disabled(struct nvme_ns *ns) |
| 225 | 225 | { |
| 226 | + enum nvme_ctrl_state state = nvme_ctrl_state(ns->ctrl); | |
| 227 | + | |
| 226 | 228 | /* |
| 227 | 229 | * We don't treat NVME_CTRL_DELETING as a disabled path as I/O should |
| 228 | 230 | * still be able to complete assuming that the controller is connected. |
| 229 | 231 | * Otherwise it will fail immediately and return to the requeue list. |
| 230 | 232 | */ |
| 231 | − if (ns->ctrl->state != NVME_CTRL_LIVE && | |
| 232 | − ns->ctrl->state != NVME_CTRL_DELETING) | |
| 233 | + if (state != NVME_CTRL_LIVE && state != NVME_CTRL_DELETING) | |
| 233 | 234 | return true; |
| 234 | 235 | if (test_bit(NVME_NS_ANA_PENDING, &ns->flags) || |
| 235 | 236 | !test_bit(NVME_NS_READY, &ns->flags)) |
| @@ -331,7 +332,7 @@ out: · 95 unmodified lines | ||
| 331 | 332 | |
| 332 | 333 | static inline bool nvme_path_is_optimized(struct nvme_ns *ns) |
| 333 | 334 | { |
| 334 | − return ns->ctrl->state == NVME_CTRL_LIVE && | |
| 335 | + return nvme_ctrl_state(ns->ctrl) == NVME_CTRL_LIVE && | |
| 335 | 336 | ns->ana_state == NVME_ANA_OPTIMIZED; |
| 336 | 337 | } |
| 337 | 338 | |
| @@ -358,7 +359,7 @@ static bool nvme_available_path(struct nvme_ns_head *head) · 20 unmodified lines | ||
| 358 | 359 | list_for_each_entry_rcu(ns, &head->list, siblings) { |
| 359 | 360 | if (test_bit(NVME_CTRL_FAILFAST_EXPIRED, &ns->ctrl->flags)) |
| 360 | 361 | continue; |
| 361 | − switch (ns->ctrl->state) { | |
| 362 | + switch (nvme_ctrl_state(ns->ctrl)) { | |
| 362 | 363 | case NVME_CTRL_LIVE: |
| 363 | 364 | case NVME_CTRL_RESETTING: |
| 364 | 365 | case NVME_CTRL_CONNECTING: |
| @@ -667,7 +668,7 @@ static void nvme_update_ns_ana_state(struct nvme_ana_group_desc *desc, · 302 unmodified lines | ||
| 667 | 668 | * controller is ready. |
| 668 | 669 | */ |
| 669 | 670 | if (nvme_state_is_live(ns->ana_state) && |
| 670 | − ns->ctrl->state == NVME_CTRL_LIVE) | |
| 671 | + nvme_ctrl_state(ns->ctrl) == NVME_CTRL_LIVE) | |
| 671 | 672 | nvme_mpath_set_live(ns); |
| 672 | 673 | } |
| 673 | 674 | |
| @@ -748,7 +749,7 @@ static void nvme_ana_work(struct work_struct *work) · 74 unmodified lines | ||
| 748 | 749 | { |
| 749 | 750 | struct nvme_ctrl *ctrl = container_of(work, struct nvme_ctrl, ana_work); |
| 750 | 751 | |
| 751 | − if (ctrl->state != NVME_CTRL_LIVE) | |
| 752 | + if (nvme_ctrl_state(ctrl) != NVME_CTRL_LIVE) | |
| 752 | 753 | return; |
| 753 | 754 | |
| 754 | 755 | nvme_read_ana_log(ctrl); |
| @@ -263,6 +263,7 @@ enum nvme_ctrl_flags { · 262 unmodified lines | ||
| 263 | 263 | struct nvme_ctrl { |
| 264 | 264 | bool comp_seen; |
| 265 | 265 | bool identified; |
| 266 | + bool passthru_err_log_enabled; | |
| 266 | 267 | enum nvme_ctrl_state state; |
| 267 | 268 | spinlock_t lock; |
| 268 | 269 | struct mutex scan_lock; |
| @@ -522,7 +523,7 @@ struct nvme_ns { · 253 unmodified lines | ||
| 522 | 523 | struct device cdev_device; |
| 523 | 524 | |
| 524 | 525 | struct nvme_fault_inject fault_inject; |
| 525 | − | |
| 526 | + bool passthru_err_log_enabled; | |
| 526 | 527 | }; |
| 527 | 528 | |
| 528 | 529 | /* NVMe ns supports metadata actions by the controller (generate/strip) */ |
| @@ -805,17 +806,18 @@ blk_status_t nvme_setup_cmd(struct nvme_ns *ns, struct request *req); · 276 unmodified lines | ||
| 805 | 806 | blk_status_t nvme_fail_nonready_command(struct nvme_ctrl *ctrl, |
| 806 | 807 | struct request *req); |
| 807 | 808 | bool __nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq, |
| 808 | − bool queue_live); | |
| 809 | + bool queue_live, enum nvme_ctrl_state state); | |
| 809 | 810 | |
| 810 | 811 | static inline bool nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq, |
| 811 | 812 | bool queue_live) |
| 812 | 813 | { |
| 813 | − if (likely(ctrl->state == NVME_CTRL_LIVE)) | |
| 814 | + enum nvme_ctrl_state state = nvme_ctrl_state(ctrl); | |
| 815 | + | |
| 816 | + if (likely(state == NVME_CTRL_LIVE)) | |
| 814 | 817 | return true; |
| 815 | − if (ctrl->ops->flags & NVME_F_FABRICS && | |
| 816 | − ctrl->state == NVME_CTRL_DELETING) | |
| 818 | + if (ctrl->ops->flags & NVME_F_FABRICS && state == NVME_CTRL_DELETING) | |
| 817 | 819 | return queue_live; |
| 818 | − return __nvme_check_ready(ctrl, rq, queue_live); | |
| 820 | + return __nvme_check_ready(ctrl, rq, queue_live, state); | |
| 819 | 821 | } |
| 820 | 822 | |
| 821 | 823 | /* |
| @@ -836,12 +838,27 @@ static inline bool nvme_is_unique_nsid(struct nvme_ctrl *ctrl, · 14 unmodified lines | ||
| 836 | 838 | (ctrl->ctratt & NVME_CTRL_CTRATT_NVM_SETS); |
| 837 | 839 | } |
| 838 | 840 | |
| 841 | +/* | |
| 842 | + * Flags for __nvme_submit_sync_cmd() | |
| 843 | + */ | |
| 844 | +typedef __u32 __bitwise nvme_submit_flags_t; | |
| 845 | + | |
| 846 | +enum { | |
| 847 | + /* Insert request at the head of the queue */ | |
| 848 | + NVME_SUBMIT_AT_HEAD = (__force nvme_submit_flags_t)(1 << 0), | |
| 849 | + /* Set BLK_MQ_REQ_NOWAIT when allocating request */ | |
| 850 | + NVME_SUBMIT_NOWAIT = (__force nvme_submit_flags_t)(1 << 1), | |
| 851 | + /* Set BLK_MQ_REQ_RESERVED when allocating request */ | |
| 852 | + NVME_SUBMIT_RESERVED = (__force nvme_submit_flags_t)(1 << 2), | |
| 853 | + /* Retry command when NVME_SC_DNR is not set in the result */ | |
| 854 | + NVME_SUBMIT_RETRY = (__force nvme_submit_flags_t)(1 << 3), | |
| 855 | +}; | |
| 856 | + | |
| 839 | 857 | int nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, |
| 840 | 858 | void *buf, unsigned bufflen); |
| 841 | 859 | int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, |
| 842 | 860 | union nvme_result *result, void *buffer, unsigned bufflen, |
| 843 | − int qid, int at_head, | |
| 844 | − blk_mq_req_flags_t flags); | |
| 861 | + int qid, nvme_submit_flags_t flags); | |
| 845 | 862 | int nvme_set_features(struct nvme_ctrl *dev, unsigned int fid, |
| 846 | 863 | unsigned int dword11, void *buffer, size_t buflen, |
| 847 | 864 | u32 *result); |
| @@ -1124,35 +1141,42 @@ static inline bool nvme_multi_css(struct nvme_ctrl *ctrl) · 276 unmodified lines | ||
| 1124 | 1141 | } |
| 1125 | 1142 | |
| 1126 | 1143 | #ifdef CONFIG_NVME_VERBOSE_ERRORS |
| 1127 | −const unsigned char *nvme_get_error_status_str(u16 status); | |
| 1128 | −const unsigned char *nvme_get_opcode_str(u8 opcode); | |
| 1129 | −const unsigned char *nvme_get_admin_opcode_str(u8 opcode); | |
| 1130 | −const unsigned char *nvme_get_fabrics_opcode_str(u8 opcode); | |
| 1144 | +const char *nvme_get_error_status_str(u16 status); | |
| 1145 | +const char *nvme_get_opcode_str(u8 opcode); | |
| 1146 | +const char *nvme_get_admin_opcode_str(u8 opcode); | |
| 1147 | +const char *nvme_get_fabrics_opcode_str(u8 opcode); | |
| 1131 | 1148 | #else /* CONFIG_NVME_VERBOSE_ERRORS */ |
| 1132 | −static inline const unsigned char *nvme_get_error_status_str(u16 status) | |
| 1149 | +static inline const char *nvme_get_error_status_str(u16 status) | |
| 1133 | 1150 | { |
| 1134 | 1151 | return "I/O Error"; |
| 1135 | 1152 | } |
| 1136 | −static inline const unsigned char *nvme_get_opcode_str(u8 opcode) | |
| 1153 | +static inline const char *nvme_get_opcode_str(u8 opcode) | |
| 1137 | 1154 | { |
| 1138 | 1155 | return "I/O Cmd"; |
| 1139 | 1156 | } |
| 1140 | −static inline const unsigned char *nvme_get_admin_opcode_str(u8 opcode) | |
| 1157 | +static inline const char *nvme_get_admin_opcode_str(u8 opcode) | |
| 1141 | 1158 | { |
| 1142 | 1159 | return "Admin Cmd"; |
| 1143 | 1160 | } |
| 1144 | 1161 | |
| 1145 | −static inline const unsigned char *nvme_get_fabrics_opcode_str(u8 opcode) | |
| 1162 | +static inline const char *nvme_get_fabrics_opcode_str(u8 opcode) | |
| 1146 | 1163 | { |
| 1147 | 1164 | return "Fabrics Cmd"; |
| 1148 | 1165 | } |
| 1149 | 1166 | #endif /* CONFIG_NVME_VERBOSE_ERRORS */ |
| 1150 | 1167 | |
| 1151 | −static inline const unsigned char *nvme_opcode_str(int qid, u8 opcode, u8 fctype) | |
| 1168 | +static inline const char *nvme_opcode_str(int qid, u8 opcode) | |
| 1152 | 1169 | { |
| 1153 | − if (opcode == nvme_fabrics_command) | |
| 1154 | − return nvme_get_fabrics_opcode_str(fctype); | |
| 1155 | 1170 | return qid ? nvme_get_opcode_str(opcode) : |
| 1156 | 1171 | nvme_get_admin_opcode_str(opcode); |
| 1157 | 1172 | } |
| 1173 | + | |
| 1174 | +static inline const char *nvme_fabrics_opcode_str( | |
| 1175 | + int qid, const struct nvme_command *cmd) | |
| 1176 | +{ | |
| 1177 | + if (nvme_is_fabrics(cmd)) | |
| 1178 | + return nvme_get_fabrics_opcode_str(cmd->fabrics.fctype); | |
| 1179 | + | |
| 1180 | + return nvme_opcode_str(qid, cmd->common.opcode); | |
| 1181 | +} | |
| 1158 | 1182 | #endif /* _NVME_H */ |
| @@ -1349,7 +1349,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req) · 1348 unmodified lines | ||
| 1349 | 1349 | dev_warn(dev->ctrl.device, |
| 1350 | 1350 | "I/O tag %d (%04x) opcode %#x (%s) QID %d timeout, reset controller\n", |
| 1351 | 1351 | req->tag, nvme_cid(req), opcode, |
| 1352 | − nvme_opcode_str(nvmeq->qid, opcode, 0), nvmeq->qid); | |
| 1352 | + nvme_opcode_str(nvmeq->qid, opcode), nvmeq->qid); | |
| 1353 | 1353 | nvme_req(req)->flags |= NVME_REQ_CANCELLED; |
| 1354 | 1354 | goto disable; |
| 1355 | 1355 | } |
| @@ -3543,5 +3543,6 @@ static void __exit nvme_exit(void) · 2187 unmodified lines | ||
| 3543 | 3543 | MODULE_AUTHOR("Matthew Wilcox <willy@linux.intel.com>"); |
| 3544 | 3544 | MODULE_LICENSE("GPL"); |
| 3545 | 3545 | MODULE_VERSION("1.0"); |
| 3546 | +MODULE_DESCRIPTION("NVMe host PCIe transport driver"); | |
| 3546 | 3547 | module_init(nvme_init); |
| 3547 | 3548 | module_exit(nvme_exit); |
| @@ -1410,6 +1410,8 @@ static int nvme_rdma_map_sg_pi(struct nvme_rdma_queue *queue, · 1409 unmodified lines | ||
| 1410 | 1410 | struct nvme_ns *ns = rq->q->queuedata; |
| 1411 | 1411 | struct bio *bio = rq->bio; |
| 1412 | 1412 | struct nvme_keyed_sgl_desc *sg = &c->common.dptr.ksgl; |
| 1413 | + struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); | |
| 1414 | + u32 xfer_len; | |
| 1413 | 1415 | int nr; |
| 1414 | 1416 | |
| 1415 | 1417 | req->mr = ib_mr_pool_get(queue->qp, &queue->qp->sig_mrs); |
| @@ -1422,8 +1424,7 @@ static int nvme_rdma_map_sg_pi(struct nvme_rdma_queue *queue, · 6 unmodified lines | ||
| 1422 | 1424 | if (unlikely(nr)) |
| 1423 | 1425 | goto mr_put; |
| 1424 | 1426 | |
| 1425 | − nvme_rdma_set_sig_attrs(blk_get_integrity(bio->bi_bdev->bd_disk), c, | |
| 1426 | − req->mr->sig_attrs, ns->head->pi_type); | |
| 1427 | + nvme_rdma_set_sig_attrs(bi, c, req->mr->sig_attrs, ns->head->pi_type); | |
| 1427 | 1428 | nvme_rdma_set_prot_checks(c, &req->mr->sig_attrs->check_mask); |
| 1428 | 1429 | |
| 1429 | 1430 | ib_update_fast_reg_key(req->mr, ib_inc_rkey(req->mr->rkey)); |
| @@ -1441,7 +1442,11 @@ static int nvme_rdma_map_sg_pi(struct nvme_rdma_queue *queue, · 11 unmodified lines | ||
| 1441 | 1442 | IB_ACCESS_REMOTE_WRITE; |
| 1442 | 1443 | |
| 1443 | 1444 | sg->addr = cpu_to_le64(req->mr->iova); |
| 1444 | − put_unaligned_le24(req->mr->length, sg->length); | |
| 1445 | + xfer_len = req->mr->length; | |
| 1446 | + /* Check if PI is added by the HW */ | |
| 1447 | + if (!pi_count) | |
| 1448 | + xfer_len += (xfer_len >> bi->interval_exp) * ns->head->pi_size; | |
| 1449 | + put_unaligned_le24(xfer_len, sg->length); | |
| 1445 | 1450 | put_unaligned_le32(req->mr->rkey, sg->key); |
| 1446 | 1451 | sg->type = NVME_KEY_SGL_FMT_DATA_DESC << 4; |
| 1447 | 1452 | |
| @@ -1946,14 +1951,13 @@ static enum blk_eh_timer_return nvme_rdma_timeout(struct request *rq) · 498 unmodified lines | ||
| 1946 | 1951 | struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq); |
| 1947 | 1952 | struct nvme_rdma_queue *queue = req->queue; |
| 1948 | 1953 | struct nvme_rdma_ctrl *ctrl = queue->ctrl; |
| 1949 | − u8 opcode = req->req.cmd->common.opcode; | |
| 1950 | − u8 fctype = req->req.cmd->fabrics.fctype; | |
| 1954 | + struct nvme_command *cmd = req->req.cmd; | |
| 1951 | 1955 | int qid = nvme_rdma_queue_idx(queue); |
| 1952 | 1956 | |
| 1953 | 1957 | dev_warn(ctrl->ctrl.device, |
| 1954 | 1958 | "I/O tag %d (%04x) opcode %#x (%s) QID %d timeout\n", |
| 1955 | − rq->tag, nvme_cid(rq), opcode, | |
| 1956 | − nvme_opcode_str(qid, opcode, fctype), qid); | |
| 1959 | + rq->tag, nvme_cid(rq), cmd->common.opcode, | |
| 1960 | + nvme_fabrics_opcode_str(qid, cmd), qid); | |
| 1957 | 1961 | |
| 1958 | 1962 | if (nvme_ctrl_state(&ctrl->ctrl) != NVME_CTRL_LIVE) { |
| 1959 | 1963 | /* |
| @@ -2296,8 +2300,8 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev, · 336 unmodified lines | ||
| 2296 | 2300 | if (ret) |
| 2297 | 2301 | goto out_uninit_ctrl; |
| 2298 | 2302 | |
| 2299 | − dev_info(ctrl->ctrl.device, "new ctrl: NQN \"%s\", addr %pISpcs\n", | |
| 2300 | − nvmf_ctrl_subsysnqn(&ctrl->ctrl), &ctrl->addr); | |
| 2303 | + dev_info(ctrl->ctrl.device, "new ctrl: NQN \"%s\", addr %pISpcs, hostnqn: %s\n", | |
| 2304 | + nvmf_ctrl_subsysnqn(&ctrl->ctrl), &ctrl->addr, opts->host->nqn); | |
| 2301 | 2305 | |
| 2302 | 2306 | mutex_lock(&nvme_rdma_ctrl_mutex); |
| 2303 | 2307 | list_add_tail(&ctrl->list, &nvme_rdma_ctrl_list); |
| @@ -2400,4 +2404,5 @@ static void __exit nvme_rdma_cleanup_module(void) · 96 unmodified lines | ||
| 2400 | 2404 | module_init(nvme_rdma_init_module); |
| 2401 | 2405 | module_exit(nvme_rdma_cleanup_module); |
| 2402 | 2406 | |
| 2407 | +MODULE_DESCRIPTION("NVMe host RDMA transport driver"); | |
| 2403 | 2408 | MODULE_LICENSE("GPL v2"); |
| @@ -35,6 +35,62 @@ static ssize_t nvme_sysfs_rescan(struct device *dev, · 34 unmodified lines | ||
| 35 | 35 | } |
| 36 | 36 | static DEVICE_ATTR(rescan_controller, S_IWUSR, NULL, nvme_sysfs_rescan); |
| 37 | 37 | |
| 38 | +static ssize_t nvme_adm_passthru_err_log_enabled_show(struct device *dev, | |
| 39 | + struct device_attribute *attr, char *buf) | |
| 40 | +{ | |
| 41 | + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); | |
| 42 | + | |
| 43 | + return sysfs_emit(buf, | |
| 44 | + ctrl->passthru_err_log_enabled ? "on\n" : "off\n"); | |
| 45 | +} | |
| 46 | + | |
| 47 | +static ssize_t nvme_adm_passthru_err_log_enabled_store(struct device *dev, | |
| 48 | + struct device_attribute *attr, const char *buf, size_t count) | |
| 49 | +{ | |
| 50 | + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); | |
| 51 | + int err; | |
| 52 | + bool passthru_err_log_enabled; | |
| 53 | + | |
| 54 | + err = kstrtobool(buf, &passthru_err_log_enabled); | |
| 55 | + if (err) | |
| 56 | + return -EINVAL; | |
| 57 | + | |
| 58 | + ctrl->passthru_err_log_enabled = passthru_err_log_enabled; | |
| 59 | + | |
| 60 | + return count; | |
| 61 | +} | |
| 62 | + | |
| 63 | +static ssize_t nvme_io_passthru_err_log_enabled_show(struct device *dev, | |
| 64 | + struct device_attribute *attr, char *buf) | |
| 65 | +{ | |
| 66 | + struct nvme_ns *n = dev_get_drvdata(dev); | |
| 67 | + | |
| 68 | + return sysfs_emit(buf, n->passthru_err_log_enabled ? "on\n" : "off\n"); | |
| 69 | +} | |
| 70 | + | |
| 71 | +static ssize_t nvme_io_passthru_err_log_enabled_store(struct device *dev, | |
| 72 | + struct device_attribute *attr, const char *buf, size_t count) | |
| 73 | +{ | |
| 74 | + struct nvme_ns *ns = dev_get_drvdata(dev); | |
| 75 | + int err; | |
| 76 | + bool passthru_err_log_enabled; | |
| 77 | + | |
| 78 | + err = kstrtobool(buf, &passthru_err_log_enabled); | |
| 79 | + if (err) | |
| 80 | + return -EINVAL; | |
| 81 | + ns->passthru_err_log_enabled = passthru_err_log_enabled; | |
| 82 | + | |
| 83 | + return count; | |
| 84 | +} | |
| 85 | + | |
| 86 | +static struct device_attribute dev_attr_adm_passthru_err_log_enabled = \ | |
| 87 | + __ATTR(passthru_err_log_enabled, S_IRUGO | S_IWUSR, \ | |
| 88 | + nvme_adm_passthru_err_log_enabled_show, nvme_adm_passthru_err_log_enabled_store); | |
| 89 | + | |
| 90 | +static struct device_attribute dev_attr_io_passthru_err_log_enabled = \ | |
| 91 | + __ATTR(passthru_err_log_enabled, S_IRUGO | S_IWUSR, \ | |
| 92 | + nvme_io_passthru_err_log_enabled_show, nvme_io_passthru_err_log_enabled_store); | |
| 93 | + | |
| 38 | 94 | static inline struct nvme_ns_head *dev_to_ns_head(struct device *dev) |
| 39 | 95 | { |
| 40 | 96 | struct gendisk *disk = dev_to_disk(dev); |
| @@ -208,6 +264,7 @@ static struct attribute *nvme_ns_attrs[] = { · 167 unmodified lines | ||
| 208 | 264 | &dev_attr_ana_grpid.attr, |
| 209 | 265 | &dev_attr_ana_state.attr, |
| 210 | 266 | #endif |
| 267 | + &dev_attr_io_passthru_err_log_enabled.attr, | |
| 211 | 268 | NULL, |
| 212 | 269 | }; |
| 213 | 270 | |
| @@ -311,6 +368,7 @@ static ssize_t nvme_sysfs_show_state(struct device *dev, · 97 unmodified lines | ||
| 311 | 368 | char *buf) |
| 312 | 369 | { |
| 313 | 370 | struct nvme_ctrl *ctrl = dev_get_drvdata(dev); |
| 371 | + unsigned state = (unsigned)nvme_ctrl_state(ctrl); | |
| 314 | 372 | static const char *const state_name[] = { |
| 315 | 373 | [NVME_CTRL_NEW] = "new", |
| 316 | 374 | [NVME_CTRL_LIVE] = "live", |
| @@ -321,9 +379,8 @@ static ssize_t nvme_sysfs_show_state(struct device *dev, · 4 unmodified lines | ||
| 321 | 379 | [NVME_CTRL_DEAD] = "dead", |
| 322 | 380 | }; |
| 323 | 381 | |
| 324 | − if ((unsigned)ctrl->state < ARRAY_SIZE(state_name) && | |
| 325 | − state_name[ctrl->state]) | |
| 326 | − return sysfs_emit(buf, "%s\n", state_name[ctrl->state]); | |
| 382 | + if (state < ARRAY_SIZE(state_name) && state_name[state]) | |
| 383 | + return sysfs_emit(buf, "%s\n", state_name[state]); | |
| 327 | 384 | |
| 328 | 385 | return sysfs_emit(buf, "unknown state\n"); |
| 329 | 386 | } |
| @@ -655,6 +712,7 @@ static struct attribute *nvme_dev_attrs[] = { · 325 unmodified lines | ||
| 655 | 712 | #ifdef CONFIG_NVME_TCP_TLS |
| 656 | 713 | &dev_attr_tls_key.attr, |
| 657 | 714 | #endif |
| 715 | + &dev_attr_adm_passthru_err_log_enabled.attr, | |
| 658 | 716 | NULL |
| 659 | 717 | }; |
| 660 | 718 | |
| @@ -2428,13 +2428,13 @@ static enum blk_eh_timer_return nvme_tcp_timeout(struct request *rq) · 2427 unmodified lines | ||
| 2428 | 2428 | struct nvme_tcp_request *req = blk_mq_rq_to_pdu(rq); |
| 2429 | 2429 | struct nvme_ctrl *ctrl = &req->queue->ctrl->ctrl; |
| 2430 | 2430 | struct nvme_tcp_cmd_pdu *pdu = nvme_tcp_req_cmd_pdu(req); |
| 2431 | − u8 opc = pdu->cmd.common.opcode, fctype = pdu->cmd.fabrics.fctype; | |
| 2431 | + struct nvme_command *cmd = &pdu->cmd; | |
| 2432 | 2432 | int qid = nvme_tcp_queue_id(req->queue); |
| 2433 | 2433 | |
| 2434 | 2434 | dev_warn(ctrl->device, |
| 2435 | 2435 | "I/O tag %d (%04x) type %d opcode %#x (%s) QID %d timeout\n", |
| 2436 | − rq->tag, nvme_cid(rq), pdu->hdr.type, opc, | |
| 2437 | − nvme_opcode_str(qid, opc, fctype), qid); | |
| 2436 | + rq->tag, nvme_cid(rq), pdu->hdr.type, cmd->common.opcode, | |
| 2437 | + nvme_fabrics_opcode_str(qid, cmd), qid); | |
| 2438 | 2438 | |
| 2439 | 2439 | if (nvme_ctrl_state(ctrl) != NVME_CTRL_LIVE) { |
| 2440 | 2440 | /* |
| @@ -2753,8 +2753,8 @@ static struct nvme_ctrl *nvme_tcp_create_ctrl(struct device *dev, · 312 unmodified lines | ||
| 2753 | 2753 | if (ret) |
| 2754 | 2754 | goto out_uninit_ctrl; |
| 2755 | 2755 | |
| 2756 | − dev_info(ctrl->ctrl.device, "new ctrl: NQN \"%s\", addr %pISp\n", | |
| 2757 | − nvmf_ctrl_subsysnqn(&ctrl->ctrl), &ctrl->addr); | |
| 2756 | + dev_info(ctrl->ctrl.device, "new ctrl: NQN \"%s\", addr %pISp, hostnqn: %s\n", | |
| 2757 | + nvmf_ctrl_subsysnqn(&ctrl->ctrl), &ctrl->addr, opts->host->nqn); | |
| 2758 | 2758 | |
| 2759 | 2759 | mutex_lock(&nvme_tcp_ctrl_mutex); |
| 2760 | 2760 | list_add_tail(&ctrl->list, &nvme_tcp_ctrl_list); |
| @@ -2826,4 +2826,5 @@ static void __exit nvme_tcp_cleanup_module(void) · 65 unmodified lines | ||
| 2826 | 2826 | module_init(nvme_tcp_init_module); |
| 2827 | 2827 | module_exit(nvme_tcp_cleanup_module); |
| 2828 | 2828 | |
| 2829 | +MODULE_DESCRIPTION("NVMe host TCP transport driver"); | |
| 2829 | 2830 | MODULE_LICENSE("GPL v2"); |
| @@ -248,7 +248,7 @@ void nvmet_ns_changed(struct nvmet_subsys *subsys, u32 nsid) · 247 unmodified lines | ||
| 248 | 248 | nvmet_add_to_changed_ns_log(ctrl, cpu_to_le32(nsid)); |
| 249 | 249 | if (nvmet_aen_bit_disabled(ctrl, NVME_AEN_BIT_NS_ATTR)) |
| 250 | 250 | continue; |
| 251 | − nvmet_add_async_event(ctrl, NVME_AER_TYPE_NOTICE, | |
| 251 | + nvmet_add_async_event(ctrl, NVME_AER_NOTICE, | |
| 252 | 252 | NVME_AER_NOTICE_NS_CHANGED, |
| 253 | 253 | NVME_LOG_CHANGED_NS); |
| 254 | 254 | } |
| @@ -265,7 +265,7 @@ void nvmet_send_ana_event(struct nvmet_subsys *subsys, · 10 unmodified lines | ||
| 265 | 265 | continue; |
| 266 | 266 | if (nvmet_aen_bit_disabled(ctrl, NVME_AEN_BIT_ANA_CHANGE)) |
| 267 | 267 | continue; |
| 268 | − nvmet_add_async_event(ctrl, NVME_AER_TYPE_NOTICE, | |
| 268 | + nvmet_add_async_event(ctrl, NVME_AER_NOTICE, | |
| 269 | 269 | NVME_AER_NOTICE_ANA, NVME_LOG_ANA); |
| 270 | 270 | } |
| 271 | 271 | mutex_unlock(&subsys->lock); |
| @@ -1705,4 +1705,5 @@ static void __exit nvmet_exit(void) · 1433 unmodified lines | ||
| 1705 | 1705 | module_init(nvmet_init); |
| 1706 | 1706 | module_exit(nvmet_exit); |
| 1707 | 1707 | |
| 1708 | +MODULE_DESCRIPTION("NVMe target core framework"); | |
| 1708 | 1709 | MODULE_LICENSE("GPL v2"); |
| @@ -21,7 +21,7 @@ static void __nvmet_disc_changed(struct nvmet_port *port, · 20 unmodified lines | ||
| 21 | 21 | if (nvmet_aen_bit_disabled(ctrl, NVME_AEN_BIT_DISC_CHANGE)) |
| 22 | 22 | return; |
| 23 | 23 | |
| 24 | − nvmet_add_async_event(ctrl, NVME_AER_TYPE_NOTICE, | |
| 24 | + nvmet_add_async_event(ctrl, NVME_AER_NOTICE, | |
| 25 | 25 | NVME_AER_NOTICE_DISC_CHANGED, NVME_LOG_DISC); |
| 26 | 26 | } |
| 27 | 27 | |
| @@ -111,6 +111,8 @@ struct nvmet_fc_tgtport { · 110 unmodified lines | ||
| 111 | 111 | struct nvmet_fc_port_entry *pe; |
| 112 | 112 | struct kref ref; |
| 113 | 113 | u32 max_sg_cnt; |
| 114 | + | |
| 115 | + struct work_struct put_work; | |
| 114 | 116 | }; |
| 115 | 117 | |
| 116 | 118 | struct nvmet_fc_port_entry { |
| @@ -145,7 +147,6 @@ struct nvmet_fc_tgt_queue { · 28 unmodified lines | ||
| 145 | 147 | struct list_head avail_defer_list; |
| 146 | 148 | struct workqueue_struct *work_q; |
| 147 | 149 | struct kref ref; |
| 148 | − struct rcu_head rcu; | |
| 149 | 150 | /* array of fcp_iods */ |
| 150 | 151 | struct nvmet_fc_fcp_iod fod[] __counted_by(sqsize); |
| 151 | 152 | } __aligned(sizeof(unsigned long long)); |
| @@ -166,10 +167,9 @@ struct nvmet_fc_tgt_assoc { · 14 unmodified lines | ||
| 166 | 167 | struct nvmet_fc_hostport *hostport; |
| 167 | 168 | struct nvmet_fc_ls_iod *rcv_disconn; |
| 168 | 169 | struct list_head a_list; |
| 169 | − struct nvmet_fc_tgt_queue __rcu *queues[NVMET_NR_QUEUES + 1]; | |
| 170 | + struct nvmet_fc_tgt_queue *queues[NVMET_NR_QUEUES + 1]; | |
| 170 | 171 | struct kref ref; |
| 171 | 172 | struct work_struct del_work; |
| 172 | − struct rcu_head rcu; | |
| 173 | 173 | }; |
| 174 | 174 | |
| 175 | 175 | |
| @@ -249,6 +249,13 @@ static int nvmet_fc_tgt_a_get(struct nvmet_fc_tgt_assoc *assoc); · 73 unmodified lines | ||
| 249 | 249 | static void nvmet_fc_tgt_q_put(struct nvmet_fc_tgt_queue *queue); |
| 250 | 250 | static int nvmet_fc_tgt_q_get(struct nvmet_fc_tgt_queue *queue); |
| 251 | 251 | static void nvmet_fc_tgtport_put(struct nvmet_fc_tgtport *tgtport); |
| 252 | +static void nvmet_fc_put_tgtport_work(struct work_struct *work) | |
| 253 | +{ | |
| 254 | + struct nvmet_fc_tgtport *tgtport = | |
| 255 | + container_of(work, struct nvmet_fc_tgtport, put_work); | |
| 256 | + | |
| 257 | + nvmet_fc_tgtport_put(tgtport); | |
| 258 | +} | |
| 252 | 259 | static int nvmet_fc_tgtport_get(struct nvmet_fc_tgtport *tgtport); |
| 253 | 260 | static void nvmet_fc_handle_fcp_rqst(struct nvmet_fc_tgtport *tgtport, |
| 254 | 261 | struct nvmet_fc_fcp_iod *fod); |
| @@ -360,7 +367,7 @@ __nvmet_fc_finish_ls_req(struct nvmet_fc_ls_req_op *lsop) · 105 unmodified lines | ||
| 360 | 367 | |
| 361 | 368 | if (!lsop->req_queued) { |
| 362 | 369 | spin_unlock_irqrestore(&tgtport->lock, flags); |
| 363 | − return; | |
| 370 | + goto out_putwork; | |
| 364 | 371 | } |
| 365 | 372 | |
| 366 | 373 | list_del(&lsop->lsreq_list); |
| @@ -373,7 +380,8 @@ __nvmet_fc_finish_ls_req(struct nvmet_fc_ls_req_op *lsop) · 6 unmodified lines | ||
| 373 | 380 | (lsreq->rqstlen + lsreq->rsplen), |
| 374 | 381 | DMA_BIDIRECTIONAL); |
| 375 | 382 | |
| 376 | − nvmet_fc_tgtport_put(tgtport); | |
| 383 | +out_putwork: | |
| 384 | + queue_work(nvmet_wq, &tgtport->put_work); | |
| 377 | 385 | } |
| 378 | 386 | |
| 379 | 387 | static int |
| @@ -489,8 +497,7 @@ nvmet_fc_xmt_disconnect_assoc(struct nvmet_fc_tgt_assoc *assoc) · 109 unmodified lines | ||
| 489 | 497 | * message is normal. Otherwise, send unless the hostport has |
| 490 | 498 | * already been invalidated by the lldd. |
| 491 | 499 | */ |
| 492 | − if (!tgtport->ops->ls_req || !assoc->hostport || | |
| 493 | − assoc->hostport->invalid) | |
| 500 | + if (!tgtport->ops->ls_req || assoc->hostport->invalid) | |
| 494 | 501 | return; |
| 495 | 502 | |
| 496 | 503 | lsop = kzalloc((sizeof(*lsop) + |
| @@ -802,14 +809,11 @@ nvmet_fc_alloc_target_queue(struct nvmet_fc_tgt_assoc *assoc, · 305 unmodified lines | ||
| 802 | 809 | if (!queue) |
| 803 | 810 | return NULL; |
| 804 | 811 | |
| 805 | − if (!nvmet_fc_tgt_a_get(assoc)) | |
| 806 | − goto out_free_queue; | |
| 807 | − | |
| 808 | 812 | queue->work_q = alloc_workqueue("ntfc%d.%d.%d", 0, 0, |
| 809 | 813 | assoc->tgtport->fc_target_port.port_num, |
| 810 | 814 | assoc->a_id, qid); |
| 811 | 815 | if (!queue->work_q) |
| 812 | − goto out_a_put; | |
| 816 | + goto out_free_queue; | |
| 813 | 817 | |
| 814 | 818 | queue->qid = qid; |
| 815 | 819 | queue->sqsize = sqsize; |
| @@ -831,15 +835,13 @@ nvmet_fc_alloc_target_queue(struct nvmet_fc_tgt_assoc *assoc, · 15 unmodified lines | ||
| 831 | 835 | goto out_fail_iodlist; |
| 832 | 836 | |
| 833 | 837 | WARN_ON(assoc->queues[qid]); |
| 834 | − rcu_assign_pointer(assoc->queues[qid], queue); | |
| 838 | + assoc->queues[qid] = queue; | |
| 835 | 839 | |
| 836 | 840 | return queue; |
| 837 | 841 | |
| 838 | 842 | out_fail_iodlist: |
| 839 | 843 | nvmet_fc_destroy_fcp_iodlist(assoc->tgtport, queue); |
| 840 | 844 | destroy_workqueue(queue->work_q); |
| 841 | −out_a_put: | |
| 842 | − nvmet_fc_tgt_a_put(assoc); | |
| 843 | 845 | out_free_queue: |
| 844 | 846 | kfree(queue); |
| 845 | 847 | return NULL; |
| @@ -852,15 +854,11 @@ nvmet_fc_tgt_queue_free(struct kref *ref) · 6 unmodified lines | ||
| 852 | 854 | struct nvmet_fc_tgt_queue *queue = |
| 853 | 855 | container_of(ref, struct nvmet_fc_tgt_queue, ref); |
| 854 | 856 | |
| 855 | − rcu_assign_pointer(queue->assoc->queues[queue->qid], NULL); | |
| 856 | − | |
| 857 | 857 | nvmet_fc_destroy_fcp_iodlist(queue->assoc->tgtport, queue); |
| 858 | 858 | |
| 859 | − nvmet_fc_tgt_a_put(queue->assoc); | |
| 860 | − | |
| 861 | 859 | destroy_workqueue(queue->work_q); |
| 862 | 860 | |
| 863 | − kfree_rcu(queue, rcu); | |
| 861 | + kfree(queue); | |
| 864 | 862 | } |
| 865 | 863 | |
| 866 | 864 | static void |
| @@ -969,7 +967,7 @@ nvmet_fc_find_target_queue(struct nvmet_fc_tgtport *tgtport, · 102 unmodified lines | ||
| 969 | 967 | rcu_read_lock(); |
| 970 | 968 | list_for_each_entry_rcu(assoc, &tgtport->assoc_list, a_list) { |
| 971 | 969 | if (association_id == assoc->association_id) { |
| 972 | − queue = rcu_dereference(assoc->queues[qid]); | |
| 970 | + queue = assoc->queues[qid]; | |
| 973 | 971 | if (queue && |
| 974 | 972 | (!atomic_read(&queue->connected) || |
| 975 | 973 | !nvmet_fc_tgt_q_get(queue))) |
| @@ -1078,8 +1076,6 @@ nvmet_fc_alloc_hostport(struct nvmet_fc_tgtport *tgtport, void *hosthandle) · 102 unmodified lines | ||
| 1078 | 1076 | /* new allocation not needed */ |
| 1079 | 1077 | kfree(newhost); |
| 1080 | 1078 | newhost = match; |
| 1081 | − /* no new allocation - release reference */ | |
| 1082 | − nvmet_fc_tgtport_put(tgtport); | |
| 1083 | 1079 | } else { |
| 1084 | 1080 | newhost->tgtport = tgtport; |
| 1085 | 1081 | newhost->hosthandle = hosthandle; |
| @@ -1094,23 +1090,54 @@ nvmet_fc_alloc_hostport(struct nvmet_fc_tgtport *tgtport, void *hosthandle) · 8 unmodified lines | ||
| 1094 | 1090 | } |
| 1095 | 1091 | |
| 1096 | 1092 | static void |
| 1097 | −nvmet_fc_delete_assoc(struct work_struct *work) | |
| 1093 | +nvmet_fc_delete_assoc(struct nvmet_fc_tgt_assoc *assoc) | |
| 1094 | +{ | |
| 1095 | + nvmet_fc_delete_target_assoc(assoc); | |
| 1096 | + nvmet_fc_tgt_a_put(assoc); | |
| 1097 | +} | |
| 1098 | + | |
| 1099 | +static void | |
| 1100 | +nvmet_fc_delete_assoc_work(struct work_struct *work) | |
| 1098 | 1101 | { |
| 1099 | 1102 | struct nvmet_fc_tgt_assoc *assoc = |
| 1100 | 1103 | container_of(work, struct nvmet_fc_tgt_assoc, del_work); |
| 1104 | + struct nvmet_fc_tgtport *tgtport = assoc->tgtport; | |
| 1101 | 1105 | |
| 1102 | − nvmet_fc_delete_target_assoc(assoc); | |
| 1103 | − nvmet_fc_tgt_a_put(assoc); | |
| 1106 | + nvmet_fc_delete_assoc(assoc); | |
| 1107 | + nvmet_fc_tgtport_put(tgtport); | |
| 1108 | +} | |
| 1109 | + | |
| 1110 | +static void | |
| 1111 | +nvmet_fc_schedule_delete_assoc(struct nvmet_fc_tgt_assoc *assoc) | |
| 1112 | +{ | |
| 1113 | + nvmet_fc_tgtport_get(assoc->tgtport); | |
| 1114 | + queue_work(nvmet_wq, &assoc->del_work); | |
| 1115 | +} | |
| 1116 | + | |
| 1117 | +static bool | |
| 1118 | +nvmet_fc_assoc_exits(struct nvmet_fc_tgtport *tgtport, u64 association_id) | |
| 1119 | +{ | |
| 1120 | + struct nvmet_fc_tgt_assoc *a; | |
| 1121 | + | |
| 1122 | + list_for_each_entry_rcu(a, &tgtport->assoc_list, a_list) { | |
| 1123 | + if (association_id == a->association_id) | |
| 1124 | + return true; | |
| 1125 | + } | |
| 1126 | + | |
| 1127 | + return false; | |
| 1104 | 1128 | } |
| 1105 | 1129 | |
| 1106 | 1130 | static struct nvmet_fc_tgt_assoc * |
| 1107 | 1131 | nvmet_fc_alloc_target_assoc(struct nvmet_fc_tgtport *tgtport, void *hosthandle) |
| 1108 | 1132 | { |
| 1109 | − struct nvmet_fc_tgt_assoc *assoc, *tmpassoc; | |
| 1133 | + struct nvmet_fc_tgt_assoc *assoc; | |
| 1110 | 1134 | unsigned long flags; |
| 1135 | + bool done; | |
| 1111 | 1136 | u64 ran; |
| 1112 | 1137 | int idx; |
| 1113 | − bool needrandom = true; | |
| 1138 | + | |
| 1139 | + if (!tgtport->pe) | |
| 1140 | + return NULL; | |
| 1114 | 1141 | |
| 1115 | 1142 | assoc = kzalloc(sizeof(*assoc), GFP_KERNEL); |
| 1116 | 1143 | if (!assoc) |
| @@ -1120,43 +1147,35 @@ nvmet_fc_alloc_target_assoc(struct nvmet_fc_tgtport *tgtport, void *hosthandle) · 3 unmodified lines | ||
| 1120 | 1147 | if (idx < 0) |
| 1121 | 1148 | goto out_free_assoc; |
| 1122 | 1149 | |
| 1123 | − if (!nvmet_fc_tgtport_get(tgtport)) | |
| 1124 | − goto out_ida; | |
| 1125 | − | |
| 1126 | 1150 | assoc->hostport = nvmet_fc_alloc_hostport(tgtport, hosthandle); |
| 1127 | 1151 | if (IS_ERR(assoc->hostport)) |
| 1128 | − goto out_put; | |
| 1152 | + goto out_ida; | |
| 1129 | 1153 | |
| 1130 | 1154 | assoc->tgtport = tgtport; |
| 1131 | 1155 | assoc->a_id = idx; |
| 1132 | 1156 | INIT_LIST_HEAD(&assoc->a_list); |
| 1133 | 1157 | kref_init(&assoc->ref); |
| 1134 | − INIT_WORK(&assoc->del_work, nvmet_fc_delete_assoc); | |
| 1158 | + INIT_WORK(&assoc->del_work, nvmet_fc_delete_assoc_work); | |
| 1135 | 1159 | atomic_set(&assoc->terminating, 0); |
| 1136 | 1160 | |
| 1137 | − while (needrandom) { | |
| 1161 | + done = false; | |
| 1162 | + do { | |
| 1138 | 1163 | get_random_bytes(&ran, sizeof(ran) - BYTES_FOR_QID); |
| 1139 | 1164 | ran = ran << BYTES_FOR_QID_SHIFT; |
| 1140 | 1165 | |
| 1141 | 1166 | spin_lock_irqsave(&tgtport->lock, flags); |
| 1142 | − needrandom = false; | |
| 1143 | − list_for_each_entry(tmpassoc, &tgtport->assoc_list, a_list) { | |
| 1144 | − if (ran == tmpassoc->association_id) { | |
| 1145 | − needrandom = true; | |
| 1146 | − break; | |
| 1147 | − } | |
| 1148 | − } | |
| 1149 | − if (!needrandom) { | |
| 1167 | + rcu_read_lock(); | |
| 1168 | + if (!nvmet_fc_assoc_exits(tgtport, ran)) { | |
| 1150 | 1169 | assoc->association_id = ran; |
| 1151 | 1170 | list_add_tail_rcu(&assoc->a_list, &tgtport->assoc_list); |
| 1171 | + done = true; | |
| 1152 | 1172 | } |
| 1173 | + rcu_read_unlock(); | |
| 1153 | 1174 | spin_unlock_irqrestore(&tgtport->lock, flags); |
| 1154 | − } | |
| 1175 | + } while (!done); | |
| 1155 | 1176 | |
| 1156 | 1177 | return assoc; |
| 1157 | 1178 | |
| 1158 | −out_put: | |
| 1159 | − nvmet_fc_tgtport_put(tgtport); | |
| 1160 | 1179 | out_ida: |
| 1161 | 1180 | ida_free(&tgtport->assoc_cnt, idx); |
| 1162 | 1181 | out_free_assoc: |
| @@ -1172,13 +1191,18 @@ nvmet_fc_target_assoc_free(struct kref *ref) · 9 unmodified lines | ||
| 1172 | 1191 | struct nvmet_fc_tgtport *tgtport = assoc->tgtport; |
| 1173 | 1192 | struct nvmet_fc_ls_iod *oldls; |
| 1174 | 1193 | unsigned long flags; |
| 1194 | + int i; | |
| 1195 | + | |
| 1196 | + for (i = NVMET_NR_QUEUES; i >= 0; i--) { | |
| 1197 | + if (assoc->queues[i]) | |
| 1198 | + nvmet_fc_delete_target_queue(assoc->queues[i]); | |
| 1199 | + } | |
| 1175 | 1200 | |
| 1176 | 1201 | /* Send Disconnect now that all i/o has completed */ |
| 1177 | 1202 | nvmet_fc_xmt_disconnect_assoc(assoc); |
| 1178 | 1203 | |
| 1179 | 1204 | nvmet_fc_free_hostport(assoc->hostport); |
| 1180 | 1205 | spin_lock_irqsave(&tgtport->lock, flags); |
| 1181 | − list_del_rcu(&assoc->a_list); | |
| 1182 | 1206 | oldls = assoc->rcv_disconn; |
| 1183 | 1207 | spin_unlock_irqrestore(&tgtport->lock, flags); |
| 1184 | 1208 | /* if pending Rcv Disconnect Association LS, send rsp now */ |
| @@ -1188,8 +1212,7 @@ nvmet_fc_target_assoc_free(struct kref *ref) · 3 unmodified lines | ||
| 1188 | 1212 | dev_info(tgtport->dev, |
| 1189 | 1213 | "{%d:%d} Association freed\n", |
| 1190 | 1214 | tgtport->fc_target_port.port_num, assoc->a_id); |
| 1191 | − kfree_rcu(assoc, rcu); | |
| 1192 | − nvmet_fc_tgtport_put(tgtport); | |
| 1215 | + kfree(assoc); | |
| 1193 | 1216 | } |
| 1194 | 1217 | |
| 1195 | 1218 | static void |
| @@ -1208,7 +1231,7 @@ static void · 12 unmodified lines | ||
| 1208 | 1231 | nvmet_fc_delete_target_assoc(struct nvmet_fc_tgt_assoc *assoc) |
| 1209 | 1232 | { |
| 1210 | 1233 | struct nvmet_fc_tgtport *tgtport = assoc->tgtport; |
| 1211 | − struct nvmet_fc_tgt_queue *queue; | |
| 1234 | + unsigned long flags; | |
| 1212 | 1235 | int i, terminating; |
| 1213 | 1236 | |
| 1214 | 1237 | terminating = atomic_xchg(&assoc->terminating, 1); |
| @@ -1217,29 +1240,21 @@ nvmet_fc_delete_target_assoc(struct nvmet_fc_tgt_assoc *assoc) · 2 unmodified lines | ||
| 1217 | 1240 | if (terminating) |
| 1218 | 1241 | return; |
| 1219 | 1242 | |
| 1243 | + spin_lock_irqsave(&tgtport->lock, flags); | |
| 1244 | + list_del_rcu(&assoc->a_list); | |
| 1245 | + spin_unlock_irqrestore(&tgtport->lock, flags); | |
| 1220 | 1246 | |
| 1221 | − for (i = NVMET_NR_QUEUES; i >= 0; i--) { | |
| 1222 | − rcu_read_lock(); | |
| 1223 | − queue = rcu_dereference(assoc->queues[i]); | |
| 1224 | − if (!queue) { | |
| 1225 | − rcu_read_unlock(); | |
| 1226 | − continue; | |
| 1227 | − } | |
| 1247 | + synchronize_rcu(); | |
| 1228 | 1248 | |
| 1229 | − if (!nvmet_fc_tgt_q_get(queue)) { | |
| 1230 | − rcu_read_unlock(); | |
| 1231 | − continue; | |
| 1232 | − } | |
| 1233 | − rcu_read_unlock(); | |
| 1234 | − nvmet_fc_delete_target_queue(queue); | |
| 1235 | − nvmet_fc_tgt_q_put(queue); | |
| 1249 | + /* ensure all in-flight I/Os have been processed */ | |
| 1250 | + for (i = NVMET_NR_QUEUES; i >= 0; i--) { | |
| 1251 | + if (assoc->queues[i]) | |
| 1252 | + flush_workqueue(assoc->queues[i]->work_q); | |
| 1236 | 1253 | } |
| 1237 | 1254 | |
| 1238 | 1255 | dev_info(tgtport->dev, |
| 1239 | 1256 | "{%d:%d} Association deleted\n", |
| 1240 | 1257 | tgtport->fc_target_port.port_num, assoc->a_id); |
| 1241 | − | |
| 1242 | − nvmet_fc_tgt_a_put(assoc); | |
| 1243 | 1258 | } |
| 1244 | 1259 | |
| 1245 | 1260 | static struct nvmet_fc_tgt_assoc * |
| @@ -1415,6 +1430,7 @@ nvmet_fc_register_targetport(struct nvmet_fc_port_info *pinfo, · 169 unmodified lines | ||
| 1415 | 1430 | kref_init(&newrec->ref); |
| 1416 | 1431 | ida_init(&newrec->assoc_cnt); |
| 1417 | 1432 | newrec->max_sg_cnt = template->max_sgl_segments; |
| 1433 | + INIT_WORK(&newrec->put_work, nvmet_fc_put_tgtport_work); | |
| 1418 | 1434 | |
| 1419 | 1435 | ret = nvmet_fc_alloc_ls_iodlist(newrec); |
| 1420 | 1436 | if (ret) { |
| @@ -1492,9 +1508,8 @@ __nvmet_fc_free_assocs(struct nvmet_fc_tgtport *tgtport) · 71 unmodified lines | ||
| 1492 | 1508 | list_for_each_entry_rcu(assoc, &tgtport->assoc_list, a_list) { |
| 1493 | 1509 | if (!nvmet_fc_tgt_a_get(assoc)) |
| 1494 | 1510 | continue; |
| 1495 | − if (!queue_work(nvmet_wq, &assoc->del_work)) | |
| 1496 | − /* already deleting - release local reference */ | |
| 1497 | − nvmet_fc_tgt_a_put(assoc); | |
| 1511 | + nvmet_fc_schedule_delete_assoc(assoc); | |
| 1512 | + nvmet_fc_tgt_a_put(assoc); | |
| 1498 | 1513 | } |
| 1499 | 1514 | rcu_read_unlock(); |
| 1500 | 1515 | } |
| @@ -1540,16 +1555,14 @@ nvmet_fc_invalidate_host(struct nvmet_fc_target_port *target_port, · 39 unmodified lines | ||
| 1540 | 1555 | spin_lock_irqsave(&tgtport->lock, flags); |
| 1541 | 1556 | list_for_each_entry_safe(assoc, next, |
| 1542 | 1557 | &tgtport->assoc_list, a_list) { |
| 1543 | − if (!assoc->hostport || | |
| 1544 | − assoc->hostport->hosthandle != hosthandle) | |
| 1558 | + if (assoc->hostport->hosthandle != hosthandle) | |
| 1545 | 1559 | continue; |
| 1546 | 1560 | if (!nvmet_fc_tgt_a_get(assoc)) |
| 1547 | 1561 | continue; |
| 1548 | 1562 | assoc->hostport->invalid = 1; |
| 1549 | 1563 | noassoc = false; |
| 1550 | − if (!queue_work(nvmet_wq, &assoc->del_work)) | |
| 1551 | − /* already deleting - release local reference */ | |
| 1552 | − nvmet_fc_tgt_a_put(assoc); | |
| 1564 | + nvmet_fc_schedule_delete_assoc(assoc); | |
| 1565 | + nvmet_fc_tgt_a_put(assoc); | |
| 1553 | 1566 | } |
| 1554 | 1567 | spin_unlock_irqrestore(&tgtport->lock, flags); |
| 1555 | 1568 | |
| @@ -1581,7 +1594,7 @@ nvmet_fc_delete_ctrl(struct nvmet_ctrl *ctrl) · 25 unmodified lines | ||
| 1581 | 1594 | |
| 1582 | 1595 | rcu_read_lock(); |
| 1583 | 1596 | list_for_each_entry_rcu(assoc, &tgtport->assoc_list, a_list) { |
| 1584 | − queue = rcu_dereference(assoc->queues[0]); | |
| 1597 | + queue = assoc->queues[0]; | |
| 1585 | 1598 | if (queue && queue->nvme_sq.ctrl == ctrl) { |
| 1586 | 1599 | if (nvmet_fc_tgt_a_get(assoc)) |
| 1587 | 1600 | found_ctrl = true; |
| @@ -1593,9 +1606,8 @@ nvmet_fc_delete_ctrl(struct nvmet_ctrl *ctrl) · 5 unmodified lines | ||
| 1593 | 1606 | nvmet_fc_tgtport_put(tgtport); |
| 1594 | 1607 | |
| 1595 | 1608 | if (found_ctrl) { |
| 1596 | − if (!queue_work(nvmet_wq, &assoc->del_work)) | |
| 1597 | − /* already deleting - release local reference */ | |
| 1598 | − nvmet_fc_tgt_a_put(assoc); | |
| 1609 | + nvmet_fc_schedule_delete_assoc(assoc); | |
| 1610 | + nvmet_fc_tgt_a_put(assoc); | |
| 1599 | 1611 | return; |
| 1600 | 1612 | } |
| 1601 | 1613 | |
| @@ -1625,6 +1637,8 @@ nvmet_fc_unregister_targetport(struct nvmet_fc_target_port *target_port) · 23 unmodified lines | ||
| 1625 | 1637 | /* terminate any outstanding associations */ |
| 1626 | 1638 | __nvmet_fc_free_assocs(tgtport); |
| 1627 | 1639 | |
| 1640 | + flush_workqueue(nvmet_wq); | |
| 1641 | + | |
| 1628 | 1642 | /* |
| 1629 | 1643 | * should terminate LS's as well. However, LS's will be generated |
| 1630 | 1644 | * at the tail end of association termination, so they likely don't |
| @@ -1870,9 +1884,6 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport, · 239 unmodified lines | ||
| 1870 | 1884 | sizeof(struct fcnvme_ls_disconnect_assoc_acc)), |
| 1871 | 1885 | FCNVME_LS_DISCONNECT_ASSOC); |
| 1872 | 1886 | |
| 1873 | − /* release get taken in nvmet_fc_find_target_assoc */ | |
| 1874 | − nvmet_fc_tgt_a_put(assoc); | |
| 1875 | − | |
| 1876 | 1887 | /* |
| 1877 | 1888 | * The rules for LS response says the response cannot |
| 1878 | 1889 | * go back until ABTS's have been sent for all outstanding |
| @@ -1887,8 +1898,6 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport, · 8 unmodified lines | ||
| 1887 | 1898 | assoc->rcv_disconn = iod; |
| 1888 | 1899 | spin_unlock_irqrestore(&tgtport->lock, flags); |
| 1889 | 1900 | |
| 1890 | − nvmet_fc_delete_target_assoc(assoc); | |
| 1891 | − | |
| 1892 | 1901 | if (oldls) { |
| 1893 | 1902 | dev_info(tgtport->dev, |
| 1894 | 1903 | "{%d:%d} Multiple Disconnect Association LS's " |
| @@ -1904,6 +1913,9 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport, · 9 unmodified lines | ||
| 1904 | 1913 | nvmet_fc_xmt_ls_rsp(tgtport, oldls); |
| 1905 | 1914 | } |
| 1906 | 1915 | |
| 1916 | + nvmet_fc_schedule_delete_assoc(assoc); | |
| 1917 | + nvmet_fc_tgt_a_put(assoc); | |
| 1918 | + | |
| 1907 | 1919 | return false; |
| 1908 | 1920 | } |
| 1909 | 1921 | |
| @@ -2540,8 +2552,9 @@ nvmet_fc_handle_fcp_rqst(struct nvmet_fc_tgtport *tgtport, · 630 unmodified lines | ||
| 2540 | 2552 | |
| 2541 | 2553 | fod->req.cmd = &fod->cmdiubuf.sqe; |
| 2542 | 2554 | fod->req.cqe = &fod->rspiubuf.cqe; |
| 2543 | − if (tgtport->pe) | |
| 2544 | − fod->req.port = tgtport->pe->port; | |
| 2555 | + if (!tgtport->pe) | |
| 2556 | + goto transport_error; | |
| 2557 | + fod->req.port = tgtport->pe->port; | |
| 2545 | 2558 | |
| 2546 | 2559 | /* clear any response payload */ |
| 2547 | 2560 | memset(&fod->rspiubuf, 0, sizeof(fod->rspiubuf)); |
| @@ -2902,6 +2915,9 @@ nvmet_fc_remove_port(struct nvmet_port *port) · 354 unmodified lines | ||
| 2902 | 2915 | |
| 2903 | 2916 | nvmet_fc_portentry_unbind(pe); |
| 2904 | 2917 | |
| 2918 | + /* terminate any outstanding associations */ | |
| 2919 | + __nvmet_fc_free_assocs(pe->tgtport); | |
| 2920 | + | |
| 2905 | 2921 | kfree(pe); |
| 2906 | 2922 | } |
| 2907 | 2923 | |
| @@ -2933,6 +2949,9 @@ static int __init nvmet_fc_init_module(void) · 25 unmodified lines | ||
| 2933 | 2949 | |
| 2934 | 2950 | static void __exit nvmet_fc_exit_module(void) |
| 2935 | 2951 | { |
| 2952 | + /* ensure any shutdown operation, e.g. delete ctrls have finished */ | |
| 2953 | + flush_workqueue(nvmet_wq); | |
| 2954 | + | |
| 2936 | 2955 | /* sanity check - all lports should be removed */ |
| 2937 | 2956 | if (!list_empty(&nvmet_fc_target_list)) |
| 2938 | 2957 | pr_warn("%s: targetport list not empty\n", __func__); |
| @@ -2945,4 +2964,5 @@ static void __exit nvmet_fc_exit_module(void) · 6 unmodified lines | ||
| 2945 | 2964 | module_init(nvmet_fc_init_module); |
| 2946 | 2965 | module_exit(nvmet_fc_exit_module); |
| 2947 | 2966 | |
| 2967 | +MODULE_DESCRIPTION("NVMe target FC transport driver"); | |
| 2948 | 2968 | MODULE_LICENSE("GPL v2"); |
| @@ -358,7 +358,7 @@ fcloop_h2t_ls_req(struct nvme_fc_local_port *localport, · 357 unmodified lines | ||
| 358 | 358 | if (!rport->targetport) { |
| 359 | 359 | tls_req->status = -ECONNREFUSED; |
| 360 | 360 | spin_lock(&rport->lock); |
| 361 | − list_add_tail(&rport->ls_list, &tls_req->ls_list); | |
| 361 | + list_add_tail(&tls_req->ls_list, &rport->ls_list); | |
| 362 | 362 | spin_unlock(&rport->lock); |
| 363 | 363 | queue_work(nvmet_wq, &rport->ls_work); |
| 364 | 364 | return ret; |
| @@ -391,7 +391,7 @@ fcloop_h2t_xmt_ls_rsp(struct nvmet_fc_target_port *targetport, · 26 unmodified lines | ||
| 391 | 391 | if (remoteport) { |
| 392 | 392 | rport = remoteport->private; |
| 393 | 393 | spin_lock(&rport->lock); |
| 394 | − list_add_tail(&rport->ls_list, &tls_req->ls_list); | |
| 394 | + list_add_tail(&tls_req->ls_list, &rport->ls_list); | |
| 395 | 395 | spin_unlock(&rport->lock); |
| 396 | 396 | queue_work(nvmet_wq, &rport->ls_work); |
| 397 | 397 | } |
| @@ -446,7 +446,7 @@ fcloop_t2h_ls_req(struct nvmet_fc_target_port *targetport, void *hosthandle, · 48 unmodified lines | ||
| 446 | 446 | if (!tport->remoteport) { |
| 447 | 447 | tls_req->status = -ECONNREFUSED; |
| 448 | 448 | spin_lock(&tport->lock); |
| 449 | − list_add_tail(&tport->ls_list, &tls_req->ls_list); | |
| 449 | + list_add_tail(&tls_req->ls_list, &tport->ls_list); | |
| 450 | 450 | spin_unlock(&tport->lock); |
| 451 | 451 | queue_work(nvmet_wq, &tport->ls_work); |
| 452 | 452 | return ret; |
| @@ -1650,4 +1650,5 @@ static void __exit fcloop_exit(void) · 1197 unmodified lines | ||
| 1650 | 1650 | module_init(fcloop_init); |
| 1651 | 1651 | module_exit(fcloop_exit); |
| 1652 | 1652 | |
| 1653 | +MODULE_DESCRIPTION("NVMe target FC loop transport driver"); | |
| 1653 | 1654 | MODULE_LICENSE("GPL v2"); |
| @@ -400,7 +400,7 @@ static void nvme_loop_shutdown_ctrl(struct nvme_loop_ctrl *ctrl) · 399 unmodified lines | ||
| 400 | 400 | } |
| 401 | 401 | |
| 402 | 402 | nvme_quiesce_admin_queue(&ctrl->ctrl); |
| 403 | − if (ctrl->ctrl.state == NVME_CTRL_LIVE) | |
| 403 | + if (nvme_ctrl_state(&ctrl->ctrl) == NVME_CTRL_LIVE) | |
| 404 | 404 | nvme_disable_ctrl(&ctrl->ctrl, true); |
| 405 | 405 | |
| 406 | 406 | nvme_cancel_admin_tagset(&ctrl->ctrl); |
| @@ -434,8 +434,10 @@ static void nvme_loop_reset_ctrl_work(struct work_struct *work) · 27 unmodified lines | ||
| 434 | 434 | nvme_loop_shutdown_ctrl(ctrl); |
| 435 | 435 | |
| 436 | 436 | if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING)) { |
| 437 | − if (ctrl->ctrl.state != NVME_CTRL_DELETING && | |
| 438 | − ctrl->ctrl.state != NVME_CTRL_DELETING_NOIO) | |
| 437 | + enum nvme_ctrl_state state = nvme_ctrl_state(&ctrl->ctrl); | |
| 438 | + | |
| 439 | + if (state != NVME_CTRL_DELETING && | |
| 440 | + state != NVME_CTRL_DELETING_NOIO) | |
| 439 | 441 | /* state change failure for non-deleted ctrl? */ |
| 440 | 442 | WARN_ON_ONCE(1); |
| 441 | 443 | return; |
| @@ -688,5 +690,6 @@ static void __exit nvme_loop_cleanup_module(void) · 246 unmodified lines | ||
| 688 | 690 | module_init(nvme_loop_init_module); |
| 689 | 691 | module_exit(nvme_loop_cleanup_module); |
| 690 | 692 | |
| 693 | +MODULE_DESCRIPTION("NVMe target loop transport driver"); | |
| 691 | 694 | MODULE_LICENSE("GPL v2"); |
| 692 | 695 | MODULE_ALIAS("nvmet-transport-254"); /* 254 == NVMF_TRTYPE_LOOP */ |
| @@ -2104,5 +2104,6 @@ static void __exit nvmet_rdma_exit(void) · 2103 unmodified lines | ||
| 2104 | 2104 | module_init(nvmet_rdma_init); |
| 2105 | 2105 | module_exit(nvmet_rdma_exit); |
| 2106 | 2106 | |
| 2107 | +MODULE_DESCRIPTION("NVMe target RDMA transport driver"); | |
| 2107 | 2108 | MODULE_LICENSE("GPL v2"); |
| 2108 | 2109 | MODULE_ALIAS("nvmet-transport-1"); /* 1 == NVMF_TRTYPE_RDMA */ |
| @@ -2216,10 +2216,12 @@ static void __exit nvmet_tcp_exit(void) · 2215 unmodified lines | ||
| 2216 | 2216 | flush_workqueue(nvmet_wq); |
| 2217 | 2217 | |
| 2218 | 2218 | destroy_workqueue(nvmet_tcp_wq); |
| 2219 | + ida_destroy(&nvmet_tcp_queue_ida); | |
| 2219 | 2220 | } |
| 2220 | 2221 | |
| 2221 | 2222 | module_init(nvmet_tcp_init); |
| 2222 | 2223 | module_exit(nvmet_tcp_exit); |
| 2223 | 2224 | |
| 2225 | +MODULE_DESCRIPTION("NVMe target TCP transport driver"); | |
| 2224 | 2226 | MODULE_LICENSE("GPL v2"); |
| 2225 | 2227 | MODULE_ALIAS("nvmet-transport-3"); /* 3 == NVMF_TRTYPE_TCP */ |
| @@ -386,21 +386,8 @@ void pci_bus_add_devices(const struct pci_bus *bus) · 385 unmodified lines | ||
| 386 | 386 | } |
| 387 | 387 | EXPORT_SYMBOL(pci_bus_add_devices); |
| 388 | 388 | |
| 389 | −/** pci_walk_bus - walk devices on/under bus, calling callback. | |
| 390 | − * @top bus whose devices should be walked | |
| 391 | − * @cb callback to be called for each device found | |
| 392 | − * @userdata arbitrary pointer to be passed to callback. | |
| 393 | − * | |
| 394 | − * Walk the given bus, including any bridged devices | |
| 395 | − * on buses under this bus. Call the provided callback | |
| 396 | − * on each device found. | |
| 397 | − * | |
| 398 | − * We check the return of @cb each time. If it returns anything | |
| 399 | − * other than 0, we break out. | |
| 400 | − * | |
| 401 | − */ | |
| 402 | −void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), | |
| 403 | − void *userdata) | |
| 389 | +static void __pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), | |
| 390 | + void *userdata, bool locked) | |
| 404 | 391 | { |
| 405 | 392 | struct pci_dev *dev; |
| 406 | 393 | struct pci_bus *bus; |
| @@ -408,7 +395,8 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), · 1 unmodified line | ||
| 408 | 395 | int retval; |
| 409 | 396 | |
| 410 | 397 | bus = top; |
| 411 | − down_read(&pci_bus_sem); | |
| 398 | + if (!locked) | |
| 399 | + down_read(&pci_bus_sem); | |
| 412 | 400 | next = top->devices.next; |
| 413 | 401 | for (;;) { |
| 414 | 402 | if (next == &bus->devices) { |
| @@ -431,10 +419,37 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), · 16 unmodified lines | ||
| 431 | 419 | if (retval) |
| 432 | 420 | break; |
| 433 | 421 | } |
| 434 | − up_read(&pci_bus_sem); | |
| 422 | + if (!locked) | |
| 423 | + up_read(&pci_bus_sem); | |
| 424 | +} | |
| 425 | + | |
| 426 | +/** | |
| 427 | + * pci_walk_bus - walk devices on/under bus, calling callback. | |
| 428 | + * @top: bus whose devices should be walked | |
| 429 | + * @cb: callback to be called for each device found | |
| 430 | + * @userdata: arbitrary pointer to be passed to callback | |
| 431 | + * | |
| 432 | + * Walk the given bus, including any bridged devices | |
| 433 | + * on buses under this bus. Call the provided callback | |
| 434 | + * on each device found. | |
| 435 | + * | |
| 436 | + * We check the return of @cb each time. If it returns anything | |
| 437 | + * other than 0, we break out. | |
| 438 | + */ | |
| 439 | +void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), void *userdata) | |
| 440 | +{ | |
| 441 | + __pci_walk_bus(top, cb, userdata, false); | |
| 435 | 442 | } |
| 436 | 443 | EXPORT_SYMBOL_GPL(pci_walk_bus); |
| 437 | 444 | |
| 445 | +void pci_walk_bus_locked(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), void *userdata) | |
| 446 | +{ | |
| 447 | + lockdep_assert_held(&pci_bus_sem); | |
| 448 | + | |
| 449 | + __pci_walk_bus(top, cb, userdata, true); | |
| 450 | +} | |
| 451 | +EXPORT_SYMBOL_GPL(pci_walk_bus_locked); | |
| 452 | + | |
| 438 | 453 | struct pci_bus *pci_bus_get(struct pci_bus *bus) |
| 439 | 454 | { |
| 440 | 455 | if (bus) |
| @@ -972,7 +972,7 @@ static int qcom_pcie_enable_aspm(struct pci_dev *pdev, void *userdata) · 971 unmodified lines | ||
| 972 | 972 | * Downstream devices need to be in D0 state before enabling PCI PM |
| 973 | 973 | * substates. |
| 974 | 974 | */ |
| 975 | − pci_set_power_state(pdev, PCI_D0); | |
| 975 | + pci_set_power_state_locked(pdev, PCI_D0); | |
| 976 | 976 | pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL); |
| 977 | 977 | |
| 978 | 978 | return 0; |
| @@ -1354,6 +1354,7 @@ end: · 1353 unmodified lines | ||
| 1354 | 1354 | /** |
| 1355 | 1355 | * pci_set_full_power_state - Put a PCI device into D0 and update its state |
| 1356 | 1356 | * @dev: PCI device to power up |
| 1357 | + * @locked: whether pci_bus_sem is held | |
| 1357 | 1358 | * |
| 1358 | 1359 | * Call pci_power_up() to put @dev into D0, read from its PCI_PM_CTRL register |
| 1359 | 1360 | * to confirm the state change, restore its BARs if they might be lost and |
| @@ -1363,7 +1364,7 @@ end: · 3 unmodified lines | ||
| 1363 | 1364 | * to D0, it is more efficient to use pci_power_up() directly instead of this |
| 1364 | 1365 | * function. |
| 1365 | 1366 | */ |
| 1366 | −static int pci_set_full_power_state(struct pci_dev *dev) | |
| 1367 | +static int pci_set_full_power_state(struct pci_dev *dev, bool locked) | |
| 1367 | 1368 | { |
| 1368 | 1369 | u16 pmcsr; |
| 1369 | 1370 | int ret; |
| @@ -1399,7 +1400,7 @@ static int pci_set_full_power_state(struct pci_dev *dev) · 29 unmodified lines | ||
| 1399 | 1400 | } |
| 1400 | 1401 | |
| 1401 | 1402 | if (dev->bus->self) |
| 1402 | − pcie_aspm_pm_state_change(dev->bus->self); | |
| 1403 | + pcie_aspm_pm_state_change(dev->bus->self, locked); | |
| 1403 | 1404 | |
| 1404 | 1405 | return 0; |
| 1405 | 1406 | } |
| @@ -1428,10 +1429,22 @@ void pci_bus_set_current_state(struct pci_bus *bus, pci_power_t state) · 22 unmodified lines | ||
| 1428 | 1429 | pci_walk_bus(bus, __pci_dev_set_current_state, &state); |
| 1429 | 1430 | } |
| 1430 | 1431 | |
| 1432 | +static void __pci_bus_set_current_state(struct pci_bus *bus, pci_power_t state, bool locked) | |
| 1433 | +{ | |
| 1434 | + if (!bus) | |
| 1435 | + return; | |
| 1436 | + | |
| 1437 | + if (locked) | |
| 1438 | + pci_walk_bus_locked(bus, __pci_dev_set_current_state, &state); | |
| 1439 | + else | |
| 1440 | + pci_walk_bus(bus, __pci_dev_set_current_state, &state); | |
| 1441 | +} | |
| 1442 | + | |
| 1431 | 1443 | /** |
| 1432 | 1444 | * pci_set_low_power_state - Put a PCI device into a low-power state. |
| 1433 | 1445 | * @dev: PCI device to handle. |
| 1434 | 1446 | * @state: PCI power state (D1, D2, D3hot) to put the device into. |
| 1447 | + * @locked: whether pci_bus_sem is held | |
| 1435 | 1448 | * |
| 1436 | 1449 | * Use the device's PCI_PM_CTRL register to put it into a low-power state. |
| 1437 | 1450 | * |
| @@ -1442,7 +1455,7 @@ void pci_bus_set_current_state(struct pci_bus *bus, pci_power_t state) · 4 unmodified lines | ||
| 1442 | 1455 | * 0 if device already is in the requested state. |
| 1443 | 1456 | * 0 if device's power state has been successfully changed. |
| 1444 | 1457 | */ |
| 1445 | −static int pci_set_low_power_state(struct pci_dev *dev, pci_power_t state) | |
| 1458 | +static int pci_set_low_power_state(struct pci_dev *dev, pci_power_t state, bool locked) | |
| 1446 | 1459 | { |
| 1447 | 1460 | u16 pmcsr; |
| 1448 | 1461 | |
| @@ -1496,29 +1509,12 @@ static int pci_set_low_power_state(struct pci_dev *dev, pci_power_t state) · 47 unmodified lines | ||
| 1496 | 1509 | pci_power_name(state)); |
| 1497 | 1510 | |
| 1498 | 1511 | if (dev->bus->self) |
| 1499 | − pcie_aspm_pm_state_change(dev->bus->self); | |
| 1512 | + pcie_aspm_pm_state_change(dev->bus->self, locked); | |
| 1500 | 1513 | |
| 1501 | 1514 | return 0; |
| 1502 | 1515 | } |
| 1503 | 1516 | |
| 1504 | −/** | |
| 1505 | − * pci_set_power_state - Set the power state of a PCI device | |
| 1506 | − * @dev: PCI device to handle. | |
| 1507 | − * @state: PCI power state (D0, D1, D2, D3hot) to put the device into. | |
| 1508 | − * | |
| 1509 | − * Transition a device to a new power state, using the platform firmware and/or | |
| 1510 | − * the device's PCI PM registers. | |
| 1511 | − * | |
| 1512 | − * RETURN VALUE: | |
| 1513 | − * -EINVAL if the requested state is invalid. | |
| 1514 | − * -EIO if device does not support PCI PM or its PM capabilities register has a | |
| 1515 | − * wrong version, or device doesn't support the requested state. | |
| 1516 | − * 0 if the transition is to D1 or D2 but D1 and D2 are not supported. | |
| 1517 | − * 0 if device already is in the requested state. | |
| 1518 | − * 0 if the transition is to D3 but D3 is not supported. | |
| 1519 | − * 0 if device's power state has been successfully changed. | |
| 1520 | − */ | |
| 1521 | −int pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |
| 1517 | +static int __pci_set_power_state(struct pci_dev *dev, pci_power_t state, bool locked) | |
| 1522 | 1518 | { |
| 1523 | 1519 | int error; |
| 1524 | 1520 | |
| @@ -1542,7 +1538,7 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) · 17 unmodified lines | ||
| 1542 | 1538 | return 0; |
| 1543 | 1539 | |
| 1544 | 1540 | if (state == PCI_D0) |
| 1545 | − return pci_set_full_power_state(dev); | |
| 1541 | + return pci_set_full_power_state(dev, locked); | |
| 1546 | 1542 | |
| 1547 | 1543 | /* |
| 1548 | 1544 | * This device is quirked not to be put into D3, so don't put it in |
| @@ -1556,16 +1552,16 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) · 7 unmodified lines | ||
| 1556 | 1552 | * To put the device in D3cold, put it into D3hot in the native |
| 1557 | 1553 | * way, then put it into D3cold using platform ops. |
| 1558 | 1554 | */ |
| 1559 | − error = pci_set_low_power_state(dev, PCI_D3hot); | |
| 1555 | + error = pci_set_low_power_state(dev, PCI_D3hot, locked); | |
| 1560 | 1556 | |
| 1561 | 1557 | if (pci_platform_power_transition(dev, PCI_D3cold)) |
| 1562 | 1558 | return error; |
| 1563 | 1559 | |
| 1564 | 1560 | /* Powering off a bridge may power off the whole hierarchy */ |
| 1565 | 1561 | if (dev->current_state == PCI_D3cold) |
| 1566 | − pci_bus_set_current_state(dev->subordinate, PCI_D3cold); | |
| 1562 | + __pci_bus_set_current_state(dev->subordinate, PCI_D3cold, locked); | |
| 1567 | 1563 | } else { |
| 1568 | − error = pci_set_low_power_state(dev, state); | |
| 1564 | + error = pci_set_low_power_state(dev, state, locked); | |
| 1569 | 1565 | |
| 1570 | 1566 | if (pci_platform_power_transition(dev, state)) |
| 1571 | 1567 | return error; |
| @@ -1573,8 +1569,38 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) · 1 unmodified line | ||
| 1573 | 1569 | |
| 1574 | 1570 | return 0; |
| 1575 | 1571 | } |
| 1572 | + | |
| 1573 | +/** | |
| 1574 | + * pci_set_power_state - Set the power state of a PCI device | |
| 1575 | + * @dev: PCI device to handle. | |
| 1576 | + * @state: PCI power state (D0, D1, D2, D3hot) to put the device into. | |
| 1577 | + * | |
| 1578 | + * Transition a device to a new power state, using the platform firmware and/or | |
| 1579 | + * the device's PCI PM registers. | |
| 1580 | + * | |
| 1581 | + * RETURN VALUE: | |
| 1582 | + * -EINVAL if the requested state is invalid. | |
| 1583 | + * -EIO if device does not support PCI PM or its PM capabilities register has a | |
| 1584 | + * wrong version, or device doesn't support the requested state. | |
| 1585 | + * 0 if the transition is to D1 or D2 but D1 and D2 are not supported. | |
| 1586 | + * 0 if device already is in the requested state. | |
| 1587 | + * 0 if the transition is to D3 but D3 is not supported. | |
| 1588 | + * 0 if device's power state has been successfully changed. | |
| 1589 | + */ | |
| 1590 | +int pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |
| 1591 | +{ | |
| 1592 | + return __pci_set_power_state(dev, state, false); | |
| 1593 | +} | |
| 1576 | 1594 | EXPORT_SYMBOL(pci_set_power_state); |
| 1577 | 1595 | |
| 1596 | +int pci_set_power_state_locked(struct pci_dev *dev, pci_power_t state) | |
| 1597 | +{ | |
| 1598 | + lockdep_assert_held(&pci_bus_sem); | |
| 1599 | + | |
| 1600 | + return __pci_set_power_state(dev, state, true); | |
| 1601 | +} | |
| 1602 | +EXPORT_SYMBOL(pci_set_power_state_locked); | |
| 1603 | + | |
| 1578 | 1604 | #define PCI_EXP_SAVE_REGS 7 |
| 1579 | 1605 | |
| 1580 | 1606 | static struct pci_cap_saved_state *_pci_find_saved_cap(struct pci_dev *pci_dev, |
| @@ -571,12 +571,12 @@ int pcie_retrain_link(struct pci_dev *pdev, bool use_lt); · 570 unmodified lines | ||
| 571 | 571 | #ifdef CONFIG_PCIEASPM |
| 572 | 572 | void pcie_aspm_init_link_state(struct pci_dev *pdev); |
| 573 | 573 | void pcie_aspm_exit_link_state(struct pci_dev *pdev); |
| 574 | −void pcie_aspm_pm_state_change(struct pci_dev *pdev); | |
| 574 | +void pcie_aspm_pm_state_change(struct pci_dev *pdev, bool locked); | |
| 575 | 575 | void pcie_aspm_powersave_config_link(struct pci_dev *pdev); |
| 576 | 576 | #else |
| 577 | 577 | static inline void pcie_aspm_init_link_state(struct pci_dev *pdev) { } |
| 578 | 578 | static inline void pcie_aspm_exit_link_state(struct pci_dev *pdev) { } |
| 579 | −static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev) { } | |
| 579 | +static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev, bool locked) { } | |
| 580 | 580 | static inline void pcie_aspm_powersave_config_link(struct pci_dev *pdev) { } |
| 581 | 581 | #endif |
| 582 | 582 | |
| @@ -1003,8 +1003,11 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) · 1002 unmodified lines | ||
| 1003 | 1003 | up_read(&pci_bus_sem); |
| 1004 | 1004 | } |
| 1005 | 1005 | |
| 1006 | −/* @pdev: the root port or switch downstream port */ | |
| 1007 | −void pcie_aspm_pm_state_change(struct pci_dev *pdev) | |
| 1006 | +/* | |
| 1007 | + * @pdev: the root port or switch downstream port | |
| 1008 | + * @locked: whether pci_bus_sem is held | |
| 1009 | + */ | |
| 1010 | +void pcie_aspm_pm_state_change(struct pci_dev *pdev, bool locked) | |
| 1008 | 1011 | { |
| 1009 | 1012 | struct pcie_link_state *link = pdev->link_state; |
| 1010 | 1013 | |
| @@ -1014,12 +1017,14 @@ void pcie_aspm_pm_state_change(struct pci_dev *pdev) · 3 unmodified lines | ||
| 1014 | 1017 | * Devices changed PM state, we should recheck if latency |
| 1015 | 1018 | * meets all functions' requirement |
| 1016 | 1019 | */ |
| 1017 | − down_read(&pci_bus_sem); | |
| 1020 | + if (!locked) | |
| 1021 | + down_read(&pci_bus_sem); | |
| 1018 | 1022 | mutex_lock(&aspm_lock); |
| 1019 | 1023 | pcie_update_aspm_capable(link->root); |
| 1020 | 1024 | pcie_config_aspm_path(link); |
| 1021 | 1025 | mutex_unlock(&aspm_lock); |
| 1022 | − up_read(&pci_bus_sem); | |
| 1026 | + if (!locked) | |
| 1027 | + up_read(&pci_bus_sem); | |
| 1023 | 1028 | } |
| 1024 | 1029 | |
| 1025 | 1030 | void pcie_aspm_powersave_config_link(struct pci_dev *pdev) |
| @@ -96,6 +96,8 @@ static const struct serdes_mux lan966x_serdes_muxes[] = { · 95 unmodified lines | ||
| 96 | 96 | SERDES_MUX_SGMII(SERDES6G(1), 3, HSIO_HW_CFG_SD6G_1_CFG, |
| 97 | 97 | HSIO_HW_CFG_SD6G_1_CFG_SET(1)), |
| 98 | 98 | |
| 99 | + SERDES_MUX_SGMII(SERDES6G(2), 4, 0, 0), | |
| 100 | + | |
| 99 | 101 | SERDES_MUX_RGMII(RGMII(0), 2, HSIO_HW_CFG_RGMII_0_CFG | |
| 100 | 102 | HSIO_HW_CFG_RGMII_ENA | |
| 101 | 103 | HSIO_HW_CFG_GMII_ENA, |
| @@ -1556,6 +1556,14 @@ static const char * const qmp_phy_vreg_l[] = { · 1555 unmodified lines | ||
| 1556 | 1556 | "vdda-phy", "vdda-pll", |
| 1557 | 1557 | }; |
| 1558 | 1558 | |
| 1559 | +static const struct qmp_usb_offsets qmp_usb_offsets_ipq8074 = { | |
| 1560 | + .serdes = 0, | |
| 1561 | + .pcs = 0x800, | |
| 1562 | + .pcs_misc = 0x600, | |
| 1563 | + .tx = 0x200, | |
| 1564 | + .rx = 0x400, | |
| 1565 | +}; | |
| 1566 | + | |
| 1559 | 1567 | static const struct qmp_usb_offsets qmp_usb_offsets_ipq9574 = { |
| 1560 | 1568 | .serdes = 0, |
| 1561 | 1569 | .pcs = 0x800, |
| @@ -1613,10 +1621,28 @@ static const struct qmp_usb_offsets qmp_usb_offsets_v7 = { · 51 unmodified lines | ||
| 1613 | 1621 | .rx = 0x1000, |
| 1614 | 1622 | }; |
| 1615 | 1623 | |
| 1624 | +static const struct qmp_phy_cfg ipq6018_usb3phy_cfg = { | |
| 1625 | + .lanes = 1, | |
| 1626 | + | |
| 1627 | + .offsets = &qmp_usb_offsets_ipq8074, | |
| 1628 | + | |
| 1629 | + .serdes_tbl = ipq9574_usb3_serdes_tbl, | |
| 1630 | + .serdes_tbl_num = ARRAY_SIZE(ipq9574_usb3_serdes_tbl), | |
| 1631 | + .tx_tbl = msm8996_usb3_tx_tbl, | |
| 1632 | + .tx_tbl_num = ARRAY_SIZE(msm8996_usb3_tx_tbl), | |
| 1633 | + .rx_tbl = ipq8074_usb3_rx_tbl, | |
| 1634 | + .rx_tbl_num = ARRAY_SIZE(ipq8074_usb3_rx_tbl), | |
| 1635 | + .pcs_tbl = ipq8074_usb3_pcs_tbl, | |
| 1636 | + .pcs_tbl_num = ARRAY_SIZE(ipq8074_usb3_pcs_tbl), | |
| 1637 | + .vreg_list = qmp_phy_vreg_l, | |
| 1638 | + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), | |
| 1639 | + .regs = qmp_v3_usb3phy_regs_layout, | |
| 1640 | +}; | |
| 1641 | + | |
| 1616 | 1642 | static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = { |
| 1617 | 1643 | .lanes = 1, |
| 1618 | 1644 | |
| 1619 | − .offsets = &qmp_usb_offsets_v3, | |
| 1645 | + .offsets = &qmp_usb_offsets_ipq8074, | |
| 1620 | 1646 | |
| 1621 | 1647 | .serdes_tbl = ipq8074_usb3_serdes_tbl, |
| 1622 | 1648 | .serdes_tbl_num = ARRAY_SIZE(ipq8074_usb3_serdes_tbl), |
| @@ -2563,7 +2589,7 @@ err_node_put: · 940 unmodified lines | ||
| 2563 | 2589 | static const struct of_device_id qmp_usb_of_match_table[] = { |
| 2564 | 2590 | { |
| 2565 | 2591 | .compatible = "qcom,ipq6018-qmp-usb3-phy", |
| 2566 | − .data = &ipq8074_usb3phy_cfg, | |
| 2592 | + .data = &ipq6018_usb3phy_cfg, | |
| 2567 | 2593 | }, { |
| 2568 | 2594 | .compatible = "qcom,ipq8074-qmp-usb3-phy", |
| 2569 | 2595 | .data = &ipq8074_usb3phy_cfg, |
| @@ -673,8 +673,6 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) · 672 unmodified lines | ||
| 673 | 673 | channel->irq = platform_get_irq_optional(pdev, 0); |
| 674 | 674 | channel->dr_mode = rcar_gen3_get_dr_mode(dev->of_node); |
| 675 | 675 | if (channel->dr_mode != USB_DR_MODE_UNKNOWN) { |
| 676 | − int ret; | |
| 677 | − | |
| 678 | 676 | channel->is_otg_channel = true; |
| 679 | 677 | channel->uses_otg_pins = !of_property_read_bool(dev->of_node, |
| 680 | 678 | "renesas,no-otg-pins"); |
| @@ -738,8 +736,6 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) · 57 unmodified lines | ||
| 738 | 736 | ret = PTR_ERR(provider); |
| 739 | 737 | goto error; |
| 740 | 738 | } else if (channel->is_otg_channel) { |
| 741 | − int ret; | |
| 742 | − | |
| 743 | 739 | ret = device_create_file(dev, &dev_attr_role); |
| 744 | 740 | if (ret < 0) |
| 745 | 741 | goto error; |
| @@ -117,7 +117,7 @@ static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled) · 116 unmodified lines | ||
| 117 | 117 | { |
| 118 | 118 | struct omap_usb *phy = phy_to_omapusb(otg->usb_phy); |
| 119 | 119 | |
| 120 | − if (!phy->comparator) | |
| 120 | + if (!phy->comparator || !phy->comparator->set_vbus) | |
| 121 | 121 | return -ENODEV; |
| 122 | 122 | |
| 123 | 123 | return phy->comparator->set_vbus(phy->comparator, enabled); |
| @@ -127,7 +127,7 @@ static int omap_usb_start_srp(struct usb_otg *otg) · 3 unmodified lines | ||
| 127 | 127 | { |
| 128 | 128 | struct omap_usb *phy = phy_to_omapusb(otg->usb_phy); |
| 129 | 129 | |
| 130 | − if (!phy->comparator) | |
| 130 | + if (!phy->comparator || !phy->comparator->start_srp) | |
| 131 | 131 | return -ENODEV; |
| 132 | 132 | |
| 133 | 133 | return phy->comparator->start_srp(phy->comparator); |
| @@ -1159,7 +1159,7 @@ static int amd_gpio_probe(struct platform_device *pdev) · 1158 unmodified lines | ||
| 1159 | 1159 | } |
| 1160 | 1160 | |
| 1161 | 1161 | ret = devm_request_irq(&pdev->dev, gpio_dev->irq, amd_gpio_irq_handler, |
| 1162 | − IRQF_SHARED, KBUILD_MODNAME, gpio_dev); | |
| 1162 | + IRQF_SHARED | IRQF_ONESHOT, KBUILD_MODNAME, gpio_dev); | |
| 1163 | 1163 | if (ret) |
| 1164 | 1164 | goto out2; |
| 1165 | 1165 | |
| @@ -282,7 +282,6 @@ struct qcom_battmgr_wireless { · 281 unmodified lines | ||
| 282 | 282 | |
| 283 | 283 | struct qcom_battmgr { |
| 284 | 284 | struct device *dev; |
| 285 | − struct auxiliary_device *adev; | |
| 286 | 285 | struct pmic_glink_client *client; |
| 287 | 286 | |
| 288 | 287 | enum qcom_battmgr_variant variant; |
| @@ -1294,69 +1293,11 @@ static void qcom_battmgr_enable_worker(struct work_struct *work) · 1005 unmodified lines | ||
| 1294 | 1293 | dev_err(battmgr->dev, "failed to request power notifications\n"); |
| 1295 | 1294 | } |
| 1296 | 1295 | |
| 1297 | −static char *qcom_battmgr_battery[] = { "battery" }; | |
| 1298 | − | |
| 1299 | −static void qcom_battmgr_register_psy(struct qcom_battmgr *battmgr) | |
| 1300 | −{ | |
| 1301 | − struct power_supply_config psy_cfg_supply = {}; | |
| 1302 | − struct auxiliary_device *adev = battmgr->adev; | |
| 1303 | − struct power_supply_config psy_cfg = {}; | |
| 1304 | − struct device *dev = &adev->dev; | |
| 1305 | − | |
| 1306 | − psy_cfg.drv_data = battmgr; | |
| 1307 | − psy_cfg.of_node = adev->dev.of_node; | |
| 1308 | − | |
| 1309 | − psy_cfg_supply.drv_data = battmgr; | |
| 1310 | − psy_cfg_supply.of_node = adev->dev.of_node; | |
| 1311 | − psy_cfg_supply.supplied_to = qcom_battmgr_battery; | |
| 1312 | − psy_cfg_supply.num_supplicants = 1; | |
| 1313 | − | |
| 1314 | − if (battmgr->variant == QCOM_BATTMGR_SC8280XP) { | |
| 1315 | − battmgr->bat_psy = devm_power_supply_register(dev, &sc8280xp_bat_psy_desc, &psy_cfg); | |
| 1316 | − if (IS_ERR(battmgr->bat_psy)) | |
| 1317 | − dev_err(dev, "failed to register battery power supply (%ld)\n", | |
| 1318 | − PTR_ERR(battmgr->bat_psy)); | |
| 1319 | − | |
| 1320 | − battmgr->ac_psy = devm_power_supply_register(dev, &sc8280xp_ac_psy_desc, &psy_cfg_supply); | |
| 1321 | − if (IS_ERR(battmgr->ac_psy)) | |
| 1322 | − dev_err(dev, "failed to register AC power supply (%ld)\n", | |
| 1323 | − PTR_ERR(battmgr->ac_psy)); | |
| 1324 | − | |
| 1325 | − battmgr->usb_psy = devm_power_supply_register(dev, &sc8280xp_usb_psy_desc, &psy_cfg_supply); | |
| 1326 | − if (IS_ERR(battmgr->usb_psy)) | |
| 1327 | − dev_err(dev, "failed to register USB power supply (%ld)\n", | |
| 1328 | − PTR_ERR(battmgr->usb_psy)); | |
| 1329 | − | |
| 1330 | − battmgr->wls_psy = devm_power_supply_register(dev, &sc8280xp_wls_psy_desc, &psy_cfg_supply); | |
| 1331 | − if (IS_ERR(battmgr->wls_psy)) | |
| 1332 | − dev_err(dev, "failed to register wireless charing power supply (%ld)\n", | |
| 1333 | − PTR_ERR(battmgr->wls_psy)); | |
| 1334 | − } else { | |
| 1335 | − battmgr->bat_psy = devm_power_supply_register(dev, &sm8350_bat_psy_desc, &psy_cfg); | |
| 1336 | − if (IS_ERR(battmgr->bat_psy)) | |
| 1337 | − dev_err(dev, "failed to register battery power supply (%ld)\n", | |
| 1338 | − PTR_ERR(battmgr->bat_psy)); | |
| 1339 | − | |
| 1340 | − battmgr->usb_psy = devm_power_supply_register(dev, &sm8350_usb_psy_desc, &psy_cfg_supply); | |
| 1341 | − if (IS_ERR(battmgr->usb_psy)) | |
| 1342 | − dev_err(dev, "failed to register USB power supply (%ld)\n", | |
| 1343 | − PTR_ERR(battmgr->usb_psy)); | |
| 1344 | − | |
| 1345 | − battmgr->wls_psy = devm_power_supply_register(dev, &sm8350_wls_psy_desc, &psy_cfg_supply); | |
| 1346 | − if (IS_ERR(battmgr->wls_psy)) | |
| 1347 | − dev_err(dev, "failed to register wireless charing power supply (%ld)\n", | |
| 1348 | − PTR_ERR(battmgr->wls_psy)); | |
| 1349 | − } | |
| 1350 | −} | |
| 1351 | − | |
| 1352 | 1296 | static void qcom_battmgr_pdr_notify(void *priv, int state) |
| 1353 | 1297 | { |
| 1354 | 1298 | struct qcom_battmgr *battmgr = priv; |
| 1355 | 1299 | |
| 1356 | 1300 | if (state == SERVREG_SERVICE_STATE_UP) { |
| 1357 | − if (!battmgr->bat_psy) | |
| 1358 | − qcom_battmgr_register_psy(battmgr); | |
| 1359 | − | |
| 1360 | 1301 | battmgr->service_up = true; |
| 1361 | 1302 | schedule_work(&battmgr->enable_work); |
| 1362 | 1303 | } else { |
| @@ -1371,9 +1312,13 @@ static const struct of_device_id qcom_battmgr_of_variants[] = { · 8 unmodified lines | ||
| 1371 | 1312 | {} |
| 1372 | 1313 | }; |
| 1373 | 1314 | |
| 1315 | +static char *qcom_battmgr_battery[] = { "battery" }; | |
| 1316 | + | |
| 1374 | 1317 | static int qcom_battmgr_probe(struct auxiliary_device *adev, |
| 1375 | 1318 | const struct auxiliary_device_id *id) |
| 1376 | 1319 | { |
| 1320 | + struct power_supply_config psy_cfg_supply = {}; | |
| 1321 | + struct power_supply_config psy_cfg = {}; | |
| 1377 | 1322 | const struct of_device_id *match; |
| 1378 | 1323 | struct qcom_battmgr *battmgr; |
| 1379 | 1324 | struct device *dev = &adev->dev; |
| @@ -1383,7 +1328,14 @@ static int qcom_battmgr_probe(struct auxiliary_device *adev, · 3 unmodified lines | ||
| 1383 | 1328 | return -ENOMEM; |
| 1384 | 1329 | |
| 1385 | 1330 | battmgr->dev = dev; |
| 1386 | − battmgr->adev = adev; | |
| 1331 | + | |
| 1332 | + psy_cfg.drv_data = battmgr; | |
| 1333 | + psy_cfg.of_node = adev->dev.of_node; | |
| 1334 | + | |
| 1335 | + psy_cfg_supply.drv_data = battmgr; | |
| 1336 | + psy_cfg_supply.of_node = adev->dev.of_node; | |
| 1337 | + psy_cfg_supply.supplied_to = qcom_battmgr_battery; | |
| 1338 | + psy_cfg_supply.num_supplicants = 1; | |
| 1387 | 1339 | |
| 1388 | 1340 | INIT_WORK(&battmgr->enable_work, qcom_battmgr_enable_worker); |
| 1389 | 1341 | mutex_init(&battmgr->lock); |
| @@ -1395,6 +1347,43 @@ static int qcom_battmgr_probe(struct auxiliary_device *adev, · 5 unmodified lines | ||
| 1395 | 1347 | else |
| 1396 | 1348 | battmgr->variant = QCOM_BATTMGR_SM8350; |
| 1397 | 1349 | |
| 1350 | + if (battmgr->variant == QCOM_BATTMGR_SC8280XP) { | |
| 1351 | + battmgr->bat_psy = devm_power_supply_register(dev, &sc8280xp_bat_psy_desc, &psy_cfg); | |
| 1352 | + if (IS_ERR(battmgr->bat_psy)) | |
| 1353 | + return dev_err_probe(dev, PTR_ERR(battmgr->bat_psy), | |
| 1354 | + "failed to register battery power supply\n"); | |
| 1355 | + | |
| 1356 | + battmgr->ac_psy = devm_power_supply_register(dev, &sc8280xp_ac_psy_desc, &psy_cfg_supply); | |
| 1357 | + if (IS_ERR(battmgr->ac_psy)) | |
| 1358 | + return dev_err_probe(dev, PTR_ERR(battmgr->ac_psy), | |
| 1359 | + "failed to register AC power supply\n"); | |
| 1360 | + | |
| 1361 | + battmgr->usb_psy = devm_power_supply_register(dev, &sc8280xp_usb_psy_desc, &psy_cfg_supply); | |
| 1362 | + if (IS_ERR(battmgr->usb_psy)) | |
| 1363 | + return dev_err_probe(dev, PTR_ERR(battmgr->usb_psy), | |
| 1364 | + "failed to register USB power supply\n"); | |
| 1365 | + | |
| 1366 | + battmgr->wls_psy = devm_power_supply_register(dev, &sc8280xp_wls_psy_desc, &psy_cfg_supply); | |
| 1367 | + if (IS_ERR(battmgr->wls_psy)) | |
| 1368 | + return dev_err_probe(dev, PTR_ERR(battmgr->wls_psy), | |
| 1369 | + "failed to register wireless charing power supply\n"); | |
| 1370 | + } else { | |
| 1371 | + battmgr->bat_psy = devm_power_supply_register(dev, &sm8350_bat_psy_desc, &psy_cfg); | |
| 1372 | + if (IS_ERR(battmgr->bat_psy)) | |
| 1373 | + return dev_err_probe(dev, PTR_ERR(battmgr->bat_psy), | |
| 1374 | + "failed to register battery power supply\n"); | |
| 1375 | + | |
| 1376 | + battmgr->usb_psy = devm_power_supply_register(dev, &sm8350_usb_psy_desc, &psy_cfg_supply); | |
| 1377 | + if (IS_ERR(battmgr->usb_psy)) | |
| 1378 | + return dev_err_probe(dev, PTR_ERR(battmgr->usb_psy), | |
| 1379 | + "failed to register USB power supply\n"); | |
| 1380 | + | |
| 1381 | + battmgr->wls_psy = devm_power_supply_register(dev, &sm8350_wls_psy_desc, &psy_cfg_supply); | |
| 1382 | + if (IS_ERR(battmgr->wls_psy)) | |
| 1383 | + return dev_err_probe(dev, PTR_ERR(battmgr->wls_psy), | |
| 1384 | + "failed to register wireless charing power supply\n"); | |
| 1385 | + } | |
| 1386 | + | |
| 1398 | 1387 | battmgr->client = devm_pmic_glink_register_client(dev, |
| 1399 | 1388 | PMIC_GLINK_OWNER_BATTMGR, |
| 1400 | 1389 | qcom_battmgr_callback, |
| @@ -255,9 +255,10 @@ static void qeth_l3_clear_ip_htable(struct qeth_card *card, int recover) · 254 unmodified lines | ||
| 255 | 255 | if (!recover) { |
| 256 | 256 | hash_del(&addr->hnode); |
| 257 | 257 | kfree(addr); |
| 258 | − continue; | |
| 258 | + } else { | |
| 259 | + /* prepare for recovery */ | |
| 260 | + addr->disp_flag = QETH_DISP_ADDR_ADD; | |
| 259 | 261 | } |
| 260 | − addr->disp_flag = QETH_DISP_ADDR_ADD; | |
| 261 | 262 | } |
| 262 | 263 | |
| 263 | 264 | mutex_unlock(&card->ip_lock); |
| @@ -278,9 +279,11 @@ static void qeth_l3_recover_ip(struct qeth_card *card) · 14 unmodified lines | ||
| 278 | 279 | if (addr->disp_flag == QETH_DISP_ADDR_ADD) { |
| 279 | 280 | rc = qeth_l3_register_addr_entry(card, addr); |
| 280 | 281 | |
| 281 | − if (!rc) { | |
| 282 | + if (!rc || rc == -EADDRINUSE || rc == -ENETDOWN) { | |
| 283 | + /* keep it in the records */ | |
| 282 | 284 | addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING; |
| 283 | 285 | } else { |
| 286 | + /* bad address */ | |
| 284 | 287 | hash_del(&addr->hnode); |
| 285 | 288 | kfree(addr); |
| 286 | 289 | } |
| @@ -302,7 +302,7 @@ static void pci1xxxx_process_read_data(struct uart_port *port, · 301 unmodified lines | ||
| 302 | 302 | * to read, the data is received one byte at a time. |
| 303 | 303 | */ |
| 304 | 304 | while (valid_burst_count--) { |
| 305 | − if (*buff_index > (RX_BUF_SIZE - UART_BURST_SIZE)) | |
| 305 | + if (*buff_index >= (RX_BUF_SIZE - UART_BURST_SIZE)) | |
| 306 | 306 | break; |
| 307 | 307 | burst_buf = (u32 *)&rx_buff[*buff_index]; |
| 308 | 308 | *burst_buf = readl(port->membase + UART_RX_BURST_FIFO); |
| @@ -311,7 +311,7 @@ static void pci1xxxx_process_read_data(struct uart_port *port, · 2 unmodified lines | ||
| 311 | 311 | } |
| 312 | 312 | |
| 313 | 313 | while (*valid_byte_count) { |
| 314 | − if (*buff_index > RX_BUF_SIZE) | |
| 314 | + if (*buff_index >= RX_BUF_SIZE) | |
| 315 | 315 | break; |
| 316 | 316 | rx_buff[*buff_index] = readb(port->membase + |
| 317 | 317 | UART_RX_BYTE_FIFO); |
| @@ -237,6 +237,14 @@ · 236 unmodified lines | ||
| 237 | 237 | #define MAX310x_REV_MASK (0xf8) |
| 238 | 238 | #define MAX310X_WRITE_BIT 0x80 |
| 239 | 239 | |
| 240 | +/* Port startup definitions */ | |
| 241 | +#define MAX310X_PORT_STARTUP_WAIT_RETRIES 20 /* Number of retries */ | |
| 242 | +#define MAX310X_PORT_STARTUP_WAIT_DELAY_MS 10 /* Delay between retries */ | |
| 243 | + | |
| 244 | +/* Crystal-related definitions */ | |
| 245 | +#define MAX310X_XTAL_WAIT_RETRIES 20 /* Number of retries */ | |
| 246 | +#define MAX310X_XTAL_WAIT_DELAY_MS 10 /* Delay between retries */ | |
| 247 | + | |
| 240 | 248 | /* MAX3107 specific */ |
| 241 | 249 | #define MAX3107_REV_ID (0xa0) |
| 242 | 250 | |
| @@ -583,7 +591,7 @@ static int max310x_update_best_err(unsigned long f, long *besterr) · 340 unmodified lines | ||
| 583 | 591 | return 1; |
| 584 | 592 | } |
| 585 | 593 | |
| 586 | −static u32 max310x_set_ref_clk(struct device *dev, struct max310x_port *s, | |
| 594 | +static s32 max310x_set_ref_clk(struct device *dev, struct max310x_port *s, | |
| 587 | 595 | unsigned long freq, bool xtal) |
| 588 | 596 | { |
| 589 | 597 | unsigned int div, clksrc, pllcfg = 0; |
| @@ -641,12 +649,20 @@ static u32 max310x_set_ref_clk(struct device *dev, struct max310x_port *s, · 51 unmodified lines | ||
| 641 | 649 | |
| 642 | 650 | /* Wait for crystal */ |
| 643 | 651 | if (xtal) { |
| 644 | − unsigned int val; | |
| 645 | − msleep(10); | |
| 646 | − regmap_read(s->regmap, MAX310X_STS_IRQSTS_REG, &val); | |
| 647 | − if (!(val & MAX310X_STS_CLKREADY_BIT)) { | |
| 648 | − dev_warn(dev, "clock is not stable yet\n"); | |
| 649 | − } | |
| 652 | + bool stable = false; | |
| 653 | + unsigned int try = 0, val = 0; | |
| 654 | + | |
| 655 | + do { | |
| 656 | + msleep(MAX310X_XTAL_WAIT_DELAY_MS); | |
| 657 | + regmap_read(s->regmap, MAX310X_STS_IRQSTS_REG, &val); | |
| 658 | + | |
| 659 | + if (val & MAX310X_STS_CLKREADY_BIT) | |
| 660 | + stable = true; | |
| 661 | + } while (!stable && (++try < MAX310X_XTAL_WAIT_RETRIES)); | |
| 662 | + | |
| 663 | + if (!stable) | |
| 664 | + return dev_err_probe(dev, -EAGAIN, | |
| 665 | + "clock is not stable\n"); | |
| 650 | 666 | } |
| 651 | 667 | |
| 652 | 668 | return bestfreq; |
| @@ -1271,7 +1287,7 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty · 618 unmodified lines | ||
| 1271 | 1287 | { |
| 1272 | 1288 | int i, ret, fmin, fmax, freq; |
| 1273 | 1289 | struct max310x_port *s; |
| 1274 | − u32 uartclk = 0; | |
| 1290 | + s32 uartclk = 0; | |
| 1275 | 1291 | bool xtal; |
| 1276 | 1292 | |
| 1277 | 1293 | for (i = 0; i < devtype->nr; i++) |
| @@ -1334,6 +1350,9 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty · 56 unmodified lines | ||
| 1334 | 1350 | goto out_clk; |
| 1335 | 1351 | |
| 1336 | 1352 | for (i = 0; i < devtype->nr; i++) { |
| 1353 | + bool started = false; | |
| 1354 | + unsigned int try = 0, val = 0; | |
| 1355 | + | |
| 1337 | 1356 | /* Reset port */ |
| 1338 | 1357 | regmap_write(regmaps[i], MAX310X_MODE2_REG, |
| 1339 | 1358 | MAX310X_MODE2_RST_BIT); |
| @@ -1342,13 +1361,27 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty · 2 unmodified lines | ||
| 1342 | 1361 | |
| 1343 | 1362 | /* Wait for port startup */ |
| 1344 | 1363 | do { |
| 1345 | − regmap_read(regmaps[i], MAX310X_BRGDIVLSB_REG, &ret); | |
| 1346 | − } while (ret != 0x01); | |
| 1364 | + msleep(MAX310X_PORT_STARTUP_WAIT_DELAY_MS); | |
| 1365 | + regmap_read(regmaps[i], MAX310X_BRGDIVLSB_REG, &val); | |
| 1366 | + | |
| 1367 | + if (val == 0x01) | |
| 1368 | + started = true; | |
| 1369 | + } while (!started && (++try < MAX310X_PORT_STARTUP_WAIT_RETRIES)); | |
| 1370 | + | |
| 1371 | + if (!started) { | |
| 1372 | + ret = dev_err_probe(dev, -EAGAIN, "port reset failed\n"); | |
| 1373 | + goto out_uart; | |
| 1374 | + } | |
| 1347 | 1375 | |
| 1348 | 1376 | regmap_write(regmaps[i], MAX310X_MODE1_REG, devtype->mode1); |
| 1349 | 1377 | } |
| 1350 | 1378 | |
| 1351 | 1379 | uartclk = max310x_set_ref_clk(dev, s, freq, xtal); |
| 1380 | + if (uartclk < 0) { | |
| 1381 | + ret = uartclk; | |
| 1382 | + goto out_uart; | |
| 1383 | + } | |
| 1384 | + | |
| 1352 | 1385 | dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk); |
| 1353 | 1386 | |
| 1354 | 1387 | for (i = 0; i < devtype->nr; i++) { |
| @@ -1084,8 +1084,8 @@ static int uart_tiocmget(struct tty_struct *tty) · 1083 unmodified lines | ||
| 1084 | 1084 | goto out; |
| 1085 | 1085 | |
| 1086 | 1086 | if (!tty_io_error(tty)) { |
| 1087 | − result = uport->mctrl; | |
| 1088 | 1087 | uart_port_lock_irq(uport); |
| 1088 | + result = uport->mctrl; | |
| 1089 | 1089 | result |= uport->ops->get_mctrl(uport); |
| 1090 | 1090 | uart_port_unlock_irq(uport); |
| 1091 | 1091 | } |
| @@ -176,6 +176,7 @@ struct hw_bank { · 175 unmodified lines | ||
| 176 | 176 | * @enabled_otg_timer_bits: bits of enabled otg timers |
| 177 | 177 | * @next_otg_timer: next nearest enabled timer to be expired |
| 178 | 178 | * @work: work for role changing |
| 179 | + * @power_lost_work: work for power lost handling | |
| 179 | 180 | * @wq: workqueue thread |
| 180 | 181 | * @qh_pool: allocation pool for queue heads |
| 181 | 182 | * @td_pool: allocation pool for transfer descriptors |
| @@ -226,6 +227,7 @@ struct ci_hdrc { · 44 unmodified lines | ||
| 226 | 227 | enum otg_fsm_timer next_otg_timer; |
| 227 | 228 | struct usb_role_switch *role_switch; |
| 228 | 229 | struct work_struct work; |
| 230 | + struct work_struct power_lost_work; | |
| 229 | 231 | struct workqueue_struct *wq; |
| 230 | 232 | |
| 231 | 233 | struct dma_pool *qh_pool; |
| @@ -856,6 +856,27 @@ static int ci_extcon_register(struct ci_hdrc *ci) · 855 unmodified lines | ||
| 856 | 856 | return 0; |
| 857 | 857 | } |
| 858 | 858 | |
| 859 | +static void ci_power_lost_work(struct work_struct *work) | |
| 860 | +{ | |
| 861 | + struct ci_hdrc *ci = container_of(work, struct ci_hdrc, power_lost_work); | |
| 862 | + enum ci_role role; | |
| 863 | + | |
| 864 | + disable_irq_nosync(ci->irq); | |
| 865 | + pm_runtime_get_sync(ci->dev); | |
| 866 | + if (!ci_otg_is_fsm_mode(ci)) { | |
| 867 | + role = ci_get_role(ci); | |
| 868 | + | |
| 869 | + if (ci->role != role) { | |
| 870 | + ci_handle_id_switch(ci); | |
| 871 | + } else if (role == CI_ROLE_GADGET) { | |
| 872 | + if (ci->is_otg && hw_read_otgsc(ci, OTGSC_BSV)) | |
| 873 | + usb_gadget_vbus_connect(&ci->gadget); | |
| 874 | + } | |
| 875 | + } | |
| 876 | + pm_runtime_put_sync(ci->dev); | |
| 877 | + enable_irq(ci->irq); | |
| 878 | +} | |
| 879 | + | |
| 859 | 880 | static DEFINE_IDA(ci_ida); |
| 860 | 881 | |
| 861 | 882 | struct platform_device *ci_hdrc_add_device(struct device *dev, |
| @@ -1045,6 +1066,8 @@ static int ci_hdrc_probe(struct platform_device *pdev) · 183 unmodified lines | ||
| 1045 | 1066 | |
| 1046 | 1067 | spin_lock_init(&ci->lock); |
| 1047 | 1068 | mutex_init(&ci->mutex); |
| 1069 | + INIT_WORK(&ci->power_lost_work, ci_power_lost_work); | |
| 1070 | + | |
| 1048 | 1071 | ci->dev = dev; |
| 1049 | 1072 | ci->platdata = dev_get_platdata(dev); |
| 1050 | 1073 | ci->imx28_write_fix = !!(ci->platdata->flags & |
| @@ -1396,25 +1419,6 @@ static int ci_suspend(struct device *dev) · 345 unmodified lines | ||
| 1396 | 1419 | return 0; |
| 1397 | 1420 | } |
| 1398 | 1421 | |
| 1399 | −static void ci_handle_power_lost(struct ci_hdrc *ci) | |
| 1400 | −{ | |
| 1401 | − enum ci_role role; | |
| 1402 | − | |
| 1403 | − disable_irq_nosync(ci->irq); | |
| 1404 | − if (!ci_otg_is_fsm_mode(ci)) { | |
| 1405 | − role = ci_get_role(ci); | |
| 1406 | − | |
| 1407 | − if (ci->role != role) { | |
| 1408 | − ci_handle_id_switch(ci); | |
| 1409 | − } else if (role == CI_ROLE_GADGET) { | |
| 1410 | − if (ci->is_otg && hw_read_otgsc(ci, OTGSC_BSV)) | |
| 1411 | − usb_gadget_vbus_connect(&ci->gadget); | |
| 1412 | − } | |
| 1413 | − } | |
| 1414 | − | |
| 1415 | − enable_irq(ci->irq); | |
| 1416 | −} | |
| 1417 | − | |
| 1418 | 1422 | static int ci_resume(struct device *dev) |
| 1419 | 1423 | { |
| 1420 | 1424 | struct ci_hdrc *ci = dev_get_drvdata(dev); |
| @@ -1446,7 +1450,7 @@ static int ci_resume(struct device *dev) · 25 unmodified lines | ||
| 1446 | 1450 | ci_role(ci)->resume(ci, power_lost); |
| 1447 | 1451 | |
| 1448 | 1452 | if (power_lost) |
| 1449 | − ci_handle_power_lost(ci); | |
| 1453 | + queue_work(system_freezable_wq, &ci->power_lost_work); | |
| 1450 | 1454 | |
| 1451 | 1455 | if (ci->supports_runtime_pm) { |
| 1452 | 1456 | pm_runtime_disable(dev); |
| @@ -301,7 +301,7 @@ static int ulpi_register(struct device *dev, struct ulpi *ulpi) · 300 unmodified lines | ||
| 301 | 301 | return ret; |
| 302 | 302 | } |
| 303 | 303 | |
| 304 | − root = debugfs_create_dir(dev_name(dev), ulpi_root); | |
| 304 | + root = debugfs_create_dir(dev_name(&ulpi->dev), ulpi_root); | |
| 305 | 305 | debugfs_create_file("regs", 0444, root, ulpi, &ulpi_regs_fops); |
| 306 | 306 | |
| 307 | 307 | dev_dbg(&ulpi->dev, "registered ULPI PHY: vendor %04x, product %04x\n", |
| @@ -2053,9 +2053,19 @@ static void update_port_device_state(struct usb_device *udev) · 2052 unmodified lines | ||
| 2053 | 2053 | |
| 2054 | 2054 | if (udev->parent) { |
| 2055 | 2055 | hub = usb_hub_to_struct_hub(udev->parent); |
| 2056 | − port_dev = hub->ports[udev->portnum - 1]; | |
| 2057 | − WRITE_ONCE(port_dev->state, udev->state); | |
| 2058 | − sysfs_notify_dirent(port_dev->state_kn); | |
| 2056 | + | |
| 2057 | + /* | |
| 2058 | + * The Link Layer Validation System Driver (lvstest) | |
| 2059 | + * has a test step to unbind the hub before running the | |
| 2060 | + * rest of the procedure. This triggers hub_disconnect | |
| 2061 | + * which will set the hub's maxchild to 0, further | |
| 2062 | + * resulting in usb_hub_to_struct_hub returning NULL. | |
| 2063 | + */ | |
| 2064 | + if (hub) { | |
| 2065 | + port_dev = hub->ports[udev->portnum - 1]; | |
| 2066 | + WRITE_ONCE(port_dev->state, udev->state); | |
| 2067 | + sysfs_notify_dirent(port_dev->state_kn); | |
| 2068 | + } | |
| 2059 | 2069 | } |
| 2060 | 2070 | } |
| 2061 | 2071 | |
| @@ -2388,17 +2398,25 @@ static int usb_enumerate_device_otg(struct usb_device *udev) · 326 unmodified lines | ||
| 2388 | 2398 | } |
| 2389 | 2399 | } else if (desc->bLength == sizeof |
| 2390 | 2400 | (struct usb_otg_descriptor)) { |
| 2391 | − /* Set a_alt_hnp_support for legacy otg device */ | |
| 2392 | − err = usb_control_msg(udev, | |
| 2393 | − usb_sndctrlpipe(udev, 0), | |
| 2394 | − USB_REQ_SET_FEATURE, 0, | |
| 2395 | − USB_DEVICE_A_ALT_HNP_SUPPORT, | |
| 2396 | − 0, NULL, 0, | |
| 2397 | − USB_CTRL_SET_TIMEOUT); | |
| 2398 | − if (err < 0) | |
| 2399 | − dev_err(&udev->dev, | |
| 2400 | − "set a_alt_hnp_support failed: %d\n", | |
| 2401 | − err); | |
| 2401 | + /* | |
| 2402 | + * We are operating on a legacy OTP device | |
| 2403 | + * These should be told that they are operating | |
| 2404 | + * on the wrong port if we have another port that does | |
| 2405 | + * support HNP | |
| 2406 | + */ | |
| 2407 | + if (bus->otg_port != 0) { | |
| 2408 | + /* Set a_alt_hnp_support for legacy otg device */ | |
| 2409 | + err = usb_control_msg(udev, | |
| 2410 | + usb_sndctrlpipe(udev, 0), | |
| 2411 | + USB_REQ_SET_FEATURE, 0, | |
| 2412 | + USB_DEVICE_A_ALT_HNP_SUPPORT, | |
| 2413 | + 0, NULL, 0, | |
| 2414 | + USB_CTRL_SET_TIMEOUT); | |
| 2415 | + if (err < 0) | |
| 2416 | + dev_err(&udev->dev, | |
| 2417 | + "set a_alt_hnp_support failed: %d\n", | |
| 2418 | + err); | |
| 2419 | + } | |
| 2402 | 2420 | } |
| 2403 | 2421 | } |
| 2404 | 2422 | #endif |
| @@ -51,6 +51,8 @@ · 50 unmodified lines | ||
| 51 | 51 | #define PCI_DEVICE_ID_INTEL_MTLP 0x7ec1 |
| 52 | 52 | #define PCI_DEVICE_ID_INTEL_MTLS 0x7f6f |
| 53 | 53 | #define PCI_DEVICE_ID_INTEL_MTL 0x7e7e |
| 54 | +#define PCI_DEVICE_ID_INTEL_ARLH 0x7ec1 | |
| 55 | +#define PCI_DEVICE_ID_INTEL_ARLH_PCH 0x777e | |
| 54 | 56 | #define PCI_DEVICE_ID_INTEL_TGL 0x9a15 |
| 55 | 57 | #define PCI_DEVICE_ID_AMD_MR 0x163a |
| 56 | 58 | |
| @@ -421,6 +423,8 @@ static const struct pci_device_id dwc3_pci_id_table[] = { · 364 unmodified lines | ||
| 421 | 423 | { PCI_DEVICE_DATA(INTEL, MTLP, &dwc3_pci_intel_swnode) }, |
| 422 | 424 | { PCI_DEVICE_DATA(INTEL, MTL, &dwc3_pci_intel_swnode) }, |
| 423 | 425 | { PCI_DEVICE_DATA(INTEL, MTLS, &dwc3_pci_intel_swnode) }, |
| 426 | + { PCI_DEVICE_DATA(INTEL, ARLH, &dwc3_pci_intel_swnode) }, | |
| 427 | + { PCI_DEVICE_DATA(INTEL, ARLH_PCH, &dwc3_pci_intel_swnode) }, | |
| 424 | 428 | { PCI_DEVICE_DATA(INTEL, TGL, &dwc3_pci_intel_swnode) }, |
| 425 | 429 | |
| 426 | 430 | { PCI_DEVICE_DATA(AMD, NL_USB, &dwc3_pci_amd_swnode) }, |
| @@ -4709,15 +4709,13 @@ int dwc3_gadget_suspend(struct dwc3 *dwc) · 4708 unmodified lines | ||
| 4709 | 4709 | unsigned long flags; |
| 4710 | 4710 | int ret; |
| 4711 | 4711 | |
| 4712 | − if (!dwc->gadget_driver) | |
| 4713 | − return 0; | |
| 4714 | − | |
| 4715 | 4712 | ret = dwc3_gadget_soft_disconnect(dwc); |
| 4716 | 4713 | if (ret) |
| 4717 | 4714 | goto err; |
| 4718 | 4715 | |
| 4719 | 4716 | spin_lock_irqsave(&dwc->lock, flags); |
| 4720 | − dwc3_disconnect_gadget(dwc); | |
| 4717 | + if (dwc->gadget_driver) | |
| 4718 | + dwc3_disconnect_gadget(dwc); | |
| 4721 | 4719 | spin_unlock_irqrestore(&dwc->lock, flags); |
| 4722 | 4720 | |
| 4723 | 4721 | return 0; |
| @@ -61,7 +61,7 @@ out: · 60 unmodified lines | ||
| 61 | 61 | |
| 62 | 62 | int dwc3_host_init(struct dwc3 *dwc) |
| 63 | 63 | { |
| 64 | − struct property_entry props[4]; | |
| 64 | + struct property_entry props[5]; | |
| 65 | 65 | struct platform_device *xhci; |
| 66 | 66 | int ret, irq; |
| 67 | 67 | int prop_idx = 0; |
| @@ -89,6 +89,8 @@ int dwc3_host_init(struct dwc3 *dwc) · 21 unmodified lines | ||
| 89 | 89 | |
| 90 | 90 | memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props)); |
| 91 | 91 | |
| 92 | + props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-sg-trb-cache-size-quirk"); | |
| 93 | + | |
| 92 | 94 | if (dwc->usb3_lpm_capable) |
| 93 | 95 | props[prop_idx++] = PROPERTY_ENTRY_BOOL("usb3-lpm-capable"); |
| 94 | 96 | |
| @@ -545,21 +545,37 @@ static int start_transfer(struct fsg_dev *fsg, struct usb_ep *ep, · 544 unmodified lines | ||
| 545 | 545 | |
| 546 | 546 | static bool start_in_transfer(struct fsg_common *common, struct fsg_buffhd *bh) |
| 547 | 547 | { |
| 548 | + int rc; | |
| 549 | + | |
| 548 | 550 | if (!fsg_is_set(common)) |
| 549 | 551 | return false; |
| 550 | 552 | bh->state = BUF_STATE_SENDING; |
| 551 | − if (start_transfer(common->fsg, common->fsg->bulk_in, bh->inreq)) | |
| 553 | + rc = start_transfer(common->fsg, common->fsg->bulk_in, bh->inreq); | |
| 554 | + if (rc) { | |
| 552 | 555 | bh->state = BUF_STATE_EMPTY; |
| 556 | + if (rc == -ESHUTDOWN) { | |
| 557 | + common->running = 0; | |
| 558 | + return false; | |
| 559 | + } | |
| 560 | + } | |
| 553 | 561 | return true; |
| 554 | 562 | } |
| 555 | 563 | |
| 556 | 564 | static bool start_out_transfer(struct fsg_common *common, struct fsg_buffhd *bh) |
| 557 | 565 | { |
| 566 | + int rc; | |
| 567 | + | |
| 558 | 568 | if (!fsg_is_set(common)) |
| 559 | 569 | return false; |
| 560 | 570 | bh->state = BUF_STATE_RECEIVING; |
| 561 | − if (start_transfer(common->fsg, common->fsg->bulk_out, bh->outreq)) | |
| 571 | + rc = start_transfer(common->fsg, common->fsg->bulk_out, bh->outreq); | |
| 572 | + if (rc) { | |
| 562 | 573 | bh->state = BUF_STATE_FULL; |
| 574 | + if (rc == -ESHUTDOWN) { | |
| 575 | + common->running = 0; | |
| 576 | + return false; | |
| 577 | + } | |
| 578 | + } | |
| 563 | 579 | return true; |
| 564 | 580 | } |
| 565 | 581 | |
| @@ -105,8 +105,8 @@ static inline struct f_ncm *func_to_ncm(struct usb_function *f) · 104 unmodified lines | ||
| 105 | 105 | |
| 106 | 106 | /* |
| 107 | 107 | * Although max mtu as dictated by u_ether is 15412 bytes, setting |
| 108 | − * max_segment_sizeto 15426 would not be efficient. If user chooses segment | |
| 109 | − * size to be (>= 8192), then we can't aggregate more than one buffer in each | |
| 108 | + * max_segment_size to 15426 would not be efficient. If user chooses segment | |
| 109 | + * size to be (>= 8192), then we can't aggregate more than one buffer in each | |
| 110 | 110 | * NTB (assuming each packet coming from network layer is >= 8192 bytes) as ep |
| 111 | 111 | * maxpacket limit is 16384. So let max_segment_size be limited to 8000 to allow |
| 112 | 112 | * at least 2 packets to be aggregated reducing wastage of NTB buffer space |
| @@ -1489,7 +1489,7 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f) · 1376 unmodified lines | ||
| 1489 | 1489 | ncm_data_intf.bInterfaceNumber = status; |
| 1490 | 1490 | ncm_union_desc.bSlaveInterface0 = status; |
| 1491 | 1491 | |
| 1492 | − ecm_desc.wMaxSegmentSize = ncm_opts->max_segment_size; | |
| 1492 | + ecm_desc.wMaxSegmentSize = cpu_to_le16(ncm_opts->max_segment_size); | |
| 1493 | 1493 | |
| 1494 | 1494 | status = -ENODEV; |
| 1495 | 1495 | |
| @@ -1685,7 +1685,7 @@ static struct usb_function_instance *ncm_alloc_inst(void) · 189 unmodified lines | ||
| 1685 | 1685 | kfree(opts); |
| 1686 | 1686 | return ERR_CAST(net); |
| 1687 | 1687 | } |
| 1688 | − opts->max_segment_size = cpu_to_le16(ETH_FRAME_LEN); | |
| 1688 | + opts->max_segment_size = ETH_FRAME_LEN; | |
| 1689 | 1689 | INIT_LIST_HEAD(&opts->ncm_os_desc.ext_prop); |
| 1690 | 1690 | |
| 1691 | 1691 | descs[0] = &opts->ncm_os_desc; |
| @@ -274,7 +274,6 @@ struct pch_udc_cfg_data { · 273 unmodified lines | ||
| 274 | 274 | * @td_data: for data request |
| 275 | 275 | * @dev: reference to device struct |
| 276 | 276 | * @offset_addr: offset address of ep register |
| 277 | − * @desc: for this ep | |
| 278 | 277 | * @queue: queue for requests |
| 279 | 278 | * @num: endpoint number |
| 280 | 279 | * @in: endpoint is IN |
| @@ -1861,14 +1861,14 @@ void xhci_remove_secondary_interrupter(struct usb_hcd *hcd, struct xhci_interrup · 1860 unmodified lines | ||
| 1861 | 1861 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
| 1862 | 1862 | unsigned int intr_num; |
| 1863 | 1863 | |
| 1864 | + spin_lock_irq(&xhci->lock); | |
| 1865 | + | |
| 1864 | 1866 | /* interrupter 0 is primary interrupter, don't touch it */ |
| 1865 | − if (!ir || !ir->intr_num || ir->intr_num >= xhci->max_interrupters) | |
| 1867 | + if (!ir || !ir->intr_num || ir->intr_num >= xhci->max_interrupters) { | |
| 1866 | 1868 | xhci_dbg(xhci, "Invalid secondary interrupter, can't remove\n"); |
| 1867 | − | |
| 1868 | − /* fixme, should we check xhci->interrupter[intr_num] == ir */ | |
| 1869 | − /* fixme locking */ | |
| 1870 | − | |
| 1871 | − spin_lock_irq(&xhci->lock); | |
| 1869 | + spin_unlock_irq(&xhci->lock); | |
| 1870 | + return; | |
| 1871 | + } | |
| 1872 | 1872 | |
| 1873 | 1873 | intr_num = ir->intr_num; |
| 1874 | 1874 | |
| @@ -2322,7 +2322,7 @@ xhci_add_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir, · 447 unmodified lines | ||
| 2322 | 2322 | u64 erst_base; |
| 2323 | 2323 | u32 erst_size; |
| 2324 | 2324 | |
| 2325 | − if (intr_num > xhci->max_interrupters) { | |
| 2325 | + if (intr_num >= xhci->max_interrupters) { | |
| 2326 | 2326 | xhci_warn(xhci, "Can't add interrupter %d, max interrupters %d\n", |
| 2327 | 2327 | intr_num, xhci->max_interrupters); |
| 2328 | 2328 | return -EINVAL; |
| @@ -253,6 +253,9 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s · 252 unmodified lines | ||
| 253 | 253 | if (device_property_read_bool(tmpdev, "quirk-broken-port-ped")) |
| 254 | 254 | xhci->quirks |= XHCI_BROKEN_PORT_PED; |
| 255 | 255 | |
| 256 | + if (device_property_read_bool(tmpdev, "xhci-sg-trb-cache-size-quirk")) | |
| 257 | + xhci->quirks |= XHCI_SG_TRB_CACHE_SIZE_QUIRK; | |
| 258 | + | |
| 256 | 259 | device_property_read_u32(tmpdev, "imod-interval-ns", |
| 257 | 260 | &xhci->imod_interval); |
| 258 | 261 | } |
| @@ -2376,6 +2376,9 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, · 2375 unmodified lines | ||
| 2376 | 2376 | /* handle completion code */ |
| 2377 | 2377 | switch (trb_comp_code) { |
| 2378 | 2378 | case COMP_SUCCESS: |
| 2379 | + /* Don't overwrite status if TD had an error, see xHCI 4.9.1 */ | |
| 2380 | + if (td->error_mid_td) | |
| 2381 | + break; | |
| 2379 | 2382 | if (remaining) { |
| 2380 | 2383 | frame->status = short_framestatus; |
| 2381 | 2384 | if (xhci->quirks & XHCI_TRUST_TX_LENGTH) |
| @@ -2391,9 +2394,13 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, · 9 unmodified lines | ||
| 2391 | 2394 | case COMP_BANDWIDTH_OVERRUN_ERROR: |
| 2392 | 2395 | frame->status = -ECOMM; |
| 2393 | 2396 | break; |
| 2394 | − case COMP_ISOCH_BUFFER_OVERRUN: | |
| 2395 | 2397 | case COMP_BABBLE_DETECTED_ERROR: |
| 2398 | + sum_trbs_for_length = true; | |
| 2399 | + fallthrough; | |
| 2400 | + case COMP_ISOCH_BUFFER_OVERRUN: | |
| 2396 | 2401 | frame->status = -EOVERFLOW; |
| 2402 | + if (ep_trb != td->last_trb) | |
| 2403 | + td->error_mid_td = true; | |
| 2397 | 2404 | break; |
| 2398 | 2405 | case COMP_INCOMPATIBLE_DEVICE_ERROR: |
| 2399 | 2406 | case COMP_STALL_ERROR: |
| @@ -2401,8 +2408,9 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, · 1 unmodified line | ||
| 2401 | 2408 | break; |
| 2402 | 2409 | case COMP_USB_TRANSACTION_ERROR: |
| 2403 | 2410 | frame->status = -EPROTO; |
| 2411 | + sum_trbs_for_length = true; | |
| 2404 | 2412 | if (ep_trb != td->last_trb) |
| 2405 | − return 0; | |
| 2413 | + td->error_mid_td = true; | |
| 2406 | 2414 | break; |
| 2407 | 2415 | case COMP_STOPPED: |
| 2408 | 2416 | sum_trbs_for_length = true; |
| @@ -2422,6 +2430,9 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, · 13 unmodified lines | ||
| 2422 | 2430 | break; |
| 2423 | 2431 | } |
| 2424 | 2432 | |
| 2433 | + if (td->urb_length_set) | |
| 2434 | + goto finish_td; | |
| 2435 | + | |
| 2425 | 2436 | if (sum_trbs_for_length) |
| 2426 | 2437 | frame->actual_length = sum_trb_lengths(xhci, ep->ring, ep_trb) + |
| 2427 | 2438 | ep_trb_len - remaining; |
| @@ -2430,6 +2441,14 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, · 2 unmodified lines | ||
| 2430 | 2441 | |
| 2431 | 2442 | td->urb->actual_length += frame->actual_length; |
| 2432 | 2443 | |
| 2444 | +finish_td: | |
| 2445 | + /* Don't give back TD yet if we encountered an error mid TD */ | |
| 2446 | + if (td->error_mid_td && ep_trb != td->last_trb) { | |
| 2447 | + xhci_dbg(xhci, "Error mid isoc TD, wait for final completion event\n"); | |
| 2448 | + td->urb_length_set = true; | |
| 2449 | + return 0; | |
| 2450 | + } | |
| 2451 | + | |
| 2433 | 2452 | return finish_td(xhci, ep, ep_ring, td, trb_comp_code); |
| 2434 | 2453 | } |
| 2435 | 2454 | |
| @@ -2808,17 +2827,51 @@ static int handle_tx_event(struct xhci_hcd *xhci, · 372 unmodified lines | ||
| 2808 | 2827 | } |
| 2809 | 2828 | |
| 2810 | 2829 | if (!ep_seg) { |
| 2811 | − if (!ep->skip || | |
| 2812 | − !usb_endpoint_xfer_isoc(&td->urb->ep->desc)) { | |
| 2813 | − /* Some host controllers give a spurious | |
| 2814 | − * successful event after a short transfer. | |
| 2815 | − * Ignore it. | |
| 2816 | − */ | |
| 2817 | − if ((xhci->quirks & XHCI_SPURIOUS_SUCCESS) && | |
| 2818 | − ep_ring->last_td_was_short) { | |
| 2819 | − ep_ring->last_td_was_short = false; | |
| 2820 | − goto cleanup; | |
| 2830 | + | |
| 2831 | + if (ep->skip && usb_endpoint_xfer_isoc(&td->urb->ep->desc)) { | |
| 2832 | + skip_isoc_td(xhci, td, ep, status); | |
| 2833 | + goto cleanup; | |
| 2834 | + } | |
| 2835 | + | |
| 2836 | + /* | |
| 2837 | + * Some hosts give a spurious success event after a short | |
| 2838 | + * transfer. Ignore it. | |
| 2839 | + */ | |
| 2840 | + if ((xhci->quirks & XHCI_SPURIOUS_SUCCESS) && | |
| 2841 | + ep_ring->last_td_was_short) { | |
| 2842 | + ep_ring->last_td_was_short = false; | |
| 2843 | + goto cleanup; | |
| 2844 | + } | |
| 2845 | + | |
| 2846 | + /* | |
| 2847 | + * xhci 4.10.2 states isoc endpoints should continue | |
| 2848 | + * processing the next TD if there was an error mid TD. | |
| 2849 | + * So host like NEC don't generate an event for the last | |
| 2850 | + * isoc TRB even if the IOC flag is set. | |
| 2851 | + * xhci 4.9.1 states that if there are errors in mult-TRB | |
| 2852 | + * TDs xHC should generate an error for that TRB, and if xHC | |
| 2853 | + * proceeds to the next TD it should genete an event for | |
| 2854 | + * any TRB with IOC flag on the way. Other host follow this. | |
| 2855 | + * So this event might be for the next TD. | |
| 2856 | + */ | |
| 2857 | + if (td->error_mid_td && | |
| 2858 | + !list_is_last(&td->td_list, &ep_ring->td_list)) { | |
| 2859 | + struct xhci_td *td_next = list_next_entry(td, td_list); | |
| 2860 | + | |
| 2861 | + ep_seg = trb_in_td(xhci, td_next->start_seg, td_next->first_trb, | |
| 2862 | + td_next->last_trb, ep_trb_dma, false); | |
| 2863 | + if (ep_seg) { | |
| 2864 | + /* give back previous TD, start handling new */ | |
| 2865 | + xhci_dbg(xhci, "Missing TD completion event after mid TD error\n"); | |
| 2866 | + ep_ring->dequeue = td->last_trb; | |
| 2867 | + ep_ring->deq_seg = td->last_trb_seg; | |
| 2868 | + inc_deq(xhci, ep_ring); | |
| 2869 | + xhci_td_cleanup(xhci, td, ep_ring, td->status); | |
| 2870 | + td = td_next; | |
| 2821 | 2871 | } |
| 2872 | + } | |
| 2873 | + | |
| 2874 | + if (!ep_seg) { | |
| 2822 | 2875 | /* HC is busted, give up! */ |
| 2823 | 2876 | xhci_err(xhci, |
| 2824 | 2877 | "ERROR Transfer event TRB DMA ptr not " |
| @@ -2830,9 +2883,6 @@ static int handle_tx_event(struct xhci_hcd *xhci, · 5 unmodified lines | ||
| 2830 | 2883 | ep_trb_dma, true); |
| 2831 | 2884 | return -ESHUTDOWN; |
| 2832 | 2885 | } |
| 2833 | − | |
| 2834 | − skip_isoc_td(xhci, td, ep, status); | |
| 2835 | − goto cleanup; | |
| 2836 | 2886 | } |
| 2837 | 2887 | if (trb_comp_code == COMP_SHORT_PACKET) |
| 2838 | 2888 | ep_ring->last_td_was_short = true; |
| @@ -1549,6 +1549,7 @@ struct xhci_td { · 1548 unmodified lines | ||
| 1549 | 1549 | struct xhci_segment *bounce_seg; |
| 1550 | 1550 | /* actual_length of the URB has already been set */ |
| 1551 | 1551 | bool urb_length_set; |
| 1552 | + bool error_mid_td; | |
| 1552 | 1553 | unsigned int num_trbs; |
| 1553 | 1554 | }; |
| 1554 | 1555 | |
| @@ -146,6 +146,7 @@ static const struct usb_device_id id_table[] = { · 145 unmodified lines | ||
| 146 | 146 | { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */ |
| 147 | 147 | { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */ |
| 148 | 148 | { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */ |
| 149 | + { USB_DEVICE(0x10C4, 0x87ED) }, /* IMST USB-Stick for Smart Meter */ | |
| 149 | 150 | { USB_DEVICE(0x10C4, 0x8856) }, /* CEL EM357 ZigBee USB Stick - LR */ |
| 150 | 151 | { USB_DEVICE(0x10C4, 0x8857) }, /* CEL EM357 ZigBee USB Stick */ |
| 151 | 152 | { USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */ |
| @@ -2269,6 +2269,7 @@ static const struct usb_device_id option_ids[] = { · 2268 unmodified lines | ||
| 2269 | 2269 | { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0111, 0xff) }, /* Fibocom FM160 (MBIM mode) */ |
| 2270 | 2270 | { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) }, /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */ |
| 2271 | 2271 | { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a2, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */ |
| 2272 | + { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a3, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */ | |
| 2272 | 2273 | { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a4, 0xff), /* Fibocom FM101-GL (laptop MBIM) */ |
| 2273 | 2274 | .driver_info = RSVD(4) }, |
| 2274 | 2275 | { USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */ |
| @@ -184,6 +184,8 @@ static const struct usb_device_id id_table[] = { · 183 unmodified lines | ||
| 184 | 184 | {DEVICE_SWI(0x413c, 0x81d0)}, /* Dell Wireless 5819 */ |
| 185 | 185 | {DEVICE_SWI(0x413c, 0x81d1)}, /* Dell Wireless 5818 */ |
| 186 | 186 | {DEVICE_SWI(0x413c, 0x81d2)}, /* Dell Wireless 5818 */ |
| 187 | + {DEVICE_SWI(0x413c, 0x8217)}, /* Dell Wireless DW5826e */ | |
| 188 | + {DEVICE_SWI(0x413c, 0x8218)}, /* Dell Wireless DW5826e QDL */ | |
| 187 | 189 | |
| 188 | 190 | /* Huawei devices */ |
| 189 | 191 | {DEVICE_HWI(0x03f0, 0x581d)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Modem (Huawei me906e) */ |
| @@ -4876,8 +4876,7 @@ static void run_state_machine(struct tcpm_port *port) · 4875 unmodified lines | ||
| 4876 | 4876 | break; |
| 4877 | 4877 | case PORT_RESET: |
| 4878 | 4878 | tcpm_reset_port(port); |
| 4879 | − tcpm_set_cc(port, tcpm_default_state(port) == SNK_UNATTACHED ? | |
| 4880 | − TYPEC_CC_RD : tcpm_rp_cc(port)); | |
| 4879 | + tcpm_set_cc(port, TYPEC_CC_OPEN); | |
| 4881 | 4880 | tcpm_set_state(port, PORT_RESET_WAIT_OFF, |
| 4882 | 4881 | PD_T_ERROR_RECOVERY); |
| 4883 | 4882 | break; |
| @@ -6848,7 +6847,8 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) · 1964 unmodified lines | ||
| 6848 | 6847 | if (err) |
| 6849 | 6848 | goto out_role_sw_put; |
| 6850 | 6849 | |
| 6851 | − port->typec_caps.pd = port->pds[0]; | |
| 6850 | + if (port->pds) | |
| 6851 | + port->typec_caps.pd = port->pds[0]; | |
| 6852 | 6852 | |
| 6853 | 6853 | port->typec_port = typec_register_port(port->dev, &port->typec_caps); |
| 6854 | 6854 | if (IS_ERR(port->typec_port)) { |
| @@ -938,7 +938,9 @@ static void ucsi_handle_connector_change(struct work_struct *work) · 937 unmodified lines | ||
| 938 | 938 | |
| 939 | 939 | clear_bit(EVENT_PENDING, &con->ucsi->flags); |
| 940 | 940 | |
| 941 | + mutex_lock(&ucsi->ppm_lock); | |
| 941 | 942 | ret = ucsi_acknowledge_connector_change(ucsi); |
| 943 | + mutex_unlock(&ucsi->ppm_lock); | |
| 942 | 944 | if (ret) |
| 943 | 945 | dev_err(ucsi->dev, "%s: ACK failed (%d)", __func__, ret); |
| 944 | 946 | |
| @@ -25,6 +25,8 @@ struct ucsi_acpi { · 24 unmodified lines | ||
| 25 | 25 | unsigned long flags; |
| 26 | 26 | guid_t guid; |
| 27 | 27 | u64 cmd; |
| 28 | + bool dell_quirk_probed; | |
| 29 | + bool dell_quirk_active; | |
| 28 | 30 | }; |
| 29 | 31 | |
| 30 | 32 | static int ucsi_acpi_dsm(struct ucsi_acpi *ua, int func) |
| @@ -73,9 +75,13 @@ static int ucsi_acpi_sync_write(struct ucsi *ucsi, unsigned int offset, · 42 unmodified lines | ||
| 73 | 75 | const void *val, size_t val_len) |
| 74 | 76 | { |
| 75 | 77 | struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); |
| 78 | + bool ack = UCSI_COMMAND(*(u64 *)val) == UCSI_ACK_CC_CI; | |
| 76 | 79 | int ret; |
| 77 | 80 | |
| 78 | − set_bit(COMMAND_PENDING, &ua->flags); | |
| 81 | + if (ack) | |
| 82 | + set_bit(ACK_PENDING, &ua->flags); | |
| 83 | + else | |
| 84 | + set_bit(COMMAND_PENDING, &ua->flags); | |
| 79 | 85 | |
| 80 | 86 | ret = ucsi_acpi_async_write(ucsi, offset, val, val_len); |
| 81 | 87 | if (ret) |
| @@ -85,7 +91,10 @@ static int ucsi_acpi_sync_write(struct ucsi *ucsi, unsigned int offset, · 3 unmodified lines | ||
| 85 | 91 | ret = -ETIMEDOUT; |
| 86 | 92 | |
| 87 | 93 | out_clear_bit: |
| 88 | − clear_bit(COMMAND_PENDING, &ua->flags); | |
| 94 | + if (ack) | |
| 95 | + clear_bit(ACK_PENDING, &ua->flags); | |
| 96 | + else | |
| 97 | + clear_bit(COMMAND_PENDING, &ua->flags); | |
| 89 | 98 | |
| 90 | 99 | return ret; |
| 91 | 100 | } |
| @@ -119,12 +128,73 @@ static const struct ucsi_operations ucsi_zenbook_ops = { · 27 unmodified lines | ||
| 119 | 128 | .async_write = ucsi_acpi_async_write |
| 120 | 129 | }; |
| 121 | 130 | |
| 122 | −static const struct dmi_system_id zenbook_dmi_id[] = { | |
| 131 | +/* | |
| 132 | + * Some Dell laptops expect that an ACK command with the | |
| 133 | + * UCSI_ACK_CONNECTOR_CHANGE bit set is followed by a (separate) | |
| 134 | + * ACK command that only has the UCSI_ACK_COMMAND_COMPLETE bit set. | |
| 135 | + * If this is not done events are not delivered to OSPM and | |
| 136 | + * subsequent commands will timeout. | |
| 137 | + */ | |
| 138 | +static int | |
| 139 | +ucsi_dell_sync_write(struct ucsi *ucsi, unsigned int offset, | |
| 140 | + const void *val, size_t val_len) | |
| 141 | +{ | |
| 142 | + struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); | |
| 143 | + u64 cmd = *(u64 *)val, ack = 0; | |
| 144 | + int ret; | |
| 145 | + | |
| 146 | + if (UCSI_COMMAND(cmd) == UCSI_ACK_CC_CI && | |
| 147 | + cmd & UCSI_ACK_CONNECTOR_CHANGE) | |
| 148 | + ack = UCSI_ACK_CC_CI | UCSI_ACK_COMMAND_COMPLETE; | |
| 149 | + | |
| 150 | + ret = ucsi_acpi_sync_write(ucsi, offset, val, val_len); | |
| 151 | + if (ret != 0) | |
| 152 | + return ret; | |
| 153 | + if (ack == 0) | |
| 154 | + return ret; | |
| 155 | + | |
| 156 | + if (!ua->dell_quirk_probed) { | |
| 157 | + ua->dell_quirk_probed = true; | |
| 158 | + | |
| 159 | + cmd = UCSI_GET_CAPABILITY; | |
| 160 | + ret = ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &cmd, | |
| 161 | + sizeof(cmd)); | |
| 162 | + if (ret == 0) | |
| 163 | + return ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, | |
| 164 | + &ack, sizeof(ack)); | |
| 165 | + if (ret != -ETIMEDOUT) | |
| 166 | + return ret; | |
| 167 | + | |
| 168 | + ua->dell_quirk_active = true; | |
| 169 | + dev_err(ua->dev, "Firmware bug: Additional ACK required after ACKing a connector change.\n"); | |
| 170 | + dev_err(ua->dev, "Firmware bug: Enabling workaround\n"); | |
| 171 | + } | |
| 172 | + | |
| 173 | + if (!ua->dell_quirk_active) | |
| 174 | + return ret; | |
| 175 | + | |
| 176 | + return ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &ack, sizeof(ack)); | |
| 177 | +} | |
| 178 | + | |
| 179 | +static const struct ucsi_operations ucsi_dell_ops = { | |
| 180 | + .read = ucsi_acpi_read, | |
| 181 | + .sync_write = ucsi_dell_sync_write, | |
| 182 | + .async_write = ucsi_acpi_async_write | |
| 183 | +}; | |
| 184 | + | |
| 185 | +static const struct dmi_system_id ucsi_acpi_quirks[] = { | |
| 123 | 186 | { |
| 124 | 187 | .matches = { |
| 125 | 188 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 126 | 189 | DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX325UA_UM325UA"), |
| 127 | 190 | }, |
| 191 | + .driver_data = (void *)&ucsi_zenbook_ops, | |
| 192 | + }, | |
| 193 | + { | |
| 194 | + .matches = { | |
| 195 | + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | |
| 196 | + }, | |
| 197 | + .driver_data = (void *)&ucsi_dell_ops, | |
| 128 | 198 | }, |
| 129 | 199 | { } |
| 130 | 200 | }; |
| @@ -142,8 +212,10 @@ static void ucsi_acpi_notify(acpi_handle handle, u32 event, void *data) · 11 unmodified lines | ||
| 142 | 212 | if (UCSI_CCI_CONNECTOR(cci)) |
| 143 | 213 | ucsi_connector_change(ua->ucsi, UCSI_CCI_CONNECTOR(cci)); |
| 144 | 214 | |
| 145 | − if (test_bit(COMMAND_PENDING, &ua->flags) && | |
| 146 | − cci & (UCSI_CCI_ACK_COMPLETE | UCSI_CCI_COMMAND_COMPLETE)) | |
| 215 | + if (cci & UCSI_CCI_ACK_COMPLETE && test_bit(ACK_PENDING, &ua->flags)) | |
| 216 | + complete(&ua->complete); | |
| 217 | + if (cci & UCSI_CCI_COMMAND_COMPLETE && | |
| 218 | + test_bit(COMMAND_PENDING, &ua->flags)) | |
| 147 | 219 | complete(&ua->complete); |
| 148 | 220 | } |
| 149 | 221 | |
| @@ -151,6 +223,7 @@ static int ucsi_acpi_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 151 | 223 | { |
| 152 | 224 | struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); |
| 153 | 225 | const struct ucsi_operations *ops = &ucsi_acpi_ops; |
| 226 | + const struct dmi_system_id *id; | |
| 154 | 227 | struct ucsi_acpi *ua; |
| 155 | 228 | struct resource *res; |
| 156 | 229 | acpi_status status; |
| @@ -180,8 +253,9 @@ static int ucsi_acpi_probe(struct platform_device *pdev) · 23 unmodified lines | ||
| 180 | 253 | init_completion(&ua->complete); |
| 181 | 254 | ua->dev = &pdev->dev; |
| 182 | 255 | |
| 183 | − if (dmi_check_system(zenbook_dmi_id)) | |
| 184 | − ops = &ucsi_zenbook_ops; | |
| 256 | + id = dmi_first_match(ucsi_acpi_quirks); | |
| 257 | + if (id) | |
| 258 | + ops = id->driver_data; | |
| 185 | 259 | |
| 186 | 260 | ua->ucsi = ucsi_create(&pdev->dev, ops); |
| 187 | 261 | if (IS_ERR(ua->ucsi)) |
| @@ -455,6 +455,7 @@ static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp, · 454 unmodified lines | ||
| 455 | 455 | if (IS_ERR(victim)) |
| 456 | 456 | return PTR_ERR(victim); |
| 457 | 457 | |
| 458 | + dir = d_inode(path.dentry); | |
| 458 | 459 | if (victim->d_sb->s_fs_info != c) { |
| 459 | 460 | ret = -EXDEV; |
| 460 | 461 | goto err; |
| @@ -463,14 +464,13 @@ static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp, · 2 unmodified lines | ||
| 463 | 464 | ret = -ENOENT; |
| 464 | 465 | goto err; |
| 465 | 466 | } |
| 466 | − dir = d_inode(path.dentry); | |
| 467 | 467 | ret = __bch2_unlink(dir, victim, true); |
| 468 | 468 | if (!ret) { |
| 469 | 469 | fsnotify_rmdir(dir, victim); |
| 470 | 470 | d_delete(victim); |
| 471 | 471 | } |
| 472 | − inode_unlock(dir); | |
| 473 | 472 | err: |
| 473 | + inode_unlock(dir); | |
| 474 | 474 | dput(victim); |
| 475 | 475 | path_put(&path); |
| 476 | 476 | return ret; |
| @@ -17,7 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | * Rust and rustc has issues with u128. |
| 18 | 18 | */ |
| 19 | 19 | |
| 20 | −#if defined(__SIZEOF_INT128__) && defined(__KERNEL__) | |
| 20 | +#if defined(__SIZEOF_INT128__) && defined(__KERNEL__) && !defined(CONFIG_PARISC) | |
| 21 | 21 | |
| 22 | 22 | typedef struct { |
| 23 | 23 | unsigned __int128 v; |
| @@ -53,9 +53,9 @@ int bch2_run_thread_with_file(struct thread_with_file *thr, · 52 unmodified lines | ||
| 53 | 53 | if (ret) |
| 54 | 54 | goto err; |
| 55 | 55 | |
| 56 | − fd_install(fd, file); | |
| 57 | 56 | get_task_struct(thr->task); |
| 58 | 57 | wake_up_process(thr->task); |
| 58 | + fd_install(fd, file); | |
| 59 | 59 | return fd; |
| 60 | 60 | err: |
| 61 | 61 | if (fd >= 0) |
| @@ -418,14 +418,15 @@ static inline void bch2_time_stats_update_one(struct bch2_time_stats *stats, · 417 unmodified lines | ||
| 418 | 418 | bch2_quantiles_update(&stats->quantiles, duration); |
| 419 | 419 | } |
| 420 | 420 | |
| 421 | − if (time_after64(end, stats->last_event)) { | |
| 421 | + if (stats->last_event && time_after64(end, stats->last_event)) { | |
| 422 | 422 | freq = end - stats->last_event; |
| 423 | 423 | mean_and_variance_update(&stats->freq_stats, freq); |
| 424 | 424 | mean_and_variance_weighted_update(&stats->freq_stats_weighted, freq); |
| 425 | 425 | stats->max_freq = max(stats->max_freq, freq); |
| 426 | 426 | stats->min_freq = min(stats->min_freq, freq); |
| 427 | − stats->last_event = end; | |
| 428 | 427 | } |
| 428 | + | |
| 429 | + stats->last_event = end; | |
| 429 | 430 | } |
| 430 | 431 | |
| 431 | 432 | static void __bch2_time_stats_clear_buffer(struct bch2_time_stats *stats, |
| @@ -1336,8 +1336,17 @@ static struct btrfs_root *btrfs_get_root_ref(struct btrfs_fs_info *fs_info, · 1335 unmodified lines | ||
| 1336 | 1336 | again: |
| 1337 | 1337 | root = btrfs_lookup_fs_root(fs_info, objectid); |
| 1338 | 1338 | if (root) { |
| 1339 | − /* Shouldn't get preallocated anon_dev for cached roots */ | |
| 1340 | − ASSERT(!anon_dev); | |
| 1339 | + /* | |
| 1340 | + * Some other caller may have read out the newly inserted | |
| 1341 | + * subvolume already (for things like backref walk etc). Not | |
| 1342 | + * that common but still possible. In that case, we just need | |
| 1343 | + * to free the anon_dev. | |
| 1344 | + */ | |
| 1345 | + if (unlikely(anon_dev)) { | |
| 1346 | + free_anon_bdev(anon_dev); | |
| 1347 | + anon_dev = 0; | |
| 1348 | + } | |
| 1349 | + | |
| 1341 | 1350 | if (check_ref && btrfs_root_refs(&root->root_item) == 0) { |
| 1342 | 1351 | btrfs_put_root(root); |
| 1343 | 1352 | return ERR_PTR(-ENOENT); |
| @@ -3815,6 +3815,11 @@ static long btrfs_ioctl_qgroup_create(struct file *file, void __user *arg) · 3814 unmodified lines | ||
| 3815 | 3815 | goto out; |
| 3816 | 3816 | } |
| 3817 | 3817 | |
| 3818 | + if (sa->create && is_fstree(sa->qgroupid)) { | |
| 3819 | + ret = -EINVAL; | |
| 3820 | + goto out; | |
| 3821 | + } | |
| 3822 | + | |
| 3818 | 3823 | trans = btrfs_join_transaction(root); |
| 3819 | 3824 | if (IS_ERR(trans)) { |
| 3820 | 3825 | ret = PTR_ERR(trans); |
| @@ -1736,6 +1736,15 @@ out: · 1735 unmodified lines | ||
| 1736 | 1736 | return ret; |
| 1737 | 1737 | } |
| 1738 | 1738 | |
| 1739 | +static bool qgroup_has_usage(struct btrfs_qgroup *qgroup) | |
| 1740 | +{ | |
| 1741 | + return (qgroup->rfer > 0 || qgroup->rfer_cmpr > 0 || | |
| 1742 | + qgroup->excl > 0 || qgroup->excl_cmpr > 0 || | |
| 1743 | + qgroup->rsv.values[BTRFS_QGROUP_RSV_DATA] > 0 || | |
| 1744 | + qgroup->rsv.values[BTRFS_QGROUP_RSV_META_PREALLOC] > 0 || | |
| 1745 | + qgroup->rsv.values[BTRFS_QGROUP_RSV_META_PERTRANS] > 0); | |
| 1746 | +} | |
| 1747 | + | |
| 1739 | 1748 | int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid) |
| 1740 | 1749 | { |
| 1741 | 1750 | struct btrfs_fs_info *fs_info = trans->fs_info; |
| @@ -1755,6 +1764,11 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid) · 13 unmodified lines | ||
| 1755 | 1764 | goto out; |
| 1756 | 1765 | } |
| 1757 | 1766 | |
| 1767 | + if (is_fstree(qgroupid) && qgroup_has_usage(qgroup)) { | |
| 1768 | + ret = -EBUSY; | |
| 1769 | + goto out; | |
| 1770 | + } | |
| 1771 | + | |
| 1758 | 1772 | /* Check if there are no children of this qgroup */ |
| 1759 | 1773 | if (!list_empty(&qgroup->members)) { |
| 1760 | 1774 | ret = -EBUSY; |
| @@ -8111,7 +8111,7 @@ long btrfs_ioctl_send(struct inode *inode, struct btrfs_ioctl_send_args *arg) · 8110 unmodified lines | ||
| 8111 | 8111 | } |
| 8112 | 8112 | |
| 8113 | 8113 | if (arg->flags & ~BTRFS_SEND_FLAG_MASK) { |
| 8114 | − ret = -EINVAL; | |
| 8114 | + ret = -EOPNOTSUPP; | |
| 8115 | 8115 | goto out; |
| 8116 | 8116 | } |
| 8117 | 8117 | |
| @@ -252,8 +252,10 @@ struct ext4_allocation_request { · 251 unmodified lines | ||
| 252 | 252 | #define EXT4_MAP_MAPPED BIT(BH_Mapped) |
| 253 | 253 | #define EXT4_MAP_UNWRITTEN BIT(BH_Unwritten) |
| 254 | 254 | #define EXT4_MAP_BOUNDARY BIT(BH_Boundary) |
| 255 | +#define EXT4_MAP_DELAYED BIT(BH_Delay) | |
| 255 | 256 | #define EXT4_MAP_FLAGS (EXT4_MAP_NEW | EXT4_MAP_MAPPED |\ |
| 256 | − EXT4_MAP_UNWRITTEN | EXT4_MAP_BOUNDARY) | |
| 257 | + EXT4_MAP_UNWRITTEN | EXT4_MAP_BOUNDARY |\ | |
| 258 | + EXT4_MAP_DELAYED) | |
| 257 | 259 | |
| 258 | 260 | struct ext4_map_blocks { |
| 259 | 261 | ext4_fsblk_t m_pblk; |
| @@ -2912,10 +2914,10 @@ extern const struct seq_operations ext4_mb_seq_groups_ops; · 2652 unmodified lines | ||
| 2912 | 2914 | extern const struct seq_operations ext4_mb_seq_structs_summary_ops; |
| 2913 | 2915 | extern int ext4_seq_mb_stats_show(struct seq_file *seq, void *offset); |
| 2914 | 2916 | extern int ext4_mb_init(struct super_block *); |
| 2915 | −extern int ext4_mb_release(struct super_block *); | |
| 2917 | +extern void ext4_mb_release(struct super_block *); | |
| 2916 | 2918 | extern ext4_fsblk_t ext4_mb_new_blocks(handle_t *, |
| 2917 | 2919 | struct ext4_allocation_request *, int *); |
| 2918 | −extern void ext4_discard_preallocations(struct inode *, unsigned int); | |
| 2920 | +extern void ext4_discard_preallocations(struct inode *); | |
| 2919 | 2921 | extern int __init ext4_init_mballoc(void); |
| 2920 | 2922 | extern void ext4_exit_mballoc(void); |
| 2921 | 2923 | extern ext4_group_t ext4_mb_prefetch(struct super_block *sb, |
| @@ -100,7 +100,7 @@ static int ext4_ext_trunc_restart_fn(struct inode *inode, int *dropped) · 99 unmodified lines | ||
| 100 | 100 | * i_rwsem. So we can safely drop the i_data_sem here. |
| 101 | 101 | */ |
| 102 | 102 | BUG_ON(EXT4_JOURNAL(inode) == NULL); |
| 103 | − ext4_discard_preallocations(inode, 0); | |
| 103 | + ext4_discard_preallocations(inode); | |
| 104 | 104 | up_write(&EXT4_I(inode)->i_data_sem); |
| 105 | 105 | *dropped = 1; |
| 106 | 106 | return 0; |
| @@ -2229,7 +2229,7 @@ static int ext4_fill_es_cache_info(struct inode *inode, · 2122 unmodified lines | ||
| 2229 | 2229 | |
| 2230 | 2230 | |
| 2231 | 2231 | /* |
| 2232 | − * ext4_ext_determine_hole - determine hole around given block | |
| 2232 | + * ext4_ext_find_hole - find hole around given block according to the given path | |
| 2233 | 2233 | * @inode: inode we lookup in |
| 2234 | 2234 | * @path: path in extent tree to @lblk |
| 2235 | 2235 | * @lblk: pointer to logical block around which we want to determine hole |
| @@ -2241,9 +2241,9 @@ static int ext4_fill_es_cache_info(struct inode *inode, · 5 unmodified lines | ||
| 2241 | 2241 | * The function returns the length of a hole starting at @lblk. We update @lblk |
| 2242 | 2242 | * to the beginning of the hole if we managed to find it. |
| 2243 | 2243 | */ |
| 2244 | −static ext4_lblk_t ext4_ext_determine_hole(struct inode *inode, | |
| 2245 | − struct ext4_ext_path *path, | |
| 2246 | − ext4_lblk_t *lblk) | |
| 2244 | +static ext4_lblk_t ext4_ext_find_hole(struct inode *inode, | |
| 2245 | + struct ext4_ext_path *path, | |
| 2246 | + ext4_lblk_t *lblk) | |
| 2247 | 2247 | { |
| 2248 | 2248 | int depth = ext_depth(inode); |
| 2249 | 2249 | struct ext4_extent *ex; |
| @@ -2270,30 +2270,6 @@ static ext4_lblk_t ext4_ext_determine_hole(struct inode *inode, · 20 unmodified lines | ||
| 2270 | 2270 | return len; |
| 2271 | 2271 | } |
| 2272 | 2272 | |
| 2273 | −/* | |
| 2274 | − * ext4_ext_put_gap_in_cache: | |
| 2275 | − * calculate boundaries of the gap that the requested block fits into | |
| 2276 | − * and cache this gap | |
| 2277 | − */ | |
| 2278 | −static void | |
| 2279 | −ext4_ext_put_gap_in_cache(struct inode *inode, ext4_lblk_t hole_start, | |
| 2280 | − ext4_lblk_t hole_len) | |
| 2281 | −{ | |
| 2282 | − struct extent_status es; | |
| 2283 | − | |
| 2284 | − ext4_es_find_extent_range(inode, &ext4_es_is_delayed, hole_start, | |
| 2285 | − hole_start + hole_len - 1, &es); | |
| 2286 | − if (es.es_len) { | |
| 2287 | − /* There's delayed extent containing lblock? */ | |
| 2288 | − if (es.es_lblk <= hole_start) | |
| 2289 | − return; | |
| 2290 | − hole_len = min(es.es_lblk - hole_start, hole_len); | |
| 2291 | − } | |
| 2292 | − ext_debug(inode, " -> %u:%u\n", hole_start, hole_len); | |
| 2293 | − ext4_es_insert_extent(inode, hole_start, hole_len, ~0, | |
| 2294 | − EXTENT_STATUS_HOLE); | |
| 2295 | −} | |
| 2296 | − | |
| 2297 | 2273 | /* |
| 2298 | 2274 | * ext4_ext_rm_idx: |
| 2299 | 2275 | * removes index from the index block. |
| @@ -4062,6 +4038,72 @@ static int get_implied_cluster_alloc(struct super_block *sb, · 1762 unmodified lines | ||
| 4062 | 4038 | return 0; |
| 4063 | 4039 | } |
| 4064 | 4040 | |
| 4041 | +/* | |
| 4042 | + * Determine hole length around the given logical block, first try to | |
| 4043 | + * locate and expand the hole from the given @path, and then adjust it | |
| 4044 | + * if it's partially or completely converted to delayed extents, insert | |
| 4045 | + * it into the extent cache tree if it's indeed a hole, finally return | |
| 4046 | + * the length of the determined extent. | |
| 4047 | + */ | |
| 4048 | +static ext4_lblk_t ext4_ext_determine_insert_hole(struct inode *inode, | |
| 4049 | + struct ext4_ext_path *path, | |
| 4050 | + ext4_lblk_t lblk) | |
| 4051 | +{ | |
| 4052 | + ext4_lblk_t hole_start, len; | |
| 4053 | + struct extent_status es; | |
| 4054 | + | |
| 4055 | + hole_start = lblk; | |
| 4056 | + len = ext4_ext_find_hole(inode, path, &hole_start); | |
| 4057 | +again: | |
| 4058 | + ext4_es_find_extent_range(inode, &ext4_es_is_delayed, hole_start, | |
| 4059 | + hole_start + len - 1, &es); | |
| 4060 | + if (!es.es_len) | |
| 4061 | + goto insert_hole; | |
| 4062 | + | |
| 4063 | + /* | |
| 4064 | + * There's a delalloc extent in the hole, handle it if the delalloc | |
| 4065 | + * extent is in front of, behind and straddle the queried range. | |
| 4066 | + */ | |
| 4067 | + if (lblk >= es.es_lblk + es.es_len) { | |
| 4068 | + /* | |
| 4069 | + * The delalloc extent is in front of the queried range, | |
| 4070 | + * find again from the queried start block. | |
| 4071 | + */ | |
| 4072 | + len -= lblk - hole_start; | |
| 4073 | + hole_start = lblk; | |
| 4074 | + goto again; | |
| 4075 | + } else if (in_range(lblk, es.es_lblk, es.es_len)) { | |
| 4076 | + /* | |
| 4077 | + * The delalloc extent containing lblk, it must have been | |
| 4078 | + * added after ext4_map_blocks() checked the extent status | |
| 4079 | + * tree so we are not holding i_rwsem and delalloc info is | |
| 4080 | + * only stabilized by i_data_sem we are going to release | |
| 4081 | + * soon. Don't modify the extent status tree and report | |
| 4082 | + * extent as a hole, just adjust the length to the delalloc | |
| 4083 | + * extent's after lblk. | |
| 4084 | + */ | |
| 4085 | + len = es.es_lblk + es.es_len - lblk; | |
| 4086 | + return len; | |
| 4087 | + } else { | |
| 4088 | + /* | |
| 4089 | + * The delalloc extent is partially or completely behind | |
| 4090 | + * the queried range, update hole length until the | |
| 4091 | + * beginning of the delalloc extent. | |
| 4092 | + */ | |
| 4093 | + len = min(es.es_lblk - hole_start, len); | |
| 4094 | + } | |
| 4095 | + | |
| 4096 | +insert_hole: | |
| 4097 | + /* Put just found gap into cache to speed up subsequent requests */ | |
| 4098 | + ext_debug(inode, " -> %u:%u\n", hole_start, len); | |
| 4099 | + ext4_es_insert_extent(inode, hole_start, len, ~0, EXTENT_STATUS_HOLE); | |
| 4100 | + | |
| 4101 | + /* Update hole_len to reflect hole size after lblk */ | |
| 4102 | + if (hole_start != lblk) | |
| 4103 | + len -= lblk - hole_start; | |
| 4104 | + | |
| 4105 | + return len; | |
| 4106 | +} | |
| 4065 | 4107 | |
| 4066 | 4108 | /* |
| 4067 | 4109 | * Block allocation/map/preallocation routine for extents based files |
| @@ -4179,22 +4221,12 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, · 111 unmodified lines | ||
| 4179 | 4221 | * we couldn't try to create block if create flag is zero |
| 4180 | 4222 | */ |
| 4181 | 4223 | if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) { |
| 4182 | − ext4_lblk_t hole_start, hole_len; | |
| 4224 | + ext4_lblk_t len; | |
| 4183 | 4225 | |
| 4184 | − hole_start = map->m_lblk; | |
| 4185 | − hole_len = ext4_ext_determine_hole(inode, path, &hole_start); | |
| 4186 | − /* | |
| 4187 | − * put just found gap into cache to speed up | |
| 4188 | − * subsequent requests | |
| 4189 | − */ | |
| 4190 | − ext4_ext_put_gap_in_cache(inode, hole_start, hole_len); | |
| 4226 | + len = ext4_ext_determine_insert_hole(inode, path, map->m_lblk); | |
| 4191 | 4227 | |
| 4192 | − /* Update hole_len to reflect hole size after map->m_lblk */ | |
| 4193 | − if (hole_start != map->m_lblk) | |
| 4194 | − hole_len -= map->m_lblk - hole_start; | |
| 4195 | 4228 | map->m_pblk = 0; |
| 4196 | − map->m_len = min_t(unsigned int, map->m_len, hole_len); | |
| 4197 | − | |
| 4229 | + map->m_len = min_t(unsigned int, map->m_len, len); | |
| 4198 | 4230 | goto out; |
| 4199 | 4231 | } |
| 4200 | 4232 | |
| @@ -4313,7 +4345,7 @@ got_allocated_blocks: · 112 unmodified lines | ||
| 4313 | 4345 | * not a good idea to call discard here directly, |
| 4314 | 4346 | * but otherwise we'd need to call it every free(). |
| 4315 | 4347 | */ |
| 4316 | − ext4_discard_preallocations(inode, 0); | |
| 4348 | + ext4_discard_preallocations(inode); | |
| 4317 | 4349 | if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) |
| 4318 | 4350 | fb_flags = EXT4_FREE_BLOCKS_NO_QUOT_UPDATE; |
| 4319 | 4351 | ext4_free_blocks(handle, inode, NULL, newblock, |
| @@ -5357,7 +5389,7 @@ static int ext4_collapse_range(struct file *file, loff_t offset, loff_t len) · 1037 unmodified lines | ||
| 5357 | 5389 | ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_FALLOC_RANGE, handle); |
| 5358 | 5390 | |
| 5359 | 5391 | down_write(&EXT4_I(inode)->i_data_sem); |
| 5360 | − ext4_discard_preallocations(inode, 0); | |
| 5392 | + ext4_discard_preallocations(inode); | |
| 5361 | 5393 | ext4_es_remove_extent(inode, punch_start, EXT_MAX_BLOCKS - punch_start); |
| 5362 | 5394 | |
| 5363 | 5395 | ret = ext4_ext_remove_space(inode, punch_start, punch_stop - 1); |
| @@ -5365,7 +5397,7 @@ static int ext4_collapse_range(struct file *file, loff_t offset, loff_t len) · 1 unmodified line | ||
| 5365 | 5397 | up_write(&EXT4_I(inode)->i_data_sem); |
| 5366 | 5398 | goto out_stop; |
| 5367 | 5399 | } |
| 5368 | − ext4_discard_preallocations(inode, 0); | |
| 5400 | + ext4_discard_preallocations(inode); | |
| 5369 | 5401 | |
| 5370 | 5402 | ret = ext4_ext_shift_extents(inode, handle, punch_stop, |
| 5371 | 5403 | punch_stop - punch_start, SHIFT_LEFT); |
| @@ -5497,7 +5529,7 @@ static int ext4_insert_range(struct file *file, loff_t offset, loff_t len) · 125 unmodified lines | ||
| 5497 | 5529 | goto out_stop; |
| 5498 | 5530 | |
| 5499 | 5531 | down_write(&EXT4_I(inode)->i_data_sem); |
| 5500 | − ext4_discard_preallocations(inode, 0); | |
| 5532 | + ext4_discard_preallocations(inode); | |
| 5501 | 5533 | |
| 5502 | 5534 | path = ext4_find_extent(inode, offset_lblk, NULL, 0); |
| 5503 | 5535 | if (IS_ERR(path)) { |
| @@ -174,7 +174,7 @@ static int ext4_release_file(struct inode *inode, struct file *filp) · 173 unmodified lines | ||
| 174 | 174 | (atomic_read(&inode->i_writecount) == 1) && |
| 175 | 175 | !EXT4_I(inode)->i_reserved_data_blocks) { |
| 176 | 176 | down_write(&EXT4_I(inode)->i_data_sem); |
| 177 | − ext4_discard_preallocations(inode, 0); | |
| 177 | + ext4_discard_preallocations(inode); | |
| 178 | 178 | up_write(&EXT4_I(inode)->i_data_sem); |
| 179 | 179 | } |
| 180 | 180 | if (is_dx(inode) && filp->private_data) |
| @@ -714,7 +714,7 @@ static int ext4_ind_trunc_restart_fn(handle_t *handle, struct inode *inode, · 713 unmodified lines | ||
| 714 | 714 | * i_rwsem. So we can safely drop the i_data_sem here. |
| 715 | 715 | */ |
| 716 | 716 | BUG_ON(EXT4_JOURNAL(inode) == NULL); |
| 717 | − ext4_discard_preallocations(inode, 0); | |
| 717 | + ext4_discard_preallocations(inode); | |
| 718 | 718 | up_write(&EXT4_I(inode)->i_data_sem); |
| 719 | 719 | *dropped = 1; |
| 720 | 720 | return 0; |
| @@ -371,7 +371,7 @@ void ext4_da_update_reserve_space(struct inode *inode, · 370 unmodified lines | ||
| 371 | 371 | */ |
| 372 | 372 | if ((ei->i_reserved_data_blocks == 0) && |
| 373 | 373 | !inode_is_open_for_write(inode)) |
| 374 | − ext4_discard_preallocations(inode, 0); | |
| 374 | + ext4_discard_preallocations(inode); | |
| 375 | 375 | } |
| 376 | 376 | |
| 377 | 377 | static int __check_block_validity(struct inode *inode, const char *func, |
| @@ -515,6 +515,8 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, · 137 unmodified lines | ||
| 515 | 515 | map->m_len = retval; |
| 516 | 516 | } else if (ext4_es_is_delayed(&es) || ext4_es_is_hole(&es)) { |
| 517 | 517 | map->m_pblk = 0; |
| 518 | + map->m_flags |= ext4_es_is_delayed(&es) ? | |
| 519 | + EXT4_MAP_DELAYED : 0; | |
| 518 | 520 | retval = es.es_len - (map->m_lblk - es.es_lblk); |
| 519 | 521 | if (retval > map->m_len) |
| 520 | 522 | retval = map->m_len; |
| @@ -1703,11 +1705,8 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock, · 1182 unmodified lines | ||
| 1703 | 1705 | |
| 1704 | 1706 | /* Lookup extent status tree firstly */ |
| 1705 | 1707 | if (ext4_es_lookup_extent(inode, iblock, NULL, &es)) { |
| 1706 | − if (ext4_es_is_hole(&es)) { | |
| 1707 | − retval = 0; | |
| 1708 | − down_read(&EXT4_I(inode)->i_data_sem); | |
| 1708 | + if (ext4_es_is_hole(&es)) | |
| 1709 | 1709 | goto add_delayed; |
| 1710 | − } | |
| 1711 | 1710 | |
| 1712 | 1711 | /* |
| 1713 | 1712 | * Delayed extent could be allocated by fallocate. |
| @@ -1749,26 +1748,11 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock, · 35 unmodified lines | ||
| 1749 | 1748 | retval = ext4_ext_map_blocks(NULL, inode, map, 0); |
| 1750 | 1749 | else |
| 1751 | 1750 | retval = ext4_ind_map_blocks(NULL, inode, map, 0); |
| 1752 | − | |
| 1753 | −add_delayed: | |
| 1754 | − if (retval == 0) { | |
| 1755 | − int ret; | |
| 1756 | − | |
| 1757 | − /* | |
| 1758 | − * XXX: __block_prepare_write() unmaps passed block, | |
| 1759 | − * is it OK? | |
| 1760 | − */ | |
| 1761 | − | |
| 1762 | − ret = ext4_insert_delayed_block(inode, map->m_lblk); | |
| 1763 | − if (ret != 0) { | |
| 1764 | − retval = ret; | |
| 1765 | − goto out_unlock; | |
| 1766 | − } | |
| 1767 | − | |
| 1768 | − map_bh(bh, inode->i_sb, invalid_block); | |
| 1769 | − set_buffer_new(bh); | |
| 1770 | − set_buffer_delay(bh); | |
| 1771 | − } else if (retval > 0) { | |
| 1751 | + if (retval < 0) { | |
| 1752 | + up_read(&EXT4_I(inode)->i_data_sem); | |
| 1753 | + return retval; | |
| 1754 | + } | |
| 1755 | + if (retval > 0) { | |
| 1772 | 1756 | unsigned int status; |
| 1773 | 1757 | |
| 1774 | 1758 | if (unlikely(retval != map->m_len)) { |
| @@ -1783,11 +1767,21 @@ add_delayed: · 8 unmodified lines | ||
| 1783 | 1767 | EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; |
| 1784 | 1768 | ext4_es_insert_extent(inode, map->m_lblk, map->m_len, |
| 1785 | 1769 | map->m_pblk, status); |
| 1770 | + up_read(&EXT4_I(inode)->i_data_sem); | |
| 1771 | + return retval; | |
| 1786 | 1772 | } |
| 1773 | + up_read(&EXT4_I(inode)->i_data_sem); | |
| 1787 | 1774 | |
| 1788 | −out_unlock: | |
| 1789 | − up_read((&EXT4_I(inode)->i_data_sem)); | |
| 1775 | +add_delayed: | |
| 1776 | + down_write(&EXT4_I(inode)->i_data_sem); | |
| 1777 | + retval = ext4_insert_delayed_block(inode, map->m_lblk); | |
| 1778 | + up_write(&EXT4_I(inode)->i_data_sem); | |
| 1779 | + if (retval) | |
| 1780 | + return retval; | |
| 1790 | 1781 | |
| 1782 | + map_bh(bh, inode->i_sb, invalid_block); | |
| 1783 | + set_buffer_new(bh); | |
| 1784 | + set_buffer_delay(bh); | |
| 1791 | 1785 | return retval; |
| 1792 | 1786 | } |
| 1793 | 1787 | |
| @@ -3268,6 +3262,9 @@ static void ext4_set_iomap(struct inode *inode, struct iomap *iomap, · 1474 unmodified lines | ||
| 3268 | 3262 | iomap->addr = (u64) map->m_pblk << blkbits; |
| 3269 | 3263 | if (flags & IOMAP_DAX) |
| 3270 | 3264 | iomap->addr += EXT4_SB(inode->i_sb)->s_dax_part_off; |
| 3265 | + } else if (map->m_flags & EXT4_MAP_DELAYED) { | |
| 3266 | + iomap->type = IOMAP_DELALLOC; | |
| 3267 | + iomap->addr = IOMAP_NULL_ADDR; | |
| 3271 | 3268 | } else { |
| 3272 | 3269 | iomap->type = IOMAP_HOLE; |
| 3273 | 3270 | iomap->addr = IOMAP_NULL_ADDR; |
| @@ -3430,35 +3427,11 @@ const struct iomap_ops ext4_iomap_overwrite_ops = { · 156 unmodified lines | ||
| 3430 | 3427 | .iomap_end = ext4_iomap_end, |
| 3431 | 3428 | }; |
| 3432 | 3429 | |
| 3433 | −static bool ext4_iomap_is_delalloc(struct inode *inode, | |
| 3434 | − struct ext4_map_blocks *map) | |
| 3435 | −{ | |
| 3436 | − struct extent_status es; | |
| 3437 | − ext4_lblk_t offset = 0, end = map->m_lblk + map->m_len - 1; | |
| 3438 | − | |
| 3439 | − ext4_es_find_extent_range(inode, &ext4_es_is_delayed, | |
| 3440 | − map->m_lblk, end, &es); | |
| 3441 | − | |
| 3442 | − if (!es.es_len || es.es_lblk > end) | |
| 3443 | − return false; | |
| 3444 | − | |
| 3445 | − if (es.es_lblk > map->m_lblk) { | |
| 3446 | − map->m_len = es.es_lblk - map->m_lblk; | |
| 3447 | − return false; | |
| 3448 | − } | |
| 3449 | − | |
| 3450 | − offset = map->m_lblk - es.es_lblk; | |
| 3451 | − map->m_len = es.es_len - offset; | |
| 3452 | − | |
| 3453 | − return true; | |
| 3454 | −} | |
| 3455 | − | |
| 3456 | 3430 | static int ext4_iomap_begin_report(struct inode *inode, loff_t offset, |
| 3457 | 3431 | loff_t length, unsigned int flags, |
| 3458 | 3432 | struct iomap *iomap, struct iomap *srcmap) |
| 3459 | 3433 | { |
| 3460 | 3434 | int ret; |
| 3461 | − bool delalloc = false; | |
| 3462 | 3435 | struct ext4_map_blocks map; |
| 3463 | 3436 | u8 blkbits = inode->i_blkbits; |
| 3464 | 3437 | |
| @@ -3499,13 +3472,8 @@ static int ext4_iomap_begin_report(struct inode *inode, loff_t offset, · 34 unmodified lines | ||
| 3499 | 3472 | ret = ext4_map_blocks(NULL, inode, &map, 0); |
| 3500 | 3473 | if (ret < 0) |
| 3501 | 3474 | return ret; |
| 3502 | − if (ret == 0) | |
| 3503 | − delalloc = ext4_iomap_is_delalloc(inode, &map); | |
| 3504 | − | |
| 3505 | 3475 | set_iomap: |
| 3506 | 3476 | ext4_set_iomap(inode, iomap, &map, offset, length, flags); |
| 3507 | − if (delalloc && iomap->type == IOMAP_HOLE) | |
| 3508 | − iomap->type = IOMAP_DELALLOC; | |
| 3509 | 3477 | |
| 3510 | 3478 | return 0; |
| 3511 | 3479 | } |
| @@ -4015,12 +3983,12 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length) · 503 unmodified lines | ||
| 4015 | 3983 | |
| 4016 | 3984 | /* If there are blocks to remove, do it */ |
| 4017 | 3985 | if (stop_block > first_block) { |
| 3986 | + ext4_lblk_t hole_len = stop_block - first_block; | |
| 4018 | 3987 | |
| 4019 | 3988 | down_write(&EXT4_I(inode)->i_data_sem); |
| 4020 | − ext4_discard_preallocations(inode, 0); | |
| 3989 | + ext4_discard_preallocations(inode); | |
| 4021 | 3990 | |
| 4022 | − ext4_es_remove_extent(inode, first_block, | |
| 4023 | − stop_block - first_block); | |
| 3991 | + ext4_es_remove_extent(inode, first_block, hole_len); | |
| 4024 | 3992 | |
| 4025 | 3993 | if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) |
| 4026 | 3994 | ret = ext4_ext_remove_space(inode, first_block, |
| @@ -4029,6 +3997,8 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length) · 2 unmodified lines | ||
| 4029 | 3997 | ret = ext4_ind_remove_space(handle, inode, first_block, |
| 4030 | 3998 | stop_block); |
| 4031 | 3999 | |
| 4000 | + ext4_es_insert_extent(inode, first_block, hole_len, ~0, | |
| 4001 | + EXTENT_STATUS_HOLE); | |
| 4032 | 4002 | up_write(&EXT4_I(inode)->i_data_sem); |
| 4033 | 4003 | } |
| 4034 | 4004 | ext4_fc_track_range(handle, inode, first_block, stop_block); |
| @@ -4170,7 +4140,7 @@ int ext4_truncate(struct inode *inode) · 135 unmodified lines | ||
| 4170 | 4140 | |
| 4171 | 4141 | down_write(&EXT4_I(inode)->i_data_sem); |
| 4172 | 4142 | |
| 4173 | − ext4_discard_preallocations(inode, 0); | |
| 4143 | + ext4_discard_preallocations(inode); | |
| 4174 | 4144 | |
| 4175 | 4145 | if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) |
| 4176 | 4146 | err = ext4_ext_truncate(handle, inode); |
| @@ -467,7 +467,7 @@ static long swap_inode_boot_loader(struct super_block *sb, · 466 unmodified lines | ||
| 467 | 467 | ext4_reset_inode_seed(inode); |
| 468 | 468 | ext4_reset_inode_seed(inode_bl); |
| 469 | 469 | |
| 470 | − ext4_discard_preallocations(inode, 0); | |
| 470 | + ext4_discard_preallocations(inode); | |
| 471 | 471 | |
| 472 | 472 | err = ext4_mark_inode_dirty(handle, inode); |
| 473 | 473 | if (err < 0) { |
| @@ -564,14 +564,14 @@ static void mb_free_blocks_double(struct inode *inode, struct ext4_buddy *e4b, · 563 unmodified lines | ||
| 564 | 564 | |
| 565 | 565 | blocknr = ext4_group_first_block_no(sb, e4b->bd_group); |
| 566 | 566 | blocknr += EXT4_C2B(EXT4_SB(sb), first + i); |
| 567 | + ext4_mark_group_bitmap_corrupted(sb, e4b->bd_group, | |
| 568 | + EXT4_GROUP_INFO_BBITMAP_CORRUPT); | |
| 567 | 569 | ext4_grp_locked_error(sb, e4b->bd_group, |
| 568 | 570 | inode ? inode->i_ino : 0, |
| 569 | 571 | blocknr, |
| 570 | 572 | "freeing block already freed " |
| 571 | 573 | "(bit %u)", |
| 572 | 574 | first + i); |
| 573 | − ext4_mark_group_bitmap_corrupted(sb, e4b->bd_group, | |
| 574 | − EXT4_GROUP_INFO_BBITMAP_CORRUPT); | |
| 575 | 575 | } |
| 576 | 576 | mb_clear_bit(first + i, e4b->bd_info->bb_bitmap); |
| 577 | 577 | } |
| @@ -677,7 +677,7 @@ do { \ · 99 unmodified lines | ||
| 677 | 677 | } \ |
| 678 | 678 | } while (0) |
| 679 | 679 | |
| 680 | −static int __mb_check_buddy(struct ext4_buddy *e4b, char *file, | |
| 680 | +static void __mb_check_buddy(struct ext4_buddy *e4b, char *file, | |
| 681 | 681 | const char *function, int line) |
| 682 | 682 | { |
| 683 | 683 | struct super_block *sb = e4b->bd_sb; |
| @@ -696,7 +696,7 @@ static int __mb_check_buddy(struct ext4_buddy *e4b, char *file, · 12 unmodified lines | ||
| 696 | 696 | void *buddy2; |
| 697 | 697 | |
| 698 | 698 | if (e4b->bd_info->bb_check_counter++ % 10) |
| 699 | − return 0; | |
| 699 | + return; | |
| 700 | 700 | |
| 701 | 701 | while (order > 1) { |
| 702 | 702 | buddy = mb_find_buddy(e4b, order, &max); |
| @@ -758,7 +758,7 @@ static int __mb_check_buddy(struct ext4_buddy *e4b, char *file, · 55 unmodified lines | ||
| 758 | 758 | |
| 759 | 759 | grp = ext4_get_group_info(sb, e4b->bd_group); |
| 760 | 760 | if (!grp) |
| 761 | − return NULL; | |
| 761 | + return; | |
| 762 | 762 | list_for_each(cur, &grp->bb_prealloc_list) { |
| 763 | 763 | ext4_group_t groupnr; |
| 764 | 764 | struct ext4_prealloc_space *pa; |
| @@ -768,7 +768,6 @@ static int __mb_check_buddy(struct ext4_buddy *e4b, char *file, · 3 unmodified lines | ||
| 768 | 768 | for (i = 0; i < pa->pa_len; i++) |
| 769 | 769 | MB_CHECK_ASSERT(mb_test_bit(k + i, buddy)); |
| 770 | 770 | } |
| 771 | − return 0; | |
| 772 | 771 | } |
| 773 | 772 | #undef MB_CHECK_ASSERT |
| 774 | 773 | #define mb_check_buddy(e4b) __mb_check_buddy(e4b, \ |
| @@ -842,7 +841,7 @@ mb_update_avg_fragment_size(struct super_block *sb, struct ext4_group_info *grp) · 67 unmodified lines | ||
| 842 | 841 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
| 843 | 842 | int new_order; |
| 844 | 843 | |
| 845 | − if (!test_opt2(sb, MB_OPTIMIZE_SCAN) || grp->bb_free == 0) | |
| 844 | + if (!test_opt2(sb, MB_OPTIMIZE_SCAN) || grp->bb_fragments == 0) | |
| 846 | 845 | return; |
| 847 | 846 | |
| 848 | 847 | new_order = mb_avg_fragment_size_order(sb, |
| @@ -871,7 +870,7 @@ mb_update_avg_fragment_size(struct super_block *sb, struct ext4_group_info *grp) · 22 unmodified lines | ||
| 871 | 870 | * cr level needs an update. |
| 872 | 871 | */ |
| 873 | 872 | static void ext4_mb_choose_next_group_p2_aligned(struct ext4_allocation_context *ac, |
| 874 | − enum criteria *new_cr, ext4_group_t *group, ext4_group_t ngroups) | |
| 873 | + enum criteria *new_cr, ext4_group_t *group) | |
| 875 | 874 | { |
| 876 | 875 | struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb); |
| 877 | 876 | struct ext4_group_info *iter; |
| @@ -945,7 +944,7 @@ ext4_mb_find_good_group_avg_frag_lists(struct ext4_allocation_context *ac, int o · 67 unmodified lines | ||
| 945 | 944 | * order. Updates *new_cr if cr level needs an update. |
| 946 | 945 | */ |
| 947 | 946 | static void ext4_mb_choose_next_group_goal_fast(struct ext4_allocation_context *ac, |
| 948 | − enum criteria *new_cr, ext4_group_t *group, ext4_group_t ngroups) | |
| 947 | + enum criteria *new_cr, ext4_group_t *group) | |
| 949 | 948 | { |
| 950 | 949 | struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb); |
| 951 | 950 | struct ext4_group_info *grp = NULL; |
| @@ -990,7 +989,7 @@ static void ext4_mb_choose_next_group_goal_fast(struct ext4_allocation_context * · 38 unmodified lines | ||
| 990 | 989 | * much and fall to CR_GOAL_LEN_SLOW in that case. |
| 991 | 990 | */ |
| 992 | 991 | static void ext4_mb_choose_next_group_best_avail(struct ext4_allocation_context *ac, |
| 993 | − enum criteria *new_cr, ext4_group_t *group, ext4_group_t ngroups) | |
| 992 | + enum criteria *new_cr, ext4_group_t *group) | |
| 994 | 993 | { |
| 995 | 994 | struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb); |
| 996 | 995 | struct ext4_group_info *grp = NULL; |
| @@ -1125,11 +1124,11 @@ static void ext4_mb_choose_next_group(struct ext4_allocation_context *ac, · 128 unmodified lines | ||
| 1125 | 1124 | } |
| 1126 | 1125 | |
| 1127 | 1126 | if (*new_cr == CR_POWER2_ALIGNED) { |
| 1128 | − ext4_mb_choose_next_group_p2_aligned(ac, new_cr, group, ngroups); | |
| 1127 | + ext4_mb_choose_next_group_p2_aligned(ac, new_cr, group); | |
| 1129 | 1128 | } else if (*new_cr == CR_GOAL_LEN_FAST) { |
| 1130 | − ext4_mb_choose_next_group_goal_fast(ac, new_cr, group, ngroups); | |
| 1129 | + ext4_mb_choose_next_group_goal_fast(ac, new_cr, group); | |
| 1131 | 1130 | } else if (*new_cr == CR_BEST_AVAIL_LEN) { |
| 1132 | − ext4_mb_choose_next_group_best_avail(ac, new_cr, group, ngroups); | |
| 1131 | + ext4_mb_choose_next_group_best_avail(ac, new_cr, group); | |
| 1133 | 1132 | } else { |
| 1134 | 1133 | /* |
| 1135 | 1134 | * TODO: For CR=2, we can arrange groups in an rb tree sorted by |
| @@ -1233,6 +1232,24 @@ void ext4_mb_generate_buddy(struct super_block *sb, · 97 unmodified lines | ||
| 1233 | 1232 | atomic64_add(period, &sbi->s_mb_generation_time); |
| 1234 | 1233 | } |
| 1235 | 1234 | |
| 1235 | +static void mb_regenerate_buddy(struct ext4_buddy *e4b) | |
| 1236 | +{ | |
| 1237 | + int count; | |
| 1238 | + int order = 1; | |
| 1239 | + void *buddy; | |
| 1240 | + | |
| 1241 | + while ((buddy = mb_find_buddy(e4b, order++, &count))) | |
| 1242 | + mb_set_bits(buddy, 0, count); | |
| 1243 | + | |
| 1244 | + e4b->bd_info->bb_fragments = 0; | |
| 1245 | + memset(e4b->bd_info->bb_counters, 0, | |
| 1246 | + sizeof(*e4b->bd_info->bb_counters) * | |
| 1247 | + (e4b->bd_sb->s_blocksize_bits + 2)); | |
| 1248 | + | |
| 1249 | + ext4_mb_generate_buddy(e4b->bd_sb, e4b->bd_buddy, | |
| 1250 | + e4b->bd_bitmap, e4b->bd_group, e4b->bd_info); | |
| 1251 | +} | |
| 1252 | + | |
| 1236 | 1253 | /* The buddy information is attached the buddy cache inode |
| 1237 | 1254 | * for convenience. The information regarding each group |
| 1238 | 1255 | * is loaded via ext4_mb_load_buddy. The information involve |
| @@ -1891,11 +1908,6 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b, · 652 unmodified lines | ||
| 1891 | 1908 | mb_check_buddy(e4b); |
| 1892 | 1909 | mb_free_blocks_double(inode, e4b, first, count); |
| 1893 | 1910 | |
| 1894 | − this_cpu_inc(discard_pa_seq); | |
| 1895 | − e4b->bd_info->bb_free += count; | |
| 1896 | − if (first < e4b->bd_info->bb_first_free) | |
| 1897 | − e4b->bd_info->bb_first_free = first; | |
| 1898 | − | |
| 1899 | 1911 | /* access memory sequentially: check left neighbour, |
| 1900 | 1912 | * clear range and then check right neighbour |
| 1901 | 1913 | */ |
| @@ -1909,21 +1921,31 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b, · 7 unmodified lines | ||
| 1909 | 1921 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
| 1910 | 1922 | ext4_fsblk_t blocknr; |
| 1911 | 1923 | |
| 1924 | + /* | |
| 1925 | + * Fastcommit replay can free already freed blocks which | |
| 1926 | + * corrupts allocation info. Regenerate it. | |
| 1927 | + */ | |
| 1928 | + if (sbi->s_mount_state & EXT4_FC_REPLAY) { | |
| 1929 | + mb_regenerate_buddy(e4b); | |
| 1930 | + goto check; | |
| 1931 | + } | |
| 1932 | + | |
| 1912 | 1933 | blocknr = ext4_group_first_block_no(sb, e4b->bd_group); |
| 1913 | 1934 | blocknr += EXT4_C2B(sbi, block); |
| 1914 | − if (!(sbi->s_mount_state & EXT4_FC_REPLAY)) { | |
| 1915 | − ext4_grp_locked_error(sb, e4b->bd_group, | |
| 1916 | − inode ? inode->i_ino : 0, | |
| 1917 | − blocknr, | |
| 1918 | − "freeing already freed block (bit %u); block bitmap corrupt.", | |
| 1919 | − block); | |
| 1920 | − ext4_mark_group_bitmap_corrupted( | |
| 1921 | − sb, e4b->bd_group, | |
| 1935 | + ext4_mark_group_bitmap_corrupted(sb, e4b->bd_group, | |
| 1922 | 1936 | EXT4_GROUP_INFO_BBITMAP_CORRUPT); |
| 1923 | − } | |
| 1924 | − goto done; | |
| 1937 | + ext4_grp_locked_error(sb, e4b->bd_group, | |
| 1938 | + inode ? inode->i_ino : 0, blocknr, | |
| 1939 | + "freeing already freed block (bit %u); block bitmap corrupt.", | |
| 1940 | + block); | |
| 1941 | + return; | |
| 1925 | 1942 | } |
| 1926 | 1943 | |
| 1944 | + this_cpu_inc(discard_pa_seq); | |
| 1945 | + e4b->bd_info->bb_free += count; | |
| 1946 | + if (first < e4b->bd_info->bb_first_free) | |
| 1947 | + e4b->bd_info->bb_first_free = first; | |
| 1948 | + | |
| 1927 | 1949 | /* let's maintain fragments counter */ |
| 1928 | 1950 | if (left_is_free && right_is_free) |
| 1929 | 1951 | e4b->bd_info->bb_fragments--; |
| @@ -1948,9 +1970,9 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b, · 18 unmodified lines | ||
| 1948 | 1970 | if (first <= last) |
| 1949 | 1971 | mb_buddy_mark_free(e4b, first >> 1, last >> 1); |
| 1950 | 1972 | |
| 1951 | −done: | |
| 1952 | 1973 | mb_set_largest_free_order(sb, e4b->bd_info); |
| 1953 | 1974 | mb_update_avg_fragment_size(sb, e4b->bd_info); |
| 1975 | +check: | |
| 1954 | 1976 | mb_check_buddy(e4b); |
| 1955 | 1977 | } |
| 1956 | 1978 | |
| @@ -2276,6 +2298,9 @@ void ext4_mb_try_best_found(struct ext4_allocation_context *ac, · 319 unmodified lines | ||
| 2276 | 2298 | return; |
| 2277 | 2299 | |
| 2278 | 2300 | ext4_lock_group(ac->ac_sb, group); |
| 2301 | + if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info))) | |
| 2302 | + goto out; | |
| 2303 | + | |
| 2279 | 2304 | max = mb_find_extent(e4b, ex.fe_start, ex.fe_len, &ex); |
| 2280 | 2305 | |
| 2281 | 2306 | if (max > 0) { |
| @@ -2283,6 +2308,7 @@ void ext4_mb_try_best_found(struct ext4_allocation_context *ac, · 1 unmodified line | ||
| 2283 | 2308 | ext4_mb_use_best_found(ac, e4b); |
| 2284 | 2309 | } |
| 2285 | 2310 | |
| 2311 | +out: | |
| 2286 | 2312 | ext4_unlock_group(ac->ac_sb, group); |
| 2287 | 2313 | ext4_mb_unload_buddy(e4b); |
| 2288 | 2314 | } |
| @@ -2309,12 +2335,10 @@ int ext4_mb_find_by_goal(struct ext4_allocation_context *ac, · 20 unmodified lines | ||
| 2309 | 2335 | if (err) |
| 2310 | 2336 | return err; |
| 2311 | 2337 | |
| 2312 | − if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info))) { | |
| 2313 | − ext4_mb_unload_buddy(e4b); | |
| 2314 | − return 0; | |
| 2315 | − } | |
| 2316 | − | |
| 2317 | 2338 | ext4_lock_group(ac->ac_sb, group); |
| 2339 | + if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info))) | |
| 2340 | + goto out; | |
| 2341 | + | |
| 2318 | 2342 | max = mb_find_extent(e4b, ac->ac_g_ex.fe_start, |
| 2319 | 2343 | ac->ac_g_ex.fe_len, &ex); |
| 2320 | 2344 | ex.fe_logical = 0xDEADFA11; /* debug value */ |
| @@ -2347,6 +2371,7 @@ int ext4_mb_find_by_goal(struct ext4_allocation_context *ac, · 26 unmodified lines | ||
| 2347 | 2371 | ac->ac_b_ex = ex; |
| 2348 | 2372 | ext4_mb_use_best_found(ac, e4b); |
| 2349 | 2373 | } |
| 2374 | +out: | |
| 2350 | 2375 | ext4_unlock_group(ac->ac_sb, group); |
| 2351 | 2376 | ext4_mb_unload_buddy(e4b); |
| 2352 | 2377 | |
| @@ -2380,12 +2405,12 @@ void ext4_mb_simple_scan_group(struct ext4_allocation_context *ac, · 27 unmodified lines | ||
| 2380 | 2405 | |
| 2381 | 2406 | k = mb_find_next_zero_bit(buddy, max, 0); |
| 2382 | 2407 | if (k >= max) { |
| 2408 | + ext4_mark_group_bitmap_corrupted(ac->ac_sb, | |
| 2409 | + e4b->bd_group, | |
| 2410 | + EXT4_GROUP_INFO_BBITMAP_CORRUPT); | |
| 2383 | 2411 | ext4_grp_locked_error(ac->ac_sb, e4b->bd_group, 0, 0, |
| 2384 | 2412 | "%d free clusters of order %d. But found 0", |
| 2385 | 2413 | grp->bb_counters[i], i); |
| 2386 | − ext4_mark_group_bitmap_corrupted(ac->ac_sb, | |
| 2387 | − e4b->bd_group, | |
| 2388 | − EXT4_GROUP_INFO_BBITMAP_CORRUPT); | |
| 2389 | 2414 | break; |
| 2390 | 2415 | } |
| 2391 | 2416 | ac->ac_found++; |
| @@ -2436,12 +2461,12 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac, · 44 unmodified lines | ||
| 2436 | 2461 | * free blocks even though group info says we |
| 2437 | 2462 | * have free blocks |
| 2438 | 2463 | */ |
| 2464 | + ext4_mark_group_bitmap_corrupted(sb, e4b->bd_group, | |
| 2465 | + EXT4_GROUP_INFO_BBITMAP_CORRUPT); | |
| 2439 | 2466 | ext4_grp_locked_error(sb, e4b->bd_group, 0, 0, |
| 2440 | 2467 | "%d free clusters as per " |
| 2441 | 2468 | "group info. But bitmap says 0", |
| 2442 | 2469 | free); |
| 2443 | − ext4_mark_group_bitmap_corrupted(sb, e4b->bd_group, | |
| 2444 | − EXT4_GROUP_INFO_BBITMAP_CORRUPT); | |
| 2445 | 2470 | break; |
| 2446 | 2471 | } |
| 2447 | 2472 | |
| @@ -2467,12 +2492,12 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac, · 19 unmodified lines | ||
| 2467 | 2492 | if (WARN_ON(ex.fe_len <= 0)) |
| 2468 | 2493 | break; |
| 2469 | 2494 | if (free < ex.fe_len) { |
| 2495 | + ext4_mark_group_bitmap_corrupted(sb, e4b->bd_group, | |
| 2496 | + EXT4_GROUP_INFO_BBITMAP_CORRUPT); | |
| 2470 | 2497 | ext4_grp_locked_error(sb, e4b->bd_group, 0, 0, |
| 2471 | 2498 | "%d free clusters as per " |
| 2472 | 2499 | "group info. But got %d blocks", |
| 2473 | 2500 | free, ex.fe_len); |
| 2474 | − ext4_mark_group_bitmap_corrupted(sb, e4b->bd_group, | |
| 2475 | − EXT4_GROUP_INFO_BBITMAP_CORRUPT); | |
| 2476 | 2501 | /* |
| 2477 | 2502 | * The number of free blocks differs. This mostly |
| 2478 | 2503 | * indicate that the bitmap is corrupt. So exit |
| @@ -3725,7 +3750,7 @@ static int ext4_mb_cleanup_pa(struct ext4_group_info *grp) · 1246 unmodified lines | ||
| 3725 | 3750 | return count; |
| 3726 | 3751 | } |
| 3727 | 3752 | |
| 3728 | −int ext4_mb_release(struct super_block *sb) | |
| 3753 | +void ext4_mb_release(struct super_block *sb) | |
| 3729 | 3754 | { |
| 3730 | 3755 | ext4_group_t ngroups = ext4_get_groups_count(sb); |
| 3731 | 3756 | ext4_group_t i; |
| @@ -3801,8 +3826,6 @@ int ext4_mb_release(struct super_block *sb) · 69 unmodified lines | ||
| 3801 | 3826 | } |
| 3802 | 3827 | |
| 3803 | 3828 | free_percpu(sbi->s_locality_groups); |
| 3804 | − | |
| 3805 | − return 0; | |
| 3806 | 3829 | } |
| 3807 | 3830 | |
| 3808 | 3831 | static inline int ext4_issue_discard(struct super_block *sb, |
| @@ -5284,7 +5307,7 @@ static void ext4_mb_new_preallocation(struct ext4_allocation_context *ac) · 1475 unmodified lines | ||
| 5284 | 5307 | * the caller MUST hold group/inode locks. |
| 5285 | 5308 | * TODO: optimize the case when there are no in-core structures yet |
| 5286 | 5309 | */ |
| 5287 | −static noinline_for_stack int | |
| 5310 | +static noinline_for_stack void | |
| 5288 | 5311 | ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh, |
| 5289 | 5312 | struct ext4_prealloc_space *pa) |
| 5290 | 5313 | { |
| @@ -5334,11 +5357,9 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh, · 43 unmodified lines | ||
| 5334 | 5357 | */ |
| 5335 | 5358 | } |
| 5336 | 5359 | atomic_add(free, &sbi->s_mb_discarded); |
| 5337 | − | |
| 5338 | − return 0; | |
| 5339 | 5360 | } |
| 5340 | 5361 | |
| 5341 | −static noinline_for_stack int | |
| 5362 | +static noinline_for_stack void | |
| 5342 | 5363 | ext4_mb_release_group_pa(struct ext4_buddy *e4b, |
| 5343 | 5364 | struct ext4_prealloc_space *pa) |
| 5344 | 5365 | { |
| @@ -5352,13 +5373,11 @@ ext4_mb_release_group_pa(struct ext4_buddy *e4b, · 7 unmodified lines | ||
| 5352 | 5373 | if (unlikely(group != e4b->bd_group && pa->pa_len != 0)) { |
| 5353 | 5374 | ext4_warning(sb, "bad group: expected %u, group %u, pa_start %llu", |
| 5354 | 5375 | e4b->bd_group, group, pa->pa_pstart); |
| 5355 | − return 0; | |
| 5376 | + return; | |
| 5356 | 5377 | } |
| 5357 | 5378 | mb_free_blocks(pa->pa_inode, e4b, bit, pa->pa_len); |
| 5358 | 5379 | atomic_add(pa->pa_len, &EXT4_SB(sb)->s_mb_discarded); |
| 5359 | 5380 | trace_ext4_mballoc_discard(sb, NULL, group, bit, pa->pa_len); |
| 5360 | − | |
| 5361 | − return 0; | |
| 5362 | 5381 | } |
| 5363 | 5382 | |
| 5364 | 5383 | /* |
| @@ -5479,7 +5498,7 @@ out_dbg: · 114 unmodified lines | ||
| 5479 | 5498 | * |
| 5480 | 5499 | * FIXME!! Make sure it is valid at all the call sites |
| 5481 | 5500 | */ |
| 5482 | −void ext4_discard_preallocations(struct inode *inode, unsigned int needed) | |
| 5501 | +void ext4_discard_preallocations(struct inode *inode) | |
| 5483 | 5502 | { |
| 5484 | 5503 | struct ext4_inode_info *ei = EXT4_I(inode); |
| 5485 | 5504 | struct super_block *sb = inode->i_sb; |
| @@ -5491,9 +5510,8 @@ void ext4_discard_preallocations(struct inode *inode, unsigned int needed) · 5 unmodified lines | ||
| 5491 | 5510 | struct rb_node *iter; |
| 5492 | 5511 | int err; |
| 5493 | 5512 | |
| 5494 | − if (!S_ISREG(inode->i_mode)) { | |
| 5513 | + if (!S_ISREG(inode->i_mode)) | |
| 5495 | 5514 | return; |
| 5496 | − } | |
| 5497 | 5515 | |
| 5498 | 5516 | if (EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY) |
| 5499 | 5517 | return; |
| @@ -5501,15 +5519,12 @@ void ext4_discard_preallocations(struct inode *inode, unsigned int needed) · 1 unmodified line | ||
| 5501 | 5519 | mb_debug(sb, "discard preallocation for inode %lu\n", |
| 5502 | 5520 | inode->i_ino); |
| 5503 | 5521 | trace_ext4_discard_preallocations(inode, |
| 5504 | − atomic_read(&ei->i_prealloc_active), needed); | |
| 5505 | − | |
| 5506 | − if (needed == 0) | |
| 5507 | − needed = UINT_MAX; | |
| 5522 | + atomic_read(&ei->i_prealloc_active)); | |
| 5508 | 5523 | |
| 5509 | 5524 | repeat: |
| 5510 | 5525 | /* first, collect all pa's in the inode */ |
| 5511 | 5526 | write_lock(&ei->i_prealloc_lock); |
| 5512 | − for (iter = rb_first(&ei->i_prealloc_node); iter && needed; | |
| 5527 | + for (iter = rb_first(&ei->i_prealloc_node); iter; | |
| 5513 | 5528 | iter = rb_next(iter)) { |
| 5514 | 5529 | pa = rb_entry(iter, struct ext4_prealloc_space, |
| 5515 | 5530 | pa_node.inode_node); |
| @@ -5533,7 +5548,6 @@ repeat: · 17 unmodified lines | ||
| 5533 | 5548 | spin_unlock(&pa->pa_lock); |
| 5534 | 5549 | rb_erase(&pa->pa_node.inode_node, &ei->i_prealloc_node); |
| 5535 | 5550 | list_add(&pa->u.pa_tmp_list, &list); |
| 5536 | − needed--; | |
| 5537 | 5551 | continue; |
| 5538 | 5552 | } |
| 5539 | 5553 | |
| @@ -5943,7 +5957,7 @@ static void ext4_mb_add_n_trim(struct ext4_allocation_context *ac) · 403 unmodified lines | ||
| 5943 | 5957 | /* |
| 5944 | 5958 | * release all resource we used in allocation |
| 5945 | 5959 | */ |
| 5946 | −static int ext4_mb_release_context(struct ext4_allocation_context *ac) | |
| 5960 | +static void ext4_mb_release_context(struct ext4_allocation_context *ac) | |
| 5947 | 5961 | { |
| 5948 | 5962 | struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb); |
| 5949 | 5963 | struct ext4_prealloc_space *pa = ac->ac_pa; |
| @@ -5980,7 +5994,6 @@ static int ext4_mb_release_context(struct ext4_allocation_context *ac) · 30 unmodified lines | ||
| 5980 | 5994 | if (ac->ac_flags & EXT4_MB_HINT_GROUP_ALLOC) |
| 5981 | 5995 | mutex_unlock(&ac->ac_lg->lg_mutex); |
| 5982 | 5996 | ext4_mb_collect_stats(ac); |
| 5983 | − return 0; | |
| 5984 | 5997 | } |
| 5985 | 5998 | |
| 5986 | 5999 | static int ext4_mb_discard_preallocations(struct super_block *sb, int needed) |
| @@ -6761,6 +6774,9 @@ __releases(ext4_group_lock_ptr(sb, e4b->bd_group)) · 774 unmodified lines | ||
| 6761 | 6774 | bool set_trimmed = false; |
| 6762 | 6775 | void *bitmap; |
| 6763 | 6776 | |
| 6777 | + if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info))) | |
| 6778 | + return 0; | |
| 6779 | + | |
| 6764 | 6780 | last = ext4_last_grp_cluster(sb, e4b->bd_group); |
| 6765 | 6781 | bitmap = e4b->bd_bitmap; |
| 6766 | 6782 | if (start == 0 && max >= last) |
| @@ -192,7 +192,6 @@ struct ext4_allocation_context { · 191 unmodified lines | ||
| 192 | 192 | */ |
| 193 | 193 | ext4_grpblk_t ac_orig_goal_len; |
| 194 | 194 | |
| 195 | − __u32 ac_groups_considered; | |
| 196 | 195 | __u32 ac_flags; /* allocation hints */ |
| 197 | 196 | __u16 ac_groups_scanned; |
| 198 | 197 | __u16 ac_groups_linear_remaining; |
| @@ -618,6 +618,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, __u64 orig_blk, · 617 unmodified lines | ||
| 618 | 618 | goto out; |
| 619 | 619 | o_end = o_start + len; |
| 620 | 620 | |
| 621 | + *moved_len = 0; | |
| 621 | 622 | while (o_start < o_end) { |
| 622 | 623 | struct ext4_extent *ex; |
| 623 | 624 | ext4_lblk_t cur_blk, next_blk; |
| @@ -672,7 +673,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, __u64 orig_blk, · 48 unmodified lines | ||
| 672 | 673 | */ |
| 673 | 674 | ext4_double_up_write_data_sem(orig_inode, donor_inode); |
| 674 | 675 | /* Swap original branches with new branches */ |
| 675 | − move_extent_per_page(o_filp, donor_inode, | |
| 676 | + *moved_len += move_extent_per_page(o_filp, donor_inode, | |
| 676 | 677 | orig_page_index, donor_page_index, |
| 677 | 678 | offset_in_page, cur_len, |
| 678 | 679 | unwritten, &ret); |
| @@ -682,14 +683,11 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, __u64 orig_blk, · 3 unmodified lines | ||
| 682 | 683 | o_start += cur_len; |
| 683 | 684 | d_start += cur_len; |
| 684 | 685 | } |
| 685 | − *moved_len = o_start - orig_blk; | |
| 686 | − if (*moved_len > len) | |
| 687 | − *moved_len = len; | |
| 688 | 686 | |
| 689 | 687 | out: |
| 690 | 688 | if (*moved_len) { |
| 691 | − ext4_discard_preallocations(orig_inode, 0); | |
| 692 | − ext4_discard_preallocations(donor_inode, 0); | |
| 689 | + ext4_discard_preallocations(orig_inode); | |
| 690 | + ext4_discard_preallocations(donor_inode); | |
| 693 | 691 | } |
| 694 | 692 | |
| 695 | 693 | ext4_free_ext_path(path); |
| @@ -1525,7 +1525,7 @@ void ext4_clear_inode(struct inode *inode) · 1524 unmodified lines | ||
| 1525 | 1525 | ext4_fc_del(inode); |
| 1526 | 1526 | invalidate_inode_buffers(inode); |
| 1527 | 1527 | clear_inode(inode); |
| 1528 | − ext4_discard_preallocations(inode, 0); | |
| 1528 | + ext4_discard_preallocations(inode); | |
| 1529 | 1529 | ext4_es_remove_extent(inode, 0, EXT_MAX_BLOCKS); |
| 1530 | 1530 | dquot_drop(inode); |
| 1531 | 1531 | if (EXT4_I(inode)->jinode) { |
| @@ -32,25 +32,21 @@ · 31 unmodified lines | ||
| 32 | 32 | |
| 33 | 33 | static int gfs2_drevalidate(struct dentry *dentry, unsigned int flags) |
| 34 | 34 | { |
| 35 | − struct dentry *parent = NULL; | |
| 35 | + struct dentry *parent; | |
| 36 | 36 | struct gfs2_sbd *sdp; |
| 37 | 37 | struct gfs2_inode *dip; |
| 38 | − struct inode *dinode, *inode; | |
| 38 | + struct inode *inode; | |
| 39 | 39 | struct gfs2_holder d_gh; |
| 40 | 40 | struct gfs2_inode *ip = NULL; |
| 41 | 41 | int error, valid = 0; |
| 42 | 42 | int had_lock = 0; |
| 43 | 43 | |
| 44 | − if (flags & LOOKUP_RCU) { | |
| 45 | − dinode = d_inode_rcu(READ_ONCE(dentry->d_parent)); | |
| 46 | − if (!dinode) | |
| 47 | − return -ECHILD; | |
| 48 | − } else { | |
| 49 | − parent = dget_parent(dentry); | |
| 50 | − dinode = d_inode(parent); | |
| 51 | − } | |
| 52 | − sdp = GFS2_SB(dinode); | |
| 53 | − dip = GFS2_I(dinode); | |
| 44 | + if (flags & LOOKUP_RCU) | |
| 45 | + return -ECHILD; | |
| 46 | + | |
| 47 | + parent = dget_parent(dentry); | |
| 48 | + sdp = GFS2_SB(d_inode(parent)); | |
| 49 | + dip = GFS2_I(d_inode(parent)); | |
| 54 | 50 | inode = d_inode(dentry); |
| 55 | 51 | |
| 56 | 52 | if (inode) { |
| @@ -66,8 +62,7 @@ static int gfs2_drevalidate(struct dentry *dentry, unsigned int flags) · 9 unmodified lines | ||
| 66 | 62 | |
| 67 | 63 | had_lock = (gfs2_glock_is_locked_by_me(dip->i_gl) != NULL); |
| 68 | 64 | if (!had_lock) { |
| 69 | − error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, | |
| 70 | − flags & LOOKUP_RCU ? GL_NOBLOCK : 0, &d_gh); | |
| 65 | + error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); | |
| 71 | 66 | if (error) |
| 72 | 67 | goto out; |
| 73 | 68 | } |
| @@ -1882,10 +1882,10 @@ int gfs2_permission(struct mnt_idmap *idmap, struct inode *inode, · 1881 unmodified lines | ||
| 1882 | 1882 | WARN_ON_ONCE(!may_not_block); |
| 1883 | 1883 | return -ECHILD; |
| 1884 | 1884 | } |
| 1885 | − if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { | |
| 1886 | − int noblock = may_not_block ? GL_NOBLOCK : 0; | |
| 1887 | − error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, | |
| 1888 | − LM_FLAG_ANY | noblock, &i_gh); | |
| 1885 | + if (gfs2_glock_is_locked_by_me(gl) == NULL) { | |
| 1886 | + if (may_not_block) | |
| 1887 | + return -ECHILD; | |
| 1888 | + error = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); | |
| 1889 | 1889 | if (error) |
| 1890 | 1890 | return error; |
| 1891 | 1891 | } |
| @@ -4945,10 +4945,8 @@ nfsd_break_deleg_cb(struct file_lock *fl) · 4944 unmodified lines | ||
| 4945 | 4945 | */ |
| 4946 | 4946 | fl->fl_break_time = 0; |
| 4947 | 4947 | |
| 4948 | − spin_lock(&fp->fi_lock); | |
| 4949 | 4948 | fp->fi_had_conflict = true; |
| 4950 | 4949 | nfsd_break_one_deleg(dp); |
| 4951 | − spin_unlock(&fp->fi_lock); | |
| 4952 | 4950 | return false; |
| 4953 | 4951 | } |
| 4954 | 4952 | |
| @@ -5557,12 +5555,13 @@ nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp, · 602 unmodified lines | ||
| 5557 | 5555 | if (status) |
| 5558 | 5556 | goto out_unlock; |
| 5559 | 5557 | |
| 5558 | + status = -EAGAIN; | |
| 5559 | + if (fp->fi_had_conflict) | |
| 5560 | + goto out_unlock; | |
| 5561 | + | |
| 5560 | 5562 | spin_lock(&state_lock); |
| 5561 | 5563 | spin_lock(&fp->fi_lock); |
| 5562 | − if (fp->fi_had_conflict) | |
| 5563 | − status = -EAGAIN; | |
| 5564 | − else | |
| 5565 | − status = hash_delegation_locked(dp, fp); | |
| 5564 | + status = hash_delegation_locked(dp, fp); | |
| 5566 | 5565 | spin_unlock(&fp->fi_lock); |
| 5567 | 5566 | spin_unlock(&state_lock); |
| 5568 | 5567 | |
| @@ -87,7 +87,7 @@ · 86 unmodified lines | ||
| 87 | 87 | #define SMB_INTERFACE_POLL_INTERVAL 600 |
| 88 | 88 | |
| 89 | 89 | /* maximum number of PDUs in one compound */ |
| 90 | −#define MAX_COMPOUND 5 | |
| 90 | +#define MAX_COMPOUND 7 | |
| 91 | 91 | |
| 92 | 92 | /* |
| 93 | 93 | * Default number of credits to keep available for SMB3. |
| @@ -1032,6 +1032,8 @@ struct cifs_chan { · 938 unmodified lines | ||
| 1032 | 1032 | __u8 signkey[SMB3_SIGN_KEY_SIZE]; |
| 1033 | 1033 | }; |
| 1034 | 1034 | |
| 1035 | +#define CIFS_SES_FLAG_SCALE_CHANNELS (0x1) | |
| 1036 | + | |
| 1035 | 1037 | /* |
| 1036 | 1038 | * Session structure. One of these for each uid session with a particular host |
| 1037 | 1039 | */ |
| @@ -1064,6 +1066,7 @@ struct cifs_ses { · 26 unmodified lines | ||
| 1064 | 1066 | enum securityEnum sectype; /* what security flavor was specified? */ |
| 1065 | 1067 | bool sign; /* is signing required? */ |
| 1066 | 1068 | bool domainAuto:1; |
| 1069 | + unsigned int flags; | |
| 1067 | 1070 | __u16 session_flags; |
| 1068 | 1071 | __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE]; |
| 1069 | 1072 | __u8 smb3encryptionkey[SMB3_ENC_DEC_KEY_SIZE]; |
| @@ -75,6 +75,10 @@ cifs_ses_get_chan_index(struct cifs_ses *ses, · 74 unmodified lines | ||
| 75 | 75 | { |
| 76 | 76 | unsigned int i; |
| 77 | 77 | |
| 78 | + /* if the channel is waiting for termination */ | |
| 79 | + if (server->terminate) | |
| 80 | + return CIFS_INVAL_CHAN_INDEX; | |
| 81 | + | |
| 78 | 82 | for (i = 0; i < ses->chan_count; i++) { |
| 79 | 83 | if (ses->chans[i].server == server) |
| 80 | 84 | return i; |
| @@ -269,6 +273,8 @@ int cifs_try_adding_channels(struct cifs_ses *ses) · 188 unmodified lines | ||
| 269 | 273 | &iface->sockaddr, |
| 270 | 274 | rc); |
| 271 | 275 | kref_put(&iface->refcount, release_iface); |
| 276 | + /* failure to add chan should increase weight */ | |
| 277 | + iface->weight_fulfilled++; | |
| 272 | 278 | continue; |
| 273 | 279 | } |
| 274 | 280 | |
| @@ -178,6 +178,7 @@ cifs_chan_skip_or_disable(struct cifs_ses *ses, · 177 unmodified lines | ||
| 178 | 178 | } |
| 179 | 179 | |
| 180 | 180 | ses->chans[chan_index].server = NULL; |
| 181 | + server->terminate = true; | |
| 181 | 182 | spin_unlock(&ses->chan_lock); |
| 182 | 183 | |
| 183 | 184 | /* |
| @@ -188,7 +189,6 @@ cifs_chan_skip_or_disable(struct cifs_ses *ses, · 4 unmodified lines | ||
| 188 | 189 | */ |
| 189 | 190 | cifs_put_tcp_session(server, from_reconnect); |
| 190 | 191 | |
| 191 | − server->terminate = true; | |
| 192 | 192 | cifs_signal_cifsd_for_reconnect(server, false); |
| 193 | 193 | |
| 194 | 194 | /* mark primary server as needing reconnect */ |
| @@ -399,6 +399,15 @@ skip_sess_setup: · 204 unmodified lines | ||
| 399 | 399 | goto out; |
| 400 | 400 | } |
| 401 | 401 | |
| 402 | + spin_lock(&ses->ses_lock); | |
| 403 | + if (ses->flags & CIFS_SES_FLAG_SCALE_CHANNELS) { | |
| 404 | + spin_unlock(&ses->ses_lock); | |
| 405 | + mutex_unlock(&ses->session_mutex); | |
| 406 | + goto skip_add_channels; | |
| 407 | + } | |
| 408 | + ses->flags |= CIFS_SES_FLAG_SCALE_CHANNELS; | |
| 409 | + spin_unlock(&ses->ses_lock); | |
| 410 | + | |
| 402 | 411 | if (!rc && |
| 403 | 412 | (server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) { |
| 404 | 413 | mutex_unlock(&ses->session_mutex); |
| @@ -410,7 +419,7 @@ skip_sess_setup: · 5 unmodified lines | ||
| 410 | 419 | rc = SMB3_request_interfaces(xid, tcon, false); |
| 411 | 420 | free_xid(xid); |
| 412 | 421 | |
| 413 | − if (rc == -EOPNOTSUPP) { | |
| 422 | + if (rc == -EOPNOTSUPP && ses->chan_count > 1) { | |
| 414 | 423 | /* |
| 415 | 424 | * some servers like Azure SMB server do not advertise |
| 416 | 425 | * that multichannel has been disabled with server |
| @@ -428,17 +437,22 @@ skip_sess_setup: · 11 unmodified lines | ||
| 428 | 437 | if (ses->chan_max > ses->chan_count && |
| 429 | 438 | ses->iface_count && |
| 430 | 439 | !SERVER_IS_CHAN(server)) { |
| 431 | − if (ses->chan_count == 1) | |
| 440 | + if (ses->chan_count == 1) { | |
| 432 | 441 | cifs_server_dbg(VFS, "supports multichannel now\n"); |
| 442 | + queue_delayed_work(cifsiod_wq, &tcon->query_interfaces, | |
| 443 | + (SMB_INTERFACE_POLL_INTERVAL * HZ)); | |
| 444 | + } | |
| 433 | 445 | |
| 434 | 446 | cifs_try_adding_channels(ses); |
| 435 | − queue_delayed_work(cifsiod_wq, &tcon->query_interfaces, | |
| 436 | − (SMB_INTERFACE_POLL_INTERVAL * HZ)); | |
| 437 | 447 | } |
| 438 | 448 | } else { |
| 439 | 449 | mutex_unlock(&ses->session_mutex); |
| 440 | 450 | } |
| 451 | + | |
| 441 | 452 | skip_add_channels: |
| 453 | + spin_lock(&ses->ses_lock); | |
| 454 | + ses->flags &= ~CIFS_SES_FLAG_SCALE_CHANNELS; | |
| 455 | + spin_unlock(&ses->ses_lock); | |
| 442 | 456 | |
| 443 | 457 | if (smb2_command != SMB2_INTERNAL_CMD) |
| 444 | 458 | mod_delayed_work(cifsiod_wq, &server->reconnect, 0); |
| @@ -435,8 +435,8 @@ smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, · 434 unmodified lines | ||
| 435 | 435 | if (!(flags & CIFS_TRANSFORM_REQ)) |
| 436 | 436 | return __smb_send_rqst(server, num_rqst, rqst); |
| 437 | 437 | |
| 438 | − if (num_rqst > MAX_COMPOUND - 1) | |
| 439 | − return -ENOMEM; | |
| 438 | + if (WARN_ON_ONCE(num_rqst > MAX_COMPOUND - 1)) | |
| 439 | + return -EIO; | |
| 440 | 440 | |
| 441 | 441 | if (!server->ops->init_transform_rq) { |
| 442 | 442 | cifs_server_dbg(VFS, "Encryption requested but transform callback is missing\n"); |
| @@ -62,6 +62,46 @@ enum { · 61 unmodified lines | ||
| 62 | 62 | |
| 63 | 63 | #define EVENTFS_MODE_MASK (EVENTFS_SAVE_MODE - 1) |
| 64 | 64 | |
| 65 | +/* | |
| 66 | + * eventfs_inode reference count management. | |
| 67 | + * | |
| 68 | + * NOTE! We count only references from dentries, in the | |
| 69 | + * form 'dentry->d_fsdata'. There are also references from | |
| 70 | + * directory inodes ('ti->private'), but the dentry reference | |
| 71 | + * count is always a superset of the inode reference count. | |
| 72 | + */ | |
| 73 | +static void release_ei(struct kref *ref) | |
| 74 | +{ | |
| 75 | + struct eventfs_inode *ei = container_of(ref, struct eventfs_inode, kref); | |
| 76 | + | |
| 77 | + WARN_ON_ONCE(!ei->is_freed); | |
| 78 | + | |
| 79 | + kfree(ei->entry_attrs); | |
| 80 | + kfree_const(ei->name); | |
| 81 | + kfree_rcu(ei, rcu); | |
| 82 | +} | |
| 83 | + | |
| 84 | +static inline void put_ei(struct eventfs_inode *ei) | |
| 85 | +{ | |
| 86 | + if (ei) | |
| 87 | + kref_put(&ei->kref, release_ei); | |
| 88 | +} | |
| 89 | + | |
| 90 | +static inline void free_ei(struct eventfs_inode *ei) | |
| 91 | +{ | |
| 92 | + if (ei) { | |
| 93 | + ei->is_freed = 1; | |
| 94 | + put_ei(ei); | |
| 95 | + } | |
| 96 | +} | |
| 97 | + | |
| 98 | +static inline struct eventfs_inode *get_ei(struct eventfs_inode *ei) | |
| 99 | +{ | |
| 100 | + if (ei) | |
| 101 | + kref_get(&ei->kref); | |
| 102 | + return ei; | |
| 103 | +} | |
| 104 | + | |
| 65 | 105 | static struct dentry *eventfs_root_lookup(struct inode *dir, |
| 66 | 106 | struct dentry *dentry, |
| 67 | 107 | unsigned int flags); |
| @@ -156,33 +196,30 @@ static int eventfs_set_attr(struct mnt_idmap *idmap, struct dentry *dentry, · 88 unmodified lines | ||
| 156 | 196 | return ret; |
| 157 | 197 | } |
| 158 | 198 | |
| 159 | −static void update_top_events_attr(struct eventfs_inode *ei, struct dentry *dentry) | |
| 199 | +static void update_top_events_attr(struct eventfs_inode *ei, struct super_block *sb) | |
| 160 | 200 | { |
| 161 | − struct inode *inode; | |
| 201 | + struct inode *root; | |
| 162 | 202 | |
| 163 | 203 | /* Only update if the "events" was on the top level */ |
| 164 | 204 | if (!ei || !(ei->attr.mode & EVENTFS_TOPLEVEL)) |
| 165 | 205 | return; |
| 166 | 206 | |
| 167 | 207 | /* Get the tracefs root inode. */ |
| 168 | − inode = d_inode(dentry->d_sb->s_root); | |
| 169 | − ei->attr.uid = inode->i_uid; | |
| 170 | − ei->attr.gid = inode->i_gid; | |
| 208 | + root = d_inode(sb->s_root); | |
| 209 | + ei->attr.uid = root->i_uid; | |
| 210 | + ei->attr.gid = root->i_gid; | |
| 171 | 211 | } |
| 172 | 212 | |
| 173 | 213 | static void set_top_events_ownership(struct inode *inode) |
| 174 | 214 | { |
| 175 | 215 | struct tracefs_inode *ti = get_tracefs(inode); |
| 176 | 216 | struct eventfs_inode *ei = ti->private; |
| 177 | − struct dentry *dentry; | |
| 178 | 217 | |
| 179 | 218 | /* The top events directory doesn't get automatically updated */ |
| 180 | 219 | if (!ei || !ei->is_events || !(ei->attr.mode & EVENTFS_TOPLEVEL)) |
| 181 | 220 | return; |
| 182 | 221 | |
| 183 | − dentry = ei->dentry; | |
| 184 | − | |
| 185 | − update_top_events_attr(ei, dentry); | |
| 222 | + update_top_events_attr(ei, inode->i_sb); | |
| 186 | 223 | |
| 187 | 224 | if (!(ei->attr.mode & EVENTFS_SAVE_UID)) |
| 188 | 225 | inode->i_uid = ei->attr.uid; |
| @@ -233,10 +270,11 @@ static struct eventfs_inode *eventfs_find_events(struct dentry *dentry) · 44 unmodified lines | ||
| 233 | 270 | { |
| 234 | 271 | struct eventfs_inode *ei; |
| 235 | 272 | |
| 236 | − mutex_lock(&eventfs_mutex); | |
| 237 | 273 | do { |
| 238 | − /* The parent always has an ei, except for events itself */ | |
| 239 | − ei = dentry->d_parent->d_fsdata; | |
| 274 | + // The parent is stable because we do not do renames | |
| 275 | + dentry = dentry->d_parent; | |
| 276 | + // ... and directories always have d_fsdata | |
| 277 | + ei = dentry->d_fsdata; | |
| 240 | 278 | |
| 241 | 279 | /* |
| 242 | 280 | * If the ei is being freed, the ownership of the children |
| @@ -246,12 +284,10 @@ static struct eventfs_inode *eventfs_find_events(struct dentry *dentry) · 3 unmodified lines | ||
| 246 | 284 | ei = NULL; |
| 247 | 285 | break; |
| 248 | 286 | } |
| 249 | − | |
| 250 | − dentry = ei->dentry; | |
| 287 | + // Walk upwards until you find the events inode | |
| 251 | 288 | } while (!ei->is_events); |
| 252 | − mutex_unlock(&eventfs_mutex); | |
| 253 | 289 | |
| 254 | − update_top_events_attr(ei, dentry); | |
| 290 | + update_top_events_attr(ei, dentry->d_sb); | |
| 255 | 291 | |
| 256 | 292 | return ei; |
| 257 | 293 | } |
| @@ -282,11 +318,10 @@ static void update_inode_attr(struct dentry *dentry, struct inode *inode, · 24 unmodified lines | ||
| 282 | 318 | } |
| 283 | 319 | |
| 284 | 320 | /** |
| 285 | − * create_file - create a file in the tracefs filesystem | |
| 286 | − * @name: the name of the file to create. | |
| 321 | + * lookup_file - look up a file in the tracefs filesystem | |
| 322 | + * @dentry: the dentry to look up | |
| 287 | 323 | * @mode: the permission that the file should have. |
| 288 | 324 | * @attr: saved attributes changed by user |
| 289 | − * @parent: parent dentry for this file. | |
| 290 | 325 | * @data: something that the caller will want to get to later on. |
| 291 | 326 | * @fop: struct file_operations that should be used for this file. |
| 292 | 327 | * |
| @@ -294,30 +329,25 @@ static void update_inode_attr(struct dentry *dentry, struct inode *inode, · 1 unmodified line | ||
| 294 | 329 | * directory. The inode.i_private pointer will point to @data in the open() |
| 295 | 330 | * call. |
| 296 | 331 | */ |
| 297 | −static struct dentry *create_file(const char *name, umode_t mode, | |
| 332 | +static struct dentry *lookup_file(struct eventfs_inode *parent_ei, | |
| 333 | + struct dentry *dentry, | |
| 334 | + umode_t mode, | |
| 298 | 335 | struct eventfs_attr *attr, |
| 299 | − struct dentry *parent, void *data, | |
| 336 | + void *data, | |
| 300 | 337 | const struct file_operations *fop) |
| 301 | 338 | { |
| 302 | 339 | struct tracefs_inode *ti; |
| 303 | − struct dentry *dentry; | |
| 304 | 340 | struct inode *inode; |
| 305 | 341 | |
| 306 | 342 | if (!(mode & S_IFMT)) |
| 307 | 343 | mode |= S_IFREG; |
| 308 | 344 | |
| 309 | 345 | if (WARN_ON_ONCE(!S_ISREG(mode))) |
| 310 | − return NULL; | |
| 311 | − | |
| 312 | − WARN_ON_ONCE(!parent); | |
| 313 | − dentry = eventfs_start_creating(name, parent); | |
| 314 | − | |
| 315 | − if (IS_ERR(dentry)) | |
| 316 | − return dentry; | |
| 346 | + return ERR_PTR(-EIO); | |
| 317 | 347 | |
| 318 | 348 | inode = tracefs_get_inode(dentry->d_sb); |
| 319 | 349 | if (unlikely(!inode)) |
| 320 | − return eventfs_failed_creating(dentry); | |
| 350 | + return ERR_PTR(-ENOMEM); | |
| 321 | 351 | |
| 322 | 352 | /* If the user updated the directory's attributes, use them */ |
| 323 | 353 | update_inode_attr(dentry, inode, attr, mode); |
| @@ -331,32 +361,31 @@ static struct dentry *create_file(const char *name, umode_t mode, · 7 unmodified lines | ||
| 331 | 361 | |
| 332 | 362 | ti = get_tracefs(inode); |
| 333 | 363 | ti->flags |= TRACEFS_EVENT_INODE; |
| 334 | − d_instantiate(dentry, inode); | |
| 335 | − fsnotify_create(dentry->d_parent->d_inode, dentry); | |
| 336 | − return eventfs_end_creating(dentry); | |
| 364 | + | |
| 365 | + // Files have their parent's ei as their fsdata | |
| 366 | + dentry->d_fsdata = get_ei(parent_ei); | |
| 367 | + | |
| 368 | + d_add(dentry, inode); | |
| 369 | + return NULL; | |
| 337 | 370 | }; |
| 338 | 371 | |
| 339 | 372 | /** |
| 340 | − * create_dir - create a dir in the tracefs filesystem | |
| 373 | + * lookup_dir_entry - look up a dir in the tracefs filesystem | |
| 374 | + * @dentry: the directory to look up | |
| 341 | 375 | * @ei: the eventfs_inode that represents the directory to create |
| 342 | − * @parent: parent dentry for this file. | |
| 343 | 376 | * |
| 344 | − * This function will create a dentry for a directory represented by | |
| 377 | + * This function will look up a dentry for a directory represented by | |
| 345 | 378 | * a eventfs_inode. |
| 346 | 379 | */ |
| 347 | −static struct dentry *create_dir(struct eventfs_inode *ei, struct dentry *parent) | |
| 380 | +static struct dentry *lookup_dir_entry(struct dentry *dentry, | |
| 381 | + struct eventfs_inode *pei, struct eventfs_inode *ei) | |
| 348 | 382 | { |
| 349 | 383 | struct tracefs_inode *ti; |
| 350 | − struct dentry *dentry; | |
| 351 | 384 | struct inode *inode; |
| 352 | 385 | |
| 353 | − dentry = eventfs_start_creating(ei->name, parent); | |
| 354 | − if (IS_ERR(dentry)) | |
| 355 | − return dentry; | |
| 356 | − | |
| 357 | 386 | inode = tracefs_get_inode(dentry->d_sb); |
| 358 | 387 | if (unlikely(!inode)) |
| 359 | − return eventfs_failed_creating(dentry); | |
| 388 | + return ERR_PTR(-ENOMEM); | |
| 360 | 389 | |
| 361 | 390 | /* If the user updated the directory's attributes, use them */ |
| 362 | 391 | update_inode_attr(dentry, inode, &ei->attr, |
| @@ -370,64 +399,46 @@ static struct dentry *create_dir(struct eventfs_inode *ei, struct dentry *parent · 7 unmodified lines | ||
| 370 | 399 | |
| 371 | 400 | ti = get_tracefs(inode); |
| 372 | 401 | ti->flags |= TRACEFS_EVENT_INODE; |
| 402 | + /* Only directories have ti->private set to an ei, not files */ | |
| 403 | + ti->private = ei; | |
| 373 | 404 | |
| 374 | − inc_nlink(inode); | |
| 375 | − d_instantiate(dentry, inode); | |
| 376 | − inc_nlink(dentry->d_parent->d_inode); | |
| 377 | − fsnotify_mkdir(dentry->d_parent->d_inode, dentry); | |
| 378 | − return eventfs_end_creating(dentry); | |
| 405 | + dentry->d_fsdata = get_ei(ei); | |
| 406 | + | |
| 407 | + d_add(dentry, inode); | |
| 408 | + return NULL; | |
| 379 | 409 | } |
| 380 | 410 | |
| 381 | −static void free_ei(struct eventfs_inode *ei) | |
| 411 | +static inline struct eventfs_inode *alloc_ei(const char *name) | |
| 382 | 412 | { |
| 383 | − kfree_const(ei->name); | |
| 384 | − kfree(ei->d_children); | |
| 385 | − kfree(ei->entry_attrs); | |
| 386 | − kfree(ei); | |
| 413 | + struct eventfs_inode *ei = kzalloc(sizeof(*ei), GFP_KERNEL); | |
| 414 | + | |
| 415 | + if (!ei) | |
| 416 | + return NULL; | |
| 417 | + | |
| 418 | + ei->name = kstrdup_const(name, GFP_KERNEL); | |
| 419 | + if (!ei->name) { | |
| 420 | + kfree(ei); | |
| 421 | + return NULL; | |
| 422 | + } | |
| 423 | + kref_init(&ei->kref); | |
| 424 | + return ei; | |
| 387 | 425 | } |
| 388 | 426 | |
| 389 | 427 | /** |
| 390 | − * eventfs_set_ei_status_free - remove the dentry reference from an eventfs_inode | |
| 391 | − * @ti: the tracefs_inode of the dentry | |
| 428 | + * eventfs_d_release - dentry is going away | |
| 392 | 429 | * @dentry: dentry which has the reference to remove. |
| 393 | 430 | * |
| 394 | 431 | * Remove the association between a dentry from an eventfs_inode. |
| 395 | 432 | */ |
| 396 | −void eventfs_set_ei_status_free(struct tracefs_inode *ti, struct dentry *dentry) | |
| 433 | +void eventfs_d_release(struct dentry *dentry) | |
| 397 | 434 | { |
| 398 | − struct eventfs_inode *ei; | |
| 399 | − int i; | |
| 400 | − | |
| 401 | − mutex_lock(&eventfs_mutex); | |
| 402 | − | |
| 403 | − ei = dentry->d_fsdata; | |
| 404 | − if (!ei) | |
| 405 | − goto out; | |
| 406 | − | |
| 407 | − /* This could belong to one of the files of the ei */ | |
| 408 | − if (ei->dentry != dentry) { | |
| 409 | − for (i = 0; i < ei->nr_entries; i++) { | |
| 410 | − if (ei->d_children[i] == dentry) | |
| 411 | − break; | |
| 412 | − } | |
| 413 | − if (WARN_ON_ONCE(i == ei->nr_entries)) | |
| 414 | − goto out; | |
| 415 | − ei->d_children[i] = NULL; | |
| 416 | − } else if (ei->is_freed) { | |
| 417 | − free_ei(ei); | |
| 418 | − } else { | |
| 419 | − ei->dentry = NULL; | |
| 420 | − } | |
| 421 | − | |
| 422 | − dentry->d_fsdata = NULL; | |
| 423 | − out: | |
| 424 | − mutex_unlock(&eventfs_mutex); | |
| 435 | + put_ei(dentry->d_fsdata); | |
| 425 | 436 | } |
| 426 | 437 | |
| 427 | 438 | /** |
| 428 | − * create_file_dentry - create a dentry for a file of an eventfs_inode | |
| 439 | + * lookup_file_dentry - create a dentry for a file of an eventfs_inode | |
| 429 | 440 | * @ei: the eventfs_inode that the file will be created under |
| 430 | − * @idx: the index into the d_children[] of the @ei | |
| 441 | + * @idx: the index into the entry_attrs[] of the @ei | |
| 431 | 442 | * @parent: The parent dentry of the created file. |
| 432 | 443 | * @name: The name of the file to create |
| 433 | 444 | * @mode: The mode of the file. |
| @@ -438,163 +449,17 @@ void eventfs_set_ei_status_free(struct tracefs_inode *ti, struct dentry *dentry) · 4 unmodified lines | ||
| 438 | 449 | * address located at @e_dentry. |
| 439 | 450 | */ |
| 440 | 451 | static struct dentry * |
| 441 | −create_file_dentry(struct eventfs_inode *ei, int idx, | |
| 442 | − struct dentry *parent, const char *name, umode_t mode, void *data, | |
| 452 | +lookup_file_dentry(struct dentry *dentry, | |
| 453 | + struct eventfs_inode *ei, int idx, | |
| 454 | + umode_t mode, void *data, | |
| 443 | 455 | const struct file_operations *fops) |
| 444 | 456 | { |
| 445 | 457 | struct eventfs_attr *attr = NULL; |
| 446 | − struct dentry **e_dentry = &ei->d_children[idx]; | |
| 447 | − struct dentry *dentry; | |
| 448 | − | |
| 449 | − WARN_ON_ONCE(!inode_is_locked(parent->d_inode)); | |
| 450 | 458 | |
| 451 | − mutex_lock(&eventfs_mutex); | |
| 452 | − if (ei->is_freed) { | |
| 453 | − mutex_unlock(&eventfs_mutex); | |
| 454 | − return NULL; | |
| 455 | − } | |
| 456 | − /* If the e_dentry already has a dentry, use it */ | |
| 457 | − if (*e_dentry) { | |
| 458 | − dget(*e_dentry); | |
| 459 | − mutex_unlock(&eventfs_mutex); | |
| 460 | − return *e_dentry; | |
| 461 | − } | |
| 462 | − | |
| 463 | − /* ei->entry_attrs are protected by SRCU */ | |
| 464 | 459 | if (ei->entry_attrs) |
| 465 | 460 | attr = &ei->entry_attrs[idx]; |
| 466 | 461 | |
| 467 | − mutex_unlock(&eventfs_mutex); | |
| 468 | − | |
| 469 | − dentry = create_file(name, mode, attr, parent, data, fops); | |
| 470 | − | |
| 471 | − mutex_lock(&eventfs_mutex); | |
| 472 | − | |
| 473 | − if (IS_ERR_OR_NULL(dentry)) { | |
| 474 | − /* | |
| 475 | − * When the mutex was released, something else could have | |
| 476 | − * created the dentry for this e_dentry. In which case | |
| 477 | − * use that one. | |
| 478 | − * | |
| 479 | − * If ei->is_freed is set, the e_dentry is currently on its | |
| 480 | − * way to being freed, don't return it. If e_dentry is NULL | |
| 481 | − * it means it was already freed. | |
| 482 | − */ | |
| 483 | − if (ei->is_freed) { | |
| 484 | − dentry = NULL; | |
| 485 | − } else { | |
| 486 | − dentry = *e_dentry; | |
| 487 | − dget(dentry); | |
| 488 | − } | |
| 489 | − mutex_unlock(&eventfs_mutex); | |
| 490 | − return dentry; | |
| 491 | − } | |
| 492 | − | |
| 493 | − if (!*e_dentry && !ei->is_freed) { | |
| 494 | − *e_dentry = dentry; | |
| 495 | − dentry->d_fsdata = ei; | |
| 496 | − } else { | |
| 497 | − /* | |
| 498 | − * Should never happen unless we get here due to being freed. | |
| 499 | − * Otherwise it means two dentries exist with the same name. | |
| 500 | − */ | |
| 501 | − WARN_ON_ONCE(!ei->is_freed); | |
| 502 | − dentry = NULL; | |
| 503 | − } | |
| 504 | − mutex_unlock(&eventfs_mutex); | |
| 505 | − | |
| 506 | − return dentry; | |
| 507 | −} | |
| 508 | − | |
| 509 | −/** | |
| 510 | − * eventfs_post_create_dir - post create dir routine | |
| 511 | − * @ei: eventfs_inode of recently created dir | |
| 512 | − * | |
| 513 | − * Map the meta-data of files within an eventfs dir to their parent dentry | |
| 514 | − */ | |
| 515 | −static void eventfs_post_create_dir(struct eventfs_inode *ei) | |
| 516 | −{ | |
| 517 | − struct eventfs_inode *ei_child; | |
| 518 | − struct tracefs_inode *ti; | |
| 519 | − | |
| 520 | − lockdep_assert_held(&eventfs_mutex); | |
| 521 | − | |
| 522 | − /* srcu lock already held */ | |
| 523 | − /* fill parent-child relation */ | |
| 524 | − list_for_each_entry_srcu(ei_child, &ei->children, list, | |
| 525 | − srcu_read_lock_held(&eventfs_srcu)) { | |
| 526 | − ei_child->d_parent = ei->dentry; | |
| 527 | − } | |
| 528 | − | |
| 529 | − ti = get_tracefs(ei->dentry->d_inode); | |
| 530 | − ti->private = ei; | |
| 531 | −} | |
| 532 | − | |
| 533 | −/** | |
| 534 | − * create_dir_dentry - Create a directory dentry for the eventfs_inode | |
| 535 | − * @pei: The eventfs_inode parent of ei. | |
| 536 | − * @ei: The eventfs_inode to create the directory for | |
| 537 | − * @parent: The dentry of the parent of this directory | |
| 538 | − * | |
| 539 | − * This creates and attaches a directory dentry to the eventfs_inode @ei. | |
| 540 | − */ | |
| 541 | −static struct dentry * | |
| 542 | −create_dir_dentry(struct eventfs_inode *pei, struct eventfs_inode *ei, | |
| 543 | − struct dentry *parent) | |
| 544 | −{ | |
| 545 | − struct dentry *dentry = NULL; | |
| 546 | − | |
| 547 | − WARN_ON_ONCE(!inode_is_locked(parent->d_inode)); | |
| 548 | − | |
| 549 | − mutex_lock(&eventfs_mutex); | |
| 550 | − if (pei->is_freed || ei->is_freed) { | |
| 551 | − mutex_unlock(&eventfs_mutex); | |
| 552 | − return NULL; | |
| 553 | − } | |
| 554 | − if (ei->dentry) { | |
| 555 | − /* If the eventfs_inode already has a dentry, use it */ | |
| 556 | − dentry = ei->dentry; | |
| 557 | − dget(dentry); | |
| 558 | − mutex_unlock(&eventfs_mutex); | |
| 559 | − return dentry; | |
| 560 | − } | |
| 561 | − mutex_unlock(&eventfs_mutex); | |
| 562 | − | |
| 563 | − dentry = create_dir(ei, parent); | |
| 564 | − | |
| 565 | − mutex_lock(&eventfs_mutex); | |
| 566 | − | |
| 567 | − if (IS_ERR_OR_NULL(dentry) && !ei->is_freed) { | |
| 568 | − /* | |
| 569 | − * When the mutex was released, something else could have | |
| 570 | − * created the dentry for this e_dentry. In which case | |
| 571 | − * use that one. | |
| 572 | − * | |
| 573 | − * If ei->is_freed is set, the e_dentry is currently on its | |
| 574 | − * way to being freed. | |
| 575 | − */ | |
| 576 | − dentry = ei->dentry; | |
| 577 | − if (dentry) | |
| 578 | − dget(dentry); | |
| 579 | − mutex_unlock(&eventfs_mutex); | |
| 580 | − return dentry; | |
| 581 | − } | |
| 582 | − | |
| 583 | − if (!ei->dentry && !ei->is_freed) { | |
| 584 | − ei->dentry = dentry; | |
| 585 | − eventfs_post_create_dir(ei); | |
| 586 | − dentry->d_fsdata = ei; | |
| 587 | − } else { | |
| 588 | − /* | |
| 589 | − * Should never happen unless we get here due to being freed. | |
| 590 | − * Otherwise it means two dentries exist with the same name. | |
| 591 | − */ | |
| 592 | − WARN_ON_ONCE(!ei->is_freed); | |
| 593 | − dentry = NULL; | |
| 594 | − } | |
| 595 | − mutex_unlock(&eventfs_mutex); | |
| 596 | − | |
| 597 | − return dentry; | |
| 462 | + return lookup_file(ei, dentry, mode, attr, data, fops); | |
| 598 | 463 | } |
| 599 | 464 | |
| 600 | 465 | /** |
| @@ -611,79 +476,50 @@ static struct dentry *eventfs_root_lookup(struct inode *dir, · 10 unmodified lines | ||
| 611 | 476 | struct dentry *dentry, |
| 612 | 477 | unsigned int flags) |
| 613 | 478 | { |
| 614 | − const struct file_operations *fops; | |
| 615 | − const struct eventfs_entry *entry; | |
| 616 | 479 | struct eventfs_inode *ei_child; |
| 617 | 480 | struct tracefs_inode *ti; |
| 618 | 481 | struct eventfs_inode *ei; |
| 619 | − struct dentry *ei_dentry = NULL; | |
| 620 | − struct dentry *ret = NULL; | |
| 621 | − struct dentry *d; | |
| 622 | 482 | const char *name = dentry->d_name.name; |
| 623 | − umode_t mode; | |
| 624 | − void *data; | |
| 625 | − int idx; | |
| 626 | − int i; | |
| 627 | − int r; | |
| 483 | + struct dentry *result = NULL; | |
| 628 | 484 | |
| 629 | 485 | ti = get_tracefs(dir); |
| 630 | 486 | if (!(ti->flags & TRACEFS_EVENT_INODE)) |
| 631 | − return NULL; | |
| 487 | + return ERR_PTR(-EIO); | |
| 632 | 488 | |
| 633 | − /* Grab srcu to prevent the ei from going away */ | |
| 634 | − idx = srcu_read_lock(&eventfs_srcu); | |
| 635 | − | |
| 636 | − /* | |
| 637 | − * Grab the eventfs_mutex to consistent value from ti->private. | |
| 638 | − * This s | |
| 639 | − */ | |
| 640 | 489 | mutex_lock(&eventfs_mutex); |
| 641 | − ei = READ_ONCE(ti->private); | |
| 642 | − if (ei && !ei->is_freed) | |
| 643 | − ei_dentry = READ_ONCE(ei->dentry); | |
| 644 | − mutex_unlock(&eventfs_mutex); | |
| 645 | 490 | |
| 646 | − if (!ei || !ei_dentry) | |
| 491 | + ei = ti->private; | |
| 492 | + if (!ei || ei->is_freed) | |
| 647 | 493 | goto out; |
| 648 | 494 | |
| 649 | − data = ei->data; | |
| 650 | − | |
| 651 | − list_for_each_entry_srcu(ei_child, &ei->children, list, | |
| 652 | − srcu_read_lock_held(&eventfs_srcu)) { | |
| 495 | + list_for_each_entry(ei_child, &ei->children, list) { | |
| 653 | 496 | if (strcmp(ei_child->name, name) != 0) |
| 654 | 497 | continue; |
| 655 | − ret = simple_lookup(dir, dentry, flags); | |
| 656 | − if (IS_ERR(ret)) | |
| 498 | + if (ei_child->is_freed) | |
| 657 | 499 | goto out; |
| 658 | − d = create_dir_dentry(ei, ei_child, ei_dentry); | |
| 659 | − dput(d); | |
| 500 | + result = lookup_dir_entry(dentry, ei, ei_child); | |
| 660 | 501 | goto out; |
| 661 | 502 | } |
| 662 | 503 | |
| 663 | − for (i = 0; i < ei->nr_entries; i++) { | |
| 664 | − entry = &ei->entries[i]; | |
| 665 | − if (strcmp(name, entry->name) == 0) { | |
| 666 | − void *cdata = data; | |
| 667 | − mutex_lock(&eventfs_mutex); | |
| 668 | − /* If ei->is_freed, then the event itself may be too */ | |
| 669 | − if (!ei->is_freed) | |
| 670 | − r = entry->callback(name, &mode, &cdata, &fops); | |
| 671 | − else | |
| 672 | − r = -1; | |
| 673 | − mutex_unlock(&eventfs_mutex); | |
| 674 | − if (r <= 0) | |
| 675 | − continue; | |
| 676 | − ret = simple_lookup(dir, dentry, flags); | |
| 677 | − if (IS_ERR(ret)) | |
| 678 | − goto out; | |
| 679 | − d = create_file_dentry(ei, i, ei_dentry, name, mode, cdata, fops); | |
| 680 | − dput(d); | |
| 681 | − break; | |
| 682 | − } | |
| 504 | + for (int i = 0; i < ei->nr_entries; i++) { | |
| 505 | + void *data; | |
| 506 | + umode_t mode; | |
| 507 | + const struct file_operations *fops; | |
| 508 | + const struct eventfs_entry *entry = &ei->entries[i]; | |
| 509 | + | |
| 510 | + if (strcmp(name, entry->name) != 0) | |
| 511 | + continue; | |
| 512 | + | |
| 513 | + data = ei->data; | |
| 514 | + if (entry->callback(name, &mode, &data, &fops) <= 0) | |
| 515 | + goto out; | |
| 516 | + | |
| 517 | + result = lookup_file_dentry(dentry, ei, i, mode, data, fops); | |
| 518 | + goto out; | |
| 683 | 519 | } |
| 684 | 520 | out: |
| 685 | − srcu_read_unlock(&eventfs_srcu, idx); | |
| 686 | − return ret; | |
| 521 | + mutex_unlock(&eventfs_mutex); | |
| 522 | + return result; | |
| 687 | 523 | } |
| 688 | 524 | |
| 689 | 525 | /* |
| @@ -833,25 +669,10 @@ struct eventfs_inode *eventfs_create_dir(const char *name, struct eventfs_inode · 143 unmodified lines | ||
| 833 | 669 | if (!parent) |
| 834 | 670 | return ERR_PTR(-EINVAL); |
| 835 | 671 | |
| 836 | − ei = kzalloc(sizeof(*ei), GFP_KERNEL); | |
| 672 | + ei = alloc_ei(name); | |
| 837 | 673 | if (!ei) |
| 838 | 674 | return ERR_PTR(-ENOMEM); |
| 839 | 675 | |
| 840 | − ei->name = kstrdup_const(name, GFP_KERNEL); | |
| 841 | − if (!ei->name) { | |
| 842 | − kfree(ei); | |
| 843 | − return ERR_PTR(-ENOMEM); | |
| 844 | − } | |
| 845 | − | |
| 846 | − if (size) { | |
| 847 | − ei->d_children = kcalloc(size, sizeof(*ei->d_children), GFP_KERNEL); | |
| 848 | − if (!ei->d_children) { | |
| 849 | − kfree_const(ei->name); | |
| 850 | − kfree(ei); | |
| 851 | − return ERR_PTR(-ENOMEM); | |
| 852 | − } | |
| 853 | − } | |
| 854 | − | |
| 855 | 676 | ei->entries = entries; |
| 856 | 677 | ei->nr_entries = size; |
| 857 | 678 | ei->data = data; |
| @@ -859,10 +680,8 @@ struct eventfs_inode *eventfs_create_dir(const char *name, struct eventfs_inode · 1 unmodified line | ||
| 859 | 680 | INIT_LIST_HEAD(&ei->list); |
| 860 | 681 | |
| 861 | 682 | mutex_lock(&eventfs_mutex); |
| 862 | − if (!parent->is_freed) { | |
| 683 | + if (!parent->is_freed) | |
| 863 | 684 | list_add_tail(&ei->list, &parent->children); |
| 864 | − ei->d_parent = parent->dentry; | |
| 865 | − } | |
| 866 | 685 | mutex_unlock(&eventfs_mutex); |
| 867 | 686 | |
| 868 | 687 | /* Was the parent freed? */ |
| @@ -902,28 +721,20 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry · 33 unmodified lines | ||
| 902 | 721 | if (IS_ERR(dentry)) |
| 903 | 722 | return ERR_CAST(dentry); |
| 904 | 723 | |
| 905 | − ei = kzalloc(sizeof(*ei), GFP_KERNEL); | |
| 724 | + ei = alloc_ei(name); | |
| 906 | 725 | if (!ei) |
| 907 | − goto fail_ei; | |
| 726 | + goto fail; | |
| 908 | 727 | |
| 909 | 728 | inode = tracefs_get_inode(dentry->d_sb); |
| 910 | 729 | if (unlikely(!inode)) |
| 911 | 730 | goto fail; |
| 912 | 731 | |
| 913 | − if (size) { | |
| 914 | − ei->d_children = kcalloc(size, sizeof(*ei->d_children), GFP_KERNEL); | |
| 915 | − if (!ei->d_children) | |
| 916 | − goto fail; | |
| 917 | − } | |
| 918 | − | |
| 919 | − ei->dentry = dentry; | |
| 732 | + // Note: we have a ref to the dentry from tracefs_start_creating() | |
| 733 | + ei->events_dir = dentry; | |
| 920 | 734 | ei->entries = entries; |
| 921 | 735 | ei->nr_entries = size; |
| 922 | 736 | ei->is_events = 1; |
| 923 | 737 | ei->data = data; |
| 924 | − ei->name = kstrdup_const(name, GFP_KERNEL); | |
| 925 | − if (!ei->name) | |
| 926 | − goto fail; | |
| 927 | 738 | |
| 928 | 739 | /* Save the ownership of this directory */ |
| 929 | 740 | uid = d_inode(dentry->d_parent)->i_uid; |
| @@ -954,11 +765,19 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry · 24 unmodified lines | ||
| 954 | 765 | inode->i_op = &eventfs_root_dir_inode_operations; |
| 955 | 766 | inode->i_fop = &eventfs_file_operations; |
| 956 | 767 | |
| 957 | − dentry->d_fsdata = ei; | |
| 768 | + dentry->d_fsdata = get_ei(ei); | |
| 958 | 769 | |
| 959 | − /* directory inodes start off with i_nlink == 2 (for "." entry) */ | |
| 960 | − inc_nlink(inode); | |
| 770 | + /* | |
| 771 | + * Keep all eventfs directories with i_nlink == 1. | |
| 772 | + * Due to the dynamic nature of the dentry creations and not | |
| 773 | + * wanting to add a pointer to the parent eventfs_inode in the | |
| 774 | + * eventfs_inode structure, keeping the i_nlink in sync with the | |
| 775 | + * number of directories would cause too much complexity for | |
| 776 | + * something not worth much. Keeping directory links at 1 | |
| 777 | + * tells userspace not to trust the link number. | |
| 778 | + */ | |
| 961 | 779 | d_instantiate(dentry, inode); |
| 780 | + /* The dentry of the "events" parent does keep track though */ | |
| 962 | 781 | inc_nlink(dentry->d_parent->d_inode); |
| 963 | 782 | fsnotify_mkdir(dentry->d_parent->d_inode, dentry); |
| 964 | 783 | tracefs_end_creating(dentry); |
| @@ -966,72 +785,11 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry · 1 unmodified line | ||
| 966 | 785 | return ei; |
| 967 | 786 | |
| 968 | 787 | fail: |
| 969 | − kfree(ei->d_children); | |
| 970 | − kfree(ei); | |
| 971 | − fail_ei: | |
| 788 | + free_ei(ei); | |
| 972 | 789 | tracefs_failed_creating(dentry); |
| 973 | 790 | return ERR_PTR(-ENOMEM); |
| 974 | 791 | } |
| 975 | 792 | |
| 976 | −static LLIST_HEAD(free_list); | |
| 977 | − | |
| 978 | −static void eventfs_workfn(struct work_struct *work) | |
| 979 | −{ | |
| 980 | − struct eventfs_inode *ei, *tmp; | |
| 981 | − struct llist_node *llnode; | |
| 982 | − | |
| 983 | − llnode = llist_del_all(&free_list); | |
| 984 | − llist_for_each_entry_safe(ei, tmp, llnode, llist) { | |
| 985 | − /* This dput() matches the dget() from unhook_dentry() */ | |
| 986 | − for (int i = 0; i < ei->nr_entries; i++) { | |
| 987 | − if (ei->d_children[i]) | |
| 988 | − dput(ei->d_children[i]); | |
| 989 | − } | |
| 990 | − /* This should only get here if it had a dentry */ | |
| 991 | − if (!WARN_ON_ONCE(!ei->dentry)) | |
| 992 | − dput(ei->dentry); | |
| 993 | − } | |
| 994 | −} | |
| 995 | − | |
| 996 | −static DECLARE_WORK(eventfs_work, eventfs_workfn); | |
| 997 | − | |
| 998 | −static void free_rcu_ei(struct rcu_head *head) | |
| 999 | −{ | |
| 1000 | − struct eventfs_inode *ei = container_of(head, struct eventfs_inode, rcu); | |
| 1001 | − | |
| 1002 | − if (ei->dentry) { | |
| 1003 | − /* Do not free the ei until all references of dentry are gone */ | |
| 1004 | − if (llist_add(&ei->llist, &free_list)) | |
| 1005 | − queue_work(system_unbound_wq, &eventfs_work); | |
| 1006 | − return; | |
| 1007 | − } | |
| 1008 | − | |
| 1009 | − /* If the ei doesn't have a dentry, neither should its children */ | |
| 1010 | − for (int i = 0; i < ei->nr_entries; i++) { | |
| 1011 | − WARN_ON_ONCE(ei->d_children[i]); | |
| 1012 | − } | |
| 1013 | − | |
| 1014 | − free_ei(ei); | |
| 1015 | −} | |
| 1016 | − | |
| 1017 | −static void unhook_dentry(struct dentry *dentry) | |
| 1018 | −{ | |
| 1019 | − if (!dentry) | |
| 1020 | − return; | |
| 1021 | − /* | |
| 1022 | − * Need to add a reference to the dentry that is expected by | |
| 1023 | − * simple_recursive_removal(), which will include a dput(). | |
| 1024 | − */ | |
| 1025 | − dget(dentry); | |
| 1026 | − | |
| 1027 | − /* | |
| 1028 | − * Also add a reference for the dput() in eventfs_workfn(). | |
| 1029 | − * That is required as that dput() will free the ei after | |
| 1030 | − * the SRCU grace period is over. | |
| 1031 | − */ | |
| 1032 | − dget(dentry); | |
| 1033 | −} | |
| 1034 | − | |
| 1035 | 793 | /** |
| 1036 | 794 | * eventfs_remove_rec - remove eventfs dir or file from list |
| 1037 | 795 | * @ei: eventfs_inode to be removed. |
| @@ -1044,8 +802,6 @@ static void eventfs_remove_rec(struct eventfs_inode *ei, int level) · 6 unmodified lines | ||
| 1044 | 802 | { |
| 1045 | 803 | struct eventfs_inode *ei_child; |
| 1046 | 804 | |
| 1047 | − if (!ei) | |
| 1048 | − return; | |
| 1049 | 805 | /* |
| 1050 | 806 | * Check recursion depth. It should never be greater than 3: |
| 1051 | 807 | * 0 - events/ |
| @@ -1057,28 +813,11 @@ static void eventfs_remove_rec(struct eventfs_inode *ei, int level) · 5 unmodified lines | ||
| 1057 | 813 | return; |
| 1058 | 814 | |
| 1059 | 815 | /* search for nested folders or files */ |
| 1060 | − list_for_each_entry_srcu(ei_child, &ei->children, list, | |
| 1061 | − lockdep_is_held(&eventfs_mutex)) { | |
| 1062 | − /* Children only have dentry if parent does */ | |
| 1063 | − WARN_ON_ONCE(ei_child->dentry && !ei->dentry); | |
| 816 | + list_for_each_entry(ei_child, &ei->children, list) | |
| 1064 | 817 | eventfs_remove_rec(ei_child, level + 1); |
| 1065 | − } | |
| 1066 | − | |
| 1067 | 818 | |
| 1068 | − ei->is_freed = 1; | |
| 1069 | − | |
| 1070 | − for (int i = 0; i < ei->nr_entries; i++) { | |
| 1071 | − if (ei->d_children[i]) { | |
| 1072 | − /* Children only have dentry if parent does */ | |
| 1073 | − WARN_ON_ONCE(!ei->dentry); | |
| 1074 | − unhook_dentry(ei->d_children[i]); | |
| 1075 | − } | |
| 1076 | − } | |
| 1077 | − | |
| 1078 | − unhook_dentry(ei->dentry); | |
| 1079 | − | |
| 1080 | − list_del_rcu(&ei->list); | |
| 1081 | − call_srcu(&eventfs_srcu, &ei->rcu, free_rcu_ei); | |
| 819 | + list_del(&ei->list); | |
| 820 | + free_ei(ei); | |
| 1082 | 821 | } |
| 1083 | 822 | |
| 1084 | 823 | /** |
| @@ -1089,22 +828,12 @@ static void eventfs_remove_rec(struct eventfs_inode *ei, int level) · 4 unmodified lines | ||
| 1089 | 828 | */ |
| 1090 | 829 | void eventfs_remove_dir(struct eventfs_inode *ei) |
| 1091 | 830 | { |
| 1092 | − struct dentry *dentry; | |
| 1093 | − | |
| 1094 | 831 | if (!ei) |
| 1095 | 832 | return; |
| 1096 | 833 | |
| 1097 | 834 | mutex_lock(&eventfs_mutex); |
| 1098 | − dentry = ei->dentry; | |
| 1099 | 835 | eventfs_remove_rec(ei, 0); |
| 1100 | 836 | mutex_unlock(&eventfs_mutex); |
| 1101 | − | |
| 1102 | − /* | |
| 1103 | − * If any of the ei children has a dentry, then the ei itself | |
| 1104 | − * must have a dentry. | |
| 1105 | − */ | |
| 1106 | − if (dentry) | |
| 1107 | − simple_recursive_removal(dentry, NULL); | |
| 1108 | 837 | } |
| 1109 | 838 | |
| 1110 | 839 | /** |
| @@ -1117,7 +846,11 @@ void eventfs_remove_events_dir(struct eventfs_inode *ei) · 6 unmodified lines | ||
| 1117 | 846 | { |
| 1118 | 847 | struct dentry *dentry; |
| 1119 | 848 | |
| 1120 | − dentry = ei->dentry; | |
| 849 | + dentry = ei->events_dir; | |
| 850 | + if (!dentry) | |
| 851 | + return; | |
| 852 | + | |
| 853 | + ei->events_dir = NULL; | |
| 1121 | 854 | eventfs_remove_dir(ei); |
| 1122 | 855 | |
| 1123 | 856 | /* |
| @@ -1127,5 +860,6 @@ void eventfs_remove_events_dir(struct eventfs_inode *ei) · 3 unmodified lines | ||
| 1127 | 860 | * sticks around while the other ei->dentry are created |
| 1128 | 861 | * and destroyed dynamically. |
| 1129 | 862 | */ |
| 863 | + d_invalidate(dentry); | |
| 1130 | 864 | dput(dentry); |
| 1131 | 865 | } |
| @@ -38,8 +38,6 @@ static struct inode *tracefs_alloc_inode(struct super_block *sb) · 37 unmodified lines | ||
| 38 | 38 | if (!ti) |
| 39 | 39 | return NULL; |
| 40 | 40 | |
| 41 | − ti->flags = 0; | |
| 42 | − | |
| 43 | 41 | return &ti->vfs_inode; |
| 44 | 42 | } |
| 45 | 43 | |
| @@ -379,21 +377,30 @@ static const struct super_operations tracefs_super_operations = { · 333 unmodified lines | ||
| 379 | 377 | .show_options = tracefs_show_options, |
| 380 | 378 | }; |
| 381 | 379 | |
| 382 | −static void tracefs_dentry_iput(struct dentry *dentry, struct inode *inode) | |
| 380 | +/* | |
| 381 | + * It would be cleaner if eventfs had its own dentry ops. | |
| 382 | + * | |
| 383 | + * Note that d_revalidate is called potentially under RCU, | |
| 384 | + * so it can't take the eventfs mutex etc. It's fine - if | |
| 385 | + * we open a file just as it's marked dead, things will | |
| 386 | + * still work just fine, and just see the old stale case. | |
| 387 | + */ | |
| 388 | +static void tracefs_d_release(struct dentry *dentry) | |
| 383 | 389 | { |
| 384 | − struct tracefs_inode *ti; | |
| 390 | + if (dentry->d_fsdata) | |
| 391 | + eventfs_d_release(dentry); | |
| 392 | +} | |
| 385 | 393 | |
| 386 | − if (!dentry || !inode) | |
| 387 | − return; | |
| 394 | +static int tracefs_d_revalidate(struct dentry *dentry, unsigned int flags) | |
| 395 | +{ | |
| 396 | + struct eventfs_inode *ei = dentry->d_fsdata; | |
| 388 | 397 | |
| 389 | − ti = get_tracefs(inode); | |
| 390 | − if (ti && ti->flags & TRACEFS_EVENT_INODE) | |
| 391 | − eventfs_set_ei_status_free(ti, dentry); | |
| 392 | − iput(inode); | |
| 398 | + return !(ei && ei->is_freed); | |
| 393 | 399 | } |
| 394 | 400 | |
| 395 | 401 | static const struct dentry_operations tracefs_dentry_operations = { |
| 396 | − .d_iput = tracefs_dentry_iput, | |
| 402 | + .d_revalidate = tracefs_d_revalidate, | |
| 403 | + .d_release = tracefs_d_release, | |
| 397 | 404 | }; |
| 398 | 405 | |
| 399 | 406 | static int trace_fill_super(struct super_block *sb, void *data, int silent) |
| @@ -497,75 +504,6 @@ struct dentry *tracefs_end_creating(struct dentry *dentry) · 97 unmodified lines | ||
| 497 | 504 | return dentry; |
| 498 | 505 | } |
| 499 | 506 | |
| 500 | −/** | |
| 501 | − * eventfs_start_creating - start the process of creating a dentry | |
| 502 | − * @name: Name of the file created for the dentry | |
| 503 | − * @parent: The parent dentry where this dentry will be created | |
| 504 | − * | |
| 505 | − * This is a simple helper function for the dynamically created eventfs | |
| 506 | − * files. When the directory of the eventfs files are accessed, their | |
| 507 | − * dentries are created on the fly. This function is used to start that | |
| 508 | − * process. | |
| 509 | − */ | |
| 510 | −struct dentry *eventfs_start_creating(const char *name, struct dentry *parent) | |
| 511 | −{ | |
| 512 | − struct dentry *dentry; | |
| 513 | − int error; | |
| 514 | − | |
| 515 | − /* Must always have a parent. */ | |
| 516 | − if (WARN_ON_ONCE(!parent)) | |
| 517 | − return ERR_PTR(-EINVAL); | |
| 518 | − | |
| 519 | − error = simple_pin_fs(&trace_fs_type, &tracefs_mount, | |
| 520 | − &tracefs_mount_count); | |
| 521 | − if (error) | |
| 522 | − return ERR_PTR(error); | |
| 523 | − | |
| 524 | − if (unlikely(IS_DEADDIR(parent->d_inode))) | |
| 525 | − dentry = ERR_PTR(-ENOENT); | |
| 526 | − else | |
| 527 | − dentry = lookup_one_len(name, parent, strlen(name)); | |
| 528 | − | |
| 529 | − if (!IS_ERR(dentry) && dentry->d_inode) { | |
| 530 | − dput(dentry); | |
| 531 | − dentry = ERR_PTR(-EEXIST); | |
| 532 | − } | |
| 533 | − | |
| 534 | − if (IS_ERR(dentry)) | |
| 535 | − simple_release_fs(&tracefs_mount, &tracefs_mount_count); | |
| 536 | − | |
| 537 | − return dentry; | |
| 538 | −} | |
| 539 | − | |
| 540 | −/** | |
| 541 | − * eventfs_failed_creating - clean up a failed eventfs dentry creation | |
| 542 | − * @dentry: The dentry to clean up | |
| 543 | − * | |
| 544 | − * If after calling eventfs_start_creating(), a failure is detected, the | |
| 545 | − * resources created by eventfs_start_creating() needs to be cleaned up. In | |
| 546 | − * that case, this function should be called to perform that clean up. | |
| 547 | − */ | |
| 548 | −struct dentry *eventfs_failed_creating(struct dentry *dentry) | |
| 549 | −{ | |
| 550 | − dput(dentry); | |
| 551 | − simple_release_fs(&tracefs_mount, &tracefs_mount_count); | |
| 552 | − return NULL; | |
| 553 | −} | |
| 554 | − | |
| 555 | −/** | |
| 556 | − * eventfs_end_creating - Finish the process of creating a eventfs dentry | |
| 557 | − * @dentry: The dentry that has successfully been created. | |
| 558 | − * | |
| 559 | − * This function is currently just a place holder to match | |
| 560 | − * eventfs_start_creating(). In case any synchronization needs to be added, | |
| 561 | − * this function will be used to implement that without having to modify | |
| 562 | − * the callers of eventfs_start_creating(). | |
| 563 | − */ | |
| 564 | −struct dentry *eventfs_end_creating(struct dentry *dentry) | |
| 565 | −{ | |
| 566 | − return dentry; | |
| 567 | −} | |
| 568 | − | |
| 569 | 507 | /* Find the inode that this will use for default */ |
| 570 | 508 | static struct inode *instance_inode(struct dentry *parent, struct inode *inode) |
| 571 | 509 | { |
| @@ -779,7 +717,11 @@ static void init_once(void *foo) · 207 unmodified lines | ||
| 779 | 717 | { |
| 780 | 718 | struct tracefs_inode *ti = (struct tracefs_inode *) foo; |
| 781 | 719 | |
| 720 | + /* inode_init_once() calls memset() on the vfs_inode portion */ | |
| 782 | 721 | inode_init_once(&ti->vfs_inode); |
| 722 | + | |
| 723 | + /* Zero out the rest */ | |
| 724 | + memset_after(ti, 0, vfs_inode); | |
| 783 | 725 | } |
| 784 | 726 | |
| 785 | 727 | static int __init tracefs_init(void) |
| @@ -11,9 +11,10 @@ enum { · 10 unmodified lines | ||
| 11 | 11 | }; |
| 12 | 12 | |
| 13 | 13 | struct tracefs_inode { |
| 14 | + struct inode vfs_inode; | |
| 15 | + /* The below gets initialized with memset_after(ti, 0, vfs_inode) */ | |
| 14 | 16 | unsigned long flags; |
| 15 | 17 | void *private; |
| 16 | − struct inode vfs_inode; | |
| 17 | 18 | }; |
| 18 | 19 | |
| 19 | 20 | /* |
| @@ -31,43 +32,37 @@ struct eventfs_attr { · 11 unmodified lines | ||
| 31 | 32 | /* |
| 32 | 33 | * struct eventfs_inode - hold the properties of the eventfs directories. |
| 33 | 34 | * @list: link list into the parent directory |
| 35 | + * @rcu: Union with @list for freeing | |
| 36 | + * @children: link list into the child eventfs_inode | |
| 34 | 37 | * @entries: the array of entries representing the files in the directory |
| 35 | 38 | * @name: the name of the directory to create |
| 36 | − * @children: link list into the child eventfs_inode | |
| 37 | − * @dentry: the dentry of the directory | |
| 38 | − * @d_parent: pointer to the parent's dentry | |
| 39 | − * @d_children: The array of dentries to represent the files when created | |
| 39 | + * @events_dir: the dentry of the events directory | |
| 40 | 40 | * @entry_attrs: Saved mode and ownership of the @d_children |
| 41 | − * @attr: Saved mode and ownership of eventfs_inode itself | |
| 42 | 41 | * @data: The private data to pass to the callbacks |
| 42 | + * @attr: Saved mode and ownership of eventfs_inode itself | |
| 43 | 43 | * @is_freed: Flag set if the eventfs is on its way to be freed |
| 44 | 44 | * Note if is_freed is set, then dentry is corrupted. |
| 45 | + * @is_events: Flag set for only the top level "events" directory | |
| 45 | 46 | * @nr_entries: The number of items in @entries |
| 47 | + * @ino: The saved inode number | |
| 46 | 48 | */ |
| 47 | 49 | struct eventfs_inode { |
| 48 | − struct list_head list; | |
| 50 | + union { | |
| 51 | + struct list_head list; | |
| 52 | + struct rcu_head rcu; | |
| 53 | + }; | |
| 54 | + struct list_head children; | |
| 49 | 55 | const struct eventfs_entry *entries; |
| 50 | 56 | const char *name; |
| 51 | − struct list_head children; | |
| 52 | − struct dentry *dentry; /* Check is_freed to access */ | |
| 53 | − struct dentry *d_parent; | |
| 54 | − struct dentry **d_children; | |
| 57 | + struct dentry *events_dir; | |
| 55 | 58 | struct eventfs_attr *entry_attrs; |
| 56 | − struct eventfs_attr attr; | |
| 57 | 59 | void *data; |
| 60 | + struct eventfs_attr attr; | |
| 61 | + struct kref kref; | |
| 58 | 62 | unsigned int is_freed:1; |
| 59 | 63 | unsigned int is_events:1; |
| 60 | 64 | unsigned int nr_entries:30; |
| 61 | 65 | unsigned int ino; |
| 62 | − /* | |
| 63 | − * Union - used for deletion | |
| 64 | − * @llist: for calling dput() if needed after RCU | |
| 65 | − * @rcu: eventfs_inode to delete in RCU | |
| 66 | − */ | |
| 67 | − union { | |
| 68 | − struct llist_node llist; | |
| 69 | − struct rcu_head rcu; | |
| 70 | − }; | |
| 71 | 66 | }; |
| 72 | 67 | |
| 73 | 68 | static inline struct tracefs_inode *get_tracefs(const struct inode *inode) |
| @@ -79,9 +74,7 @@ struct dentry *tracefs_start_creating(const char *name, struct dentry *parent); · 5 unmodified lines | ||
| 79 | 74 | struct dentry *tracefs_end_creating(struct dentry *dentry); |
| 80 | 75 | struct dentry *tracefs_failed_creating(struct dentry *dentry); |
| 81 | 76 | struct inode *tracefs_get_inode(struct super_block *sb); |
| 82 | −struct dentry *eventfs_start_creating(const char *name, struct dentry *parent); | |
| 83 | −struct dentry *eventfs_failed_creating(struct dentry *dentry); | |
| 84 | −struct dentry *eventfs_end_creating(struct dentry *dentry); | |
| 85 | −void eventfs_set_ei_status_free(struct tracefs_inode *ti, struct dentry *dentry); | |
| 77 | + | |
| 78 | +void eventfs_d_release(struct dentry *dentry); | |
| 86 | 79 | |
| 87 | 80 | #endif /* _TRACEFS_INTERNAL_H */ |
| @@ -421,10 +421,10 @@ xfs_attr_complete_op( · 420 unmodified lines | ||
| 421 | 421 | bool do_replace = args->op_flags & XFS_DA_OP_REPLACE; |
| 422 | 422 | |
| 423 | 423 | args->op_flags &= ~XFS_DA_OP_REPLACE; |
| 424 | − if (do_replace) { | |
| 425 | − args->attr_filter &= ~XFS_ATTR_INCOMPLETE; | |
| 424 | + args->attr_filter &= ~XFS_ATTR_INCOMPLETE; | |
| 425 | + if (do_replace) | |
| 426 | 426 | return replace_state; |
| 427 | − } | |
| 427 | + | |
| 428 | 428 | return XFS_DAS_DONE; |
| 429 | 429 | } |
| 430 | 430 | |
| @@ -1118,20 +1118,6 @@ xfs_rtbitmap_blockcount( · 1117 unmodified lines | ||
| 1118 | 1118 | return howmany_64(rtextents, NBBY * mp->m_sb.sb_blocksize); |
| 1119 | 1119 | } |
| 1120 | 1120 | |
| 1121 | −/* | |
| 1122 | − * Compute the maximum level number of the realtime summary file, as defined by | |
| 1123 | − * mkfs. The historic use of highbit32 on a 64-bit quantity prohibited correct | |
| 1124 | − * use of rt volumes with more than 2^32 extents. | |
| 1125 | − */ | |
| 1126 | −uint8_t | |
| 1127 | −xfs_compute_rextslog( | |
| 1128 | − xfs_rtbxlen_t rtextents) | |
| 1129 | −{ | |
| 1130 | − if (!rtextents) | |
| 1131 | − return 0; | |
| 1132 | − return xfs_highbit64(rtextents); | |
| 1133 | −} | |
| 1134 | − | |
| 1135 | 1121 | /* |
| 1136 | 1122 | * Compute the number of rtbitmap words needed to populate every block of a |
| 1137 | 1123 | * bitmap that is large enough to track the given number of rt extents. |
| @@ -351,20 +351,6 @@ xfs_rtfree_extent( · 350 unmodified lines | ||
| 351 | 351 | int xfs_rtfree_blocks(struct xfs_trans *tp, xfs_fsblock_t rtbno, |
| 352 | 352 | xfs_filblks_t rtlen); |
| 353 | 353 | |
| 354 | −uint8_t xfs_compute_rextslog(xfs_rtbxlen_t rtextents); | |
| 355 | − | |
| 356 | −/* Do we support an rt volume having this number of rtextents? */ | |
| 357 | −static inline bool | |
| 358 | −xfs_validate_rtextents( | |
| 359 | − xfs_rtbxlen_t rtextents) | |
| 360 | −{ | |
| 361 | − /* No runt rt volumes */ | |
| 362 | − if (rtextents == 0) | |
| 363 | − return false; | |
| 364 | − | |
| 365 | − return true; | |
| 366 | −} | |
| 367 | − | |
| 368 | 354 | xfs_filblks_t xfs_rtbitmap_blockcount(struct xfs_mount *mp, xfs_rtbxlen_t |
| 369 | 355 | rtextents); |
| 370 | 356 | unsigned long long xfs_rtbitmap_wordcount(struct xfs_mount *mp, |
| @@ -383,8 +369,6 @@ unsigned long long xfs_rtsummary_wordcount(struct xfs_mount *mp, · 12 unmodified lines | ||
| 383 | 369 | # define xfs_rtsummary_read_buf(a,b) (-ENOSYS) |
| 384 | 370 | # define xfs_rtbuf_cache_relse(a) (0) |
| 385 | 371 | # define xfs_rtalloc_extent_is_free(m,t,s,l,i) (-ENOSYS) |
| 386 | −# define xfs_compute_rextslog(rtx) (0) | |
| 387 | −# define xfs_validate_rtextents(rtx) (false) | |
| 388 | 372 | static inline xfs_filblks_t |
| 389 | 373 | xfs_rtbitmap_blockcount(struct xfs_mount *mp, xfs_rtbxlen_t rtextents) |
| 390 | 374 | { |
| @@ -1377,3 +1377,17 @@ xfs_validate_stripe_geometry( · 1376 unmodified lines | ||
| 1377 | 1377 | } |
| 1378 | 1378 | return true; |
| 1379 | 1379 | } |
| 1380 | + | |
| 1381 | +/* | |
| 1382 | + * Compute the maximum level number of the realtime summary file, as defined by | |
| 1383 | + * mkfs. The historic use of highbit32 on a 64-bit quantity prohibited correct | |
| 1384 | + * use of rt volumes with more than 2^32 extents. | |
| 1385 | + */ | |
| 1386 | +uint8_t | |
| 1387 | +xfs_compute_rextslog( | |
| 1388 | + xfs_rtbxlen_t rtextents) | |
| 1389 | +{ | |
| 1390 | + if (!rtextents) | |
| 1391 | + return 0; | |
| 1392 | + return xfs_highbit64(rtextents); | |
| 1393 | +} | |
| @@ -38,4 +38,6 @@ extern int xfs_sb_get_secondary(struct xfs_mount *mp, · 37 unmodified lines | ||
| 38 | 38 | extern bool xfs_validate_stripe_geometry(struct xfs_mount *mp, |
| 39 | 39 | __s64 sunit, __s64 swidth, int sectorsize, bool silent); |
| 40 | 40 | |
| 41 | +uint8_t xfs_compute_rextslog(xfs_rtbxlen_t rtextents); | |
| 42 | + | |
| 41 | 43 | #endif /* __XFS_SB_H__ */ |
| @@ -251,4 +251,16 @@ bool xfs_verify_fileoff(struct xfs_mount *mp, xfs_fileoff_t off); · 250 unmodified lines | ||
| 251 | 251 | bool xfs_verify_fileext(struct xfs_mount *mp, xfs_fileoff_t off, |
| 252 | 252 | xfs_fileoff_t len); |
| 253 | 253 | |
| 254 | +/* Do we support an rt volume having this number of rtextents? */ | |
| 255 | +static inline bool | |
| 256 | +xfs_validate_rtextents( | |
| 257 | + xfs_rtbxlen_t rtextents) | |
| 258 | +{ | |
| 259 | + /* No runt rt volumes */ | |
| 260 | + if (rtextents == 0) | |
| 261 | + return false; | |
| 262 | + | |
| 263 | + return true; | |
| 264 | +} | |
| 265 | + | |
| 254 | 266 | #endif /* __XFS_TYPES_H__ */ |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #include "xfs_inode.h" |
| 16 | 16 | #include "xfs_bmap.h" |
| 17 | 17 | #include "xfs_bit.h" |
| 18 | +#include "xfs_sb.h" | |
| 18 | 19 | #include "scrub/scrub.h" |
| 19 | 20 | #include "scrub/common.h" |
| 20 | 21 | #include "scrub/repair.h" |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include "xfs_rtbitmap.h" |
| 17 | 17 | #include "xfs_bit.h" |
| 18 | 18 | #include "xfs_bmap.h" |
| 19 | +#include "xfs_sb.h" | |
| 19 | 20 | #include "scrub/scrub.h" |
| 20 | 21 | #include "scrub/common.h" |
| 21 | 22 | #include "scrub/trace.h" |
| @@ -953,7 +953,8 @@ static inline int dmaengine_slave_config(struct dma_chan *chan, · 952 unmodified lines | ||
| 953 | 953 | |
| 954 | 954 | static inline bool is_slave_direction(enum dma_transfer_direction direction) |
| 955 | 955 | { |
| 956 | − return (direction == DMA_MEM_TO_DEV) || (direction == DMA_DEV_TO_MEM); | |
| 956 | + return (direction == DMA_MEM_TO_DEV) || (direction == DMA_DEV_TO_MEM) || | |
| 957 | + (direction == DMA_DEV_TO_DEV); | |
| 957 | 958 | } |
| 958 | 959 | |
| 959 | 960 | static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( |
| @@ -816,12 +816,6 @@ struct nvme_reservation_status_ext { · 815 unmodified lines | ||
| 816 | 816 | struct nvme_registered_ctrl_ext regctl_eds[]; |
| 817 | 817 | }; |
| 818 | 818 | |
| 819 | −enum nvme_async_event_type { | |
| 820 | − NVME_AER_TYPE_ERROR = 0, | |
| 821 | − NVME_AER_TYPE_SMART = 1, | |
| 822 | − NVME_AER_TYPE_NOTICE = 2, | |
| 823 | −}; | |
| 824 | − | |
| 825 | 819 | /* I/O commands */ |
| 826 | 820 | |
| 827 | 821 | enum nvme_opcode { |
| @@ -1818,7 +1812,7 @@ struct nvme_command { · 990 unmodified lines | ||
| 1818 | 1812 | }; |
| 1819 | 1813 | }; |
| 1820 | 1814 | |
| 1821 | −static inline bool nvme_is_fabrics(struct nvme_command *cmd) | |
| 1815 | +static inline bool nvme_is_fabrics(const struct nvme_command *cmd) | |
| 1822 | 1816 | { |
| 1823 | 1817 | return cmd->common.opcode == nvme_fabrics_command; |
| 1824 | 1818 | } |
| @@ -1837,7 +1831,7 @@ struct nvme_error_slot { · 12 unmodified lines | ||
| 1837 | 1831 | __u8 resv2[24]; |
| 1838 | 1832 | }; |
| 1839 | 1833 | |
| 1840 | −static inline bool nvme_is_write(struct nvme_command *cmd) | |
| 1834 | +static inline bool nvme_is_write(const struct nvme_command *cmd) | |
| 1841 | 1835 | { |
| 1842 | 1836 | /* |
| 1843 | 1837 | * What a mess... |
| @@ -1422,6 +1422,7 @@ int pci_load_and_free_saved_state(struct pci_dev *dev, · 1421 unmodified lines | ||
| 1422 | 1422 | struct pci_saved_state **state); |
| 1423 | 1423 | int pci_platform_power_transition(struct pci_dev *dev, pci_power_t state); |
| 1424 | 1424 | int pci_set_power_state(struct pci_dev *dev, pci_power_t state); |
| 1425 | +int pci_set_power_state_locked(struct pci_dev *dev, pci_power_t state); | |
| 1425 | 1426 | pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state); |
| 1426 | 1427 | bool pci_pme_capable(struct pci_dev *dev, pci_power_t state); |
| 1427 | 1428 | void pci_pme_active(struct pci_dev *dev, bool enable); |
| @@ -1625,6 +1626,8 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, · 197 unmodified lines | ||
| 1625 | 1626 | |
| 1626 | 1627 | void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), |
| 1627 | 1628 | void *userdata); |
| 1629 | +void pci_walk_bus_locked(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), | |
| 1630 | + void *userdata); | |
| 1628 | 1631 | int pci_cfg_space_size(struct pci_dev *dev); |
| 1629 | 1632 | unsigned char pci_bus_max_busnr(struct pci_bus *bus); |
| 1630 | 1633 | void pci_setup_bridge(struct pci_bus *bus); |
| @@ -2025,6 +2028,8 @@ static inline int pci_save_state(struct pci_dev *dev) { return 0; } · 394 unmodified lines | ||
| 2025 | 2028 | static inline void pci_restore_state(struct pci_dev *dev) { } |
| 2026 | 2029 | static inline int pci_set_power_state(struct pci_dev *dev, pci_power_t state) |
| 2027 | 2030 | { return 0; } |
| 2031 | +static inline int pci_set_power_state_locked(struct pci_dev *dev, pci_power_t state) | |
| 2032 | +{ return 0; } | |
| 2028 | 2033 | static inline int pci_wake_from_d3(struct pci_dev *dev, bool enable) |
| 2029 | 2034 | { return 0; } |
| 2030 | 2035 | static inline pci_power_t pci_choose_state(struct pci_dev *dev, |
| @@ -2910,6 +2910,8 @@ struct cfg80211_bss_ies { · 2909 unmodified lines | ||
| 2910 | 2910 | * own the beacon_ies, but they're just pointers to the ones from the |
| 2911 | 2911 | * @hidden_beacon_bss struct) |
| 2912 | 2912 | * @proberesp_ies: the information elements from the last Probe Response frame |
| 2913 | + * @proberesp_ecsa_stuck: ECSA element is stuck in the Probe Response frame, | |
| 2914 | + * cannot rely on it having valid data | |
| 2913 | 2915 | * @hidden_beacon_bss: in case this BSS struct represents a probe response from |
| 2914 | 2916 | * a BSS that hides the SSID in its beacon, this points to the BSS struct |
| 2915 | 2917 | * that holds the beacon data. @beacon_ies is still valid, of course, and |
| @@ -2950,6 +2952,8 @@ struct cfg80211_bss { · 34 unmodified lines | ||
| 2950 | 2952 | u8 chains; |
| 2951 | 2953 | s8 chain_signal[IEEE80211_MAX_CHAINS]; |
| 2952 | 2954 | |
| 2955 | + u8 proberesp_ecsa_stuck:1; | |
| 2956 | + | |
| 2953 | 2957 | u8 bssid_index; |
| 2954 | 2958 | u8 max_bssid_indicator; |
| 2955 | 2959 | |
| @@ -808,10 +808,16 @@ static inline struct nft_set_elem_expr *nft_set_ext_expr(const struct nft_set_ex · 807 unmodified lines | ||
| 808 | 808 | return nft_set_ext(ext, NFT_SET_EXT_EXPRESSIONS); |
| 809 | 809 | } |
| 810 | 810 | |
| 811 | −static inline bool nft_set_elem_expired(const struct nft_set_ext *ext) | |
| 811 | +static inline bool __nft_set_elem_expired(const struct nft_set_ext *ext, | |
| 812 | + u64 tstamp) | |
| 812 | 813 | { |
| 813 | 814 | return nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION) && |
| 814 | − time_is_before_eq_jiffies64(*nft_set_ext_expiration(ext)); | |
| 815 | + time_after_eq64(tstamp, *nft_set_ext_expiration(ext)); | |
| 816 | +} | |
| 817 | + | |
| 818 | +static inline bool nft_set_elem_expired(const struct nft_set_ext *ext) | |
| 819 | +{ | |
| 820 | + return __nft_set_elem_expired(ext, get_jiffies_64()); | |
| 815 | 821 | } |
| 816 | 822 | |
| 817 | 823 | static inline struct nft_set_ext *nft_set_elem_ext(const struct nft_set *set, |
| @@ -1785,6 +1791,7 @@ struct nftables_pernet { · 967 unmodified lines | ||
| 1785 | 1791 | struct list_head notify_list; |
| 1786 | 1792 | struct mutex commit_mutex; |
| 1787 | 1793 | u64 table_handle; |
| 1794 | + u64 tstamp; | |
| 1788 | 1795 | unsigned int base_seq; |
| 1789 | 1796 | unsigned int gc_seq; |
| 1790 | 1797 | u8 validate_state; |
| @@ -1797,6 +1804,11 @@ static inline struct nftables_pernet *nft_pernet(const struct net *net) · 6 unmodified lines | ||
| 1797 | 1804 | return net_generic(net, nf_tables_net_id); |
| 1798 | 1805 | } |
| 1799 | 1806 | |
| 1807 | +static inline u64 nft_net_tstamp(const struct net *net) | |
| 1808 | +{ | |
| 1809 | + return nft_pernet(net)->tstamp; | |
| 1810 | +} | |
| 1811 | + | |
| 1800 | 1812 | #define __NFT_REDUCE_READONLY 1UL |
| 1801 | 1813 | #define NFT_REDUCE_READONLY (void *)__NFT_REDUCE_READONLY |
| 1802 | 1814 | |
| @@ -75,6 +75,7 @@ · 74 unmodified lines | ||
| 75 | 75 | #define CS35L56_DSP1_AHBM_WINDOW_DEBUG_0 0x25E2040 |
| 76 | 76 | #define CS35L56_DSP1_AHBM_WINDOW_DEBUG_1 0x25E2044 |
| 77 | 77 | #define CS35L56_DSP1_XMEM_UNPACKED24_0 0x2800000 |
| 78 | +#define CS35L56_DSP1_FW_VER 0x2800010 | |
| 78 | 79 | #define CS35L56_DSP1_HALO_STATE_A1 0x2801E58 |
| 79 | 80 | #define CS35L56_DSP1_HALO_STATE 0x28021E0 |
| 80 | 81 | #define CS35L56_DSP1_PM_CUR_STATE_A1 0x2804000 |
| @@ -241,7 +242,7 @@ · 160 unmodified lines | ||
| 241 | 242 | |
| 242 | 243 | #define CS35L56_CONTROL_PORT_READY_US 2200 |
| 243 | 244 | #define CS35L56_HALO_STATE_POLL_US 1000 |
| 244 | −#define CS35L56_HALO_STATE_TIMEOUT_US 50000 | |
| 245 | +#define CS35L56_HALO_STATE_TIMEOUT_US 250000 | |
| 245 | 246 | #define CS35L56_RESET_PULSE_MIN_US 1100 |
| 246 | 247 | #define CS35L56_WAKE_HOLD_TIME_US 1000 |
| 247 | 248 | |
| @@ -272,6 +273,7 @@ extern const char * const cs35l56_tx_input_texts[CS35L56_NUM_INPUT_SRC]; · 24 unmodified lines | ||
| 272 | 273 | extern const unsigned int cs35l56_tx_input_values[CS35L56_NUM_INPUT_SRC]; |
| 273 | 274 | |
| 274 | 275 | int cs35l56_set_patch(struct cs35l56_base *cs35l56_base); |
| 276 | +int cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_base *cs35l56_base); | |
| 275 | 277 | int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command); |
| 276 | 278 | int cs35l56_firmware_shutdown(struct cs35l56_base *cs35l56_base); |
| 277 | 279 | int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base); |
| @@ -284,7 +286,10 @@ int cs35l56_is_fw_reload_needed(struct cs35l56_base *cs35l56_base); · 6 unmodified lines | ||
| 284 | 286 | int cs35l56_runtime_suspend_common(struct cs35l56_base *cs35l56_base); |
| 285 | 287 | int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_soundwire); |
| 286 | 288 | void cs35l56_init_cs_dsp(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_dsp); |
| 289 | +int cs35l56_read_prot_status(struct cs35l56_base *cs35l56_base, | |
| 290 | + bool *fw_missing, unsigned int *fw_version); | |
| 287 | 291 | int cs35l56_hw_init(struct cs35l56_base *cs35l56_base); |
| 292 | +int cs35l56_get_speaker_id(struct cs35l56_base *cs35l56_base); | |
| 288 | 293 | int cs35l56_get_bclk_freq_id(unsigned int freq); |
| 289 | 294 | void cs35l56_fill_supply_names(struct regulator_bulk_data *data); |
| 290 | 295 | |
| @@ -772,15 +772,14 @@ TRACE_EVENT(ext4_mb_release_group_pa, · 771 unmodified lines | ||
| 772 | 772 | ); |
| 773 | 773 | |
| 774 | 774 | TRACE_EVENT(ext4_discard_preallocations, |
| 775 | − TP_PROTO(struct inode *inode, unsigned int len, unsigned int needed), | |
| 775 | + TP_PROTO(struct inode *inode, unsigned int len), | |
| 776 | 776 | |
| 777 | − TP_ARGS(inode, len, needed), | |
| 777 | + TP_ARGS(inode, len), | |
| 778 | 778 | |
| 779 | 779 | TP_STRUCT__entry( |
| 780 | 780 | __field( dev_t, dev ) |
| 781 | 781 | __field( ino_t, ino ) |
| 782 | 782 | __field( unsigned int, len ) |
| 783 | − __field( unsigned int, needed ) | |
| 784 | 783 | |
| 785 | 784 | ), |
| 786 | 785 | |
| @@ -788,13 +787,11 @@ TRACE_EVENT(ext4_discard_preallocations, · 1 unmodified line | ||
| 788 | 787 | __entry->dev = inode->i_sb->s_dev; |
| 789 | 788 | __entry->ino = inode->i_ino; |
| 790 | 789 | __entry->len = len; |
| 791 | − __entry->needed = needed; | |
| 792 | 790 | ), |
| 793 | 791 | |
| 794 | − TP_printk("dev %d,%d ino %lu len: %u needed %u", | |
| 792 | + TP_printk("dev %d,%d ino %lu len: %u", | |
| 795 | 793 | MAJOR(__entry->dev), MINOR(__entry->dev), |
| 796 | − (unsigned long) __entry->ino, __entry->len, | |
| 797 | − __entry->needed) | |
| 794 | + (unsigned long) __entry->ino, __entry->len) | |
| 798 | 795 | ); |
| 799 | 796 | |
| 800 | 797 | TRACE_EVENT(ext4_mb_discard_preallocations, |
| @@ -128,6 +128,7 @@ · 127 unmodified lines | ||
| 128 | 128 | EM(rxrpc_skb_eaten_by_unshare_nomem, "ETN unshar-nm") \ |
| 129 | 129 | EM(rxrpc_skb_get_conn_secured, "GET conn-secd") \ |
| 130 | 130 | EM(rxrpc_skb_get_conn_work, "GET conn-work") \ |
| 131 | + EM(rxrpc_skb_get_last_nack, "GET last-nack") \ | |
| 131 | 132 | EM(rxrpc_skb_get_local_work, "GET locl-work") \ |
| 132 | 133 | EM(rxrpc_skb_get_reject_work, "GET rej-work ") \ |
| 133 | 134 | EM(rxrpc_skb_get_to_recvmsg, "GET to-recv ") \ |
| @@ -141,6 +142,7 @@ · 7 unmodified lines | ||
| 141 | 142 | EM(rxrpc_skb_put_error_report, "PUT error-rep") \ |
| 142 | 143 | EM(rxrpc_skb_put_input, "PUT input ") \ |
| 143 | 144 | EM(rxrpc_skb_put_jumbo_subpacket, "PUT jumbo-sub") \ |
| 145 | + EM(rxrpc_skb_put_last_nack, "PUT last-nack") \ | |
| 144 | 146 | EM(rxrpc_skb_put_purge, "PUT purge ") \ |
| 145 | 147 | EM(rxrpc_skb_put_rotate, "PUT rotate ") \ |
| 146 | 148 | EM(rxrpc_skb_put_unknown, "PUT unknown ") \ |
| @@ -1552,7 +1554,7 @@ TRACE_EVENT(rxrpc_congest, · 1405 unmodified lines | ||
| 1552 | 1554 | memcpy(&__entry->sum, summary, sizeof(__entry->sum)); |
| 1553 | 1555 | ), |
| 1554 | 1556 | |
| 1555 | − TP_printk("c=%08x r=%08x %s q=%08x %s cw=%u ss=%u nA=%u,%u+%u r=%u b=%u u=%u d=%u l=%x%s%s%s", | |
| 1557 | + TP_printk("c=%08x r=%08x %s q=%08x %s cw=%u ss=%u nA=%u,%u+%u,%u b=%u u=%u d=%u l=%x%s%s%s", | |
| 1556 | 1558 | __entry->call, |
| 1557 | 1559 | __entry->ack_serial, |
| 1558 | 1560 | __print_symbolic(__entry->sum.ack_reason, rxrpc_ack_names), |
| @@ -1560,9 +1562,9 @@ TRACE_EVENT(rxrpc_congest, · 1 unmodified line | ||
| 1560 | 1562 | __print_symbolic(__entry->sum.mode, rxrpc_congest_modes), |
| 1561 | 1563 | __entry->sum.cwnd, |
| 1562 | 1564 | __entry->sum.ssthresh, |
| 1563 | − __entry->sum.nr_acks, __entry->sum.saw_nacks, | |
| 1565 | + __entry->sum.nr_acks, __entry->sum.nr_retained_nacks, | |
| 1564 | 1566 | __entry->sum.nr_new_acks, |
| 1565 | − __entry->sum.nr_rot_new_acks, | |
| 1567 | + __entry->sum.nr_new_nacks, | |
| 1566 | 1568 | __entry->top - __entry->hard_ack, |
| 1567 | 1569 | __entry->sum.cumulative_acks, |
| 1568 | 1570 | __entry->sum.dup_acks, |
| @@ -289,9 +289,11 @@ enum nft_rule_attributes { · 288 unmodified lines | ||
| 289 | 289 | /** |
| 290 | 290 | * enum nft_rule_compat_flags - nf_tables rule compat flags |
| 291 | 291 | * |
| 292 | + * @NFT_RULE_COMPAT_F_UNUSED: unused | |
| 292 | 293 | * @NFT_RULE_COMPAT_F_INV: invert the check result |
| 293 | 294 | */ |
| 294 | 295 | enum nft_rule_compat_flags { |
| 296 | + NFT_RULE_COMPAT_F_UNUSED = (1 << 0), | |
| 295 | 297 | NFT_RULE_COMPAT_F_INV = (1 << 1), |
| 296 | 298 | NFT_RULE_COMPAT_F_MASK = NFT_RULE_COMPAT_F_INV, |
| 297 | 299 | }; |
| @@ -145,12 +145,13 @@ struct serial_rs485 { · 144 unmodified lines | ||
| 145 | 145 | #define SER_RS485_ENABLED _BITUL(0) |
| 146 | 146 | #define SER_RS485_RTS_ON_SEND _BITUL(1) |
| 147 | 147 | #define SER_RS485_RTS_AFTER_SEND _BITUL(2) |
| 148 | −#define SER_RS485_RX_DURING_TX _BITUL(3) | |
| 149 | −#define SER_RS485_TERMINATE_BUS _BITUL(4) | |
| 150 | −#define SER_RS485_ADDRB _BITUL(5) | |
| 151 | −#define SER_RS485_ADDR_RECV _BITUL(6) | |
| 152 | −#define SER_RS485_ADDR_DEST _BITUL(7) | |
| 153 | −#define SER_RS485_MODE_RS422 _BITUL(8) | |
| 148 | +/* Placeholder for bit 3: SER_RS485_RTS_BEFORE_SEND, which isn't used anymore */ | |
| 149 | +#define SER_RS485_RX_DURING_TX _BITUL(4) | |
| 150 | +#define SER_RS485_TERMINATE_BUS _BITUL(5) | |
| 151 | +#define SER_RS485_ADDRB _BITUL(6) | |
| 152 | +#define SER_RS485_ADDR_RECV _BITUL(7) | |
| 153 | +#define SER_RS485_ADDR_DEST _BITUL(8) | |
| 154 | +#define SER_RS485_MODE_RS422 _BITUL(9) | |
| 154 | 155 | |
| 155 | 156 | __u32 delay_rts_before_send; |
| 156 | 157 | __u32 delay_rts_after_send; |
| @@ -876,13 +876,13 @@ config CC_NO_ARRAY_BOUNDS · 875 unmodified lines | ||
| 876 | 876 | bool |
| 877 | 877 | default y if CC_IS_GCC && GCC_VERSION >= 110000 && GCC11_NO_ARRAY_BOUNDS |
| 878 | 878 | |
| 879 | −# Currently, disable -Wstringop-overflow for GCC 11, globally. | |
| 880 | −config GCC11_NO_STRINGOP_OVERFLOW | |
| 879 | +# Currently, disable -Wstringop-overflow for GCC globally. | |
| 880 | +config GCC_NO_STRINGOP_OVERFLOW | |
| 881 | 881 | def_bool y |
| 882 | 882 | |
| 883 | 883 | config CC_NO_STRINGOP_OVERFLOW |
| 884 | 884 | bool |
| 885 | − default y if CC_IS_GCC && GCC_VERSION >= 110000 && GCC_VERSION < 120000 && GCC11_NO_STRINGOP_OVERFLOW | |
| 885 | + default y if CC_IS_GCC && GCC_NO_STRINGOP_OVERFLOW | |
| 886 | 886 | |
| 887 | 887 | config CC_STRINGOP_OVERFLOW |
| 888 | 888 | bool |
| @@ -15,11 +15,17 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <trace/events/io_uring.h> |
| 16 | 16 | #endif |
| 17 | 17 | |
| 18 | − | |
| 19 | 18 | enum { |
| 20 | 19 | IOU_OK = 0, |
| 21 | 20 | IOU_ISSUE_SKIP_COMPLETE = -EIOCBQUEUED, |
| 22 | 21 | |
| 22 | + /* | |
| 23 | + * Requeue the task_work to restart operations on this request. The | |
| 24 | + * actual value isn't important, should just be not an otherwise | |
| 25 | + * valid error code, yet less than -MAX_ERRNO and valid internally. | |
| 26 | + */ | |
| 27 | + IOU_REQUEUE = -3072, | |
| 28 | + | |
| 23 | 29 | /* |
| 24 | 30 | * Intended only when both IO_URING_F_MULTISHOT is passed |
| 25 | 31 | * to indicate to the poll runner that multishot should be |
| @@ -60,6 +60,7 @@ struct io_sr_msg { · 59 unmodified lines | ||
| 60 | 60 | unsigned len; |
| 61 | 61 | unsigned done_io; |
| 62 | 62 | unsigned msg_flags; |
| 63 | + unsigned nr_multishot_loops; | |
| 63 | 64 | u16 flags; |
| 64 | 65 | /* initialised and used only by !msg send variants */ |
| 65 | 66 | u16 addr_len; |
| @@ -70,6 +71,13 @@ struct io_sr_msg { · 4 unmodified lines | ||
| 70 | 71 | struct io_kiocb *notif; |
| 71 | 72 | }; |
| 72 | 73 | |
| 74 | +/* | |
| 75 | + * Number of times we'll try and do receives if there's more data. If we | |
| 76 | + * exceed this limit, then add us to the back of the queue and retry from | |
| 77 | + * there. This helps fairness between flooding clients. | |
| 78 | + */ | |
| 79 | +#define MULTISHOT_MAX_RETRY 32 | |
| 80 | + | |
| 73 | 81 | static inline bool io_check_multishot(struct io_kiocb *req, |
| 74 | 82 | unsigned int issue_flags) |
| 75 | 83 | { |
| @@ -611,6 +619,7 @@ int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) · 535 unmodified lines | ||
| 611 | 619 | sr->msg_flags |= MSG_CMSG_COMPAT; |
| 612 | 620 | #endif |
| 613 | 621 | sr->done_io = 0; |
| 622 | + sr->nr_multishot_loops = 0; | |
| 614 | 623 | return 0; |
| 615 | 624 | } |
| 616 | 625 | |
| @@ -645,23 +654,35 @@ static inline bool io_recv_finish(struct io_kiocb *req, int *ret, · 28 unmodified lines | ||
| 645 | 654 | return true; |
| 646 | 655 | } |
| 647 | 656 | |
| 648 | − if (!mshot_finished) { | |
| 649 | − if (io_fill_cqe_req_aux(req, issue_flags & IO_URING_F_COMPLETE_DEFER, | |
| 650 | − *ret, cflags | IORING_CQE_F_MORE)) { | |
| 651 | − io_recv_prep_retry(req); | |
| 652 | − /* Known not-empty or unknown state, retry */ | |
| 653 | − if (cflags & IORING_CQE_F_SOCK_NONEMPTY || | |
| 654 | − msg->msg_inq == -1) | |
| 657 | + if (mshot_finished) | |
| 658 | + goto finish; | |
| 659 | + | |
| 660 | + /* | |
| 661 | + * Fill CQE for this receive and see if we should keep trying to | |
| 662 | + * receive from this socket. | |
| 663 | + */ | |
| 664 | + if (io_fill_cqe_req_aux(req, issue_flags & IO_URING_F_COMPLETE_DEFER, | |
| 665 | + *ret, cflags | IORING_CQE_F_MORE)) { | |
| 666 | + struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg); | |
| 667 | + int mshot_retry_ret = IOU_ISSUE_SKIP_COMPLETE; | |
| 668 | + | |
| 669 | + io_recv_prep_retry(req); | |
| 670 | + /* Known not-empty or unknown state, retry */ | |
| 671 | + if (cflags & IORING_CQE_F_SOCK_NONEMPTY || msg->msg_inq == -1) { | |
| 672 | + if (sr->nr_multishot_loops++ < MULTISHOT_MAX_RETRY) | |
| 655 | 673 | return false; |
| 656 | − if (issue_flags & IO_URING_F_MULTISHOT) | |
| 657 | − *ret = IOU_ISSUE_SKIP_COMPLETE; | |
| 658 | − else | |
| 659 | − *ret = -EAGAIN; | |
| 660 | − return true; | |
| 674 | + /* mshot retries exceeded, force a requeue */ | |
| 675 | + sr->nr_multishot_loops = 0; | |
| 676 | + mshot_retry_ret = IOU_REQUEUE; | |
| 661 | 677 | } |
| 662 | − /* Otherwise stop multishot but use the current result. */ | |
| 678 | + if (issue_flags & IO_URING_F_MULTISHOT) | |
| 679 | + *ret = mshot_retry_ret; | |
| 680 | + else | |
| 681 | + *ret = -EAGAIN; | |
| 682 | + return true; | |
| 663 | 683 | } |
| 664 | − | |
| 684 | + /* Otherwise stop multishot but use the current result. */ | |
| 685 | +finish: | |
| 665 | 686 | io_req_set_res(req, *ret, cflags); |
| 666 | 687 | |
| 667 | 688 | if (issue_flags & IO_URING_F_MULTISHOT) |
| @@ -902,6 +923,7 @@ retry_multishot: · 234 unmodified lines | ||
| 902 | 923 | if (!buf) |
| 903 | 924 | return -ENOBUFS; |
| 904 | 925 | sr->buf = buf; |
| 926 | + sr->len = len; | |
| 905 | 927 | } |
| 906 | 928 | |
| 907 | 929 | ret = import_ubuf(ITER_DEST, sr->buf, len, &msg.msg_iter); |
| @@ -226,8 +226,29 @@ enum { · 225 unmodified lines | ||
| 226 | 226 | IOU_POLL_NO_ACTION = 1, |
| 227 | 227 | IOU_POLL_REMOVE_POLL_USE_RES = 2, |
| 228 | 228 | IOU_POLL_REISSUE = 3, |
| 229 | + IOU_POLL_REQUEUE = 4, | |
| 229 | 230 | }; |
| 230 | 231 | |
| 232 | +static void __io_poll_execute(struct io_kiocb *req, int mask) | |
| 233 | +{ | |
| 234 | + unsigned flags = 0; | |
| 235 | + | |
| 236 | + io_req_set_res(req, mask, 0); | |
| 237 | + req->io_task_work.func = io_poll_task_func; | |
| 238 | + | |
| 239 | + trace_io_uring_task_add(req, mask); | |
| 240 | + | |
| 241 | + if (!(req->flags & REQ_F_POLL_NO_LAZY)) | |
| 242 | + flags = IOU_F_TWQ_LAZY_WAKE; | |
| 243 | + __io_req_task_work_add(req, flags); | |
| 244 | +} | |
| 245 | + | |
| 246 | +static inline void io_poll_execute(struct io_kiocb *req, int res) | |
| 247 | +{ | |
| 248 | + if (io_poll_get_ownership(req)) | |
| 249 | + __io_poll_execute(req, res); | |
| 250 | +} | |
| 251 | + | |
| 231 | 252 | /* |
| 232 | 253 | * All poll tw should go through this. Checks for poll events, manages |
| 233 | 254 | * references, does rewait, etc. |
| @@ -309,6 +330,8 @@ static int io_poll_check_events(struct io_kiocb *req, struct io_tw_state *ts) · 75 unmodified lines | ||
| 309 | 330 | int ret = io_poll_issue(req, ts); |
| 310 | 331 | if (ret == IOU_STOP_MULTISHOT) |
| 311 | 332 | return IOU_POLL_REMOVE_POLL_USE_RES; |
| 333 | + else if (ret == IOU_REQUEUE) | |
| 334 | + return IOU_POLL_REQUEUE; | |
| 312 | 335 | if (ret < 0) |
| 313 | 336 | return ret; |
| 314 | 337 | } |
| @@ -331,8 +354,12 @@ void io_poll_task_func(struct io_kiocb *req, struct io_tw_state *ts) · 16 unmodified lines | ||
| 331 | 354 | int ret; |
| 332 | 355 | |
| 333 | 356 | ret = io_poll_check_events(req, ts); |
| 334 | − if (ret == IOU_POLL_NO_ACTION) | |
| 357 | + if (ret == IOU_POLL_NO_ACTION) { | |
| 358 | + return; | |
| 359 | + } else if (ret == IOU_POLL_REQUEUE) { | |
| 360 | + __io_poll_execute(req, 0); | |
| 335 | 361 | return; |
| 362 | + } | |
| 336 | 363 | io_poll_remove_entries(req); |
| 337 | 364 | io_poll_tw_hash_eject(req, ts); |
| 338 | 365 | |
| @@ -364,26 +391,6 @@ void io_poll_task_func(struct io_kiocb *req, struct io_tw_state *ts) · 25 unmodified lines | ||
| 364 | 391 | } |
| 365 | 392 | } |
| 366 | 393 | |
| 367 | −static void __io_poll_execute(struct io_kiocb *req, int mask) | |
| 368 | −{ | |
| 369 | − unsigned flags = 0; | |
| 370 | − | |
| 371 | − io_req_set_res(req, mask, 0); | |
| 372 | − req->io_task_work.func = io_poll_task_func; | |
| 373 | − | |
| 374 | − trace_io_uring_task_add(req, mask); | |
| 375 | − | |
| 376 | − if (!(req->flags & REQ_F_POLL_NO_LAZY)) | |
| 377 | − flags = IOU_F_TWQ_LAZY_WAKE; | |
| 378 | − __io_req_task_work_add(req, flags); | |
| 379 | −} | |
| 380 | − | |
| 381 | −static inline void io_poll_execute(struct io_kiocb *req, int res) | |
| 382 | −{ | |
| 383 | − if (io_poll_get_ownership(req)) | |
| 384 | − __io_poll_execute(req, res); | |
| 385 | −} | |
| 386 | − | |
| 387 | 394 | static void io_poll_cancel_req(struct io_kiocb *req) |
| 388 | 395 | { |
| 389 | 396 | io_poll_mark_cancelled(req); |
| @@ -24,6 +24,15 @@ struct async_poll { · 23 unmodified lines | ||
| 24 | 24 | struct io_poll *double_poll; |
| 25 | 25 | }; |
| 26 | 26 | |
| 27 | +/* | |
| 28 | + * Must only be called inside issue_flags & IO_URING_F_MULTISHOT, or | |
| 29 | + * potentially other cases where we already "own" this poll request. | |
| 30 | + */ | |
| 31 | +static inline void io_poll_multishot_retry(struct io_kiocb *req) | |
| 32 | +{ | |
| 33 | + atomic_inc(&req->poll_refs); | |
| 34 | +} | |
| 35 | + | |
| 27 | 36 | int io_poll_add_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe); |
| 28 | 37 | int io_poll_add(struct io_kiocb *req, unsigned int issue_flags); |
| 29 | 38 | |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | #include "opdef.h" |
| 19 | 19 | #include "kbuf.h" |
| 20 | 20 | #include "rsrc.h" |
| 21 | +#include "poll.h" | |
| 21 | 22 | #include "rw.h" |
| 22 | 23 | |
| 23 | 24 | struct io_rw { |
| @@ -962,8 +963,15 @@ int io_read_mshot(struct io_kiocb *req, unsigned int issue_flags) · 938 unmodified lines | ||
| 962 | 963 | if (io_fill_cqe_req_aux(req, |
| 963 | 964 | issue_flags & IO_URING_F_COMPLETE_DEFER, |
| 964 | 965 | ret, cflags | IORING_CQE_F_MORE)) { |
| 965 | − if (issue_flags & IO_URING_F_MULTISHOT) | |
| 966 | + if (issue_flags & IO_URING_F_MULTISHOT) { | |
| 967 | + /* | |
| 968 | + * Force retry, as we might have more data to | |
| 969 | + * be read and otherwise it won't get retried | |
| 970 | + * until (if ever) another poll is triggered. | |
| 971 | + */ | |
| 972 | + io_poll_multishot_retry(req); | |
| 966 | 973 | return IOU_ISSUE_SKIP_COMPLETE; |
| 974 | + } | |
| 967 | 975 | return -EAGAIN; |
| 968 | 976 | } |
| 969 | 977 | } |
| @@ -944,7 +944,7 @@ __poll_t ring_buffer_poll_wait(struct trace_buffer *buffer, int cpu, · 943 unmodified lines | ||
| 944 | 944 | full = 0; |
| 945 | 945 | } else { |
| 946 | 946 | if (!cpumask_test_cpu(cpu, buffer->cpumask)) |
| 947 | − return -EINVAL; | |
| 947 | + return EPOLLERR; | |
| 948 | 948 | |
| 949 | 949 | cpu_buffer = buffer->buffers[cpu]; |
| 950 | 950 | work = &cpu_buffer->irq_work; |
| @@ -2444,6 +2444,9 @@ static int timerlat_fd_open(struct inode *inode, struct file *file) · 2443 unmodified lines | ||
| 2444 | 2444 | tlat = this_cpu_tmr_var(); |
| 2445 | 2445 | tlat->count = 0; |
| 2446 | 2446 | |
| 2447 | + hrtimer_init(&tlat->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED_HARD); | |
| 2448 | + tlat->timer.function = timerlat_irq; | |
| 2449 | + | |
| 2447 | 2450 | migrate_enable(); |
| 2448 | 2451 | return 0; |
| 2449 | 2452 | }; |
| @@ -2526,9 +2529,6 @@ timerlat_fd_read(struct file *file, char __user *ubuf, size_t count, · 76 unmodified lines | ||
| 2526 | 2529 | tlat->tracing_thread = false; |
| 2527 | 2530 | tlat->kthread = current; |
| 2528 | 2531 | |
| 2529 | − hrtimer_init(&tlat->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED_HARD); | |
| 2530 | − tlat->timer.function = timerlat_irq; | |
| 2531 | − | |
| 2532 | 2532 | /* Annotate now to drift new period */ |
| 2533 | 2533 | tlat->abs_period = hrtimer_cb_get_time(&tlat->timer); |
| 2534 | 2534 | |
| @@ -751,7 +751,7 @@ size_t memcpy_to_iter_csum(void *iter_to, size_t progress, · 750 unmodified lines | ||
| 751 | 751 | size_t len, void *from, void *priv2) |
| 752 | 752 | { |
| 753 | 753 | __wsum *csum = priv2; |
| 754 | − __wsum next = csum_partial_copy_nocheck(from, iter_to, len); | |
| 754 | + __wsum next = csum_partial_copy_nocheck(from + progress, iter_to, len); | |
| 755 | 755 | |
| 756 | 756 | *csum = csum_block_add(*csum, next, progress); |
| 757 | 757 | return 0; |
| @@ -46,7 +46,7 @@ struct devlink_rel { · 45 unmodified lines | ||
| 46 | 46 | u32 obj_index; |
| 47 | 47 | devlink_rel_notify_cb_t *notify_cb; |
| 48 | 48 | devlink_rel_cleanup_cb_t *cleanup_cb; |
| 49 | − struct work_struct notify_work; | |
| 49 | + struct delayed_work notify_work; | |
| 50 | 50 | } nested_in; |
| 51 | 51 | }; |
| 52 | 52 | |
| @@ -70,7 +70,7 @@ static void __devlink_rel_put(struct devlink_rel *rel) · 17 unmodified lines | ||
| 70 | 70 | static void devlink_rel_nested_in_notify_work(struct work_struct *work) |
| 71 | 71 | { |
| 72 | 72 | struct devlink_rel *rel = container_of(work, struct devlink_rel, |
| 73 | − nested_in.notify_work); | |
| 73 | + nested_in.notify_work.work); | |
| 74 | 74 | struct devlink *devlink; |
| 75 | 75 | |
| 76 | 76 | devlink = devlinks_xa_get(rel->nested_in.devlink_index); |
| @@ -96,13 +96,13 @@ rel_put: · 19 unmodified lines | ||
| 96 | 96 | return; |
| 97 | 97 | |
| 98 | 98 | reschedule_work: |
| 99 | − schedule_work(&rel->nested_in.notify_work); | |
| 99 | + schedule_delayed_work(&rel->nested_in.notify_work, 1); | |
| 100 | 100 | } |
| 101 | 101 | |
| 102 | 102 | static void devlink_rel_nested_in_notify_work_schedule(struct devlink_rel *rel) |
| 103 | 103 | { |
| 104 | 104 | __devlink_rel_get(rel); |
| 105 | − schedule_work(&rel->nested_in.notify_work); | |
| 105 | + schedule_delayed_work(&rel->nested_in.notify_work, 0); | |
| 106 | 106 | } |
| 107 | 107 | |
| 108 | 108 | static struct devlink_rel *devlink_rel_alloc(void) |
| @@ -123,8 +123,8 @@ static struct devlink_rel *devlink_rel_alloc(void) · 14 unmodified lines | ||
| 123 | 123 | } |
| 124 | 124 | |
| 125 | 125 | refcount_set(&rel->refcount, 1); |
| 126 | − INIT_WORK(&rel->nested_in.notify_work, | |
| 127 | − &devlink_rel_nested_in_notify_work); | |
| 126 | + INIT_DELAYED_WORK(&rel->nested_in.notify_work, | |
| 127 | + &devlink_rel_nested_in_notify_work); | |
| 128 | 128 | return rel; |
| 129 | 129 | } |
| 130 | 130 | |
| @@ -1628,10 +1628,12 @@ EXPORT_SYMBOL(inet_current_timestamp); · 1627 unmodified lines | ||
| 1628 | 1628 | |
| 1629 | 1629 | int inet_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) |
| 1630 | 1630 | { |
| 1631 | − if (sk->sk_family == AF_INET) | |
| 1631 | + unsigned int family = READ_ONCE(sk->sk_family); | |
| 1632 | + | |
| 1633 | + if (family == AF_INET) | |
| 1632 | 1634 | return ip_recv_error(sk, msg, len, addr_len); |
| 1633 | 1635 | #if IS_ENABLED(CONFIG_IPV6) |
| 1634 | − if (sk->sk_family == AF_INET6) | |
| 1636 | + if (family == AF_INET6) | |
| 1635 | 1637 | return pingv6_ops.ipv6_recv_error(sk, msg, len, addr_len); |
| 1636 | 1638 | #endif |
| 1637 | 1639 | return -EINVAL; |
| @@ -332,7 +332,7 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu) · 331 unmodified lines | ||
| 332 | 332 | }; |
| 333 | 333 | skb_reset_network_header(skb); |
| 334 | 334 | |
| 335 | − csum = csum_partial(icmp6h, len, 0); | |
| 335 | + csum = skb_checksum(skb, skb_transport_offset(skb), len, 0); | |
| 336 | 336 | icmp6h->icmp6_cksum = csum_ipv6_magic(&nip6h->saddr, &nip6h->daddr, len, |
| 337 | 337 | IPPROTO_ICMPV6, csum); |
| 338 | 338 | |
| @@ -5,7 +5,7 @@ · 4 unmodified lines | ||
| 5 | 5 | * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> |
| 6 | 6 | * Copyright 2013-2015 Intel Mobile Communications GmbH |
| 7 | 7 | * Copyright (C) 2015-2017 Intel Deutschland GmbH |
| 8 | − * Copyright (C) 2018-2022 Intel Corporation | |
| 8 | + * Copyright (C) 2018-2024 Intel Corporation | |
| 9 | 9 | */ |
| 10 | 10 | |
| 11 | 11 | #include <linux/ieee80211.h> |
| @@ -987,7 +987,8 @@ static int · 975 unmodified lines | ||
| 987 | 987 | ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata, |
| 988 | 988 | struct cfg80211_unsol_bcast_probe_resp *params, |
| 989 | 989 | struct ieee80211_link_data *link, |
| 990 | − struct ieee80211_bss_conf *link_conf) | |
| 990 | + struct ieee80211_bss_conf *link_conf, | |
| 991 | + u64 *changed) | |
| 991 | 992 | { |
| 992 | 993 | struct unsol_bcast_probe_resp_data *new, *old = NULL; |
| 993 | 994 | |
| @@ -1011,7 +1012,8 @@ ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata, · 17 unmodified lines | ||
| 1011 | 1012 | RCU_INIT_POINTER(link->u.ap.unsol_bcast_probe_resp, NULL); |
| 1012 | 1013 | } |
| 1013 | 1014 | |
| 1014 | − return BSS_CHANGED_UNSOL_BCAST_PROBE_RESP; | |
| 1015 | + *changed |= BSS_CHANGED_UNSOL_BCAST_PROBE_RESP; | |
| 1016 | + return 0; | |
| 1015 | 1017 | } |
| 1016 | 1018 | |
| 1017 | 1019 | static int ieee80211_set_ftm_responder_params( |
| @@ -1450,10 +1452,9 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, · 432 unmodified lines | ||
| 1450 | 1452 | |
| 1451 | 1453 | err = ieee80211_set_unsol_bcast_probe_resp(sdata, |
| 1452 | 1454 | ¶ms->unsol_bcast_probe_resp, |
| 1453 | − link, link_conf); | |
| 1455 | + link, link_conf, &changed); | |
| 1454 | 1456 | if (err < 0) |
| 1455 | 1457 | goto error; |
| 1456 | − changed |= err; | |
| 1457 | 1458 | |
| 1458 | 1459 | err = drv_start_ap(sdata->local, sdata, link_conf); |
| 1459 | 1460 | if (err) { |
| @@ -1525,10 +1526,9 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, · 65 unmodified lines | ||
| 1525 | 1526 | |
| 1526 | 1527 | err = ieee80211_set_unsol_bcast_probe_resp(sdata, |
| 1527 | 1528 | ¶ms->unsol_bcast_probe_resp, |
| 1528 | − link, link_conf); | |
| 1529 | + link, link_conf, &changed); | |
| 1529 | 1530 | if (err < 0) |
| 1530 | 1531 | return err; |
| 1531 | − changed |= err; | |
| 1532 | 1532 | |
| 1533 | 1533 | if (beacon->he_bss_color_valid && |
| 1534 | 1534 | beacon->he_bss_color.enabled != link_conf->he_bss_color.enabled) { |
| @@ -1869,6 +1869,8 @@ static int sta_link_apply_parameters(struct ieee80211_local *local, · 334 unmodified lines | ||
| 1869 | 1869 | sband->band); |
| 1870 | 1870 | } |
| 1871 | 1871 | |
| 1872 | + ieee80211_sta_set_rx_nss(link_sta); | |
| 1873 | + | |
| 1872 | 1874 | return ret; |
| 1873 | 1875 | } |
| 1874 | 1876 | |
| @@ -997,8 +997,8 @@ static void add_link_files(struct ieee80211_link_data *link, · 996 unmodified lines | ||
| 997 | 997 | } |
| 998 | 998 | } |
| 999 | 999 | |
| 1000 | −void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata, | |
| 1001 | − bool mld_vif) | |
| 1000 | +static void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata, | |
| 1001 | + bool mld_vif) | |
| 1002 | 1002 | { |
| 1003 | 1003 | char buf[10+IFNAMSIZ]; |
| 1004 | 1004 | |
| @@ -11,8 +11,6 @@ · 10 unmodified lines | ||
| 11 | 11 | #include "ieee80211_i.h" |
| 12 | 12 | |
| 13 | 13 | #ifdef CONFIG_MAC80211_DEBUGFS |
| 14 | −void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata, | |
| 15 | − bool mld_vif); | |
| 16 | 14 | void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata); |
| 17 | 15 | void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata); |
| 18 | 16 | void ieee80211_debugfs_recreate_netdev(struct ieee80211_sub_if_data *sdata, |
| @@ -24,9 +22,6 @@ void ieee80211_link_debugfs_remove(struct ieee80211_link_data *link); · 5 unmodified lines | ||
| 24 | 22 | void ieee80211_link_debugfs_drv_add(struct ieee80211_link_data *link); |
| 25 | 23 | void ieee80211_link_debugfs_drv_remove(struct ieee80211_link_data *link); |
| 26 | 24 | #else |
| 27 | −static inline void ieee80211_debugfs_add_netdev( | |
| 28 | − struct ieee80211_sub_if_data *sdata, bool mld_vif) | |
| 29 | −{} | |
| 30 | 25 | static inline void ieee80211_debugfs_remove_netdev( |
| 31 | 26 | struct ieee80211_sub_if_data *sdata) |
| 32 | 27 | {} |
| @@ -1783,7 +1783,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, · 1782 unmodified lines | ||
| 1783 | 1783 | /* need to do this after the switch so vif.type is correct */ |
| 1784 | 1784 | ieee80211_link_setup(&sdata->deflink); |
| 1785 | 1785 | |
| 1786 | − ieee80211_debugfs_add_netdev(sdata, false); | |
| 1786 | + ieee80211_debugfs_recreate_netdev(sdata, false); | |
| 1787 | 1787 | } |
| 1788 | 1788 | |
| 1789 | 1789 | static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, |
| @@ -8,7 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> |
| 9 | 9 | * Copyright 2013-2014 Intel Mobile Communications GmbH |
| 10 | 10 | * Copyright (C) 2015 - 2017 Intel Deutschland GmbH |
| 11 | − * Copyright (C) 2018 - 2023 Intel Corporation | |
| 11 | + * Copyright (C) 2018 - 2024 Intel Corporation | |
| 12 | 12 | */ |
| 13 | 13 | |
| 14 | 14 | #include <linux/delay.h> |
| @@ -2918,6 +2918,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, · 2903 unmodified lines | ||
| 2918 | 2918 | |
| 2919 | 2919 | /* other links will be destroyed */ |
| 2920 | 2920 | sdata->deflink.u.mgd.bss = NULL; |
| 2921 | + sdata->deflink.smps_mode = IEEE80211_SMPS_OFF; | |
| 2921 | 2922 | |
| 2922 | 2923 | netif_carrier_off(sdata->dev); |
| 2923 | 2924 | |
| @@ -5045,9 +5046,6 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, · 2121 unmodified lines | ||
| 5045 | 5046 | if (!link) |
| 5046 | 5047 | return 0; |
| 5047 | 5048 | |
| 5048 | − /* will change later if needed */ | |
| 5049 | − link->smps_mode = IEEE80211_SMPS_OFF; | |
| 5050 | − | |
| 5051 | 5049 | /* |
| 5052 | 5050 | * If this fails (possibly due to channel context sharing |
| 5053 | 5051 | * on incompatible channels, e.g. 80+80 and 160 sharing the |
| @@ -7096,6 +7094,7 @@ void ieee80211_mgd_setup_link(struct ieee80211_link_data *link) · 2042 unmodified lines | ||
| 7096 | 7094 | link->u.mgd.p2p_noa_index = -1; |
| 7097 | 7095 | link->u.mgd.conn_flags = 0; |
| 7098 | 7096 | link->conf->bssid = link->u.mgd.bssid; |
| 7097 | + link->smps_mode = IEEE80211_SMPS_OFF; | |
| 7099 | 7098 | |
| 7100 | 7099 | wiphy_work_init(&link->u.mgd.request_smps_work, |
| 7101 | 7100 | ieee80211_request_smps_mgd_work); |
| @@ -7309,6 +7308,75 @@ out_err: · 207 unmodified lines | ||
| 7309 | 7308 | return err; |
| 7310 | 7309 | } |
| 7311 | 7310 | |
| 7311 | +static bool ieee80211_mgd_csa_present(struct ieee80211_sub_if_data *sdata, | |
| 7312 | + const struct cfg80211_bss_ies *ies, | |
| 7313 | + u8 cur_channel, bool ignore_ecsa) | |
| 7314 | +{ | |
| 7315 | + const struct element *csa_elem, *ecsa_elem; | |
| 7316 | + struct ieee80211_channel_sw_ie *csa = NULL; | |
| 7317 | + struct ieee80211_ext_chansw_ie *ecsa = NULL; | |
| 7318 | + | |
| 7319 | + if (!ies) | |
| 7320 | + return false; | |
| 7321 | + | |
| 7322 | + csa_elem = cfg80211_find_elem(WLAN_EID_CHANNEL_SWITCH, | |
| 7323 | + ies->data, ies->len); | |
| 7324 | + if (csa_elem && csa_elem->datalen == sizeof(*csa)) | |
| 7325 | + csa = (void *)csa_elem->data; | |
| 7326 | + | |
| 7327 | + ecsa_elem = cfg80211_find_elem(WLAN_EID_EXT_CHANSWITCH_ANN, | |
| 7328 | + ies->data, ies->len); | |
| 7329 | + if (ecsa_elem && ecsa_elem->datalen == sizeof(*ecsa)) | |
| 7330 | + ecsa = (void *)ecsa_elem->data; | |
| 7331 | + | |
| 7332 | + if (csa && csa->count == 0) | |
| 7333 | + csa = NULL; | |
| 7334 | + if (csa && !csa->mode && csa->new_ch_num == cur_channel) | |
| 7335 | + csa = NULL; | |
| 7336 | + | |
| 7337 | + if (ecsa && ecsa->count == 0) | |
| 7338 | + ecsa = NULL; | |
| 7339 | + if (ecsa && !ecsa->mode && ecsa->new_ch_num == cur_channel) | |
| 7340 | + ecsa = NULL; | |
| 7341 | + | |
| 7342 | + if (ignore_ecsa && ecsa) { | |
| 7343 | + sdata_info(sdata, | |
| 7344 | + "Ignoring ECSA in probe response - was considered stuck!\n"); | |
| 7345 | + return csa; | |
| 7346 | + } | |
| 7347 | + | |
| 7348 | + return csa || ecsa; | |
| 7349 | +} | |
| 7350 | + | |
| 7351 | +static bool ieee80211_mgd_csa_in_process(struct ieee80211_sub_if_data *sdata, | |
| 7352 | + struct cfg80211_bss *bss) | |
| 7353 | +{ | |
| 7354 | + u8 cur_channel; | |
| 7355 | + bool ret; | |
| 7356 | + | |
| 7357 | + cur_channel = ieee80211_frequency_to_channel(bss->channel->center_freq); | |
| 7358 | + | |
| 7359 | + rcu_read_lock(); | |
| 7360 | + if (ieee80211_mgd_csa_present(sdata, | |
| 7361 | + rcu_dereference(bss->beacon_ies), | |
| 7362 | + cur_channel, false)) { | |
| 7363 | + ret = true; | |
| 7364 | + goto out; | |
| 7365 | + } | |
| 7366 | + | |
| 7367 | + if (ieee80211_mgd_csa_present(sdata, | |
| 7368 | + rcu_dereference(bss->proberesp_ies), | |
| 7369 | + cur_channel, bss->proberesp_ecsa_stuck)) { | |
| 7370 | + ret = true; | |
| 7371 | + goto out; | |
| 7372 | + } | |
| 7373 | + | |
| 7374 | + ret = false; | |
| 7375 | +out: | |
| 7376 | + rcu_read_unlock(); | |
| 7377 | + return ret; | |
| 7378 | +} | |
| 7379 | + | |
| 7312 | 7380 | /* config hooks */ |
| 7313 | 7381 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, |
| 7314 | 7382 | struct cfg80211_auth_request *req) |
| @@ -7317,7 +7385,6 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, · 2 unmodified lines | ||
| 7317 | 7385 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| 7318 | 7386 | struct ieee80211_mgd_auth_data *auth_data; |
| 7319 | 7387 | struct ieee80211_link_data *link; |
| 7320 | − const struct element *csa_elem, *ecsa_elem; | |
| 7321 | 7388 | u16 auth_alg; |
| 7322 | 7389 | int err; |
| 7323 | 7390 | bool cont_auth; |
| @@ -7360,21 +7427,10 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, · 36 unmodified lines | ||
| 7360 | 7427 | if (ifmgd->assoc_data) |
| 7361 | 7428 | return -EBUSY; |
| 7362 | 7429 | |
| 7363 | − rcu_read_lock(); | |
| 7364 | − csa_elem = ieee80211_bss_get_elem(req->bss, WLAN_EID_CHANNEL_SWITCH); | |
| 7365 | − ecsa_elem = ieee80211_bss_get_elem(req->bss, | |
| 7366 | − WLAN_EID_EXT_CHANSWITCH_ANN); | |
| 7367 | − if ((csa_elem && | |
| 7368 | − csa_elem->datalen == sizeof(struct ieee80211_channel_sw_ie) && | |
| 7369 | − ((struct ieee80211_channel_sw_ie *)csa_elem->data)->count != 0) || | |
| 7370 | − (ecsa_elem && | |
| 7371 | − ecsa_elem->datalen == sizeof(struct ieee80211_ext_chansw_ie) && | |
| 7372 | − ((struct ieee80211_ext_chansw_ie *)ecsa_elem->data)->count != 0)) { | |
| 7373 | − rcu_read_unlock(); | |
| 7430 | + if (ieee80211_mgd_csa_in_process(sdata, req->bss)) { | |
| 7374 | 7431 | sdata_info(sdata, "AP is in CSA process, reject auth\n"); |
| 7375 | 7432 | return -EINVAL; |
| 7376 | 7433 | } |
| 7377 | − rcu_read_unlock(); | |
| 7378 | 7434 | |
| 7379 | 7435 | auth_data = kzalloc(sizeof(*auth_data) + req->auth_data_len + |
| 7380 | 7436 | req->ie_len, GFP_KERNEL); |
| @@ -7684,7 +7740,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, · 303 unmodified lines | ||
| 7684 | 7740 | struct ieee80211_local *local = sdata->local; |
| 7685 | 7741 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| 7686 | 7742 | struct ieee80211_mgd_assoc_data *assoc_data; |
| 7687 | − const struct element *ssid_elem, *csa_elem, *ecsa_elem; | |
| 7743 | + const struct element *ssid_elem; | |
| 7688 | 7744 | struct ieee80211_vif_cfg *vif_cfg = &sdata->vif.cfg; |
| 7689 | 7745 | ieee80211_conn_flags_t conn_flags = 0; |
| 7690 | 7746 | struct ieee80211_link_data *link; |
| @@ -7707,23 +7763,15 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, · 16 unmodified lines | ||
| 7707 | 7763 | |
| 7708 | 7764 | cbss = req->link_id < 0 ? req->bss : req->links[req->link_id].bss; |
| 7709 | 7765 | |
| 7710 | − rcu_read_lock(); | |
| 7711 | − ssid_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_SSID); | |
| 7712 | − if (!ssid_elem || ssid_elem->datalen > sizeof(assoc_data->ssid)) { | |
| 7713 | − rcu_read_unlock(); | |
| 7766 | + if (ieee80211_mgd_csa_in_process(sdata, cbss)) { | |
| 7767 | + sdata_info(sdata, "AP is in CSA process, reject assoc\n"); | |
| 7714 | 7768 | kfree(assoc_data); |
| 7715 | 7769 | return -EINVAL; |
| 7716 | 7770 | } |
| 7717 | 7771 | |
| 7718 | − csa_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_CHANNEL_SWITCH); | |
| 7719 | − ecsa_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_EXT_CHANSWITCH_ANN); | |
| 7720 | − if ((csa_elem && | |
| 7721 | − csa_elem->datalen == sizeof(struct ieee80211_channel_sw_ie) && | |
| 7722 | − ((struct ieee80211_channel_sw_ie *)csa_elem->data)->count != 0) || | |
| 7723 | − (ecsa_elem && | |
| 7724 | − ecsa_elem->datalen == sizeof(struct ieee80211_ext_chansw_ie) && | |
| 7725 | − ((struct ieee80211_ext_chansw_ie *)ecsa_elem->data)->count != 0)) { | |
| 7726 | − sdata_info(sdata, "AP is in CSA process, reject assoc\n"); | |
| 7772 | + rcu_read_lock(); | |
| 7773 | + ssid_elem = ieee80211_bss_get_elem(cbss, WLAN_EID_SSID); | |
| 7774 | + if (!ssid_elem || ssid_elem->datalen > sizeof(assoc_data->ssid)) { | |
| 7727 | 7775 | rcu_read_unlock(); |
| 7728 | 7776 | kfree(assoc_data); |
| 7729 | 7777 | return -EINVAL; |
| @@ -7998,8 +8046,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, · 268 unmodified lines | ||
| 7998 | 8046 | |
| 7999 | 8047 | rcu_read_lock(); |
| 8000 | 8048 | beacon_ies = rcu_dereference(req->bss->beacon_ies); |
| 8001 | − | |
| 8002 | − if (beacon_ies) { | |
| 8049 | + if (!beacon_ies) { | |
| 8003 | 8050 | /* |
| 8004 | 8051 | * Wait up to one beacon interval ... |
| 8005 | 8052 | * should this be more if we miss one? |
| @@ -8080,6 +8127,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, · 74 unmodified lines | ||
| 8080 | 8127 | ieee80211_report_disconnect(sdata, frame_buf, |
| 8081 | 8128 | sizeof(frame_buf), true, |
| 8082 | 8129 | req->reason_code, false); |
| 8130 | + drv_mgd_complete_tx(sdata->local, sdata, &info); | |
| 8083 | 8131 | return 0; |
| 8084 | 8132 | } |
| 8085 | 8133 | |
| @@ -9,7 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> |
| 10 | 10 | * Copyright 2013-2015 Intel Mobile Communications GmbH |
| 11 | 11 | * Copyright 2016-2017 Intel Deutschland GmbH |
| 12 | − * Copyright (C) 2018-2023 Intel Corporation | |
| 12 | + * Copyright (C) 2018-2024 Intel Corporation | |
| 13 | 13 | */ |
| 14 | 14 | |
| 15 | 15 | #include <linux/if_arp.h> |
| @@ -237,14 +237,18 @@ ieee80211_bss_info_update(struct ieee80211_local *local, · 221 unmodified lines | ||
| 237 | 237 | } |
| 238 | 238 | |
| 239 | 239 | static bool ieee80211_scan_accept_presp(struct ieee80211_sub_if_data *sdata, |
| 240 | + struct ieee80211_channel *channel, | |
| 240 | 241 | u32 scan_flags, const u8 *da) |
| 241 | 242 | { |
| 242 | 243 | if (!sdata) |
| 243 | 244 | return false; |
| 244 | − /* accept broadcast for OCE */ | |
| 245 | − if (scan_flags & NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP && | |
| 246 | − is_broadcast_ether_addr(da)) | |
| 245 | + | |
| 246 | + /* accept broadcast on 6 GHz and for OCE */ | |
| 247 | + if (is_broadcast_ether_addr(da) && | |
| 248 | + (channel->band == NL80211_BAND_6GHZ || | |
| 249 | + scan_flags & NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP)) | |
| 247 | 250 | return true; |
| 251 | + | |
| 248 | 252 | if (scan_flags & NL80211_SCAN_FLAG_RANDOM_ADDR) |
| 249 | 253 | return true; |
| 250 | 254 | return ether_addr_equal(da, sdata->vif.addr); |
| @@ -293,6 +297,12 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) · 42 unmodified lines | ||
| 293 | 297 | wiphy_delayed_work_queue(local->hw.wiphy, &local->scan_work, 0); |
| 294 | 298 | } |
| 295 | 299 | |
| 300 | + channel = ieee80211_get_channel_khz(local->hw.wiphy, | |
| 301 | + ieee80211_rx_status_to_khz(rx_status)); | |
| 302 | + | |
| 303 | + if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | |
| 304 | + return; | |
| 305 | + | |
| 296 | 306 | if (ieee80211_is_probe_resp(mgmt->frame_control)) { |
| 297 | 307 | struct cfg80211_scan_request *scan_req; |
| 298 | 308 | struct cfg80211_sched_scan_request *sched_scan_req; |
| @@ -310,19 +320,15 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) · 11 unmodified lines | ||
| 310 | 320 | /* ignore ProbeResp to foreign address or non-bcast (OCE) |
| 311 | 321 | * unless scanning with randomised address |
| 312 | 322 | */ |
| 313 | − if (!ieee80211_scan_accept_presp(sdata1, scan_req_flags, | |
| 323 | + if (!ieee80211_scan_accept_presp(sdata1, channel, | |
| 324 | + scan_req_flags, | |
| 314 | 325 | mgmt->da) && |
| 315 | − !ieee80211_scan_accept_presp(sdata2, sched_scan_req_flags, | |
| 326 | + !ieee80211_scan_accept_presp(sdata2, channel, | |
| 327 | + sched_scan_req_flags, | |
| 316 | 328 | mgmt->da)) |
| 317 | 329 | return; |
| 318 | 330 | } |
| 319 | 331 | |
| 320 | − channel = ieee80211_get_channel_khz(local->hw.wiphy, | |
| 321 | − ieee80211_rx_status_to_khz(rx_status)); | |
| 322 | − | |
| 323 | − if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | |
| 324 | − return; | |
| 325 | − | |
| 326 | 332 | bss = ieee80211_bss_info_update(local, rx_status, |
| 327 | 333 | mgmt, skb->len, |
| 328 | 334 | channel); |
| @@ -3100,10 +3100,11 @@ void ieee80211_check_fast_xmit(struct sta_info *sta) · 3099 unmodified lines | ||
| 3100 | 3100 | /* DA SA BSSID */ |
| 3101 | 3101 | build.da_offs = offsetof(struct ieee80211_hdr, addr1); |
| 3102 | 3102 | build.sa_offs = offsetof(struct ieee80211_hdr, addr2); |
| 3103 | + rcu_read_lock(); | |
| 3103 | 3104 | link = rcu_dereference(sdata->link[tdls_link_id]); |
| 3104 | − if (WARN_ON_ONCE(!link)) | |
| 3105 | − break; | |
| 3106 | − memcpy(hdr->addr3, link->u.mgd.bssid, ETH_ALEN); | |
| 3105 | + if (!WARN_ON_ONCE(!link)) | |
| 3106 | + memcpy(hdr->addr3, link->u.mgd.bssid, ETH_ALEN); | |
| 3107 | + rcu_read_unlock(); | |
| 3107 | 3108 | build.hdr_len = 24; |
| 3108 | 3109 | break; |
| 3109 | 3110 | } |
| @@ -23,8 +23,6 @@ void ieee80211_check_wbrf_support(struct ieee80211_local *local) · 22 unmodified lines | ||
| 23 | 23 | return; |
| 24 | 24 | |
| 25 | 25 | local->wbrf_supported = acpi_amd_wbrf_supported_producer(dev); |
| 26 | − dev_dbg(dev, "WBRF is %s supported\n", | |
| 27 | − local->wbrf_supported ? "" : "not"); | |
| 28 | 26 | } |
| 29 | 27 | |
| 30 | 28 | static void get_chan_freq_boundary(u32 center_freq, u32 bandwidth, u64 *start, u64 *end) |
| @@ -1154,6 +1154,7 @@ static int ip_set_create(struct sk_buff *skb, const struct nfnl_info *info, · 1153 unmodified lines | ||
| 1154 | 1154 | return ret; |
| 1155 | 1155 | |
| 1156 | 1156 | cleanup: |
| 1157 | + set->variant->cancel_gc(set); | |
| 1157 | 1158 | set->variant->destroy(set); |
| 1158 | 1159 | put_out: |
| 1159 | 1160 | module_put(set->type->me); |
| @@ -2378,6 +2379,7 @@ ip_set_net_exit(struct net *net) · 1218 unmodified lines | ||
| 2378 | 2379 | set = ip_set(inst, i); |
| 2379 | 2380 | if (set) { |
| 2380 | 2381 | ip_set(inst, i) = NULL; |
| 2382 | + set->variant->cancel_gc(set); | |
| 2381 | 2383 | ip_set_destroy_set(set); |
| 2382 | 2384 | } |
| 2383 | 2385 | } |
| @@ -432,7 +432,7 @@ mtype_ahash_destroy(struct ip_set *set, struct htable *t, bool ext_destroy) · 431 unmodified lines | ||
| 432 | 432 | u32 i; |
| 433 | 433 | |
| 434 | 434 | for (i = 0; i < jhash_size(t->htable_bits); i++) { |
| 435 | − n = __ipset_dereference(hbucket(t, i)); | |
| 435 | + n = (__force struct hbucket *)hbucket(t, i); | |
| 436 | 436 | if (!n) |
| 437 | 437 | continue; |
| 438 | 438 | if (set->extensions & IPSET_EXT_DESTROY && ext_destroy) |
| @@ -452,7 +452,7 @@ mtype_destroy(struct ip_set *set) · 13 unmodified lines | ||
| 452 | 452 | struct htype *h = set->data; |
| 453 | 453 | struct list_head *l, *lt; |
| 454 | 454 | |
| 455 | − mtype_ahash_destroy(set, ipset_dereference_nfnl(h->table), true); | |
| 455 | + mtype_ahash_destroy(set, (__force struct htable *)h->table, true); | |
| 456 | 456 | list_for_each_safe(l, lt, &h->ad) { |
| 457 | 457 | list_del(l); |
| 458 | 458 | kfree(l); |
| @@ -876,6 +876,7 @@ struct ctnetlink_filter_u32 { · 875 unmodified lines | ||
| 876 | 876 | |
| 877 | 877 | struct ctnetlink_filter { |
| 878 | 878 | u8 family; |
| 879 | + bool zone_filter; | |
| 879 | 880 | |
| 880 | 881 | u_int32_t orig_flags; |
| 881 | 882 | u_int32_t reply_flags; |
| @@ -992,9 +993,12 @@ ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family) · 110 unmodified lines | ||
| 992 | 993 | if (err) |
| 993 | 994 | goto err_filter; |
| 994 | 995 | |
| 995 | − err = ctnetlink_parse_zone(cda[CTA_ZONE], &filter->zone); | |
| 996 | − if (err < 0) | |
| 997 | − goto err_filter; | |
| 996 | + if (cda[CTA_ZONE]) { | |
| 997 | + err = ctnetlink_parse_zone(cda[CTA_ZONE], &filter->zone); | |
| 998 | + if (err < 0) | |
| 999 | + goto err_filter; | |
| 1000 | + filter->zone_filter = true; | |
| 1001 | + } | |
| 998 | 1002 | |
| 999 | 1003 | if (!cda[CTA_FILTER]) |
| 1000 | 1004 | return filter; |
| @@ -1148,7 +1152,7 @@ static int ctnetlink_filter_match(struct nf_conn *ct, void *data) · 147 unmodified lines | ||
| 1148 | 1152 | if (filter->family && nf_ct_l3num(ct) != filter->family) |
| 1149 | 1153 | goto ignore_entry; |
| 1150 | 1154 | |
| 1151 | − if (filter->zone.id != NF_CT_DEFAULT_ZONE_ID && | |
| 1155 | + if (filter->zone_filter && | |
| 1152 | 1156 | !nf_ct_zone_equal_any(ct, &filter->zone)) |
| 1153 | 1157 | goto ignore_entry; |
| 1154 | 1158 | |
| @@ -9834,6 +9834,7 @@ dead_elem: · 9833 unmodified lines | ||
| 9834 | 9834 | struct nft_trans_gc *nft_trans_gc_catchall_sync(struct nft_trans_gc *gc) |
| 9835 | 9835 | { |
| 9836 | 9836 | struct nft_set_elem_catchall *catchall, *next; |
| 9837 | + u64 tstamp = nft_net_tstamp(gc->net); | |
| 9837 | 9838 | const struct nft_set *set = gc->set; |
| 9838 | 9839 | struct nft_elem_priv *elem_priv; |
| 9839 | 9840 | struct nft_set_ext *ext; |
| @@ -9843,7 +9844,7 @@ struct nft_trans_gc *nft_trans_gc_catchall_sync(struct nft_trans_gc *gc) · 3 unmodified lines | ||
| 9843 | 9844 | list_for_each_entry_safe(catchall, next, &set->catchall_list, list) { |
| 9844 | 9845 | ext = nft_set_elem_ext(set, catchall->elem); |
| 9845 | 9846 | |
| 9846 | − if (!nft_set_elem_expired(ext)) | |
| 9847 | + if (!__nft_set_elem_expired(ext, tstamp)) | |
| 9847 | 9848 | continue; |
| 9848 | 9849 | |
| 9849 | 9850 | gc = nft_trans_gc_queue_sync(gc, GFP_KERNEL); |
| @@ -10633,6 +10634,7 @@ static bool nf_tables_valid_genid(struct net *net, u32 genid) · 783 unmodified lines | ||
| 10633 | 10634 | bool genid_ok; |
| 10634 | 10635 | |
| 10635 | 10636 | mutex_lock(&nft_net->commit_mutex); |
| 10637 | + nft_net->tstamp = get_jiffies_64(); | |
| 10636 | 10638 | |
| 10637 | 10639 | genid_ok = genid == 0 || nft_net->base_seq == genid; |
| 10638 | 10640 | if (!genid_ok) |
| @@ -232,18 +232,25 @@ static void nfqnl_reinject(struct nf_queue_entry *entry, unsigned int verdict) · 231 unmodified lines | ||
| 232 | 232 | if (verdict == NF_ACCEPT || |
| 233 | 233 | verdict == NF_REPEAT || |
| 234 | 234 | verdict == NF_STOP) { |
| 235 | + unsigned int ct_verdict = verdict; | |
| 236 | + | |
| 235 | 237 | rcu_read_lock(); |
| 236 | 238 | ct_hook = rcu_dereference(nf_ct_hook); |
| 237 | 239 | if (ct_hook) |
| 238 | − verdict = ct_hook->update(entry->state.net, entry->skb); | |
| 240 | + ct_verdict = ct_hook->update(entry->state.net, entry->skb); | |
| 239 | 241 | rcu_read_unlock(); |
| 240 | 242 | |
| 241 | − switch (verdict & NF_VERDICT_MASK) { | |
| 243 | + switch (ct_verdict & NF_VERDICT_MASK) { | |
| 244 | + case NF_ACCEPT: | |
| 245 | + /* follow userspace verdict, could be REPEAT */ | |
| 246 | + break; | |
| 242 | 247 | case NF_STOLEN: |
| 243 | 248 | nf_queue_entry_free(entry); |
| 244 | 249 | return; |
| 250 | + default: | |
| 251 | + verdict = ct_verdict & NF_VERDICT_MASK; | |
| 252 | + break; | |
| 245 | 253 | } |
| 246 | − | |
| 247 | 254 | } |
| 248 | 255 | nf_reinject(entry, verdict); |
| 249 | 256 | } |
| @@ -135,7 +135,7 @@ static void nft_target_eval_bridge(const struct nft_expr *expr, · 134 unmodified lines | ||
| 135 | 135 | |
| 136 | 136 | static const struct nla_policy nft_target_policy[NFTA_TARGET_MAX + 1] = { |
| 137 | 137 | [NFTA_TARGET_NAME] = { .type = NLA_NUL_STRING }, |
| 138 | − [NFTA_TARGET_REV] = { .type = NLA_U32 }, | |
| 138 | + [NFTA_TARGET_REV] = NLA_POLICY_MAX(NLA_BE32, 255), | |
| 139 | 139 | [NFTA_TARGET_INFO] = { .type = NLA_BINARY }, |
| 140 | 140 | }; |
| 141 | 141 | |
| @@ -200,6 +200,7 @@ static const struct nla_policy nft_rule_compat_policy[NFTA_RULE_COMPAT_MAX + 1] · 58 unmodified lines | ||
| 200 | 200 | static int nft_parse_compat(const struct nlattr *attr, u16 *proto, bool *inv) |
| 201 | 201 | { |
| 202 | 202 | struct nlattr *tb[NFTA_RULE_COMPAT_MAX+1]; |
| 203 | + u32 l4proto; | |
| 203 | 204 | u32 flags; |
| 204 | 205 | int err; |
| 205 | 206 | |
| @@ -212,12 +213,18 @@ static int nft_parse_compat(const struct nlattr *attr, u16 *proto, bool *inv) · 6 unmodified lines | ||
| 212 | 213 | return -EINVAL; |
| 213 | 214 | |
| 214 | 215 | flags = ntohl(nla_get_be32(tb[NFTA_RULE_COMPAT_FLAGS])); |
| 215 | − if (flags & ~NFT_RULE_COMPAT_F_MASK) | |
| 216 | + if (flags & NFT_RULE_COMPAT_F_UNUSED || | |
| 217 | + flags & ~NFT_RULE_COMPAT_F_MASK) | |
| 216 | 218 | return -EINVAL; |
| 217 | 219 | if (flags & NFT_RULE_COMPAT_F_INV) |
| 218 | 220 | *inv = true; |
| 219 | 221 | |
| 220 | − *proto = ntohl(nla_get_be32(tb[NFTA_RULE_COMPAT_PROTO])); | |
| 222 | + l4proto = ntohl(nla_get_be32(tb[NFTA_RULE_COMPAT_PROTO])); | |
| 223 | + if (l4proto > U16_MAX) | |
| 224 | + return -EINVAL; | |
| 225 | + | |
| 226 | + *proto = l4proto; | |
| 227 | + | |
| 221 | 228 | return 0; |
| 222 | 229 | } |
| 223 | 230 | |
| @@ -419,7 +426,7 @@ static void nft_match_eval(const struct nft_expr *expr, · 195 unmodified lines | ||
| 419 | 426 | |
| 420 | 427 | static const struct nla_policy nft_match_policy[NFTA_MATCH_MAX + 1] = { |
| 421 | 428 | [NFTA_MATCH_NAME] = { .type = NLA_NUL_STRING }, |
| 422 | − [NFTA_MATCH_REV] = { .type = NLA_U32 }, | |
| 429 | + [NFTA_MATCH_REV] = NLA_POLICY_MAX(NLA_BE32, 255), | |
| 423 | 430 | [NFTA_MATCH_INFO] = { .type = NLA_BINARY }, |
| 424 | 431 | }; |
| 425 | 432 | |
| @@ -724,7 +731,7 @@ out_put: · 298 unmodified lines | ||
| 724 | 731 | static const struct nla_policy nfnl_compat_policy_get[NFTA_COMPAT_MAX+1] = { |
| 725 | 732 | [NFTA_COMPAT_NAME] = { .type = NLA_NUL_STRING, |
| 726 | 733 | .len = NFT_COMPAT_NAME_MAX-1 }, |
| 727 | − [NFTA_COMPAT_REV] = { .type = NLA_U32 }, | |
| 734 | + [NFTA_COMPAT_REV] = NLA_POLICY_MAX(NLA_BE32, 255), | |
| 728 | 735 | [NFTA_COMPAT_TYPE] = { .type = NLA_U32 }, |
| 729 | 736 | }; |
| 730 | 737 | |
| @@ -476,6 +476,9 @@ static int nft_ct_get_init(const struct nft_ctx *ctx, · 475 unmodified lines | ||
| 476 | 476 | break; |
| 477 | 477 | #endif |
| 478 | 478 | case NFT_CT_ID: |
| 479 | + if (tb[NFTA_CT_DIRECTION]) | |
| 480 | + return -EINVAL; | |
| 481 | + | |
| 479 | 482 | len = sizeof(u32); |
| 480 | 483 | break; |
| 481 | 484 | default: |
| @@ -36,6 +36,7 @@ struct nft_rhash_cmp_arg { · 35 unmodified lines | ||
| 36 | 36 | const struct nft_set *set; |
| 37 | 37 | const u32 *key; |
| 38 | 38 | u8 genmask; |
| 39 | + u64 tstamp; | |
| 39 | 40 | }; |
| 40 | 41 | |
| 41 | 42 | static inline u32 nft_rhash_key(const void *data, u32 len, u32 seed) |
| @@ -62,7 +63,7 @@ static inline int nft_rhash_cmp(struct rhashtable_compare_arg *arg, · 20 unmodified lines | ||
| 62 | 63 | return 1; |
| 63 | 64 | if (nft_set_elem_is_dead(&he->ext)) |
| 64 | 65 | return 1; |
| 65 | − if (nft_set_elem_expired(&he->ext)) | |
| 66 | + if (__nft_set_elem_expired(&he->ext, x->tstamp)) | |
| 66 | 67 | return 1; |
| 67 | 68 | if (!nft_set_elem_active(&he->ext, x->genmask)) |
| 68 | 69 | return 1; |
| @@ -87,6 +88,7 @@ bool nft_rhash_lookup(const struct net *net, const struct nft_set *set, · 18 unmodified lines | ||
| 87 | 88 | .genmask = nft_genmask_cur(net), |
| 88 | 89 | .set = set, |
| 89 | 90 | .key = key, |
| 91 | + .tstamp = get_jiffies_64(), | |
| 90 | 92 | }; |
| 91 | 93 | |
| 92 | 94 | he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params); |
| @@ -106,6 +108,7 @@ nft_rhash_get(const struct net *net, const struct nft_set *set, · 13 unmodified lines | ||
| 106 | 108 | .genmask = nft_genmask_cur(net), |
| 107 | 109 | .set = set, |
| 108 | 110 | .key = elem->key.val.data, |
| 111 | + .tstamp = get_jiffies_64(), | |
| 109 | 112 | }; |
| 110 | 113 | |
| 111 | 114 | he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params); |
| @@ -131,6 +134,7 @@ static bool nft_rhash_update(struct nft_set *set, const u32 *key, · 19 unmodified lines | ||
| 131 | 134 | .genmask = NFT_GENMASK_ANY, |
| 132 | 135 | .set = set, |
| 133 | 136 | .key = key, |
| 137 | + .tstamp = get_jiffies_64(), | |
| 134 | 138 | }; |
| 135 | 139 | |
| 136 | 140 | he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params); |
| @@ -175,6 +179,7 @@ static int nft_rhash_insert(const struct net *net, const struct nft_set *set, · 38 unmodified lines | ||
| 175 | 179 | .genmask = nft_genmask_next(net), |
| 176 | 180 | .set = set, |
| 177 | 181 | .key = elem->key.val.data, |
| 182 | + .tstamp = nft_net_tstamp(net), | |
| 178 | 183 | }; |
| 179 | 184 | struct nft_rhash_elem *prev; |
| 180 | 185 | |
| @@ -216,6 +221,7 @@ nft_rhash_deactivate(const struct net *net, const struct nft_set *set, · 35 unmodified lines | ||
| 216 | 221 | .genmask = nft_genmask_next(net), |
| 217 | 222 | .set = set, |
| 218 | 223 | .key = elem->key.val.data, |
| 224 | + .tstamp = nft_net_tstamp(net), | |
| 219 | 225 | }; |
| 220 | 226 | |
| 221 | 227 | rcu_read_lock(); |
| @@ -342,9 +342,6 @@ · 341 unmodified lines | ||
| 342 | 342 | #include "nft_set_pipapo_avx2.h" |
| 343 | 343 | #include "nft_set_pipapo.h" |
| 344 | 344 | |
| 345 | −/* Current working bitmap index, toggled between field matches */ | |
| 346 | −static DEFINE_PER_CPU(bool, nft_pipapo_scratch_index); | |
| 347 | − | |
| 348 | 345 | /** |
| 349 | 346 | * pipapo_refill() - For each set bit, set bits from selected mapping table item |
| 350 | 347 | * @map: Bitmap to be scanned for set bits |
| @@ -412,6 +409,7 @@ bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set, · 61 unmodified lines | ||
| 412 | 409 | const u32 *key, const struct nft_set_ext **ext) |
| 413 | 410 | { |
| 414 | 411 | struct nft_pipapo *priv = nft_set_priv(set); |
| 412 | + struct nft_pipapo_scratch *scratch; | |
| 415 | 413 | unsigned long *res_map, *fill_map; |
| 416 | 414 | u8 genmask = nft_genmask_cur(net); |
| 417 | 415 | const u8 *rp = (const u8 *)key; |
| @@ -422,15 +420,17 @@ bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set, · 4 unmodified lines | ||
| 422 | 420 | |
| 423 | 421 | local_bh_disable(); |
| 424 | 422 | |
| 425 | − map_index = raw_cpu_read(nft_pipapo_scratch_index); | |
| 426 | − | |
| 427 | 423 | m = rcu_dereference(priv->match); |
| 428 | 424 | |
| 429 | 425 | if (unlikely(!m || !*raw_cpu_ptr(m->scratch))) |
| 430 | 426 | goto out; |
| 431 | 427 | |
| 432 | − res_map = *raw_cpu_ptr(m->scratch) + (map_index ? m->bsize_max : 0); | |
| 433 | − fill_map = *raw_cpu_ptr(m->scratch) + (map_index ? 0 : m->bsize_max); | |
| 428 | + scratch = *raw_cpu_ptr(m->scratch); | |
| 429 | + | |
| 430 | + map_index = scratch->map_index; | |
| 431 | + | |
| 432 | + res_map = scratch->map + (map_index ? m->bsize_max : 0); | |
| 433 | + fill_map = scratch->map + (map_index ? 0 : m->bsize_max); | |
| 434 | 434 | |
| 435 | 435 | memset(res_map, 0xff, m->bsize_max * sizeof(*res_map)); |
| 436 | 436 | |
| @@ -460,7 +460,7 @@ next_match: · 23 unmodified lines | ||
| 460 | 460 | b = pipapo_refill(res_map, f->bsize, f->rules, fill_map, f->mt, |
| 461 | 461 | last); |
| 462 | 462 | if (b < 0) { |
| 463 | − raw_cpu_write(nft_pipapo_scratch_index, map_index); | |
| 463 | + scratch->map_index = map_index; | |
| 464 | 464 | local_bh_enable(); |
| 465 | 465 | |
| 466 | 466 | return false; |
| @@ -477,7 +477,7 @@ next_match: · 10 unmodified lines | ||
| 477 | 477 | * current inactive bitmap is clean and can be reused as |
| 478 | 478 | * *next* bitmap (not initial) for the next packet. |
| 479 | 479 | */ |
| 480 | − raw_cpu_write(nft_pipapo_scratch_index, map_index); | |
| 480 | + scratch->map_index = map_index; | |
| 481 | 481 | local_bh_enable(); |
| 482 | 482 | |
| 483 | 483 | return true; |
| @@ -504,6 +504,7 @@ out: · 20 unmodified lines | ||
| 504 | 504 | * @set: nftables API set representation |
| 505 | 505 | * @data: Key data to be matched against existing elements |
| 506 | 506 | * @genmask: If set, check that element is active in given genmask |
| 507 | + * @tstamp: timestamp to check for expired elements | |
| 507 | 508 | * |
| 508 | 509 | * This is essentially the same as the lookup function, except that it matches |
| 509 | 510 | * key data against the uncommitted copy and doesn't use preallocated maps for |
| @@ -513,7 +514,8 @@ out: · 3 unmodified lines | ||
| 513 | 514 | */ |
| 514 | 515 | static struct nft_pipapo_elem *pipapo_get(const struct net *net, |
| 515 | 516 | const struct nft_set *set, |
| 516 | − const u8 *data, u8 genmask) | |
| 517 | + const u8 *data, u8 genmask, | |
| 518 | + u64 tstamp) | |
| 517 | 519 | { |
| 518 | 520 | struct nft_pipapo_elem *ret = ERR_PTR(-ENOENT); |
| 519 | 521 | struct nft_pipapo *priv = nft_set_priv(set); |
| @@ -566,7 +568,7 @@ next_match: · 46 unmodified lines | ||
| 566 | 568 | goto out; |
| 567 | 569 | |
| 568 | 570 | if (last) { |
| 569 | − if (nft_set_elem_expired(&f->mt[b].e->ext)) | |
| 571 | + if (__nft_set_elem_expired(&f->mt[b].e->ext, tstamp)) | |
| 570 | 572 | goto next_match; |
| 571 | 573 | if ((genmask && |
| 572 | 574 | !nft_set_elem_active(&f->mt[b].e->ext, genmask))) |
| @@ -603,10 +605,10 @@ static struct nft_elem_priv * · 30 unmodified lines | ||
| 603 | 605 | nft_pipapo_get(const struct net *net, const struct nft_set *set, |
| 604 | 606 | const struct nft_set_elem *elem, unsigned int flags) |
| 605 | 607 | { |
| 606 | − static struct nft_pipapo_elem *e; | |
| 608 | + struct nft_pipapo_elem *e; | |
| 607 | 609 | |
| 608 | 610 | e = pipapo_get(net, set, (const u8 *)elem->key.val.data, |
| 609 | − nft_genmask_cur(net)); | |
| 611 | + nft_genmask_cur(net), get_jiffies_64()); | |
| 610 | 612 | if (IS_ERR(e)) |
| 611 | 613 | return ERR_CAST(e); |
| 612 | 614 | |
| @@ -1108,6 +1110,25 @@ static void pipapo_map(struct nft_pipapo_match *m, · 495 unmodified lines | ||
| 1108 | 1110 | f->mt[map[i].to + j].e = e; |
| 1109 | 1111 | } |
| 1110 | 1112 | |
| 1113 | +/** | |
| 1114 | + * pipapo_free_scratch() - Free per-CPU map at original (not aligned) address | |
| 1115 | + * @m: Matching data | |
| 1116 | + * @cpu: CPU number | |
| 1117 | + */ | |
| 1118 | +static void pipapo_free_scratch(const struct nft_pipapo_match *m, unsigned int cpu) | |
| 1119 | +{ | |
| 1120 | + struct nft_pipapo_scratch *s; | |
| 1121 | + void *mem; | |
| 1122 | + | |
| 1123 | + s = *per_cpu_ptr(m->scratch, cpu); | |
| 1124 | + if (!s) | |
| 1125 | + return; | |
| 1126 | + | |
| 1127 | + mem = s; | |
| 1128 | + mem -= s->align_off; | |
| 1129 | + kfree(mem); | |
| 1130 | +} | |
| 1131 | + | |
| 1111 | 1132 | /** |
| 1112 | 1133 | * pipapo_realloc_scratch() - Reallocate scratch maps for partial match results |
| 1113 | 1134 | * @clone: Copy of matching data with pending insertions and deletions |
| @@ -1121,12 +1142,13 @@ static int pipapo_realloc_scratch(struct nft_pipapo_match *clone, · 7 unmodified lines | ||
| 1121 | 1142 | int i; |
| 1122 | 1143 | |
| 1123 | 1144 | for_each_possible_cpu(i) { |
| 1124 | − unsigned long *scratch; | |
| 1145 | + struct nft_pipapo_scratch *scratch; | |
| 1125 | 1146 | #ifdef NFT_PIPAPO_ALIGN |
| 1126 | − unsigned long *scratch_aligned; | |
| 1147 | + void *scratch_aligned; | |
| 1148 | + u32 align_off; | |
| 1127 | 1149 | #endif |
| 1128 | − | |
| 1129 | − scratch = kzalloc_node(bsize_max * sizeof(*scratch) * 2 + | |
| 1150 | + scratch = kzalloc_node(struct_size(scratch, map, | |
| 1151 | + bsize_max * 2) + | |
| 1130 | 1152 | NFT_PIPAPO_ALIGN_HEADROOM, |
| 1131 | 1153 | GFP_KERNEL, cpu_to_node(i)); |
| 1132 | 1154 | if (!scratch) { |
| @@ -1140,14 +1162,25 @@ static int pipapo_realloc_scratch(struct nft_pipapo_match *clone, · 7 unmodified lines | ||
| 1140 | 1162 | return -ENOMEM; |
| 1141 | 1163 | } |
| 1142 | 1164 | |
| 1143 | − kfree(*per_cpu_ptr(clone->scratch, i)); | |
| 1144 | − | |
| 1145 | − *per_cpu_ptr(clone->scratch, i) = scratch; | |
| 1165 | + pipapo_free_scratch(clone, i); | |
| 1146 | 1166 | |
| 1147 | 1167 | #ifdef NFT_PIPAPO_ALIGN |
| 1148 | − scratch_aligned = NFT_PIPAPO_LT_ALIGN(scratch); | |
| 1149 | − *per_cpu_ptr(clone->scratch_aligned, i) = scratch_aligned; | |
| 1168 | + /* Align &scratch->map (not the struct itself): the extra | |
| 1169 | + * %NFT_PIPAPO_ALIGN_HEADROOM bytes passed to kzalloc_node() | |
| 1170 | + * above guarantee we can waste up to those bytes in order | |
| 1171 | + * to align the map field regardless of its offset within | |
| 1172 | + * the struct. | |
| 1173 | + */ | |
| 1174 | + BUILD_BUG_ON(offsetof(struct nft_pipapo_scratch, map) > NFT_PIPAPO_ALIGN_HEADROOM); | |
| 1175 | + | |
| 1176 | + scratch_aligned = NFT_PIPAPO_LT_ALIGN(&scratch->map); | |
| 1177 | + scratch_aligned -= offsetof(struct nft_pipapo_scratch, map); | |
| 1178 | + align_off = scratch_aligned - (void *)scratch; | |
| 1179 | + | |
| 1180 | + scratch = scratch_aligned; | |
| 1181 | + scratch->align_off = align_off; | |
| 1150 | 1182 | #endif |
| 1183 | + *per_cpu_ptr(clone->scratch, i) = scratch; | |
| 1151 | 1184 | } |
| 1152 | 1185 | |
| 1153 | 1186 | return 0; |
| @@ -1173,6 +1206,7 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set, · 19 unmodified lines | ||
| 1173 | 1206 | struct nft_pipapo_match *m = priv->clone; |
| 1174 | 1207 | u8 genmask = nft_genmask_next(net); |
| 1175 | 1208 | struct nft_pipapo_elem *e, *dup; |
| 1209 | + u64 tstamp = nft_net_tstamp(net); | |
| 1176 | 1210 | struct nft_pipapo_field *f; |
| 1177 | 1211 | const u8 *start_p, *end_p; |
| 1178 | 1212 | int i, bsize_max, err = 0; |
| @@ -1182,7 +1216,7 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set, · 3 unmodified lines | ||
| 1182 | 1216 | else |
| 1183 | 1217 | end = start; |
| 1184 | 1218 | |
| 1185 | − dup = pipapo_get(net, set, start, genmask); | |
| 1219 | + dup = pipapo_get(net, set, start, genmask, tstamp); | |
| 1186 | 1220 | if (!IS_ERR(dup)) { |
| 1187 | 1221 | /* Check if we already have the same exact entry */ |
| 1188 | 1222 | const struct nft_data *dup_key, *dup_end; |
| @@ -1204,7 +1238,7 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set, · 15 unmodified lines | ||
| 1204 | 1238 | |
| 1205 | 1239 | if (PTR_ERR(dup) == -ENOENT) { |
| 1206 | 1240 | /* Look for partially overlapping entries */ |
| 1207 | − dup = pipapo_get(net, set, end, nft_genmask_next(net)); | |
| 1241 | + dup = pipapo_get(net, set, end, nft_genmask_next(net), tstamp); | |
| 1208 | 1242 | } |
| 1209 | 1243 | |
| 1210 | 1244 | if (PTR_ERR(dup) != -ENOENT) { |
| @@ -1301,11 +1335,6 @@ static struct nft_pipapo_match *pipapo_clone(struct nft_pipapo_match *old) · 90 unmodified lines | ||
| 1301 | 1335 | if (!new->scratch) |
| 1302 | 1336 | goto out_scratch; |
| 1303 | 1337 | |
| 1304 | −#ifdef NFT_PIPAPO_ALIGN | |
| 1305 | − new->scratch_aligned = alloc_percpu(*new->scratch_aligned); | |
| 1306 | − if (!new->scratch_aligned) | |
| 1307 | − goto out_scratch; | |
| 1308 | −#endif | |
| 1309 | 1338 | for_each_possible_cpu(i) |
| 1310 | 1339 | *per_cpu_ptr(new->scratch, i) = NULL; |
| 1311 | 1340 | |
| @@ -1357,10 +1386,7 @@ out_lt: · 45 unmodified lines | ||
| 1357 | 1386 | } |
| 1358 | 1387 | out_scratch_realloc: |
| 1359 | 1388 | for_each_possible_cpu(i) |
| 1360 | − kfree(*per_cpu_ptr(new->scratch, i)); | |
| 1361 | −#ifdef NFT_PIPAPO_ALIGN | |
| 1362 | − free_percpu(new->scratch_aligned); | |
| 1363 | −#endif | |
| 1389 | + pipapo_free_scratch(new, i); | |
| 1364 | 1390 | out_scratch: |
| 1365 | 1391 | free_percpu(new->scratch); |
| 1366 | 1392 | kfree(new); |
| @@ -1560,6 +1586,7 @@ static void pipapo_gc(struct nft_set *set, struct nft_pipapo_match *m) · 193 unmodified lines | ||
| 1560 | 1586 | { |
| 1561 | 1587 | struct nft_pipapo *priv = nft_set_priv(set); |
| 1562 | 1588 | struct net *net = read_pnet(&set->net); |
| 1589 | + u64 tstamp = nft_net_tstamp(net); | |
| 1563 | 1590 | int rules_f0, first_rule = 0; |
| 1564 | 1591 | struct nft_pipapo_elem *e; |
| 1565 | 1592 | struct nft_trans_gc *gc; |
| @@ -1594,7 +1621,7 @@ static void pipapo_gc(struct nft_set *set, struct nft_pipapo_match *m) · 28 unmodified lines | ||
| 1594 | 1621 | /* synchronous gc never fails, there is no need to set on |
| 1595 | 1622 | * NFT_SET_ELEM_DEAD_BIT. |
| 1596 | 1623 | */ |
| 1597 | − if (nft_set_elem_expired(&e->ext)) { | |
| 1624 | + if (__nft_set_elem_expired(&e->ext, tstamp)) { | |
| 1598 | 1625 | priv->dirty = true; |
| 1599 | 1626 | |
| 1600 | 1627 | gc = nft_trans_gc_queue_sync(gc, GFP_KERNEL); |
| @@ -1640,13 +1667,9 @@ static void pipapo_free_match(struct nft_pipapo_match *m) · 39 unmodified lines | ||
| 1640 | 1667 | int i; |
| 1641 | 1668 | |
| 1642 | 1669 | for_each_possible_cpu(i) |
| 1643 | − kfree(*per_cpu_ptr(m->scratch, i)); | |
| 1670 | + pipapo_free_scratch(m, i); | |
| 1644 | 1671 | |
| 1645 | −#ifdef NFT_PIPAPO_ALIGN | |
| 1646 | − free_percpu(m->scratch_aligned); | |
| 1647 | −#endif | |
| 1648 | 1672 | free_percpu(m->scratch); |
| 1649 | − | |
| 1650 | 1673 | pipapo_free_fields(m); |
| 1651 | 1674 | |
| 1652 | 1675 | kfree(m); |
| @@ -1769,7 +1792,7 @@ static void *pipapo_deactivate(const struct net *net, const struct nft_set *set, · 116 unmodified lines | ||
| 1769 | 1792 | { |
| 1770 | 1793 | struct nft_pipapo_elem *e; |
| 1771 | 1794 | |
| 1772 | − e = pipapo_get(net, set, data, nft_genmask_next(net)); | |
| 1795 | + e = pipapo_get(net, set, data, nft_genmask_next(net), nft_net_tstamp(net)); | |
| 1773 | 1796 | if (IS_ERR(e)) |
| 1774 | 1797 | return NULL; |
| 1775 | 1798 | |
| @@ -2132,7 +2155,7 @@ static int nft_pipapo_init(const struct nft_set *set, · 356 unmodified lines | ||
| 2132 | 2155 | m->field_count = field_count; |
| 2133 | 2156 | m->bsize_max = 0; |
| 2134 | 2157 | |
| 2135 | − m->scratch = alloc_percpu(unsigned long *); | |
| 2158 | + m->scratch = alloc_percpu(struct nft_pipapo_scratch *); | |
| 2136 | 2159 | if (!m->scratch) { |
| 2137 | 2160 | err = -ENOMEM; |
| 2138 | 2161 | goto out_scratch; |
| @@ -2140,16 +2163,6 @@ static int nft_pipapo_init(const struct nft_set *set, · 1 unmodified line | ||
| 2140 | 2163 | for_each_possible_cpu(i) |
| 2141 | 2164 | *per_cpu_ptr(m->scratch, i) = NULL; |
| 2142 | 2165 | |
| 2143 | −#ifdef NFT_PIPAPO_ALIGN | |
| 2144 | − m->scratch_aligned = alloc_percpu(unsigned long *); | |
| 2145 | − if (!m->scratch_aligned) { | |
| 2146 | − err = -ENOMEM; | |
| 2147 | − goto out_free; | |
| 2148 | − } | |
| 2149 | − for_each_possible_cpu(i) | |
| 2150 | − *per_cpu_ptr(m->scratch_aligned, i) = NULL; | |
| 2151 | −#endif | |
| 2152 | − | |
| 2153 | 2166 | rcu_head_init(&m->rcu); |
| 2154 | 2167 | |
| 2155 | 2168 | nft_pipapo_for_each_field(f, i, m) { |
| @@ -2180,9 +2193,6 @@ static int nft_pipapo_init(const struct nft_set *set, · 24 unmodified lines | ||
| 2180 | 2193 | return 0; |
| 2181 | 2194 | |
| 2182 | 2195 | out_free: |
| 2183 | −#ifdef NFT_PIPAPO_ALIGN | |
| 2184 | − free_percpu(m->scratch_aligned); | |
| 2185 | −#endif | |
| 2186 | 2196 | free_percpu(m->scratch); |
| 2187 | 2197 | out_scratch: |
| 2188 | 2198 | kfree(m); |
| @@ -2236,11 +2246,8 @@ static void nft_pipapo_destroy(const struct nft_ctx *ctx, · 47 unmodified lines | ||
| 2236 | 2246 | |
| 2237 | 2247 | nft_set_pipapo_match_destroy(ctx, set, m); |
| 2238 | 2248 | |
| 2239 | −#ifdef NFT_PIPAPO_ALIGN | |
| 2240 | − free_percpu(m->scratch_aligned); | |
| 2241 | −#endif | |
| 2242 | 2249 | for_each_possible_cpu(cpu) |
| 2243 | − kfree(*per_cpu_ptr(m->scratch, cpu)); | |
| 2250 | + pipapo_free_scratch(m, cpu); | |
| 2244 | 2251 | free_percpu(m->scratch); |
| 2245 | 2252 | pipapo_free_fields(m); |
| 2246 | 2253 | kfree(m); |
| @@ -2253,11 +2260,8 @@ static void nft_pipapo_destroy(const struct nft_ctx *ctx, · 6 unmodified lines | ||
| 2253 | 2260 | if (priv->dirty) |
| 2254 | 2261 | nft_set_pipapo_match_destroy(ctx, set, m); |
| 2255 | 2262 | |
| 2256 | −#ifdef NFT_PIPAPO_ALIGN | |
| 2257 | − free_percpu(priv->clone->scratch_aligned); | |
| 2258 | −#endif | |
| 2259 | 2263 | for_each_possible_cpu(cpu) |
| 2260 | − kfree(*per_cpu_ptr(priv->clone->scratch, cpu)); | |
| 2264 | + pipapo_free_scratch(priv->clone, cpu); | |
| 2261 | 2265 | free_percpu(priv->clone->scratch); |
| 2262 | 2266 | |
| 2263 | 2267 | pipapo_free_fields(priv->clone); |
| @@ -130,21 +130,29 @@ struct nft_pipapo_field { · 129 unmodified lines | ||
| 130 | 130 | union nft_pipapo_map_bucket *mt; |
| 131 | 131 | }; |
| 132 | 132 | |
| 133 | +/** | |
| 134 | + * struct nft_pipapo_scratch - percpu data used for lookup and matching | |
| 135 | + * @map_index: Current working bitmap index, toggled between field matches | |
| 136 | + * @align_off: Offset to get the originally allocated address | |
| 137 | + * @map: store partial matching results during lookup | |
| 138 | + */ | |
| 139 | +struct nft_pipapo_scratch { | |
| 140 | + u8 map_index; | |
| 141 | + u32 align_off; | |
| 142 | + unsigned long map[]; | |
| 143 | +}; | |
| 144 | + | |
| 133 | 145 | /** |
| 134 | 146 | * struct nft_pipapo_match - Data used for lookup and matching |
| 135 | 147 | * @field_count Amount of fields in set |
| 136 | 148 | * @scratch: Preallocated per-CPU maps for partial matching results |
| 137 | − * @scratch_aligned: Version of @scratch aligned to NFT_PIPAPO_ALIGN bytes | |
| 138 | 149 | * @bsize_max: Maximum lookup table bucket size of all fields, in longs |
| 139 | 150 | * @rcu Matching data is swapped on commits |
| 140 | 151 | * @f: Fields, with lookup and mapping tables |
| 141 | 152 | */ |
| 142 | 153 | struct nft_pipapo_match { |
| 143 | 154 | int field_count; |
| 144 | −#ifdef NFT_PIPAPO_ALIGN | |
| 145 | − unsigned long * __percpu *scratch_aligned; | |
| 146 | −#endif | |
| 147 | − unsigned long * __percpu *scratch; | |
| 155 | + struct nft_pipapo_scratch * __percpu *scratch; | |
| 148 | 156 | size_t bsize_max; |
| 149 | 157 | struct rcu_head rcu; |
| 150 | 158 | struct nft_pipapo_field f[] __counted_by(field_count); |
| @@ -71,9 +71,6 @@ · 70 unmodified lines | ||
| 71 | 71 | #define NFT_PIPAPO_AVX2_ZERO(reg) \ |
| 72 | 72 | asm volatile("vpxor %ymm" #reg ", %ymm" #reg ", %ymm" #reg) |
| 73 | 73 | |
| 74 | −/* Current working bitmap index, toggled between field matches */ | |
| 75 | −static DEFINE_PER_CPU(bool, nft_pipapo_avx2_scratch_index); | |
| 76 | − | |
| 77 | 74 | /** |
| 78 | 75 | * nft_pipapo_avx2_prepare() - Prepare before main algorithm body |
| 79 | 76 | * |
| @@ -1120,11 +1117,12 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set, · 1040 unmodified lines | ||
| 1120 | 1117 | const u32 *key, const struct nft_set_ext **ext) |
| 1121 | 1118 | { |
| 1122 | 1119 | struct nft_pipapo *priv = nft_set_priv(set); |
| 1123 | − unsigned long *res, *fill, *scratch; | |
| 1120 | + struct nft_pipapo_scratch *scratch; | |
| 1124 | 1121 | u8 genmask = nft_genmask_cur(net); |
| 1125 | 1122 | const u8 *rp = (const u8 *)key; |
| 1126 | 1123 | struct nft_pipapo_match *m; |
| 1127 | 1124 | struct nft_pipapo_field *f; |
| 1125 | + unsigned long *res, *fill; | |
| 1128 | 1126 | bool map_index; |
| 1129 | 1127 | int i, ret = 0; |
| 1130 | 1128 | |
| @@ -1141,15 +1139,16 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set, · 10 unmodified lines | ||
| 1141 | 1139 | */ |
| 1142 | 1140 | kernel_fpu_begin_mask(0); |
| 1143 | 1141 | |
| 1144 | − scratch = *raw_cpu_ptr(m->scratch_aligned); | |
| 1142 | + scratch = *raw_cpu_ptr(m->scratch); | |
| 1145 | 1143 | if (unlikely(!scratch)) { |
| 1146 | 1144 | kernel_fpu_end(); |
| 1147 | 1145 | return false; |
| 1148 | 1146 | } |
| 1149 | − map_index = raw_cpu_read(nft_pipapo_avx2_scratch_index); | |
| 1150 | 1147 | |
| 1151 | − res = scratch + (map_index ? m->bsize_max : 0); | |
| 1152 | − fill = scratch + (map_index ? 0 : m->bsize_max); | |
| 1148 | + map_index = scratch->map_index; | |
| 1149 | + | |
| 1150 | + res = scratch->map + (map_index ? m->bsize_max : 0); | |
| 1151 | + fill = scratch->map + (map_index ? 0 : m->bsize_max); | |
| 1153 | 1152 | |
| 1154 | 1153 | /* Starting map doesn't need to be set for this implementation */ |
| 1155 | 1154 | |
| @@ -1221,7 +1220,7 @@ next_match: · 65 unmodified lines | ||
| 1221 | 1220 | |
| 1222 | 1221 | out: |
| 1223 | 1222 | if (i % 2) |
| 1224 | − raw_cpu_write(nft_pipapo_avx2_scratch_index, !map_index); | |
| 1223 | + scratch->map_index = !map_index; | |
| 1225 | 1224 | kernel_fpu_end(); |
| 1226 | 1225 | |
| 1227 | 1226 | return ret >= 0; |
| @@ -234,7 +234,7 @@ static void nft_rbtree_gc_elem_remove(struct net *net, struct nft_set *set, · 233 unmodified lines | ||
| 234 | 234 | |
| 235 | 235 | static const struct nft_rbtree_elem * |
| 236 | 236 | nft_rbtree_gc_elem(const struct nft_set *__set, struct nft_rbtree *priv, |
| 237 | − struct nft_rbtree_elem *rbe, u8 genmask) | |
| 237 | + struct nft_rbtree_elem *rbe) | |
| 238 | 238 | { |
| 239 | 239 | struct nft_set *set = (struct nft_set *)__set; |
| 240 | 240 | struct rb_node *prev = rb_prev(&rbe->node); |
| @@ -253,7 +253,7 @@ nft_rbtree_gc_elem(const struct nft_set *__set, struct nft_rbtree *priv, · 12 unmodified lines | ||
| 253 | 253 | while (prev) { |
| 254 | 254 | rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node); |
| 255 | 255 | if (nft_rbtree_interval_end(rbe_prev) && |
| 256 | − nft_set_elem_active(&rbe_prev->ext, genmask)) | |
| 256 | + nft_set_elem_active(&rbe_prev->ext, NFT_GENMASK_ANY)) | |
| 257 | 257 | break; |
| 258 | 258 | |
| 259 | 259 | prev = rb_prev(prev); |
| @@ -313,6 +313,7 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, · 53 unmodified lines | ||
| 313 | 313 | struct nft_rbtree *priv = nft_set_priv(set); |
| 314 | 314 | u8 cur_genmask = nft_genmask_cur(net); |
| 315 | 315 | u8 genmask = nft_genmask_next(net); |
| 316 | + u64 tstamp = nft_net_tstamp(net); | |
| 316 | 317 | int d; |
| 317 | 318 | |
| 318 | 319 | /* Descend the tree to search for an existing element greater than the |
| @@ -360,11 +361,11 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, · 41 unmodified lines | ||
| 360 | 361 | /* perform garbage collection to avoid bogus overlap reports |
| 361 | 362 | * but skip new elements in this transaction. |
| 362 | 363 | */ |
| 363 | − if (nft_set_elem_expired(&rbe->ext) && | |
| 364 | + if (__nft_set_elem_expired(&rbe->ext, tstamp) && | |
| 364 | 365 | nft_set_elem_active(&rbe->ext, cur_genmask)) { |
| 365 | 366 | const struct nft_rbtree_elem *removed_end; |
| 366 | 367 | |
| 367 | − removed_end = nft_rbtree_gc_elem(set, priv, rbe, genmask); | |
| 368 | + removed_end = nft_rbtree_gc_elem(set, priv, rbe); | |
| 368 | 369 | if (IS_ERR(removed_end)) |
| 369 | 370 | return PTR_ERR(removed_end); |
| 370 | 371 | |
| @@ -551,6 +552,7 @@ nft_rbtree_deactivate(const struct net *net, const struct nft_set *set, · 180 unmodified lines | ||
| 551 | 552 | const struct nft_rbtree *priv = nft_set_priv(set); |
| 552 | 553 | const struct rb_node *parent = priv->root.rb_node; |
| 553 | 554 | u8 genmask = nft_genmask_next(net); |
| 555 | + u64 tstamp = nft_net_tstamp(net); | |
| 554 | 556 | int d; |
| 555 | 557 | |
| 556 | 558 | while (parent != NULL) { |
| @@ -571,7 +573,7 @@ nft_rbtree_deactivate(const struct net *net, const struct nft_set *set, · 14 unmodified lines | ||
| 571 | 573 | nft_rbtree_interval_end(this)) { |
| 572 | 574 | parent = parent->rb_right; |
| 573 | 575 | continue; |
| 574 | − } else if (nft_set_elem_expired(&rbe->ext)) { | |
| 576 | + } else if (__nft_set_elem_expired(&rbe->ext, tstamp)) { | |
| 575 | 577 | break; |
| 576 | 578 | } else if (!nft_set_elem_active(&rbe->ext, genmask)) { |
| 577 | 579 | parent = parent->rb_left; |
| @@ -624,9 +626,10 @@ static void nft_rbtree_gc(struct nft_set *set) · 46 unmodified lines | ||
| 624 | 626 | { |
| 625 | 627 | struct nft_rbtree *priv = nft_set_priv(set); |
| 626 | 628 | struct nft_rbtree_elem *rbe, *rbe_end = NULL; |
| 629 | + struct net *net = read_pnet(&set->net); | |
| 630 | + u64 tstamp = nft_net_tstamp(net); | |
| 627 | 631 | struct rb_node *node, *next; |
| 628 | 632 | struct nft_trans_gc *gc; |
| 629 | − struct net *net; | |
| 630 | 633 | |
| 631 | 634 | set = nft_set_container_of(priv); |
| 632 | 635 | net = read_pnet(&set->net); |
| @@ -648,7 +651,7 @@ static void nft_rbtree_gc(struct nft_set *set) · 15 unmodified lines | ||
| 648 | 651 | rbe_end = rbe; |
| 649 | 652 | continue; |
| 650 | 653 | } |
| 651 | − if (!nft_set_elem_expired(&rbe->ext)) | |
| 654 | + if (!__nft_set_elem_expired(&rbe->ext, tstamp)) | |
| 652 | 655 | continue; |
| 653 | 656 | |
| 654 | 657 | gc = nft_trans_gc_queue_sync(gc, GFP_KERNEL); |
| @@ -199,11 +199,19 @@ struct rxrpc_host_header { · 198 unmodified lines | ||
| 199 | 199 | */ |
| 200 | 200 | struct rxrpc_skb_priv { |
| 201 | 201 | struct rxrpc_connection *conn; /* Connection referred to (poke packet) */ |
| 202 | − u16 offset; /* Offset of data */ | |
| 203 | − u16 len; /* Length of data */ | |
| 204 | − u8 flags; | |
| 202 | + union { | |
| 203 | + struct { | |
| 204 | + u16 offset; /* Offset of data */ | |
| 205 | + u16 len; /* Length of data */ | |
| 206 | + u8 flags; | |
| 205 | 207 | #define RXRPC_RX_VERIFIED 0x01 |
| 206 | − | |
| 208 | + }; | |
| 209 | + struct { | |
| 210 | + rxrpc_seq_t first_ack; /* First packet in acks table */ | |
| 211 | + u8 nr_acks; /* Number of acks+nacks */ | |
| 212 | + u8 nr_nacks; /* Number of nacks */ | |
| 213 | + }; | |
| 214 | + }; | |
| 207 | 215 | struct rxrpc_host_header hdr; /* RxRPC packet header from this packet */ |
| 208 | 216 | }; |
| 209 | 217 | |
| @@ -510,7 +518,7 @@ struct rxrpc_connection { · 300 unmodified lines | ||
| 510 | 518 | enum rxrpc_call_completion completion; /* Completion condition */ |
| 511 | 519 | s32 abort_code; /* Abort code of connection abort */ |
| 512 | 520 | int debug_id; /* debug ID for printks */ |
| 513 | − atomic_t serial; /* packet serial number counter */ | |
| 521 | + rxrpc_serial_t tx_serial; /* Outgoing packet serial number counter */ | |
| 514 | 522 | unsigned int hi_serial; /* highest serial number received */ |
| 515 | 523 | u32 service_id; /* Service ID, possibly upgraded */ |
| 516 | 524 | u32 security_level; /* Security level selected */ |
| @@ -692,11 +700,11 @@ struct rxrpc_call { · 175 unmodified lines | ||
| 692 | 700 | u8 cong_dup_acks; /* Count of ACKs showing missing packets */ |
| 693 | 701 | u8 cong_cumul_acks; /* Cumulative ACK count */ |
| 694 | 702 | ktime_t cong_tstamp; /* Last time cwnd was changed */ |
| 703 | + struct sk_buff *cong_last_nack; /* Last ACK with nacks received */ | |
| 695 | 704 | |
| 696 | 705 | /* Receive-phase ACK management (ACKs we send). */ |
| 697 | 706 | u8 ackr_reason; /* reason to ACK */ |
| 698 | 707 | u16 ackr_sack_base; /* Starting slot in SACK table ring */ |
| 699 | − rxrpc_serial_t ackr_serial; /* serial of packet being ACK'd */ | |
| 700 | 708 | rxrpc_seq_t ackr_window; /* Base of SACK window */ |
| 701 | 709 | rxrpc_seq_t ackr_wtop; /* Base of SACK window */ |
| 702 | 710 | unsigned int ackr_nr_unacked; /* Number of unacked packets */ |
| @@ -730,7 +738,8 @@ struct rxrpc_call { · 27 unmodified lines | ||
| 730 | 738 | struct rxrpc_ack_summary { |
| 731 | 739 | u16 nr_acks; /* Number of ACKs in packet */ |
| 732 | 740 | u16 nr_new_acks; /* Number of new ACKs in packet */ |
| 733 | − u16 nr_rot_new_acks; /* Number of rotated new ACKs */ | |
| 741 | + u16 nr_new_nacks; /* Number of new nacks in packet */ | |
| 742 | + u16 nr_retained_nacks; /* Number of nacks retained between ACKs */ | |
| 734 | 743 | u8 ack_reason; |
| 735 | 744 | bool saw_nacks; /* Saw NACKs in packet */ |
| 736 | 745 | bool new_low_nack; /* T if new low NACK found */ |
| @@ -822,6 +831,20 @@ static inline bool rxrpc_sending_to_client(const struct rxrpc_txbuf *txb) · 85 unmodified lines | ||
| 822 | 831 | |
| 823 | 832 | #include <trace/events/rxrpc.h> |
| 824 | 833 | |
| 834 | +/* | |
| 835 | + * Allocate the next serial number on a connection. 0 must be skipped. | |
| 836 | + */ | |
| 837 | +static inline rxrpc_serial_t rxrpc_get_next_serial(struct rxrpc_connection *conn) | |
| 838 | +{ | |
| 839 | + rxrpc_serial_t serial; | |
| 840 | + | |
| 841 | + serial = conn->tx_serial; | |
| 842 | + if (serial == 0) | |
| 843 | + serial = 1; | |
| 844 | + conn->tx_serial = serial + 1; | |
| 845 | + return serial; | |
| 846 | +} | |
| 847 | + | |
| 825 | 848 | /* |
| 826 | 849 | * af_rxrpc.c |
| 827 | 850 | */ |
| @@ -43,8 +43,6 @@ void rxrpc_propose_delay_ACK(struct rxrpc_call *call, rxrpc_serial_t serial, · 42 unmodified lines | ||
| 43 | 43 | unsigned long expiry = rxrpc_soft_ack_delay; |
| 44 | 44 | unsigned long now = jiffies, ack_at; |
| 45 | 45 | |
| 46 | − call->ackr_serial = serial; | |
| 47 | − | |
| 48 | 46 | if (rxrpc_soft_ack_delay < expiry) |
| 49 | 47 | expiry = rxrpc_soft_ack_delay; |
| 50 | 48 | if (call->peer->srtt_us != 0) |
| @@ -114,6 +112,7 @@ static void rxrpc_congestion_timeout(struct rxrpc_call *call) · 63 unmodified lines | ||
| 114 | 112 | void rxrpc_resend(struct rxrpc_call *call, struct sk_buff *ack_skb) |
| 115 | 113 | { |
| 116 | 114 | struct rxrpc_ackpacket *ack = NULL; |
| 115 | + struct rxrpc_skb_priv *sp; | |
| 117 | 116 | struct rxrpc_txbuf *txb; |
| 118 | 117 | unsigned long resend_at; |
| 119 | 118 | rxrpc_seq_t transmitted = READ_ONCE(call->tx_transmitted); |
| @@ -141,14 +140,15 @@ void rxrpc_resend(struct rxrpc_call *call, struct sk_buff *ack_skb) · 21 unmodified lines | ||
| 141 | 140 | * explicitly NAK'd packets. |
| 142 | 141 | */ |
| 143 | 142 | if (ack_skb) { |
| 143 | + sp = rxrpc_skb(ack_skb); | |
| 144 | 144 | ack = (void *)ack_skb->data + sizeof(struct rxrpc_wire_header); |
| 145 | 145 | |
| 146 | − for (i = 0; i < ack->nAcks; i++) { | |
| 146 | + for (i = 0; i < sp->nr_acks; i++) { | |
| 147 | 147 | rxrpc_seq_t seq; |
| 148 | 148 | |
| 149 | 149 | if (ack->acks[i] & 1) |
| 150 | 150 | continue; |
| 151 | − seq = ntohl(ack->firstPacket) + i; | |
| 151 | + seq = sp->first_ack + i; | |
| 152 | 152 | if (after(txb->seq, transmitted)) |
| 153 | 153 | break; |
| 154 | 154 | if (after(txb->seq, seq)) |
| @@ -373,7 +373,6 @@ static void rxrpc_send_initial_ping(struct rxrpc_call *call) · 218 unmodified lines | ||
| 373 | 373 | bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb) |
| 374 | 374 | { |
| 375 | 375 | unsigned long now, next, t; |
| 376 | − rxrpc_serial_t ackr_serial; | |
| 377 | 376 | bool resend = false, expired = false; |
| 378 | 377 | s32 abort_code; |
| 379 | 378 | |
| @@ -423,8 +422,7 @@ bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb) · 43 unmodified lines | ||
| 423 | 422 | if (time_after_eq(now, t)) { |
| 424 | 423 | trace_rxrpc_timer(call, rxrpc_timer_exp_ack, now); |
| 425 | 424 | cmpxchg(&call->delay_ack_at, t, now + MAX_JIFFY_OFFSET); |
| 426 | − ackr_serial = xchg(&call->ackr_serial, 0); | |
| 427 | − rxrpc_send_ACK(call, RXRPC_ACK_DELAY, ackr_serial, | |
| 425 | + rxrpc_send_ACK(call, RXRPC_ACK_DELAY, 0, | |
| 428 | 426 | rxrpc_propose_ack_ping_for_lost_ack); |
| 429 | 427 | } |
| 430 | 428 | |
| @@ -686,6 +686,7 @@ static void rxrpc_destroy_call(struct work_struct *work) · 685 unmodified lines | ||
| 686 | 686 | |
| 687 | 687 | del_timer_sync(&call->timer); |
| 688 | 688 | |
| 689 | + rxrpc_free_skb(call->cong_last_nack, rxrpc_skb_put_last_nack); | |
| 689 | 690 | rxrpc_cleanup_ring(call); |
| 690 | 691 | while ((txb = list_first_entry_or_null(&call->tx_sendmsg, |
| 691 | 692 | struct rxrpc_txbuf, call_link))) { |
| @@ -95,6 +95,14 @@ void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn, · 94 unmodified lines | ||
| 95 | 95 | |
| 96 | 96 | _enter("%d", conn->debug_id); |
| 97 | 97 | |
| 98 | + if (sp && sp->hdr.type == RXRPC_PACKET_TYPE_ACK) { | |
| 99 | + if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header), | |
| 100 | + &pkt.ack, sizeof(pkt.ack)) < 0) | |
| 101 | + return; | |
| 102 | + if (pkt.ack.reason == RXRPC_ACK_PING_RESPONSE) | |
| 103 | + return; | |
| 104 | + } | |
| 105 | + | |
| 98 | 106 | chan = &conn->channels[channel]; |
| 99 | 107 | |
| 100 | 108 | /* If the last call got moved on whilst we were waiting to run, just |
| @@ -117,7 +125,7 @@ void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn, · 16 unmodified lines | ||
| 117 | 125 | iov[2].iov_base = &ack_info; |
| 118 | 126 | iov[2].iov_len = sizeof(ack_info); |
| 119 | 127 | |
| 120 | − serial = atomic_inc_return(&conn->serial); | |
| 128 | + serial = rxrpc_get_next_serial(conn); | |
| 121 | 129 | |
| 122 | 130 | pkt.whdr.epoch = htonl(conn->proto.epoch); |
| 123 | 131 | pkt.whdr.cid = htonl(conn->proto.cid | channel); |
| @@ -45,11 +45,9 @@ static void rxrpc_congestion_management(struct rxrpc_call *call, · 44 unmodified lines | ||
| 45 | 45 | } |
| 46 | 46 | |
| 47 | 47 | cumulative_acks += summary->nr_new_acks; |
| 48 | − cumulative_acks += summary->nr_rot_new_acks; | |
| 49 | 48 | if (cumulative_acks > 255) |
| 50 | 49 | cumulative_acks = 255; |
| 51 | 50 | |
| 52 | − summary->mode = call->cong_mode; | |
| 53 | 51 | summary->cwnd = call->cong_cwnd; |
| 54 | 52 | summary->ssthresh = call->cong_ssthresh; |
| 55 | 53 | summary->cumulative_acks = cumulative_acks; |
| @@ -151,6 +149,7 @@ out_no_clear_ca: · 95 unmodified lines | ||
| 151 | 149 | cwnd = RXRPC_TX_MAX_WINDOW; |
| 152 | 150 | call->cong_cwnd = cwnd; |
| 153 | 151 | call->cong_cumul_acks = cumulative_acks; |
| 152 | + summary->mode = call->cong_mode; | |
| 154 | 153 | trace_rxrpc_congest(call, summary, acked_serial, change); |
| 155 | 154 | if (resend) |
| 156 | 155 | rxrpc_resend(call, skb); |
| @@ -213,7 +212,6 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to, · 56 unmodified lines | ||
| 213 | 212 | list_for_each_entry_rcu(txb, &call->tx_buffer, call_link, false) { |
| 214 | 213 | if (before_eq(txb->seq, call->acks_hard_ack)) |
| 215 | 214 | continue; |
| 216 | − summary->nr_rot_new_acks++; | |
| 217 | 215 | if (test_bit(RXRPC_TXBUF_LAST, &txb->flags)) { |
| 218 | 216 | set_bit(RXRPC_CALL_TX_LAST, &call->flags); |
| 219 | 217 | rot_last = true; |
| @@ -254,6 +252,11 @@ static void rxrpc_end_tx_phase(struct rxrpc_call *call, bool reply_begun, · 34 unmodified lines | ||
| 254 | 252 | { |
| 255 | 253 | ASSERT(test_bit(RXRPC_CALL_TX_LAST, &call->flags)); |
| 256 | 254 | |
| 255 | + if (unlikely(call->cong_last_nack)) { | |
| 256 | + rxrpc_free_skb(call->cong_last_nack, rxrpc_skb_put_last_nack); | |
| 257 | + call->cong_last_nack = NULL; | |
| 258 | + } | |
| 259 | + | |
| 257 | 260 | switch (__rxrpc_call_state(call)) { |
| 258 | 261 | case RXRPC_CALL_CLIENT_SEND_REQUEST: |
| 259 | 262 | case RXRPC_CALL_CLIENT_AWAIT_REPLY: |
| @@ -702,6 +705,43 @@ static void rxrpc_input_ackinfo(struct rxrpc_call *call, struct sk_buff *skb, · 442 unmodified lines | ||
| 702 | 705 | wake_up(&call->waitq); |
| 703 | 706 | } |
| 704 | 707 | |
| 708 | +/* | |
| 709 | + * Determine how many nacks from the previous ACK have now been satisfied. | |
| 710 | + */ | |
| 711 | +static rxrpc_seq_t rxrpc_input_check_prev_ack(struct rxrpc_call *call, | |
| 712 | + struct rxrpc_ack_summary *summary, | |
| 713 | + rxrpc_seq_t seq) | |
| 714 | +{ | |
| 715 | + struct sk_buff *skb = call->cong_last_nack; | |
| 716 | + struct rxrpc_ackpacket ack; | |
| 717 | + struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | |
| 718 | + unsigned int i, new_acks = 0, retained_nacks = 0; | |
| 719 | + rxrpc_seq_t old_seq = sp->first_ack; | |
| 720 | + u8 *acks = skb->data + sizeof(struct rxrpc_wire_header) + sizeof(ack); | |
| 721 | + | |
| 722 | + if (after_eq(seq, old_seq + sp->nr_acks)) { | |
| 723 | + summary->nr_new_acks += sp->nr_nacks; | |
| 724 | + summary->nr_new_acks += seq - (old_seq + sp->nr_acks); | |
| 725 | + summary->nr_retained_nacks = 0; | |
| 726 | + } else if (seq == old_seq) { | |
| 727 | + summary->nr_retained_nacks = sp->nr_nacks; | |
| 728 | + } else { | |
| 729 | + for (i = 0; i < sp->nr_acks; i++) { | |
| 730 | + if (acks[i] == RXRPC_ACK_TYPE_NACK) { | |
| 731 | + if (before(old_seq + i, seq)) | |
| 732 | + new_acks++; | |
| 733 | + else | |
| 734 | + retained_nacks++; | |
| 735 | + } | |
| 736 | + } | |
| 737 | + | |
| 738 | + summary->nr_new_acks += new_acks; | |
| 739 | + summary->nr_retained_nacks = retained_nacks; | |
| 740 | + } | |
| 741 | + | |
| 742 | + return old_seq + sp->nr_acks; | |
| 743 | +} | |
| 744 | + | |
| 705 | 745 | /* |
| 706 | 746 | * Process individual soft ACKs. |
| 707 | 747 | * |
| @@ -711,25 +751,51 @@ static void rxrpc_input_ackinfo(struct rxrpc_call *call, struct sk_buff *skb, · 3 unmodified lines | ||
| 711 | 751 | * the timer on the basis that the peer might just not have processed them at |
| 712 | 752 | * the time the ACK was sent. |
| 713 | 753 | */ |
| 714 | −static void rxrpc_input_soft_acks(struct rxrpc_call *call, u8 *acks, | |
| 715 | − rxrpc_seq_t seq, int nr_acks, | |
| 716 | − struct rxrpc_ack_summary *summary) | |
| 754 | +static void rxrpc_input_soft_acks(struct rxrpc_call *call, | |
| 755 | + struct rxrpc_ack_summary *summary, | |
| 756 | + struct sk_buff *skb, | |
| 757 | + rxrpc_seq_t seq, | |
| 758 | + rxrpc_seq_t since) | |
| 717 | 759 | { |
| 718 | − unsigned int i; | |
| 760 | + struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | |
| 761 | + unsigned int i, old_nacks = 0; | |
| 762 | + rxrpc_seq_t lowest_nak = seq + sp->nr_acks; | |
| 763 | + u8 *acks = skb->data + sizeof(struct rxrpc_wire_header) + sizeof(struct rxrpc_ackpacket); | |
| 719 | 764 | |
| 720 | − for (i = 0; i < nr_acks; i++) { | |
| 765 | + for (i = 0; i < sp->nr_acks; i++) { | |
| 721 | 766 | if (acks[i] == RXRPC_ACK_TYPE_ACK) { |
| 722 | 767 | summary->nr_acks++; |
| 723 | − summary->nr_new_acks++; | |
| 768 | + if (after_eq(seq, since)) | |
| 769 | + summary->nr_new_acks++; | |
| 724 | 770 | } else { |
| 725 | − if (!summary->saw_nacks && | |
| 726 | − call->acks_lowest_nak != seq + i) { | |
| 727 | − call->acks_lowest_nak = seq + i; | |
| 728 | − summary->new_low_nack = true; | |
| 729 | − } | |
| 730 | 771 | summary->saw_nacks = true; |
| 772 | + if (before(seq, since)) { | |
| 773 | + /* Overlap with previous ACK */ | |
| 774 | + old_nacks++; | |
| 775 | + } else { | |
| 776 | + summary->nr_new_nacks++; | |
| 777 | + sp->nr_nacks++; | |
| 778 | + } | |
| 779 | + | |
| 780 | + if (before(seq, lowest_nak)) | |
| 781 | + lowest_nak = seq; | |
| 731 | 782 | } |
| 783 | + seq++; | |
| 784 | + } | |
| 785 | + | |
| 786 | + if (lowest_nak != call->acks_lowest_nak) { | |
| 787 | + call->acks_lowest_nak = lowest_nak; | |
| 788 | + summary->new_low_nack = true; | |
| 732 | 789 | } |
| 790 | + | |
| 791 | + /* We *can* have more nacks than we did - the peer is permitted to drop | |
| 792 | + * packets it has soft-acked and re-request them. Further, it is | |
| 793 | + * possible for the nack distribution to change whilst the number of | |
| 794 | + * nacks stays the same or goes down. | |
| 795 | + */ | |
| 796 | + if (old_nacks < summary->nr_retained_nacks) | |
| 797 | + summary->nr_new_acks += summary->nr_retained_nacks - old_nacks; | |
| 798 | + summary->nr_retained_nacks = old_nacks; | |
| 733 | 799 | } |
| 734 | 800 | |
| 735 | 801 | /* |
| @@ -773,7 +839,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb) · 37 unmodified lines | ||
| 773 | 839 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); |
| 774 | 840 | struct rxrpc_ackinfo info; |
| 775 | 841 | rxrpc_serial_t ack_serial, acked_serial; |
| 776 | − rxrpc_seq_t first_soft_ack, hard_ack, prev_pkt; | |
| 842 | + rxrpc_seq_t first_soft_ack, hard_ack, prev_pkt, since; | |
| 777 | 843 | int nr_acks, offset, ioffset; |
| 778 | 844 | |
| 779 | 845 | _enter(""); |
| @@ -789,6 +855,8 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb) · 9 unmodified lines | ||
| 789 | 855 | prev_pkt = ntohl(ack.previousPacket); |
| 790 | 856 | hard_ack = first_soft_ack - 1; |
| 791 | 857 | nr_acks = ack.nAcks; |
| 858 | + sp->first_ack = first_soft_ack; | |
| 859 | + sp->nr_acks = nr_acks; | |
| 792 | 860 | summary.ack_reason = (ack.reason < RXRPC_ACK__INVALID ? |
| 793 | 861 | ack.reason : RXRPC_ACK__INVALID); |
| 794 | 862 | |
| @@ -858,6 +926,16 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb) · 63 unmodified lines | ||
| 858 | 926 | if (nr_acks > 0) |
| 859 | 927 | skb_condense(skb); |
| 860 | 928 | |
| 929 | + if (call->cong_last_nack) { | |
| 930 | + since = rxrpc_input_check_prev_ack(call, &summary, first_soft_ack); | |
| 931 | + rxrpc_free_skb(call->cong_last_nack, rxrpc_skb_put_last_nack); | |
| 932 | + call->cong_last_nack = NULL; | |
| 933 | + } else { | |
| 934 | + summary.nr_new_acks = first_soft_ack - call->acks_first_seq; | |
| 935 | + call->acks_lowest_nak = first_soft_ack + nr_acks; | |
| 936 | + since = first_soft_ack; | |
| 937 | + } | |
| 938 | + | |
| 861 | 939 | call->acks_latest_ts = skb->tstamp; |
| 862 | 940 | call->acks_first_seq = first_soft_ack; |
| 863 | 941 | call->acks_prev_seq = prev_pkt; |
| @@ -866,7 +944,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb) · 2 unmodified lines | ||
| 866 | 944 | case RXRPC_ACK_PING: |
| 867 | 945 | break; |
| 868 | 946 | default: |
| 869 | − if (after(acked_serial, call->acks_highest_serial)) | |
| 947 | + if (acked_serial && after(acked_serial, call->acks_highest_serial)) | |
| 870 | 948 | call->acks_highest_serial = acked_serial; |
| 871 | 949 | break; |
| 872 | 950 | } |
| @@ -905,8 +983,9 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb) · 32 unmodified lines | ||
| 905 | 983 | if (nr_acks > 0) { |
| 906 | 984 | if (offset > (int)skb->len - nr_acks) |
| 907 | 985 | return rxrpc_proto_abort(call, 0, rxrpc_eproto_ackr_short_sack); |
| 908 | − rxrpc_input_soft_acks(call, skb->data + offset, first_soft_ack, | |
| 909 | − nr_acks, &summary); | |
| 986 | + rxrpc_input_soft_acks(call, &summary, skb, first_soft_ack, since); | |
| 987 | + rxrpc_get_skb(skb, rxrpc_skb_get_last_nack); | |
| 988 | + call->cong_last_nack = skb; | |
| 910 | 989 | } |
| 911 | 990 | |
| 912 | 991 | if (test_bit(RXRPC_CALL_TX_LAST, &call->flags) && |
| @@ -216,7 +216,7 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb) · 215 unmodified lines | ||
| 216 | 216 | iov[0].iov_len = sizeof(txb->wire) + sizeof(txb->ack) + n; |
| 217 | 217 | len = iov[0].iov_len; |
| 218 | 218 | |
| 219 | − serial = atomic_inc_return(&conn->serial); | |
| 219 | + serial = rxrpc_get_next_serial(conn); | |
| 220 | 220 | txb->wire.serial = htonl(serial); |
| 221 | 221 | trace_rxrpc_tx_ack(call->debug_id, serial, |
| 222 | 222 | ntohl(txb->ack.firstPacket), |
| @@ -302,7 +302,7 @@ int rxrpc_send_abort_packet(struct rxrpc_call *call) · 79 unmodified lines | ||
| 302 | 302 | iov[0].iov_base = &pkt; |
| 303 | 303 | iov[0].iov_len = sizeof(pkt); |
| 304 | 304 | |
| 305 | − serial = atomic_inc_return(&conn->serial); | |
| 305 | + serial = rxrpc_get_next_serial(conn); | |
| 306 | 306 | pkt.whdr.serial = htonl(serial); |
| 307 | 307 | |
| 308 | 308 | iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, sizeof(pkt)); |
| @@ -334,7 +334,7 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb) · 25 unmodified lines | ||
| 334 | 334 | _enter("%x,{%d}", txb->seq, txb->len); |
| 335 | 335 | |
| 336 | 336 | /* Each transmission of a Tx packet needs a new serial number */ |
| 337 | − serial = atomic_inc_return(&conn->serial); | |
| 337 | + serial = rxrpc_get_next_serial(conn); | |
| 338 | 338 | txb->wire.serial = htonl(serial); |
| 339 | 339 | |
| 340 | 340 | if (test_bit(RXRPC_CONN_PROBING_FOR_UPGRADE, &conn->flags) && |
| @@ -558,7 +558,7 @@ void rxrpc_send_conn_abort(struct rxrpc_connection *conn) · 217 unmodified lines | ||
| 558 | 558 | |
| 559 | 559 | len = iov[0].iov_len + iov[1].iov_len; |
| 560 | 560 | |
| 561 | − serial = atomic_inc_return(&conn->serial); | |
| 561 | + serial = rxrpc_get_next_serial(conn); | |
| 562 | 562 | whdr.serial = htonl(serial); |
| 563 | 563 | |
| 564 | 564 | iov_iter_kvec(&msg.msg_iter, WRITE, iov, 2, len); |
| @@ -181,7 +181,7 @@ print: · 180 unmodified lines | ||
| 181 | 181 | atomic_read(&conn->active), |
| 182 | 182 | state, |
| 183 | 183 | key_serial(conn->key), |
| 184 | − atomic_read(&conn->serial), | |
| 184 | + conn->tx_serial, | |
| 185 | 185 | conn->hi_serial, |
| 186 | 186 | conn->channels[0].call_id, |
| 187 | 187 | conn->channels[1].call_id, |
| @@ -664,7 +664,7 @@ static int rxkad_issue_challenge(struct rxrpc_connection *conn) · 663 unmodified lines | ||
| 664 | 664 | |
| 665 | 665 | len = iov[0].iov_len + iov[1].iov_len; |
| 666 | 666 | |
| 667 | − serial = atomic_inc_return(&conn->serial); | |
| 667 | + serial = rxrpc_get_next_serial(conn); | |
| 668 | 668 | whdr.serial = htonl(serial); |
| 669 | 669 | |
| 670 | 670 | ret = kernel_sendmsg(conn->local->socket, &msg, iov, 2, len); |
| @@ -721,7 +721,7 @@ static int rxkad_send_response(struct rxrpc_connection *conn, · 50 unmodified lines | ||
| 721 | 721 | |
| 722 | 722 | len = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len; |
| 723 | 723 | |
| 724 | − serial = atomic_inc_return(&conn->serial); | |
| 724 | + serial = rxrpc_get_next_serial(conn); | |
| 725 | 725 | whdr.serial = htonl(serial); |
| 726 | 726 | |
| 727 | 727 | rxrpc_local_dont_fragment(conn->local, false); |
| @@ -1086,6 +1086,12 @@ int tipc_nl_bearer_add(struct sk_buff *skb, struct genl_info *info) · 1085 unmodified lines | ||
| 1086 | 1086 | |
| 1087 | 1087 | #ifdef CONFIG_TIPC_MEDIA_UDP |
| 1088 | 1088 | if (attrs[TIPC_NLA_BEARER_UDP_OPTS]) { |
| 1089 | + if (b->media->type_id != TIPC_MEDIA_TYPE_UDP) { | |
| 1090 | + rtnl_unlock(); | |
| 1091 | + NL_SET_ERR_MSG(info->extack, "UDP option is unsupported"); | |
| 1092 | + return -EINVAL; | |
| 1093 | + } | |
| 1094 | + | |
| 1089 | 1095 | err = tipc_udp_nl_bearer_add(b, |
| 1090 | 1096 | attrs[TIPC_NLA_BEARER_UDP_OPTS]); |
| 1091 | 1097 | if (err) { |
| @@ -339,6 +339,17 @@ static void __unix_gc(struct work_struct *work) · 338 unmodified lines | ||
| 339 | 339 | /* Here we are. Hitlist is filled. Die. */ |
| 340 | 340 | __skb_queue_purge(&hitlist); |
| 341 | 341 | |
| 342 | +#if IS_ENABLED(CONFIG_AF_UNIX_OOB) | |
| 343 | + list_for_each_entry_safe(u, next, &gc_candidates, link) { | |
| 344 | + struct sk_buff *skb = u->oob_skb; | |
| 345 | + | |
| 346 | + if (skb) { | |
| 347 | + u->oob_skb = NULL; | |
| 348 | + kfree_skb(skb); | |
| 349 | + } | |
| 350 | + } | |
| 351 | +#endif | |
| 352 | + | |
| 342 | 353 | spin_lock(&unix_gc_lock); |
| 343 | 354 | |
| 344 | 355 | /* All candidates should have been detached by now. */ |
| @@ -5,7 +5,7 @@ · 4 unmodified lines | ||
| 5 | 5 | * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> |
| 6 | 6 | * Copyright 2013-2014 Intel Mobile Communications GmbH |
| 7 | 7 | * Copyright 2015-2017 Intel Deutschland GmbH |
| 8 | − * Copyright (C) 2018-2023 Intel Corporation | |
| 8 | + * Copyright (C) 2018-2024 Intel Corporation | |
| 9 | 9 | */ |
| 10 | 10 | |
| 11 | 11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| @@ -1661,6 +1661,7 @@ void wiphy_delayed_work_queue(struct wiphy *wiphy, · 1649 unmodified lines | ||
| 1661 | 1661 | unsigned long delay) |
| 1662 | 1662 | { |
| 1663 | 1663 | if (!delay) { |
| 1664 | + del_timer(&dwork->timer); | |
| 1664 | 1665 | wiphy_work_queue(wiphy, &dwork->work); |
| 1665 | 1666 | return; |
| 1666 | 1667 | } |
| @@ -1731,6 +1731,61 @@ static void cfg80211_update_hidden_bsses(struct cfg80211_internal_bss *known, · 1730 unmodified lines | ||
| 1731 | 1731 | } |
| 1732 | 1732 | } |
| 1733 | 1733 | |
| 1734 | +static void cfg80211_check_stuck_ecsa(struct cfg80211_registered_device *rdev, | |
| 1735 | + struct cfg80211_internal_bss *known, | |
| 1736 | + const struct cfg80211_bss_ies *old) | |
| 1737 | +{ | |
| 1738 | + const struct ieee80211_ext_chansw_ie *ecsa; | |
| 1739 | + const struct element *elem_new, *elem_old; | |
| 1740 | + const struct cfg80211_bss_ies *new, *bcn; | |
| 1741 | + | |
| 1742 | + if (known->pub.proberesp_ecsa_stuck) | |
| 1743 | + return; | |
| 1744 | + | |
| 1745 | + new = rcu_dereference_protected(known->pub.proberesp_ies, | |
| 1746 | + lockdep_is_held(&rdev->bss_lock)); | |
| 1747 | + if (WARN_ON(!new)) | |
| 1748 | + return; | |
| 1749 | + | |
| 1750 | + if (new->tsf - old->tsf < USEC_PER_SEC) | |
| 1751 | + return; | |
| 1752 | + | |
| 1753 | + elem_old = cfg80211_find_elem(WLAN_EID_EXT_CHANSWITCH_ANN, | |
| 1754 | + old->data, old->len); | |
| 1755 | + if (!elem_old) | |
| 1756 | + return; | |
| 1757 | + | |
| 1758 | + elem_new = cfg80211_find_elem(WLAN_EID_EXT_CHANSWITCH_ANN, | |
| 1759 | + new->data, new->len); | |
| 1760 | + if (!elem_new) | |
| 1761 | + return; | |
| 1762 | + | |
| 1763 | + bcn = rcu_dereference_protected(known->pub.beacon_ies, | |
| 1764 | + lockdep_is_held(&rdev->bss_lock)); | |
| 1765 | + if (bcn && | |
| 1766 | + cfg80211_find_elem(WLAN_EID_EXT_CHANSWITCH_ANN, | |
| 1767 | + bcn->data, bcn->len)) | |
| 1768 | + return; | |
| 1769 | + | |
| 1770 | + if (elem_new->datalen != elem_old->datalen) | |
| 1771 | + return; | |
| 1772 | + if (elem_new->datalen < sizeof(struct ieee80211_ext_chansw_ie)) | |
| 1773 | + return; | |
| 1774 | + if (memcmp(elem_new->data, elem_old->data, elem_new->datalen)) | |
| 1775 | + return; | |
| 1776 | + | |
| 1777 | + ecsa = (void *)elem_new->data; | |
| 1778 | + | |
| 1779 | + if (!ecsa->mode) | |
| 1780 | + return; | |
| 1781 | + | |
| 1782 | + if (ecsa->new_ch_num != | |
| 1783 | + ieee80211_frequency_to_channel(known->pub.channel->center_freq)) | |
| 1784 | + return; | |
| 1785 | + | |
| 1786 | + known->pub.proberesp_ecsa_stuck = 1; | |
| 1787 | +} | |
| 1788 | + | |
| 1734 | 1789 | static bool |
| 1735 | 1790 | cfg80211_update_known_bss(struct cfg80211_registered_device *rdev, |
| 1736 | 1791 | struct cfg80211_internal_bss *known, |
| @@ -1750,8 +1805,10 @@ cfg80211_update_known_bss(struct cfg80211_registered_device *rdev, · 13 unmodified lines | ||
| 1750 | 1805 | /* Override possible earlier Beacon frame IEs */ |
| 1751 | 1806 | rcu_assign_pointer(known->pub.ies, |
| 1752 | 1807 | new->pub.proberesp_ies); |
| 1753 | − if (old) | |
| 1808 | + if (old) { | |
| 1809 | + cfg80211_check_stuck_ecsa(rdev, known, old); | |
| 1754 | 1810 | kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head); |
| 1811 | + } | |
| 1755 | 1812 | } |
| 1756 | 1813 | |
| 1757 | 1814 | if (rcu_access_pointer(new->pub.beacon_ies)) { |
| @@ -211,6 +211,10 @@ static const char * const snd_pcm_format_names[] = { · 210 unmodified lines | ||
| 211 | 211 | FORMAT(DSD_U32_LE), |
| 212 | 212 | FORMAT(DSD_U16_BE), |
| 213 | 213 | FORMAT(DSD_U32_BE), |
| 214 | + FORMAT(S20_LE), | |
| 215 | + FORMAT(S20_BE), | |
| 216 | + FORMAT(U20_LE), | |
| 217 | + FORMAT(U20_BE), | |
| 214 | 218 | }; |
| 215 | 219 | |
| 216 | 220 | /** |
| @@ -76,6 +76,8 @@ static const struct cs35l41_config cs35l41_config_table[] = { · 75 unmodified lines | ||
| 76 | 76 | { "10431533", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, |
| 77 | 77 | { "10431573", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, |
| 78 | 78 | { "10431663", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 1000, 4500, 24 }, |
| 79 | + { "10431683", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 }, | |
| 80 | + { "104316A3", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, | |
| 79 | 81 | { "104316D3", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, |
| 80 | 82 | { "104316F3", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, |
| 81 | 83 | { "104317F3", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 }, |
| @@ -410,6 +412,8 @@ static const struct cs35l41_prop_model cs35l41_prop_model_table[] = { · 328 unmodified lines | ||
| 410 | 412 | { "CSC3551", "10431533", generic_dsd_config }, |
| 411 | 413 | { "CSC3551", "10431573", generic_dsd_config }, |
| 412 | 414 | { "CSC3551", "10431663", generic_dsd_config }, |
| 415 | + { "CSC3551", "10431683", generic_dsd_config }, | |
| 416 | + { "CSC3551", "104316A3", generic_dsd_config }, | |
| 413 | 417 | { "CSC3551", "104316D3", generic_dsd_config }, |
| 414 | 418 | { "CSC3551", "104316F3", generic_dsd_config }, |
| 415 | 419 | { "CSC3551", "104317F3", generic_dsd_config }, |
| @@ -30,14 +30,23 @@ · 29 unmodified lines | ||
| 30 | 30 | * ASP1_RX_WL = 24 bits per sample |
| 31 | 31 | * ASP1_TX_WL = 24 bits per sample |
| 32 | 32 | * ASP1_RXn_EN 1..3 and ASP1_TXn_EN 1..4 disabled |
| 33 | + * | |
| 34 | + * Override any Windows-specific mixer settings applied by the firmware. | |
| 33 | 35 | */ |
| 34 | 36 | static const struct reg_sequence cs35l56_hda_dai_config[] = { |
| 35 | 37 | { CS35L56_ASP1_CONTROL1, 0x00000021 }, |
| 36 | 38 | { CS35L56_ASP1_CONTROL2, 0x20200200 }, |
| 37 | 39 | { CS35L56_ASP1_CONTROL3, 0x00000003 }, |
| 40 | + { CS35L56_ASP1_FRAME_CONTROL1, 0x03020100 }, | |
| 41 | + { CS35L56_ASP1_FRAME_CONTROL5, 0x00020100 }, | |
| 38 | 42 | { CS35L56_ASP1_DATA_CONTROL5, 0x00000018 }, |
| 39 | 43 | { CS35L56_ASP1_DATA_CONTROL1, 0x00000018 }, |
| 40 | 44 | { CS35L56_ASP1_ENABLES1, 0x00000000 }, |
| 45 | + { CS35L56_ASP1TX1_INPUT, 0x00000018 }, | |
| 46 | + { CS35L56_ASP1TX2_INPUT, 0x00000019 }, | |
| 47 | + { CS35L56_ASP1TX3_INPUT, 0x00000020 }, | |
| 48 | + { CS35L56_ASP1TX4_INPUT, 0x00000028 }, | |
| 49 | + | |
| 41 | 50 | }; |
| 42 | 51 | |
| 43 | 52 | static void cs35l56_hda_play(struct cs35l56_hda *cs35l56) |
| @@ -133,6 +142,10 @@ static int cs35l56_hda_runtime_resume(struct device *dev) · 89 unmodified lines | ||
| 133 | 142 | } |
| 134 | 143 | } |
| 135 | 144 | |
| 145 | + ret = cs35l56_force_sync_asp1_registers_from_cache(&cs35l56->base); | |
| 146 | + if (ret) | |
| 147 | + goto err; | |
| 148 | + | |
| 136 | 149 | return 0; |
| 137 | 150 | |
| 138 | 151 | err: |
| @@ -384,7 +397,7 @@ static const struct cs_dsp_client_ops cs35l56_hda_client_ops = { · 245 unmodified lines | ||
| 384 | 397 | |
| 385 | 398 | static int cs35l56_hda_request_firmware_file(struct cs35l56_hda *cs35l56, |
| 386 | 399 | const struct firmware **firmware, char **filename, |
| 387 | − const char *dir, const char *system_name, | |
| 400 | + const char *base_name, const char *system_name, | |
| 388 | 401 | const char *amp_name, |
| 389 | 402 | const char *filetype) |
| 390 | 403 | { |
| @@ -392,17 +405,13 @@ static int cs35l56_hda_request_firmware_file(struct cs35l56_hda *cs35l56, · 1 unmodified line | ||
| 392 | 405 | int ret = 0; |
| 393 | 406 | |
| 394 | 407 | if (system_name && amp_name) |
| 395 | − *filename = kasprintf(GFP_KERNEL, "%scs35l56%s-%02x-dsp1-misc-%s-%s.%s", dir, | |
| 396 | − cs35l56->base.secured ? "s" : "", cs35l56->base.rev, | |
| 408 | + *filename = kasprintf(GFP_KERNEL, "%s-%s-%s.%s", base_name, | |
| 397 | 409 | system_name, amp_name, filetype); |
| 398 | 410 | else if (system_name) |
| 399 | − *filename = kasprintf(GFP_KERNEL, "%scs35l56%s-%02x-dsp1-misc-%s.%s", dir, | |
| 400 | − cs35l56->base.secured ? "s" : "", cs35l56->base.rev, | |
| 411 | + *filename = kasprintf(GFP_KERNEL, "%s-%s.%s", base_name, | |
| 401 | 412 | system_name, filetype); |
| 402 | 413 | else |
| 403 | − *filename = kasprintf(GFP_KERNEL, "%scs35l56%s-%02x-dsp1-misc.%s", dir, | |
| 404 | − cs35l56->base.secured ? "s" : "", cs35l56->base.rev, | |
| 405 | − filetype); | |
| 414 | + *filename = kasprintf(GFP_KERNEL, "%s.%s", base_name, filetype); | |
| 406 | 415 | |
| 407 | 416 | if (!*filename) |
| 408 | 417 | return -ENOMEM; |
| @@ -435,8 +444,8 @@ static int cs35l56_hda_request_firmware_file(struct cs35l56_hda *cs35l56, · 26 unmodified lines | ||
| 435 | 444 | return 0; |
| 436 | 445 | } |
| 437 | 446 | |
| 438 | −static const char cirrus_dir[] = "cirrus/"; | |
| 439 | 447 | static void cs35l56_hda_request_firmware_files(struct cs35l56_hda *cs35l56, |
| 448 | + unsigned int preloaded_fw_ver, | |
| 440 | 449 | const struct firmware **wmfw_firmware, |
| 441 | 450 | char **wmfw_filename, |
| 442 | 451 | const struct firmware **coeff_firmware, |
| @@ -444,55 +453,73 @@ static void cs35l56_hda_request_firmware_files(struct cs35l56_hda *cs35l56, · 1 unmodified line | ||
| 444 | 453 | { |
| 445 | 454 | const char *system_name = cs35l56->system_name; |
| 446 | 455 | const char *amp_name = cs35l56->amp_name; |
| 456 | + char base_name[37]; | |
| 447 | 457 | int ret; |
| 448 | 458 | |
| 459 | + if (preloaded_fw_ver) { | |
| 460 | + snprintf(base_name, sizeof(base_name), | |
| 461 | + "cirrus/cs35l56-%02x%s-%06x-dsp1-misc", | |
| 462 | + cs35l56->base.rev, | |
| 463 | + cs35l56->base.secured ? "-s" : "", | |
| 464 | + preloaded_fw_ver & 0xffffff); | |
| 465 | + } else { | |
| 466 | + snprintf(base_name, sizeof(base_name), | |
| 467 | + "cirrus/cs35l56-%02x%s-dsp1-misc", | |
| 468 | + cs35l56->base.rev, | |
| 469 | + cs35l56->base.secured ? "-s" : ""); | |
| 470 | + } | |
| 471 | + | |
| 449 | 472 | if (system_name && amp_name) { |
| 450 | 473 | if (!cs35l56_hda_request_firmware_file(cs35l56, wmfw_firmware, wmfw_filename, |
| 451 | − cirrus_dir, system_name, amp_name, "wmfw")) { | |
| 474 | + base_name, system_name, amp_name, "wmfw")) { | |
| 452 | 475 | cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename, |
| 453 | − cirrus_dir, system_name, amp_name, "bin"); | |
| 476 | + base_name, system_name, amp_name, "bin"); | |
| 454 | 477 | return; |
| 455 | 478 | } |
| 456 | 479 | } |
| 457 | 480 | |
| 458 | 481 | if (system_name) { |
| 459 | 482 | if (!cs35l56_hda_request_firmware_file(cs35l56, wmfw_firmware, wmfw_filename, |
| 460 | − cirrus_dir, system_name, NULL, "wmfw")) { | |
| 483 | + base_name, system_name, NULL, "wmfw")) { | |
| 461 | 484 | if (amp_name) |
| 462 | 485 | cs35l56_hda_request_firmware_file(cs35l56, |
| 463 | 486 | coeff_firmware, coeff_filename, |
| 464 | − cirrus_dir, system_name, | |
| 487 | + base_name, system_name, | |
| 465 | 488 | amp_name, "bin"); |
| 466 | 489 | if (!*coeff_firmware) |
| 467 | 490 | cs35l56_hda_request_firmware_file(cs35l56, |
| 468 | 491 | coeff_firmware, coeff_filename, |
| 469 | − cirrus_dir, system_name, | |
| 492 | + base_name, system_name, | |
| 470 | 493 | NULL, "bin"); |
| 471 | 494 | return; |
| 472 | 495 | } |
| 496 | + | |
| 497 | + /* | |
| 498 | + * Check for system-specific bin files without wmfw before | |
| 499 | + * falling back to generic firmware | |
| 500 | + */ | |
| 501 | + if (amp_name) | |
| 502 | + cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename, | |
| 503 | + base_name, system_name, amp_name, "bin"); | |
| 504 | + if (!*coeff_firmware) | |
| 505 | + cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename, | |
| 506 | + base_name, system_name, NULL, "bin"); | |
| 507 | + | |
| 508 | + if (*coeff_firmware) | |
| 509 | + return; | |
| 473 | 510 | } |
| 474 | 511 | |
| 475 | 512 | ret = cs35l56_hda_request_firmware_file(cs35l56, wmfw_firmware, wmfw_filename, |
| 476 | − cirrus_dir, NULL, NULL, "wmfw"); | |
| 513 | + base_name, NULL, NULL, "wmfw"); | |
| 477 | 514 | if (!ret) { |
| 478 | 515 | cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename, |
| 479 | − cirrus_dir, NULL, NULL, "bin"); | |
| 516 | + base_name, NULL, NULL, "bin"); | |
| 480 | 517 | return; |
| 481 | 518 | } |
| 482 | 519 | |
| 483 | − /* When a firmware file is not found must still search for the coeff files */ | |
| 484 | − if (system_name) { | |
| 485 | − if (amp_name) | |
| 486 | − cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename, | |
| 487 | − cirrus_dir, system_name, amp_name, "bin"); | |
| 488 | − if (!*coeff_firmware) | |
| 489 | − cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename, | |
| 490 | − cirrus_dir, system_name, NULL, "bin"); | |
| 491 | − } | |
| 492 | − | |
| 493 | 520 | if (!*coeff_firmware) |
| 494 | 521 | cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename, |
| 495 | − cirrus_dir, NULL, NULL, "bin"); | |
| 522 | + base_name, NULL, NULL, "bin"); | |
| 496 | 523 | } |
| 497 | 524 | |
| 498 | 525 | static void cs35l56_hda_release_firmware_files(const struct firmware *wmfw_firmware, |
| @@ -526,7 +553,8 @@ static int cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56) · 27 unmodified lines | ||
| 526 | 553 | const struct firmware *wmfw_firmware = NULL; |
| 527 | 554 | char *coeff_filename = NULL; |
| 528 | 555 | char *wmfw_filename = NULL; |
| 529 | − unsigned int firmware_missing; | |
| 556 | + unsigned int preloaded_fw_ver; | |
| 557 | + bool firmware_missing; | |
| 530 | 558 | int ret = 0; |
| 531 | 559 | |
| 532 | 560 | /* Prepare for a new DSP power-up */ |
| @@ -537,24 +565,21 @@ static int cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56) · 4 unmodified lines | ||
| 537 | 565 | |
| 538 | 566 | pm_runtime_get_sync(cs35l56->base.dev); |
| 539 | 567 | |
| 540 | − ret = regmap_read(cs35l56->base.regmap, CS35L56_PROTECTION_STATUS, &firmware_missing); | |
| 541 | − if (ret) { | |
| 542 | − dev_err(cs35l56->base.dev, "Failed to read PROTECTION_STATUS: %d\n", ret); | |
| 568 | + /* | |
| 569 | + * The firmware can only be upgraded if it is currently running | |
| 570 | + * from the built-in ROM. If not, the wmfw/bin must be for the | |
| 571 | + * version of firmware that is running on the chip. | |
| 572 | + */ | |
| 573 | + ret = cs35l56_read_prot_status(&cs35l56->base, &firmware_missing, &preloaded_fw_ver); | |
| 574 | + if (ret) | |
| 543 | 575 | goto err_pm_put; |
| 544 | − } | |
| 545 | 576 | |
| 546 | − firmware_missing &= CS35L56_FIRMWARE_MISSING; | |
| 577 | + if (firmware_missing) | |
| 578 | + preloaded_fw_ver = 0; | |
| 547 | 579 | |
| 548 | − /* | |
| 549 | − * Firmware can only be downloaded if the CS35L56 is secured or is | |
| 550 | − * running from the built-in ROM. If it is secured the BIOS will have | |
| 551 | − * downloaded firmware, and the wmfw/bin files will only contain | |
| 552 | − * tunings that are safe to download with the firmware running. | |
| 553 | − */ | |
| 554 | − if (cs35l56->base.secured || firmware_missing) { | |
| 555 | − cs35l56_hda_request_firmware_files(cs35l56, &wmfw_firmware, &wmfw_filename, | |
| 556 | − &coeff_firmware, &coeff_filename); | |
| 557 | − } | |
| 580 | + cs35l56_hda_request_firmware_files(cs35l56, preloaded_fw_ver, | |
| 581 | + &wmfw_firmware, &wmfw_filename, | |
| 582 | + &coeff_firmware, &coeff_filename); | |
| 558 | 583 | |
| 559 | 584 | /* |
| 560 | 585 | * If the BIOS didn't patch the firmware a bin file is mandatory to |
| @@ -569,12 +594,12 @@ static int cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56) · 8 unmodified lines | ||
| 569 | 594 | mutex_lock(&cs35l56->base.irq_lock); |
| 570 | 595 | |
| 571 | 596 | /* |
| 572 | − * When the device is running in secure mode the firmware files can | |
| 573 | − * only contain insecure tunings and therefore we do not need to | |
| 574 | − * shutdown the firmware to apply them and can use the lower cost | |
| 575 | − * reinit sequence instead. | |
| 597 | + * If the firmware hasn't been patched it must be shutdown before | |
| 598 | + * doing a full patch and reset afterwards. If it is already | |
| 599 | + * running a patched version the firmware files only contain | |
| 600 | + * tunings and we can use the lower cost reinit sequence instead. | |
| 576 | 601 | */ |
| 577 | − if (!cs35l56->base.secured && (wmfw_firmware || coeff_firmware)) { | |
| 602 | + if (firmware_missing && (wmfw_firmware || coeff_firmware)) { | |
| 578 | 603 | ret = cs35l56_firmware_shutdown(&cs35l56->base); |
| 579 | 604 | if (ret) |
| 580 | 605 | goto err; |
| @@ -593,7 +618,7 @@ static int cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56) · 12 unmodified lines | ||
| 593 | 618 | if (coeff_filename) |
| 594 | 619 | dev_dbg(cs35l56->base.dev, "Loaded Coefficients: %s\n", coeff_filename); |
| 595 | 620 | |
| 596 | − if (cs35l56->base.secured) { | |
| 621 | + if (!firmware_missing) { | |
| 597 | 622 | ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_REINIT); |
| 598 | 623 | if (ret) |
| 599 | 624 | goto err_powered_up; |
| @@ -976,6 +1001,9 @@ int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int id) · 376 unmodified lines | ||
| 976 | 1001 | |
| 977 | 1002 | regmap_multi_reg_write(cs35l56->base.regmap, cs35l56_hda_dai_config, |
| 978 | 1003 | ARRAY_SIZE(cs35l56_hda_dai_config)); |
| 1004 | + ret = cs35l56_force_sync_asp1_registers_from_cache(&cs35l56->base); | |
| 1005 | + if (ret) | |
| 1006 | + goto err; | |
| 979 | 1007 | |
| 980 | 1008 | /* |
| 981 | 1009 | * By default only enable one ASP1TXn, where n=amplifier index, |
| @@ -1035,16 +1063,6 @@ const struct dev_pm_ops cs35l56_hda_pm_ops = { · 53 unmodified lines | ||
| 1035 | 1063 | }; |
| 1036 | 1064 | EXPORT_SYMBOL_NS_GPL(cs35l56_hda_pm_ops, SND_HDA_SCODEC_CS35L56); |
| 1037 | 1065 | |
| 1038 | −#if IS_ENABLED(CONFIG_SND_HDA_SCODEC_CS35L56_KUNIT_TEST) | |
| 1039 | −/* Hooks to export static function to KUnit test */ | |
| 1040 | − | |
| 1041 | −int cs35l56_hda_test_hook_get_speaker_id(struct device *dev, int amp_index, int num_amps) | |
| 1042 | −{ | |
| 1043 | − return cs35l56_hda_get_speaker_id(dev, amp_index, num_amps); | |
| 1044 | −} | |
| 1045 | −EXPORT_SYMBOL_NS_GPL(cs35l56_hda_test_hook_get_speaker_id, SND_HDA_SCODEC_CS35L56); | |
| 1046 | −#endif | |
| 1047 | − | |
| 1048 | 1066 | MODULE_DESCRIPTION("CS35L56 HDA Driver"); |
| 1049 | 1067 | MODULE_IMPORT_NS(SND_HDA_CIRRUS_SCODEC); |
| 1050 | 1068 | MODULE_IMPORT_NS(SND_HDA_CS_DSP_CONTROLS); |
| @@ -1729,9 +1729,11 @@ static int default_bdl_pos_adj(struct azx *chip) · 1728 unmodified lines | ||
| 1729 | 1729 | /* some exceptions: Atoms seem problematic with value 1 */ |
| 1730 | 1730 | if (chip->pci->vendor == PCI_VENDOR_ID_INTEL) { |
| 1731 | 1731 | switch (chip->pci->device) { |
| 1732 | − case 0x0f04: /* Baytrail */ | |
| 1733 | − case 0x2284: /* Braswell */ | |
| 1732 | + case PCI_DEVICE_ID_INTEL_HDA_BYT: | |
| 1733 | + case PCI_DEVICE_ID_INTEL_HDA_BSW: | |
| 1734 | 1734 | return 32; |
| 1735 | + case PCI_DEVICE_ID_INTEL_HDA_APL: | |
| 1736 | + return 64; | |
| 1735 | 1737 | } |
| 1736 | 1738 | } |
| 1737 | 1739 | |
| @@ -1371,6 +1371,7 @@ void dolphin_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int ac · 1370 unmodified lines | ||
| 1371 | 1371 | spec->scodecs[CS8409_CODEC1] = &dolphin_cs42l42_1; |
| 1372 | 1372 | spec->scodecs[CS8409_CODEC1]->codec = codec; |
| 1373 | 1373 | spec->num_scodecs = 2; |
| 1374 | + spec->gen.suppress_vmaster = 1; | |
| 1374 | 1375 | |
| 1375 | 1376 | codec->patch_ops = cs8409_dolphin_patch_ops; |
| 1376 | 1377 | |
| @@ -439,6 +439,10 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) · 438 unmodified lines | ||
| 439 | 439 | alc_update_coef_idx(codec, 0x67, 0xf000, 0x3000); |
| 440 | 440 | fallthrough; |
| 441 | 441 | case 0x10ec0215: |
| 442 | + case 0x10ec0285: | |
| 443 | + case 0x10ec0289: | |
| 444 | + alc_update_coef_idx(codec, 0x36, 1<<13, 0); | |
| 445 | + fallthrough; | |
| 442 | 446 | case 0x10ec0230: |
| 443 | 447 | case 0x10ec0233: |
| 444 | 448 | case 0x10ec0235: |
| @@ -452,9 +456,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) · 7 unmodified lines | ||
| 452 | 456 | case 0x10ec0283: |
| 453 | 457 | case 0x10ec0286: |
| 454 | 458 | case 0x10ec0288: |
| 455 | − case 0x10ec0285: | |
| 456 | 459 | case 0x10ec0298: |
| 457 | − case 0x10ec0289: | |
| 458 | 460 | case 0x10ec0300: |
| 459 | 461 | alc_update_coef_idx(codec, 0x10, 1<<9, 0); |
| 460 | 462 | break; |
| @@ -9577,7 +9579,7 @@ static const struct hda_fixup alc269_fixups[] = { · 9116 unmodified lines | ||
| 9577 | 9579 | .type = HDA_FIXUP_FUNC, |
| 9578 | 9580 | .v.func = cs35l41_fixup_i2c_two, |
| 9579 | 9581 | .chained = true, |
| 9580 | − .chain_id = ALC269_FIXUP_THINKPAD_ACPI, | |
| 9582 | + .chain_id = ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK, | |
| 9581 | 9583 | }, |
| 9582 | 9584 | [ALC287_FIXUP_TAS2781_I2C] = { |
| 9583 | 9585 | .type = HDA_FIXUP_FUNC, |
| @@ -9604,6 +9606,8 @@ static const struct hda_fixup alc269_fixups[] = { · 20 unmodified lines | ||
| 9604 | 9606 | [ALC287_FIXUP_THINKPAD_I2S_SPK] = { |
| 9605 | 9607 | .type = HDA_FIXUP_FUNC, |
| 9606 | 9608 | .v.func = alc287_fixup_bind_dacs, |
| 9609 | + .chained = true, | |
| 9610 | + .chain_id = ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK, | |
| 9607 | 9611 | }, |
| 9608 | 9612 | [ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD] = { |
| 9609 | 9613 | .type = HDA_FIXUP_FUNC, |
| @@ -9653,6 +9657,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 43 unmodified lines | ||
| 9653 | 9657 | SND_PCI_QUIRK(0x1025, 0x1247, "Acer vCopperbox", ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS), |
| 9654 | 9658 | SND_PCI_QUIRK(0x1025, 0x1248, "Acer Veriton N4660G", ALC269VC_FIXUP_ACER_MIC_NO_PRESENCE), |
| 9655 | 9659 | SND_PCI_QUIRK(0x1025, 0x1269, "Acer SWIFT SF314-54", ALC256_FIXUP_ACER_HEADSET_MIC), |
| 9660 | + SND_PCI_QUIRK(0x1025, 0x126a, "Acer Swift SF114-32", ALC256_FIXUP_ACER_MIC_NO_PRESENCE), | |
| 9656 | 9661 | SND_PCI_QUIRK(0x1025, 0x128f, "Acer Veriton Z6860G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC), |
| 9657 | 9662 | SND_PCI_QUIRK(0x1025, 0x1290, "Acer Veriton Z4860G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC), |
| 9658 | 9663 | SND_PCI_QUIRK(0x1025, 0x1291, "Acer Veriton Z4660G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC), |
| @@ -9732,6 +9737,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 73 unmodified lines | ||
| 9732 | 9737 | SND_PCI_QUIRK(0x1028, 0x0b71, "Dell Inspiron 16 Plus 7620", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS), |
| 9733 | 9738 | SND_PCI_QUIRK(0x1028, 0x0beb, "Dell XPS 15 9530 (2023)", ALC289_FIXUP_DELL_CS35L41_SPI_2), |
| 9734 | 9739 | SND_PCI_QUIRK(0x1028, 0x0c03, "Dell Precision 5340", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE), |
| 9740 | + SND_PCI_QUIRK(0x1028, 0x0c0d, "Dell Oasis", ALC289_FIXUP_RTK_AMP_DUAL_SPK), | |
| 9735 | 9741 | SND_PCI_QUIRK(0x1028, 0x0c19, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS), |
| 9736 | 9742 | SND_PCI_QUIRK(0x1028, 0x0c1a, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS), |
| 9737 | 9743 | SND_PCI_QUIRK(0x1028, 0x0c1b, "Dell Precision 3440", ALC236_FIXUP_DELL_DUAL_CODECS), |
| @@ -9852,6 +9858,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 114 unmodified lines | ||
| 9852 | 9858 | SND_PCI_QUIRK(0x103c, 0x8786, "HP OMEN 15", ALC285_FIXUP_HP_MUTE_LED), |
| 9853 | 9859 | SND_PCI_QUIRK(0x103c, 0x8787, "HP OMEN 15", ALC285_FIXUP_HP_MUTE_LED), |
| 9854 | 9860 | SND_PCI_QUIRK(0x103c, 0x8788, "HP OMEN 15", ALC285_FIXUP_HP_MUTE_LED), |
| 9861 | + SND_PCI_QUIRK(0x103c, 0x87b7, "HP Laptop 14-fq0xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), | |
| 9855 | 9862 | SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED), |
| 9856 | 9863 | SND_PCI_QUIRK(0x103c, 0x87e5, "HP ProBook 440 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED), |
| 9857 | 9864 | SND_PCI_QUIRK(0x103c, 0x87e7, "HP ProBook 450 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED), |
| @@ -9957,6 +9964,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 99 unmodified lines | ||
| 9957 | 9964 | SND_PCI_QUIRK(0x103c, 0x8c72, "HP EliteBook 865 G11", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED), |
| 9958 | 9965 | SND_PCI_QUIRK(0x103c, 0x8c96, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), |
| 9959 | 9966 | SND_PCI_QUIRK(0x103c, 0x8c97, "HP ZBook", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), |
| 9967 | + SND_PCI_QUIRK(0x103c, 0x8ca1, "HP ZBook Power", ALC236_FIXUP_HP_GPIO_LED), | |
| 9968 | + SND_PCI_QUIRK(0x103c, 0x8ca2, "HP ZBook Power", ALC236_FIXUP_HP_GPIO_LED), | |
| 9960 | 9969 | SND_PCI_QUIRK(0x103c, 0x8ca4, "HP ZBook Fury", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), |
| 9961 | 9970 | SND_PCI_QUIRK(0x103c, 0x8ca7, "HP ZBook Fury", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), |
| 9962 | 9971 | SND_PCI_QUIRK(0x103c, 0x8cf5, "HP ZBook Studio 16", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED), |
| @@ -10322,6 +10331,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 359 unmodified lines | ||
| 10322 | 10331 | SND_PCI_QUIRK(0x1d72, 0x1945, "Redmi G", ALC256_FIXUP_ASUS_HEADSET_MIC), |
| 10323 | 10332 | SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_HEADSET_MIC), |
| 10324 | 10333 | SND_PCI_QUIRK(0x2782, 0x0232, "CHUWI CoreBook XPro", ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO), |
| 10334 | + SND_PCI_QUIRK(0x2782, 0x1707, "Vaio VJFE-ADL", ALC298_FIXUP_SPK_VOLUME), | |
| 10325 | 10335 | SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC), |
| 10326 | 10336 | SND_PCI_QUIRK(0x8086, 0x2080, "Intel NUC 8 Rugged", ALC256_FIXUP_INTEL_NUC8_RUGGED), |
| 10327 | 10337 | SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", ALC256_FIXUP_INTEL_NUC10), |
| @@ -505,6 +505,13 @@ static int acp_card_rt5682s_hw_params(struct snd_pcm_substream *substream, · 504 unmodified lines | ||
| 505 | 505 | |
| 506 | 506 | clk_set_rate(drvdata->wclk, srate); |
| 507 | 507 | clk_set_rate(drvdata->bclk, srate * ch * format); |
| 508 | + if (!drvdata->soc_mclk) { | |
| 509 | + ret = acp_clk_enable(drvdata, srate, ch * format); | |
| 510 | + if (ret < 0) { | |
| 511 | + dev_err(rtd->card->dev, "Failed to enable HS clk: %d\n", ret); | |
| 512 | + return ret; | |
| 513 | + } | |
| 514 | + } | |
| 508 | 515 | |
| 509 | 516 | return 0; |
| 510 | 517 | } |
| @@ -1464,8 +1471,13 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card) · 953 unmodified lines | ||
| 1464 | 1471 | if (drv_data->amp_cpu_id == I2S_SP) { |
| 1465 | 1472 | links[i].name = "acp-amp-codec"; |
| 1466 | 1473 | links[i].id = AMP_BE_ID; |
| 1467 | − links[i].cpus = sof_sp_virtual; | |
| 1468 | − links[i].num_cpus = ARRAY_SIZE(sof_sp_virtual); | |
| 1474 | + if (drv_data->platform == RENOIR) { | |
| 1475 | + links[i].cpus = sof_sp; | |
| 1476 | + links[i].num_cpus = ARRAY_SIZE(sof_sp); | |
| 1477 | + } else { | |
| 1478 | + links[i].cpus = sof_sp_virtual; | |
| 1479 | + links[i].num_cpus = ARRAY_SIZE(sof_sp_virtual); | |
| 1480 | + } | |
| 1469 | 1481 | links[i].platforms = sof_component; |
| 1470 | 1482 | links[i].num_platforms = ARRAY_SIZE(sof_component); |
| 1471 | 1483 | links[i].dpcm_playback = 1; |
| @@ -48,6 +48,7 @@ static struct acp_card_drvdata sof_rt5682s_rt1019_data = { · 47 unmodified lines | ||
| 48 | 48 | .hs_codec_id = RT5682S, |
| 49 | 49 | .amp_codec_id = RT1019, |
| 50 | 50 | .dmic_codec_id = DMIC, |
| 51 | + .platform = RENOIR, | |
| 51 | 52 | .tdm_mode = false, |
| 52 | 53 | }; |
| 53 | 54 | |
| @@ -58,6 +59,7 @@ static struct acp_card_drvdata sof_rt5682s_max_data = { · 4 unmodified lines | ||
| 58 | 59 | .hs_codec_id = RT5682S, |
| 59 | 60 | .amp_codec_id = MAX98360A, |
| 60 | 61 | .dmic_codec_id = DMIC, |
| 62 | + .platform = RENOIR, | |
| 61 | 63 | .tdm_mode = false, |
| 62 | 64 | }; |
| 63 | 65 | |
| @@ -68,6 +70,7 @@ static struct acp_card_drvdata sof_nau8825_data = { · 4 unmodified lines | ||
| 68 | 70 | .hs_codec_id = NAU8825, |
| 69 | 71 | .amp_codec_id = MAX98360A, |
| 70 | 72 | .dmic_codec_id = DMIC, |
| 73 | + .platform = REMBRANDT, | |
| 71 | 74 | .soc_mclk = true, |
| 72 | 75 | .tdm_mode = false, |
| 73 | 76 | }; |
| @@ -79,6 +82,7 @@ static struct acp_card_drvdata sof_rt5682s_hs_rt1019_data = { · 5 unmodified lines | ||
| 79 | 82 | .hs_codec_id = RT5682S, |
| 80 | 83 | .amp_codec_id = RT1019, |
| 81 | 84 | .dmic_codec_id = DMIC, |
| 85 | + .platform = REMBRANDT, | |
| 82 | 86 | .soc_mclk = true, |
| 83 | 87 | .tdm_mode = false, |
| 84 | 88 | }; |
| @@ -354,6 +354,14 @@ static const struct dmi_system_id acp3x_es83xx_dmi_table[] = { · 353 unmodified lines | ||
| 354 | 354 | }, |
| 355 | 355 | .driver_data = (void *)(ES83XX_ENABLE_DMIC|ES83XX_48_MHZ_MCLK), |
| 356 | 356 | }, |
| 357 | + { | |
| 358 | + .matches = { | |
| 359 | + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"), | |
| 360 | + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HVY-WXX9"), | |
| 361 | + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "M1010"), | |
| 362 | + }, | |
| 363 | + .driver_data = (void *)(ES83XX_ENABLE_DMIC), | |
| 364 | + }, | |
| 357 | 365 | { |
| 358 | 366 | .matches = { |
| 359 | 367 | DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "HUAWEI"), |
| @@ -297,6 +297,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { · 296 unmodified lines | ||
| 297 | 297 | DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 15 B7ED"), |
| 298 | 298 | } |
| 299 | 299 | }, |
| 300 | + { | |
| 301 | + .driver_data = &acp6x_card, | |
| 302 | + .matches = { | |
| 303 | + DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."), | |
| 304 | + DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 15 C7VF"), | |
| 305 | + } | |
| 306 | + }, | |
| 300 | 307 | { |
| 301 | 308 | .driver_data = &acp6x_card, |
| 302 | 309 | .matches = { |
| @@ -5,6 +5,7 @@ · 4 unmodified lines | ||
| 5 | 5 | // Copyright (C) 2023 Cirrus Logic, Inc. and |
| 6 | 6 | // Cirrus Logic International Semiconductor Ltd. |
| 7 | 7 | |
| 8 | +#include <linux/gpio/consumer.h> | |
| 8 | 9 | #include <linux/regmap.h> |
| 9 | 10 | #include <linux/regulator/consumer.h> |
| 10 | 11 | #include <linux/types.h> |
| @@ -12,6 +13,15 @@ · 1 unmodified line | ||
| 12 | 13 | #include "cs35l56.h" |
| 13 | 14 | |
| 14 | 15 | static const struct reg_sequence cs35l56_patch[] = { |
| 16 | + /* | |
| 17 | + * Firmware can change these to non-defaults to satisfy SDCA. | |
| 18 | + * Ensure that they are at known defaults. | |
| 19 | + */ | |
| 20 | + { CS35L56_SWIRE_DP3_CH1_INPUT, 0x00000018 }, | |
| 21 | + { CS35L56_SWIRE_DP3_CH2_INPUT, 0x00000019 }, | |
| 22 | + { CS35L56_SWIRE_DP3_CH3_INPUT, 0x00000029 }, | |
| 23 | + { CS35L56_SWIRE_DP3_CH4_INPUT, 0x00000028 }, | |
| 24 | + | |
| 15 | 25 | /* These are not reset by a soft-reset, so patch to defaults. */ |
| 16 | 26 | { CS35L56_MAIN_RENDER_USER_MUTE, 0x00000000 }, |
| 17 | 27 | { CS35L56_MAIN_RENDER_USER_VOLUME, 0x00000000 }, |
| @@ -34,10 +44,9 @@ static const struct reg_default cs35l56_reg_defaults[] = { · 16 unmodified lines | ||
| 34 | 44 | { CS35L56_ASP1_FRAME_CONTROL5, 0x00020100 }, |
| 35 | 45 | { CS35L56_ASP1_DATA_CONTROL1, 0x00000018 }, |
| 36 | 46 | { CS35L56_ASP1_DATA_CONTROL5, 0x00000018 }, |
| 37 | − { CS35L56_ASP1TX1_INPUT, 0x00000018 }, | |
| 38 | − { CS35L56_ASP1TX2_INPUT, 0x00000019 }, | |
| 39 | − { CS35L56_ASP1TX3_INPUT, 0x00000020 }, | |
| 40 | − { CS35L56_ASP1TX4_INPUT, 0x00000028 }, | |
| 47 | + | |
| 48 | + /* no defaults for ASP1TX mixer */ | |
| 49 | + | |
| 41 | 50 | { CS35L56_SWIRE_DP3_CH1_INPUT, 0x00000018 }, |
| 42 | 51 | { CS35L56_SWIRE_DP3_CH2_INPUT, 0x00000019 }, |
| 43 | 52 | { CS35L56_SWIRE_DP3_CH3_INPUT, 0x00000029 }, |
| @@ -195,6 +204,47 @@ static bool cs35l56_volatile_reg(struct device *dev, unsigned int reg) · 151 unmodified lines | ||
| 195 | 204 | } |
| 196 | 205 | } |
| 197 | 206 | |
| 207 | +/* | |
| 208 | + * The firmware boot sequence can overwrite the ASP1 config registers so that | |
| 209 | + * they don't match regmap's view of their values. Rewrite the values from the | |
| 210 | + * regmap cache into the hardware registers. | |
| 211 | + */ | |
| 212 | +int cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_base *cs35l56_base) | |
| 213 | +{ | |
| 214 | + struct reg_sequence asp1_regs[] = { | |
| 215 | + { .reg = CS35L56_ASP1_ENABLES1 }, | |
| 216 | + { .reg = CS35L56_ASP1_CONTROL1 }, | |
| 217 | + { .reg = CS35L56_ASP1_CONTROL2 }, | |
| 218 | + { .reg = CS35L56_ASP1_CONTROL3 }, | |
| 219 | + { .reg = CS35L56_ASP1_FRAME_CONTROL1 }, | |
| 220 | + { .reg = CS35L56_ASP1_FRAME_CONTROL5 }, | |
| 221 | + { .reg = CS35L56_ASP1_DATA_CONTROL1 }, | |
| 222 | + { .reg = CS35L56_ASP1_DATA_CONTROL5 }, | |
| 223 | + }; | |
| 224 | + int i, ret; | |
| 225 | + | |
| 226 | + /* Read values from regmap cache into a write sequence */ | |
| 227 | + for (i = 0; i < ARRAY_SIZE(asp1_regs); ++i) { | |
| 228 | + ret = regmap_read(cs35l56_base->regmap, asp1_regs[i].reg, &asp1_regs[i].def); | |
| 229 | + if (ret) | |
| 230 | + goto err; | |
| 231 | + } | |
| 232 | + | |
| 233 | + /* Write the values cache-bypassed so that they will be written to silicon */ | |
| 234 | + ret = regmap_multi_reg_write_bypassed(cs35l56_base->regmap, asp1_regs, | |
| 235 | + ARRAY_SIZE(asp1_regs)); | |
| 236 | + if (ret) | |
| 237 | + goto err; | |
| 238 | + | |
| 239 | + return 0; | |
| 240 | + | |
| 241 | +err: | |
| 242 | + dev_err(cs35l56_base->dev, "Failed to sync ASP1 registers: %d\n", ret); | |
| 243 | + | |
| 244 | + return ret; | |
| 245 | +} | |
| 246 | +EXPORT_SYMBOL_NS_GPL(cs35l56_force_sync_asp1_registers_from_cache, SND_SOC_CS35L56_SHARED); | |
| 247 | + | |
| 198 | 248 | int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command) |
| 199 | 249 | { |
| 200 | 250 | unsigned int val; |
| @@ -400,17 +450,6 @@ int cs35l56_is_fw_reload_needed(struct cs35l56_base *cs35l56_base) · 199 unmodified lines | ||
| 400 | 450 | unsigned int val; |
| 401 | 451 | int ret; |
| 402 | 452 | |
| 403 | − /* Nothing to re-patch if we haven't done any patching yet. */ | |
| 404 | − if (!cs35l56_base->fw_patched) | |
| 405 | − return false; | |
| 406 | − | |
| 407 | − /* | |
| 408 | − * If we have control of RESET we will have asserted it so the firmware | |
| 409 | − * will need re-patching. | |
| 410 | − */ | |
| 411 | − if (cs35l56_base->reset_gpio) | |
| 412 | − return true; | |
| 413 | − | |
| 414 | 453 | /* |
| 415 | 454 | * In secure mode FIRMWARE_MISSING is cleared by the BIOS loader so |
| 416 | 455 | * can't be used here to test for memory retention. |
| @@ -590,10 +629,35 @@ void cs35l56_init_cs_dsp(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_ds · 173 unmodified lines | ||
| 590 | 629 | } |
| 591 | 630 | EXPORT_SYMBOL_NS_GPL(cs35l56_init_cs_dsp, SND_SOC_CS35L56_SHARED); |
| 592 | 631 | |
| 632 | +int cs35l56_read_prot_status(struct cs35l56_base *cs35l56_base, | |
| 633 | + bool *fw_missing, unsigned int *fw_version) | |
| 634 | +{ | |
| 635 | + unsigned int prot_status; | |
| 636 | + int ret; | |
| 637 | + | |
| 638 | + ret = regmap_read(cs35l56_base->regmap, CS35L56_PROTECTION_STATUS, &prot_status); | |
| 639 | + if (ret) { | |
| 640 | + dev_err(cs35l56_base->dev, "Get PROTECTION_STATUS failed: %d\n", ret); | |
| 641 | + return ret; | |
| 642 | + } | |
| 643 | + | |
| 644 | + *fw_missing = !!(prot_status & CS35L56_FIRMWARE_MISSING); | |
| 645 | + | |
| 646 | + ret = regmap_read(cs35l56_base->regmap, CS35L56_DSP1_FW_VER, fw_version); | |
| 647 | + if (ret) { | |
| 648 | + dev_err(cs35l56_base->dev, "Get FW VER failed: %d\n", ret); | |
| 649 | + return ret; | |
| 650 | + } | |
| 651 | + | |
| 652 | + return 0; | |
| 653 | +} | |
| 654 | +EXPORT_SYMBOL_NS_GPL(cs35l56_read_prot_status, SND_SOC_CS35L56_SHARED); | |
| 655 | + | |
| 593 | 656 | int cs35l56_hw_init(struct cs35l56_base *cs35l56_base) |
| 594 | 657 | { |
| 595 | 658 | int ret; |
| 596 | − unsigned int devid, revid, otpid, secured; | |
| 659 | + unsigned int devid, revid, otpid, secured, fw_ver; | |
| 660 | + bool fw_missing; | |
| 597 | 661 | |
| 598 | 662 | /* |
| 599 | 663 | * When the system is not using a reset_gpio ensure the device is |
| @@ -652,8 +716,13 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base) · 52 unmodified lines | ||
| 652 | 716 | return ret; |
| 653 | 717 | } |
| 654 | 718 | |
| 655 | − dev_info(cs35l56_base->dev, "Cirrus Logic CS35L56%s Rev %02X OTP%d\n", | |
| 656 | − cs35l56_base->secured ? "s" : "", cs35l56_base->rev, otpid); | |
| 719 | + ret = cs35l56_read_prot_status(cs35l56_base, &fw_missing, &fw_ver); | |
| 720 | + if (ret) | |
| 721 | + return ret; | |
| 722 | + | |
| 723 | + dev_info(cs35l56_base->dev, "Cirrus Logic CS35L56%s Rev %02X OTP%d fw:%d.%d.%d (patched=%u)\n", | |
| 724 | + cs35l56_base->secured ? "s" : "", cs35l56_base->rev, otpid, | |
| 725 | + fw_ver >> 16, (fw_ver >> 8) & 0xff, fw_ver & 0xff, !fw_missing); | |
| 657 | 726 | |
| 658 | 727 | /* Wake source and *_BLOCKED interrupts default to unmasked, so mask them */ |
| 659 | 728 | regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff); |
| @@ -668,6 +737,41 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base) · 8 unmodified lines | ||
| 668 | 737 | } |
| 669 | 738 | EXPORT_SYMBOL_NS_GPL(cs35l56_hw_init, SND_SOC_CS35L56_SHARED); |
| 670 | 739 | |
| 740 | +int cs35l56_get_speaker_id(struct cs35l56_base *cs35l56_base) | |
| 741 | +{ | |
| 742 | + struct gpio_descs *descs; | |
| 743 | + int speaker_id; | |
| 744 | + int i, ret; | |
| 745 | + | |
| 746 | + /* Read the speaker type qualifier from the motherboard GPIOs */ | |
| 747 | + descs = gpiod_get_array_optional(cs35l56_base->dev, "spk-id", GPIOD_IN); | |
| 748 | + if (!descs) { | |
| 749 | + return -ENOENT; | |
| 750 | + } else if (IS_ERR(descs)) { | |
| 751 | + ret = PTR_ERR(descs); | |
| 752 | + return dev_err_probe(cs35l56_base->dev, ret, "Failed to get spk-id-gpios\n"); | |
| 753 | + } | |
| 754 | + | |
| 755 | + speaker_id = 0; | |
| 756 | + for (i = 0; i < descs->ndescs; i++) { | |
| 757 | + ret = gpiod_get_value_cansleep(descs->desc[i]); | |
| 758 | + if (ret < 0) { | |
| 759 | + dev_err_probe(cs35l56_base->dev, ret, "Failed to read spk-id[%d]\n", i); | |
| 760 | + goto err; | |
| 761 | + } | |
| 762 | + | |
| 763 | + speaker_id |= (ret << i); | |
| 764 | + } | |
| 765 | + | |
| 766 | + dev_dbg(cs35l56_base->dev, "Speaker ID = %d\n", speaker_id); | |
| 767 | + ret = speaker_id; | |
| 768 | +err: | |
| 769 | + gpiod_put_array(descs); | |
| 770 | + | |
| 771 | + return ret; | |
| 772 | +} | |
| 773 | +EXPORT_SYMBOL_NS_GPL(cs35l56_get_speaker_id, SND_SOC_CS35L56_SHARED); | |
| 774 | + | |
| 671 | 775 | static const u32 cs35l56_bclk_valid_for_pll_freq_table[] = { |
| 672 | 776 | [0x0C] = 128000, |
| 673 | 777 | [0x0F] = 256000, |
| @@ -59,6 +59,135 @@ static int cs35l56_dspwait_put_volsw(struct snd_kcontrol *kcontrol, · 58 unmodified lines | ||
| 59 | 59 | return snd_soc_put_volsw(kcontrol, ucontrol); |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | +static const unsigned short cs35l56_asp1_mixer_regs[] = { | |
| 63 | + CS35L56_ASP1TX1_INPUT, CS35L56_ASP1TX2_INPUT, | |
| 64 | + CS35L56_ASP1TX3_INPUT, CS35L56_ASP1TX4_INPUT, | |
| 65 | +}; | |
| 66 | + | |
| 67 | +static const char * const cs35l56_asp1_mux_control_names[] = { | |
| 68 | + "ASP1 TX1 Source", "ASP1 TX2 Source", "ASP1 TX3 Source", "ASP1 TX4 Source" | |
| 69 | +}; | |
| 70 | + | |
| 71 | +static int cs35l56_dspwait_asp1tx_get(struct snd_kcontrol *kcontrol, | |
| 72 | + struct snd_ctl_elem_value *ucontrol) | |
| 73 | +{ | |
| 74 | + struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol); | |
| 75 | + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); | |
| 76 | + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | |
| 77 | + int index = e->shift_l; | |
| 78 | + unsigned int addr, val; | |
| 79 | + int ret; | |
| 80 | + | |
| 81 | + /* Wait for mux to be initialized */ | |
| 82 | + cs35l56_wait_dsp_ready(cs35l56); | |
| 83 | + flush_work(&cs35l56->mux_init_work); | |
| 84 | + | |
| 85 | + addr = cs35l56_asp1_mixer_regs[index]; | |
| 86 | + ret = regmap_read(cs35l56->base.regmap, addr, &val); | |
| 87 | + if (ret) | |
| 88 | + return ret; | |
| 89 | + | |
| 90 | + val &= CS35L56_ASP_TXn_SRC_MASK; | |
| 91 | + ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val); | |
| 92 | + | |
| 93 | + return 0; | |
| 94 | +} | |
| 95 | + | |
| 96 | +static int cs35l56_dspwait_asp1tx_put(struct snd_kcontrol *kcontrol, | |
| 97 | + struct snd_ctl_elem_value *ucontrol) | |
| 98 | +{ | |
| 99 | + struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol); | |
| 100 | + struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); | |
| 101 | + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); | |
| 102 | + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | |
| 103 | + int item = ucontrol->value.enumerated.item[0]; | |
| 104 | + int index = e->shift_l; | |
| 105 | + unsigned int addr, val; | |
| 106 | + bool changed; | |
| 107 | + int ret; | |
| 108 | + | |
| 109 | + /* Wait for mux to be initialized */ | |
| 110 | + cs35l56_wait_dsp_ready(cs35l56); | |
| 111 | + flush_work(&cs35l56->mux_init_work); | |
| 112 | + | |
| 113 | + addr = cs35l56_asp1_mixer_regs[index]; | |
| 114 | + val = snd_soc_enum_item_to_val(e, item); | |
| 115 | + | |
| 116 | + ret = regmap_update_bits_check(cs35l56->base.regmap, addr, | |
| 117 | + CS35L56_ASP_TXn_SRC_MASK, val, &changed); | |
| 118 | + if (!ret) | |
| 119 | + return ret; | |
| 120 | + | |
| 121 | + if (changed) | |
| 122 | + snd_soc_dapm_mux_update_power(dapm, kcontrol, item, e, NULL); | |
| 123 | + | |
| 124 | + return changed; | |
| 125 | +} | |
| 126 | + | |
| 127 | +static void cs35l56_mark_asp1_mixer_widgets_dirty(struct cs35l56_private *cs35l56) | |
| 128 | +{ | |
| 129 | + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cs35l56->component); | |
| 130 | + const char *prefix = cs35l56->component->name_prefix; | |
| 131 | + char full_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | |
| 132 | + const char *name; | |
| 133 | + struct snd_kcontrol *kcontrol; | |
| 134 | + struct soc_enum *e; | |
| 135 | + unsigned int val[4]; | |
| 136 | + int i, item, ret; | |
| 137 | + | |
| 138 | + /* | |
| 139 | + * Resume so we can read the registers from silicon if the regmap | |
| 140 | + * cache has not yet been populated. | |
| 141 | + */ | |
| 142 | + ret = pm_runtime_resume_and_get(cs35l56->base.dev); | |
| 143 | + if (ret < 0) | |
| 144 | + return; | |
| 145 | + | |
| 146 | + ret = regmap_bulk_read(cs35l56->base.regmap, CS35L56_ASP1TX1_INPUT, | |
| 147 | + val, ARRAY_SIZE(val)); | |
| 148 | + | |
| 149 | + pm_runtime_mark_last_busy(cs35l56->base.dev); | |
| 150 | + pm_runtime_put_autosuspend(cs35l56->base.dev); | |
| 151 | + | |
| 152 | + if (ret) { | |
| 153 | + dev_err(cs35l56->base.dev, "Failed to read ASP1 mixer regs: %d\n", ret); | |
| 154 | + return; | |
| 155 | + } | |
| 156 | + | |
| 157 | + snd_soc_card_mutex_lock(dapm->card); | |
| 158 | + WARN_ON(!dapm->card->instantiated); | |
| 159 | + | |
| 160 | + for (i = 0; i < ARRAY_SIZE(cs35l56_asp1_mux_control_names); ++i) { | |
| 161 | + name = cs35l56_asp1_mux_control_names[i]; | |
| 162 | + | |
| 163 | + if (prefix) { | |
| 164 | + snprintf(full_name, sizeof(full_name), "%s %s", prefix, name); | |
| 165 | + name = full_name; | |
| 166 | + } | |
| 167 | + | |
| 168 | + kcontrol = snd_soc_card_get_kcontrol(dapm->card, name); | |
| 169 | + if (!kcontrol) { | |
| 170 | + dev_warn(cs35l56->base.dev, "Could not find control %s\n", name); | |
| 171 | + continue; | |
| 172 | + } | |
| 173 | + | |
| 174 | + e = (struct soc_enum *)kcontrol->private_value; | |
| 175 | + item = snd_soc_enum_val_to_item(e, val[i] & CS35L56_ASP_TXn_SRC_MASK); | |
| 176 | + snd_soc_dapm_mux_update_power(dapm, kcontrol, item, e, NULL); | |
| 177 | + } | |
| 178 | + | |
| 179 | + snd_soc_card_mutex_unlock(dapm->card); | |
| 180 | +} | |
| 181 | + | |
| 182 | +static void cs35l56_mux_init_work(struct work_struct *work) | |
| 183 | +{ | |
| 184 | + struct cs35l56_private *cs35l56 = container_of(work, | |
| 185 | + struct cs35l56_private, | |
| 186 | + mux_init_work); | |
| 187 | + | |
| 188 | + cs35l56_mark_asp1_mixer_widgets_dirty(cs35l56); | |
| 189 | +} | |
| 190 | + | |
| 62 | 191 | static DECLARE_TLV_DB_SCALE(vol_tlv, -10000, 25, 0); |
| 63 | 192 | |
| 64 | 193 | static const struct snd_kcontrol_new cs35l56_controls[] = { |
| @@ -77,40 +206,44 @@ static const struct snd_kcontrol_new cs35l56_controls[] = { · 12 unmodified lines | ||
| 77 | 206 | }; |
| 78 | 207 | |
| 79 | 208 | static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_asp1tx1_enum, |
| 80 | − CS35L56_ASP1TX1_INPUT, | |
| 81 | − 0, CS35L56_ASP_TXn_SRC_MASK, | |
| 209 | + SND_SOC_NOPM, | |
| 210 | + 0, 0, | |
| 82 | 211 | cs35l56_tx_input_texts, |
| 83 | 212 | cs35l56_tx_input_values); |
| 84 | 213 | |
| 85 | 214 | static const struct snd_kcontrol_new asp1_tx1_mux = |
| 86 | − SOC_DAPM_ENUM("ASP1TX1 SRC", cs35l56_asp1tx1_enum); | |
| 215 | + SOC_DAPM_ENUM_EXT("ASP1TX1 SRC", cs35l56_asp1tx1_enum, | |
| 216 | + cs35l56_dspwait_asp1tx_get, cs35l56_dspwait_asp1tx_put); | |
| 87 | 217 | |
| 88 | 218 | static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_asp1tx2_enum, |
| 89 | − CS35L56_ASP1TX2_INPUT, | |
| 90 | − 0, CS35L56_ASP_TXn_SRC_MASK, | |
| 219 | + SND_SOC_NOPM, | |
| 220 | + 1, 0, | |
| 91 | 221 | cs35l56_tx_input_texts, |
| 92 | 222 | cs35l56_tx_input_values); |
| 93 | 223 | |
| 94 | 224 | static const struct snd_kcontrol_new asp1_tx2_mux = |
| 95 | − SOC_DAPM_ENUM("ASP1TX2 SRC", cs35l56_asp1tx2_enum); | |
| 225 | + SOC_DAPM_ENUM_EXT("ASP1TX2 SRC", cs35l56_asp1tx2_enum, | |
| 226 | + cs35l56_dspwait_asp1tx_get, cs35l56_dspwait_asp1tx_put); | |
| 96 | 227 | |
| 97 | 228 | static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_asp1tx3_enum, |
| 98 | − CS35L56_ASP1TX3_INPUT, | |
| 99 | − 0, CS35L56_ASP_TXn_SRC_MASK, | |
| 229 | + SND_SOC_NOPM, | |
| 230 | + 2, 0, | |
| 100 | 231 | cs35l56_tx_input_texts, |
| 101 | 232 | cs35l56_tx_input_values); |
| 102 | 233 | |
| 103 | 234 | static const struct snd_kcontrol_new asp1_tx3_mux = |
| 104 | − SOC_DAPM_ENUM("ASP1TX3 SRC", cs35l56_asp1tx3_enum); | |
| 235 | + SOC_DAPM_ENUM_EXT("ASP1TX3 SRC", cs35l56_asp1tx3_enum, | |
| 236 | + cs35l56_dspwait_asp1tx_get, cs35l56_dspwait_asp1tx_put); | |
| 105 | 237 | |
| 106 | 238 | static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_asp1tx4_enum, |
| 107 | − CS35L56_ASP1TX4_INPUT, | |
| 108 | − 0, CS35L56_ASP_TXn_SRC_MASK, | |
| 239 | + SND_SOC_NOPM, | |
| 240 | + 3, 0, | |
| 109 | 241 | cs35l56_tx_input_texts, |
| 110 | 242 | cs35l56_tx_input_values); |
| 111 | 243 | |
| 112 | 244 | static const struct snd_kcontrol_new asp1_tx4_mux = |
| 113 | − SOC_DAPM_ENUM("ASP1TX4 SRC", cs35l56_asp1tx4_enum); | |
| 245 | + SOC_DAPM_ENUM_EXT("ASP1TX4 SRC", cs35l56_asp1tx4_enum, | |
| 246 | + cs35l56_dspwait_asp1tx_get, cs35l56_dspwait_asp1tx_put); | |
| 114 | 247 | |
| 115 | 248 | static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx1_enum, |
| 116 | 249 | CS35L56_SWIRE_DP3_CH1_INPUT, |
| @@ -148,6 +281,21 @@ static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx4_enum, · 31 unmodified lines | ||
| 148 | 281 | static const struct snd_kcontrol_new sdw1_tx4_mux = |
| 149 | 282 | SOC_DAPM_ENUM("SDW1TX4 SRC", cs35l56_sdw1tx4_enum); |
| 150 | 283 | |
| 284 | +static int cs35l56_asp1_cfg_event(struct snd_soc_dapm_widget *w, | |
| 285 | + struct snd_kcontrol *kcontrol, int event) | |
| 286 | +{ | |
| 287 | + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); | |
| 288 | + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); | |
| 289 | + | |
| 290 | + switch (event) { | |
| 291 | + case SND_SOC_DAPM_PRE_PMU: | |
| 292 | + /* Override register values set by firmware boot */ | |
| 293 | + return cs35l56_force_sync_asp1_registers_from_cache(&cs35l56->base); | |
| 294 | + default: | |
| 295 | + return 0; | |
| 296 | + } | |
| 297 | +} | |
| 298 | + | |
| 151 | 299 | static int cs35l56_play_event(struct snd_soc_dapm_widget *w, |
| 152 | 300 | struct snd_kcontrol *kcontrol, int event) |
| 153 | 301 | { |
| @@ -184,6 +332,9 @@ static const struct snd_soc_dapm_widget cs35l56_dapm_widgets[] = { · 30 unmodified lines | ||
| 184 | 332 | SND_SOC_DAPM_REGULATOR_SUPPLY("VDD_B", 0, 0), |
| 185 | 333 | SND_SOC_DAPM_REGULATOR_SUPPLY("VDD_AMP", 0, 0), |
| 186 | 334 | |
| 335 | + SND_SOC_DAPM_SUPPLY("ASP1 CFG", SND_SOC_NOPM, 0, 0, cs35l56_asp1_cfg_event, | |
| 336 | + SND_SOC_DAPM_PRE_PMU), | |
| 337 | + | |
| 187 | 338 | SND_SOC_DAPM_SUPPLY("PLAY", SND_SOC_NOPM, 0, 0, cs35l56_play_event, |
| 188 | 339 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), |
| 189 | 340 | |
| @@ -251,6 +402,9 @@ static const struct snd_soc_dapm_route cs35l56_audio_map[] = { · 61 unmodified lines | ||
| 251 | 402 | { "AMP", NULL, "VDD_B" }, |
| 252 | 403 | { "AMP", NULL, "VDD_AMP" }, |
| 253 | 404 | |
| 405 | + { "ASP1 Playback", NULL, "ASP1 CFG" }, | |
| 406 | + { "ASP1 Capture", NULL, "ASP1 CFG" }, | |
| 407 | + | |
| 254 | 408 | { "ASP1 Playback", NULL, "PLAY" }, |
| 255 | 409 | { "SDW1 Playback", NULL, "PLAY" }, |
| 256 | 410 | |
| @@ -650,7 +804,7 @@ static struct snd_soc_dai_driver cs35l56_dai[] = { · 393 unmodified lines | ||
| 650 | 804 | } |
| 651 | 805 | }; |
| 652 | 806 | |
| 653 | −static void cs35l56_secure_patch(struct cs35l56_private *cs35l56) | |
| 807 | +static void cs35l56_reinit_patch(struct cs35l56_private *cs35l56) | |
| 654 | 808 | { |
| 655 | 809 | int ret; |
| 656 | 810 | |
| @@ -662,19 +816,10 @@ static void cs35l56_secure_patch(struct cs35l56_private *cs35l56) · 5 unmodified lines | ||
| 662 | 816 | cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_REINIT); |
| 663 | 817 | } |
| 664 | 818 | |
| 665 | −static void cs35l56_patch(struct cs35l56_private *cs35l56) | |
| 819 | +static void cs35l56_patch(struct cs35l56_private *cs35l56, bool firmware_missing) | |
| 666 | 820 | { |
| 667 | − unsigned int firmware_missing; | |
| 668 | 821 | int ret; |
| 669 | 822 | |
| 670 | − ret = regmap_read(cs35l56->base.regmap, CS35L56_PROTECTION_STATUS, &firmware_missing); | |
| 671 | − if (ret) { | |
| 672 | − dev_err(cs35l56->base.dev, "Failed to read PROTECTION_STATUS: %d\n", ret); | |
| 673 | − return; | |
| 674 | − } | |
| 675 | − | |
| 676 | − firmware_missing &= CS35L56_FIRMWARE_MISSING; | |
| 677 | − | |
| 678 | 823 | /* |
| 679 | 824 | * Disable SoundWire interrupts to prevent race with IRQ work. |
| 680 | 825 | * Setting sdw_irq_no_unmask prevents the handler re-enabling |
| @@ -747,23 +892,59 @@ static void cs35l56_dsp_work(struct work_struct *work) · 66 unmodified lines | ||
| 747 | 892 | struct cs35l56_private *cs35l56 = container_of(work, |
| 748 | 893 | struct cs35l56_private, |
| 749 | 894 | dsp_work); |
| 895 | + unsigned int firmware_version; | |
| 896 | + bool firmware_missing; | |
| 897 | + int ret; | |
| 750 | 898 | |
| 751 | 899 | if (!cs35l56->base.init_done) |
| 752 | 900 | return; |
| 753 | 901 | |
| 754 | 902 | pm_runtime_get_sync(cs35l56->base.dev); |
| 755 | 903 | |
| 904 | + ret = cs35l56_read_prot_status(&cs35l56->base, &firmware_missing, &firmware_version); | |
| 905 | + if (ret) | |
| 906 | + goto err; | |
| 907 | + | |
| 908 | + /* Populate fw file qualifier with the revision and security state */ | |
| 909 | + kfree(cs35l56->dsp.fwf_name); | |
| 910 | + if (firmware_missing) { | |
| 911 | + cs35l56->dsp.fwf_name = kasprintf(GFP_KERNEL, "%02x-dsp1", cs35l56->base.rev); | |
| 912 | + } else { | |
| 913 | + /* Firmware files must match the running firmware version */ | |
| 914 | + cs35l56->dsp.fwf_name = kasprintf(GFP_KERNEL, | |
| 915 | + "%02x%s-%06x-dsp1", | |
| 916 | + cs35l56->base.rev, | |
| 917 | + cs35l56->base.secured ? "-s" : "", | |
| 918 | + firmware_version); | |
| 919 | + } | |
| 920 | + | |
| 921 | + if (!cs35l56->dsp.fwf_name) | |
| 922 | + goto err; | |
| 923 | + | |
| 924 | + dev_dbg(cs35l56->base.dev, "DSP fwf name: '%s' system name: '%s'\n", | |
| 925 | + cs35l56->dsp.fwf_name, cs35l56->dsp.system_name); | |
| 926 | + | |
| 756 | 927 | /* |
| 757 | − * When the device is running in secure mode the firmware files can | |
| 758 | − * only contain insecure tunings and therefore we do not need to | |
| 759 | − * shutdown the firmware to apply them and can use the lower cost | |
| 760 | − * reinit sequence instead. | |
| 928 | + * The firmware cannot be patched if it is already running from | |
| 929 | + * patch RAM. In this case the firmware files are versioned to | |
| 930 | + * match the running firmware version and will only contain | |
| 931 | + * tunings. We do not need to shutdown the firmware to apply | |
| 932 | + * tunings so can use the lower cost reinit sequence instead. | |
| 761 | 933 | */ |
| 762 | − if (cs35l56->base.secured) | |
| 763 | − cs35l56_secure_patch(cs35l56); | |
| 934 | + if (!firmware_missing) | |
| 935 | + cs35l56_reinit_patch(cs35l56); | |
| 764 | 936 | else |
| 765 | − cs35l56_patch(cs35l56); | |
| 937 | + cs35l56_patch(cs35l56, firmware_missing); | |
| 766 | 938 | |
| 939 | + | |
| 940 | + /* | |
| 941 | + * Set starting value of ASP1 mux widgets. Updating a mux takes | |
| 942 | + * the DAPM mutex. Post this to a separate job so that DAPM | |
| 943 | + * power-up can wait for dsp_work to complete without deadlocking | |
| 944 | + * on the DAPM mutex. | |
| 945 | + */ | |
| 946 | + queue_work(cs35l56->dsp_wq, &cs35l56->mux_init_work); | |
| 947 | +err: | |
| 767 | 948 | pm_runtime_mark_last_busy(cs35l56->base.dev); |
| 768 | 949 | pm_runtime_put_autosuspend(cs35l56->base.dev); |
| 769 | 950 | } |
| @@ -778,10 +959,19 @@ static int cs35l56_component_probe(struct snd_soc_component *component) · 8 unmodified lines | ||
| 778 | 959 | |
| 779 | 960 | if (!cs35l56->dsp.system_name && |
| 780 | 961 | (snd_soc_card_get_pci_ssid(component->card, &vendor, &device) == 0)) { |
| 781 | − cs35l56->dsp.system_name = devm_kasprintf(cs35l56->base.dev, | |
| 782 | − GFP_KERNEL, | |
| 783 | − "%04x%04x", | |
| 784 | − vendor, device); | |
| 962 | + /* Append a speaker qualifier if there is a speaker ID */ | |
| 963 | + if (cs35l56->speaker_id >= 0) { | |
| 964 | + cs35l56->dsp.system_name = devm_kasprintf(cs35l56->base.dev, | |
| 965 | + GFP_KERNEL, | |
| 966 | + "%04x%04x-spkid%d", | |
| 967 | + vendor, device, | |
| 968 | + cs35l56->speaker_id); | |
| 969 | + } else { | |
| 970 | + cs35l56->dsp.system_name = devm_kasprintf(cs35l56->base.dev, | |
| 971 | + GFP_KERNEL, | |
| 972 | + "%04x%04x", | |
| 973 | + vendor, device); | |
| 974 | + } | |
| 785 | 975 | if (!cs35l56->dsp.system_name) |
| 786 | 976 | return -ENOMEM; |
| 787 | 977 | } |
| @@ -809,6 +999,17 @@ static void cs35l56_component_remove(struct snd_soc_component *component) · 21 unmodified lines | ||
| 809 | 999 | struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); |
| 810 | 1000 | |
| 811 | 1001 | cancel_work_sync(&cs35l56->dsp_work); |
| 1002 | + cancel_work_sync(&cs35l56->mux_init_work); | |
| 1003 | + | |
| 1004 | + if (cs35l56->dsp.cs_dsp.booted) | |
| 1005 | + wm_adsp_power_down(&cs35l56->dsp); | |
| 1006 | + | |
| 1007 | + wm_adsp2_component_remove(&cs35l56->dsp, component); | |
| 1008 | + | |
| 1009 | + kfree(cs35l56->dsp.fwf_name); | |
| 1010 | + cs35l56->dsp.fwf_name = NULL; | |
| 1011 | + | |
| 1012 | + cs35l56->component = NULL; | |
| 812 | 1013 | } |
| 813 | 1014 | |
| 814 | 1015 | static int cs35l56_set_bias_level(struct snd_soc_component *component, |
| @@ -869,8 +1070,10 @@ int cs35l56_system_suspend(struct device *dev) · 54 unmodified lines | ||
| 869 | 1070 | |
| 870 | 1071 | dev_dbg(dev, "system_suspend\n"); |
| 871 | 1072 | |
| 872 | − if (cs35l56->component) | |
| 1073 | + if (cs35l56->component) { | |
| 873 | 1074 | flush_work(&cs35l56->dsp_work); |
| 1075 | + cancel_work_sync(&cs35l56->mux_init_work); | |
| 1076 | + } | |
| 874 | 1077 | |
| 875 | 1078 | /* |
| 876 | 1079 | * The interrupt line is normally shared, but after we start suspending |
| @@ -1021,6 +1224,7 @@ static int cs35l56_dsp_init(struct cs35l56_private *cs35l56) · 144 unmodified lines | ||
| 1021 | 1224 | return -ENOMEM; |
| 1022 | 1225 | |
| 1023 | 1226 | INIT_WORK(&cs35l56->dsp_work, cs35l56_dsp_work); |
| 1227 | + INIT_WORK(&cs35l56->mux_init_work, cs35l56_mux_init_work); | |
| 1024 | 1228 | |
| 1025 | 1229 | dsp = &cs35l56->dsp; |
| 1026 | 1230 | cs35l56_init_cs_dsp(&cs35l56->base, &dsp->cs_dsp); |
| @@ -1050,7 +1254,13 @@ static int cs35l56_get_firmware_uid(struct cs35l56_private *cs35l56) · 23 unmodified lines | ||
| 1050 | 1254 | if (ret < 0) |
| 1051 | 1255 | return 0; |
| 1052 | 1256 | |
| 1053 | − cs35l56->dsp.system_name = devm_kstrdup(dev, prop, GFP_KERNEL); | |
| 1257 | + /* Append a speaker qualifier if there is a speaker ID */ | |
| 1258 | + if (cs35l56->speaker_id >= 0) | |
| 1259 | + cs35l56->dsp.system_name = devm_kasprintf(dev, GFP_KERNEL, "%s-spkid%d", | |
| 1260 | + prop, cs35l56->speaker_id); | |
| 1261 | + else | |
| 1262 | + cs35l56->dsp.system_name = devm_kstrdup(dev, prop, GFP_KERNEL); | |
| 1263 | + | |
| 1054 | 1264 | if (cs35l56->dsp.system_name == NULL) |
| 1055 | 1265 | return -ENOMEM; |
| 1056 | 1266 | |
| @@ -1065,6 +1275,7 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) · 8 unmodified lines | ||
| 1065 | 1275 | |
| 1066 | 1276 | init_completion(&cs35l56->init_completion); |
| 1067 | 1277 | mutex_init(&cs35l56->base.irq_lock); |
| 1278 | + cs35l56->speaker_id = -ENOENT; | |
| 1068 | 1279 | |
| 1069 | 1280 | dev_set_drvdata(cs35l56->base.dev, cs35l56); |
| 1070 | 1281 | |
| @@ -1101,6 +1312,12 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) · 30 unmodified lines | ||
| 1101 | 1312 | gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 1); |
| 1102 | 1313 | } |
| 1103 | 1314 | |
| 1315 | + ret = cs35l56_get_speaker_id(&cs35l56->base); | |
| 1316 | + if ((ret < 0) && (ret != -ENOENT)) | |
| 1317 | + goto err; | |
| 1318 | + | |
| 1319 | + cs35l56->speaker_id = ret; | |
| 1320 | + | |
| 1104 | 1321 | ret = cs35l56_get_firmware_uid(cs35l56); |
| 1105 | 1322 | if (ret != 0) |
| 1106 | 1323 | goto err; |
| @@ -1152,11 +1369,9 @@ int cs35l56_init(struct cs35l56_private *cs35l56) · 45 unmodified lines | ||
| 1152 | 1369 | if (ret < 0) |
| 1153 | 1370 | return ret; |
| 1154 | 1371 | |
| 1155 | − /* Populate the DSP information with the revision and security state */ | |
| 1156 | − cs35l56->dsp.part = devm_kasprintf(cs35l56->base.dev, GFP_KERNEL, "cs35l56%s-%02x", | |
| 1157 | − cs35l56->base.secured ? "s" : "", cs35l56->base.rev); | |
| 1158 | − if (!cs35l56->dsp.part) | |
| 1159 | − return -ENOMEM; | |
| 1372 | + ret = cs35l56_set_patch(&cs35l56->base); | |
| 1373 | + if (ret) | |
| 1374 | + return ret; | |
| 1160 | 1375 | |
| 1161 | 1376 | if (!cs35l56->base.reset_gpio) { |
| 1162 | 1377 | dev_dbg(cs35l56->base.dev, "No reset gpio: using soft reset\n"); |
| @@ -1190,10 +1405,6 @@ post_soft_reset: · 27 unmodified lines | ||
| 1190 | 1405 | if (ret) |
| 1191 | 1406 | return ret; |
| 1192 | 1407 | |
| 1193 | − ret = cs35l56_set_patch(&cs35l56->base); | |
| 1194 | − if (ret) | |
| 1195 | − return ret; | |
| 1196 | − | |
| 1197 | 1408 | /* Registers could be dirty after soft reset or SoundWire enumeration */ |
| 1198 | 1409 | regcache_sync(cs35l56->base.regmap); |
| 1199 | 1410 | |
| @@ -34,6 +34,7 @@ struct cs35l56_private { · 33 unmodified lines | ||
| 34 | 34 | struct wm_adsp dsp; /* must be first member */ |
| 35 | 35 | struct cs35l56_base base; |
| 36 | 36 | struct work_struct dsp_work; |
| 37 | + struct work_struct mux_init_work; | |
| 37 | 38 | struct workqueue_struct *dsp_wq; |
| 38 | 39 | struct snd_soc_component *component; |
| 39 | 40 | struct regulator_bulk_data supplies[CS35L56_NUM_BULK_SUPPLIES]; |
| @@ -44,6 +45,7 @@ struct cs35l56_private { · 4 unmodified lines | ||
| 44 | 45 | bool sdw_attached; |
| 45 | 46 | struct completion init_completion; |
| 46 | 47 | |
| 48 | + int speaker_id; | |
| 47 | 49 | u32 rx_mask; |
| 48 | 50 | u32 tx_mask; |
| 49 | 51 | u8 asp_slot_width; |
| @@ -45,6 +45,82 @@ struct es8326_priv { · 44 unmodified lines | ||
| 45 | 45 | int jack_remove_retry; |
| 46 | 46 | }; |
| 47 | 47 | |
| 48 | +static int es8326_crosstalk1_get(struct snd_kcontrol *kcontrol, | |
| 49 | + struct snd_ctl_elem_value *ucontrol) | |
| 50 | +{ | |
| 51 | + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | |
| 52 | + struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); | |
| 53 | + unsigned int crosstalk_h, crosstalk_l; | |
| 54 | + unsigned int crosstalk; | |
| 55 | + | |
| 56 | + regmap_read(es8326->regmap, ES8326_DAC_RAMPRATE, &crosstalk_h); | |
| 57 | + regmap_read(es8326->regmap, ES8326_DAC_CROSSTALK, &crosstalk_l); | |
| 58 | + crosstalk_h &= 0x20; | |
| 59 | + crosstalk_l &= 0xf0; | |
| 60 | + crosstalk = crosstalk_h >> 1 | crosstalk_l >> 4; | |
| 61 | + ucontrol->value.integer.value[0] = crosstalk; | |
| 62 | + | |
| 63 | + return 0; | |
| 64 | +} | |
| 65 | + | |
| 66 | +static int es8326_crosstalk1_set(struct snd_kcontrol *kcontrol, | |
| 67 | + struct snd_ctl_elem_value *ucontrol) | |
| 68 | +{ | |
| 69 | + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | |
| 70 | + struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); | |
| 71 | + unsigned int crosstalk_h, crosstalk_l; | |
| 72 | + unsigned int crosstalk; | |
| 73 | + | |
| 74 | + crosstalk = ucontrol->value.integer.value[0]; | |
| 75 | + regmap_read(es8326->regmap, ES8326_DAC_CROSSTALK, &crosstalk_l); | |
| 76 | + crosstalk_h = (crosstalk & 0x10) << 1; | |
| 77 | + crosstalk_l &= 0x0f; | |
| 78 | + crosstalk_l |= (crosstalk & 0x0f) << 4; | |
| 79 | + regmap_update_bits(es8326->regmap, ES8326_DAC_RAMPRATE, | |
| 80 | + 0x20, crosstalk_h); | |
| 81 | + regmap_write(es8326->regmap, ES8326_DAC_CROSSTALK, crosstalk_l); | |
| 82 | + | |
| 83 | + return 0; | |
| 84 | +} | |
| 85 | + | |
| 86 | +static int es8326_crosstalk2_get(struct snd_kcontrol *kcontrol, | |
| 87 | + struct snd_ctl_elem_value *ucontrol) | |
| 88 | +{ | |
| 89 | + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | |
| 90 | + struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); | |
| 91 | + unsigned int crosstalk_h, crosstalk_l; | |
| 92 | + unsigned int crosstalk; | |
| 93 | + | |
| 94 | + regmap_read(es8326->regmap, ES8326_DAC_RAMPRATE, &crosstalk_h); | |
| 95 | + regmap_read(es8326->regmap, ES8326_DAC_CROSSTALK, &crosstalk_l); | |
| 96 | + crosstalk_h &= 0x10; | |
| 97 | + crosstalk_l &= 0x0f; | |
| 98 | + crosstalk = crosstalk_h | crosstalk_l; | |
| 99 | + ucontrol->value.integer.value[0] = crosstalk; | |
| 100 | + | |
| 101 | + return 0; | |
| 102 | +} | |
| 103 | + | |
| 104 | +static int es8326_crosstalk2_set(struct snd_kcontrol *kcontrol, | |
| 105 | + struct snd_ctl_elem_value *ucontrol) | |
| 106 | +{ | |
| 107 | + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | |
| 108 | + struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); | |
| 109 | + unsigned int crosstalk_h, crosstalk_l; | |
| 110 | + unsigned int crosstalk; | |
| 111 | + | |
| 112 | + crosstalk = ucontrol->value.integer.value[0]; | |
| 113 | + regmap_read(es8326->regmap, ES8326_DAC_CROSSTALK, &crosstalk_l); | |
| 114 | + crosstalk_h = crosstalk & 0x10; | |
| 115 | + crosstalk_l &= 0xf0; | |
| 116 | + crosstalk_l |= crosstalk & 0x0f; | |
| 117 | + regmap_update_bits(es8326->regmap, ES8326_DAC_RAMPRATE, | |
| 118 | + 0x10, crosstalk_h); | |
| 119 | + regmap_write(es8326->regmap, ES8326_DAC_CROSSTALK, crosstalk_l); | |
| 120 | + | |
| 121 | + return 0; | |
| 122 | +} | |
| 123 | + | |
| 48 | 124 | static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(dac_vol_tlv, -9550, 50, 0); |
| 49 | 125 | static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(adc_vol_tlv, -9550, 50, 0); |
| 50 | 126 | static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(adc_analog_pga_tlv, 0, 300, 0); |
| @@ -102,6 +178,10 @@ static const struct snd_kcontrol_new es8326_snd_controls[] = { · 51 unmodified lines | ||
| 102 | 178 | SOC_SINGLE_TLV("ALC Capture Target Level", ES8326_ALC_LEVEL, |
| 103 | 179 | 0, 0x0f, 0, drc_target_tlv), |
| 104 | 180 | |
| 181 | + SOC_SINGLE_EXT("CROSSTALK1", SND_SOC_NOPM, 0, 31, 0, | |
| 182 | + es8326_crosstalk1_get, es8326_crosstalk1_set), | |
| 183 | + SOC_SINGLE_EXT("CROSSTALK2", SND_SOC_NOPM, 0, 31, 0, | |
| 184 | + es8326_crosstalk2_get, es8326_crosstalk2_set), | |
| 105 | 185 | }; |
| 106 | 186 | |
| 107 | 187 | static const struct snd_soc_dapm_widget es8326_dapm_widgets[] = { |
| @@ -117,12 +197,6 @@ static const struct snd_soc_dapm_widget es8326_dapm_widgets[] = { · 9 unmodified lines | ||
| 117 | 197 | SND_SOC_DAPM_AIF_OUT("I2S OUT", "I2S1 Capture", 0, SND_SOC_NOPM, 0, 0), |
| 118 | 198 | SND_SOC_DAPM_AIF_IN("I2S IN", "I2S1 Playback", 0, SND_SOC_NOPM, 0, 0), |
| 119 | 199 | |
| 120 | − /* ADC Digital Mute */ | |
| 121 | − SND_SOC_DAPM_PGA("ADC L1", ES8326_ADC_MUTE, 0, 1, NULL, 0), | |
| 122 | − SND_SOC_DAPM_PGA("ADC R1", ES8326_ADC_MUTE, 1, 1, NULL, 0), | |
| 123 | − SND_SOC_DAPM_PGA("ADC L2", ES8326_ADC_MUTE, 2, 1, NULL, 0), | |
| 124 | − SND_SOC_DAPM_PGA("ADC R2", ES8326_ADC_MUTE, 3, 1, NULL, 0), | |
| 125 | − | |
| 126 | 200 | /* Analog Power Supply*/ |
| 127 | 201 | SND_SOC_DAPM_DAC("Right DAC", NULL, ES8326_ANA_PDN, 0, 1), |
| 128 | 202 | SND_SOC_DAPM_DAC("Left DAC", NULL, ES8326_ANA_PDN, 1, 1), |
| @@ -142,15 +216,10 @@ static const struct snd_soc_dapm_widget es8326_dapm_widgets[] = { · 13 unmodified lines | ||
| 142 | 216 | }; |
| 143 | 217 | |
| 144 | 218 | static const struct snd_soc_dapm_route es8326_dapm_routes[] = { |
| 145 | − {"ADC L1", NULL, "MIC1"}, | |
| 146 | − {"ADC R1", NULL, "MIC2"}, | |
| 147 | − {"ADC L2", NULL, "MIC3"}, | |
| 148 | − {"ADC R2", NULL, "MIC4"}, | |
| 149 | − | |
| 150 | − {"ADC L", NULL, "ADC L1"}, | |
| 151 | − {"ADC R", NULL, "ADC R1"}, | |
| 152 | − {"ADC L", NULL, "ADC L2"}, | |
| 153 | − {"ADC R", NULL, "ADC R2"}, | |
| 219 | + {"ADC L", NULL, "MIC1"}, | |
| 220 | + {"ADC R", NULL, "MIC2"}, | |
| 221 | + {"ADC L", NULL, "MIC3"}, | |
| 222 | + {"ADC R", NULL, "MIC4"}, | |
| 154 | 223 | |
| 155 | 224 | {"I2S OUT", NULL, "ADC L"}, |
| 156 | 225 | {"I2S OUT", NULL, "ADC R"}, |
| @@ -440,10 +509,16 @@ static int es8326_mute(struct snd_soc_dai *dai, int mute, int direction) · 283 unmodified lines | ||
| 440 | 509 | unsigned int offset_l, offset_r; |
| 441 | 510 | |
| 442 | 511 | if (mute) { |
| 443 | − regmap_write(es8326->regmap, ES8326_HP_CAL, ES8326_HP_OFF); | |
| 444 | − regmap_update_bits(es8326->regmap, ES8326_DAC_MUTE, | |
| 445 | − ES8326_MUTE_MASK, ES8326_MUTE); | |
| 446 | − regmap_write(es8326->regmap, ES8326_HP_DRIVER, 0xf0); | |
| 512 | + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { | |
| 513 | + regmap_write(es8326->regmap, ES8326_HP_CAL, ES8326_HP_OFF); | |
| 514 | + regmap_update_bits(es8326->regmap, ES8326_DAC_MUTE, | |
| 515 | + ES8326_MUTE_MASK, ES8326_MUTE); | |
| 516 | + regmap_update_bits(es8326->regmap, ES8326_HP_DRIVER_REF, | |
| 517 | + 0x30, 0x00); | |
| 518 | + } else { | |
| 519 | + regmap_update_bits(es8326->regmap, ES8326_ADC_MUTE, | |
| 520 | + 0x0F, 0x0F); | |
| 521 | + } | |
| 447 | 522 | } else { |
| 448 | 523 | if (!es8326->calibrated) { |
| 449 | 524 | regmap_write(es8326->regmap, ES8326_HP_CAL, ES8326_HP_FORCE_CAL); |
| @@ -456,11 +531,22 @@ static int es8326_mute(struct snd_soc_dai *dai, int mute, int direction) · 6 unmodified lines | ||
| 456 | 531 | regmap_write(es8326->regmap, ES8326_HPR_OFFSET_INI, offset_r); |
| 457 | 532 | es8326->calibrated = true; |
| 458 | 533 | } |
| 459 | − regmap_write(es8326->regmap, ES8326_HP_DRIVER, 0xa1); | |
| 460 | − regmap_write(es8326->regmap, ES8326_HP_VOL, 0x91); | |
| 461 | − regmap_write(es8326->regmap, ES8326_HP_CAL, ES8326_HP_ON); | |
| 462 | − regmap_update_bits(es8326->regmap, ES8326_DAC_MUTE, | |
| 463 | − ES8326_MUTE_MASK, ~(ES8326_MUTE)); | |
| 534 | + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { | |
| 535 | + regmap_update_bits(es8326->regmap, ES8326_DAC_DSM, 0x01, 0x01); | |
| 536 | + usleep_range(1000, 5000); | |
| 537 | + regmap_update_bits(es8326->regmap, ES8326_DAC_DSM, 0x01, 0x00); | |
| 538 | + usleep_range(1000, 5000); | |
| 539 | + regmap_update_bits(es8326->regmap, ES8326_HP_DRIVER_REF, 0x30, 0x20); | |
| 540 | + regmap_update_bits(es8326->regmap, ES8326_HP_DRIVER_REF, 0x30, 0x30); | |
| 541 | + regmap_write(es8326->regmap, ES8326_HP_DRIVER, 0xa1); | |
| 542 | + regmap_write(es8326->regmap, ES8326_HP_CAL, ES8326_HP_ON); | |
| 543 | + regmap_update_bits(es8326->regmap, ES8326_DAC_MUTE, | |
| 544 | + ES8326_MUTE_MASK, ~(ES8326_MUTE)); | |
| 545 | + } else { | |
| 546 | + msleep(300); | |
| 547 | + regmap_update_bits(es8326->regmap, ES8326_ADC_MUTE, | |
| 548 | + 0x0F, 0x00); | |
| 549 | + } | |
| 464 | 550 | } |
| 465 | 551 | return 0; |
| 466 | 552 | } |
| @@ -477,23 +563,20 @@ static int es8326_set_bias_level(struct snd_soc_component *codec, · 10 unmodified lines | ||
| 477 | 563 | if (ret) |
| 478 | 564 | return ret; |
| 479 | 565 | |
| 480 | − regmap_update_bits(es8326->regmap, ES8326_DAC_DSM, 0x01, 0x00); | |
| 566 | + regmap_update_bits(es8326->regmap, ES8326_RESET, 0x02, 0x02); | |
| 567 | + usleep_range(5000, 10000); | |
| 481 | 568 | regmap_write(es8326->regmap, ES8326_INTOUT_IO, es8326->interrupt_clk); |
| 482 | 569 | regmap_write(es8326->regmap, ES8326_SDINOUT1_IO, |
| 483 | 570 | (ES8326_IO_DMIC_CLK << ES8326_SDINOUT1_SHIFT)); |
| 484 | − regmap_write(es8326->regmap, ES8326_VMIDSEL, 0x0E); | |
| 485 | 571 | regmap_write(es8326->regmap, ES8326_PGA_PDN, 0x40); |
| 486 | 572 | regmap_write(es8326->regmap, ES8326_ANA_PDN, 0x00); |
| 487 | 573 | regmap_update_bits(es8326->regmap, ES8326_CLK_CTL, 0x20, 0x20); |
| 488 | − | |
| 489 | − regmap_update_bits(es8326->regmap, ES8326_RESET, | |
| 490 | − ES8326_CSM_ON, ES8326_CSM_ON); | |
| 574 | + regmap_update_bits(es8326->regmap, ES8326_RESET, 0x02, 0x00); | |
| 491 | 575 | break; |
| 492 | 576 | case SND_SOC_BIAS_PREPARE: |
| 493 | 577 | break; |
| 494 | 578 | case SND_SOC_BIAS_STANDBY: |
| 495 | 579 | regmap_write(es8326->regmap, ES8326_ANA_PDN, 0x3b); |
| 496 | − regmap_write(es8326->regmap, ES8326_VMIDSEL, 0x00); | |
| 497 | 580 | regmap_update_bits(es8326->regmap, ES8326_CLK_CTL, 0x20, 0x00); |
| 498 | 581 | regmap_write(es8326->regmap, ES8326_SDINOUT1_IO, ES8326_IO_INPUT); |
| 499 | 582 | break; |
| @@ -513,7 +596,7 @@ static const struct snd_soc_dai_ops es8326_ops = { · 13 unmodified lines | ||
| 513 | 596 | .set_fmt = es8326_set_dai_fmt, |
| 514 | 597 | .set_sysclk = es8326_set_dai_sysclk, |
| 515 | 598 | .mute_stream = es8326_mute, |
| 516 | − .no_capture_mute = 1, | |
| 599 | + .no_capture_mute = 0, | |
| 517 | 600 | }; |
| 518 | 601 | |
| 519 | 602 | static struct snd_soc_dai_driver es8326_dai = { |
| @@ -672,6 +755,8 @@ static void es8326_jack_detect_handler(struct work_struct *work) · 152 unmodified lines | ||
| 672 | 755 | es8326->hp = 0; |
| 673 | 756 | } |
| 674 | 757 | regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x01); |
| 758 | + regmap_write(es8326->regmap, ES8326_SYS_BIAS, 0x0a); | |
| 759 | + regmap_update_bits(es8326->regmap, ES8326_HP_DRIVER_REF, 0x0f, 0x03); | |
| 675 | 760 | /* |
| 676 | 761 | * Inverted HPJACK_POL bit to trigger one IRQ to double check HP Removal event |
| 677 | 762 | */ |
| @@ -695,8 +780,11 @@ static void es8326_jack_detect_handler(struct work_struct *work) · 17 unmodified lines | ||
| 695 | 780 | * Don't report jack status. |
| 696 | 781 | */ |
| 697 | 782 | regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x01); |
| 783 | + es8326_enable_micbias(es8326->component); | |
| 698 | 784 | usleep_range(50000, 70000); |
| 699 | 785 | regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x00); |
| 786 | + regmap_write(es8326->regmap, ES8326_SYS_BIAS, 0x1f); | |
| 787 | + regmap_update_bits(es8326->regmap, ES8326_HP_DRIVER_REF, 0x0f, 0x08); | |
| 700 | 788 | queue_delayed_work(system_wq, &es8326->jack_detect_work, |
| 701 | 789 | msecs_to_jiffies(400)); |
| 702 | 790 | es8326->hp = 1; |
| @@ -736,13 +824,10 @@ exit: · 33 unmodified lines | ||
| 736 | 824 | static irqreturn_t es8326_irq(int irq, void *dev_id) |
| 737 | 825 | { |
| 738 | 826 | struct es8326_priv *es8326 = dev_id; |
| 739 | − struct snd_soc_component *comp = es8326->component; | |
| 740 | 827 | |
| 741 | 828 | if (!es8326->jack) |
| 742 | 829 | goto out; |
| 743 | 830 | |
| 744 | − es8326_enable_micbias(comp); | |
| 745 | − | |
| 746 | 831 | if (es8326->jack->status & SND_JACK_HEADSET) |
| 747 | 832 | queue_delayed_work(system_wq, &es8326->jack_detect_work, |
| 748 | 833 | msecs_to_jiffies(10)); |
| @@ -766,14 +851,14 @@ static int es8326_calibrate(struct snd_soc_component *component) · 17 unmodified lines | ||
| 766 | 851 | if ((es8326->version == ES8326_VERSION_B) && (es8326->calibrated == false)) { |
| 767 | 852 | dev_dbg(component->dev, "ES8326_VERSION_B, calibrating\n"); |
| 768 | 853 | regmap_write(es8326->regmap, ES8326_CLK_INV, 0xc0); |
| 769 | − regmap_write(es8326->regmap, ES8326_CLK_DIV1, 0x01); | |
| 854 | + regmap_write(es8326->regmap, ES8326_CLK_DIV1, 0x03); | |
| 770 | 855 | regmap_write(es8326->regmap, ES8326_CLK_DLL, 0x30); |
| 771 | 856 | regmap_write(es8326->regmap, ES8326_CLK_MUX, 0xed); |
| 772 | 857 | regmap_write(es8326->regmap, ES8326_CLK_DAC_SEL, 0x08); |
| 773 | 858 | regmap_write(es8326->regmap, ES8326_CLK_TRI, 0xc1); |
| 774 | 859 | regmap_write(es8326->regmap, ES8326_DAC_MUTE, 0x03); |
| 775 | 860 | regmap_write(es8326->regmap, ES8326_ANA_VSEL, 0x7f); |
| 776 | − regmap_write(es8326->regmap, ES8326_VMIDLOW, 0x03); | |
| 861 | + regmap_write(es8326->regmap, ES8326_VMIDLOW, 0x23); | |
| 777 | 862 | regmap_write(es8326->regmap, ES8326_DAC2HPMIX, 0x88); |
| 778 | 863 | usleep_range(15000, 20000); |
| 779 | 864 | regmap_write(es8326->regmap, ES8326_HP_OFFSET_CAL, 0x8c); |
| @@ -814,13 +899,13 @@ static int es8326_resume(struct snd_soc_component *component) · 34 unmodified lines | ||
| 814 | 899 | /* reset internal clock state */ |
| 815 | 900 | regmap_write(es8326->regmap, ES8326_RESET, 0x1f); |
| 816 | 901 | regmap_write(es8326->regmap, ES8326_VMIDSEL, 0x0E); |
| 902 | + regmap_write(es8326->regmap, ES8326_ANA_LP, 0xf0); | |
| 817 | 903 | usleep_range(10000, 15000); |
| 818 | 904 | regmap_write(es8326->regmap, ES8326_HPJACK_TIMER, 0xe9); |
| 819 | − regmap_write(es8326->regmap, ES8326_ANA_MICBIAS, 0x4b); | |
| 905 | + regmap_write(es8326->regmap, ES8326_ANA_MICBIAS, 0xcb); | |
| 820 | 906 | /* set headphone default type and detect pin */ |
| 821 | 907 | regmap_write(es8326->regmap, ES8326_HPDET_TYPE, 0x83); |
| 822 | 908 | regmap_write(es8326->regmap, ES8326_CLK_RESAMPLE, 0x05); |
| 823 | − regmap_write(es8326->regmap, ES8326_HP_MISC, 0x30); | |
| 824 | 909 | |
| 825 | 910 | /* set internal oscillator as clock source of headpone cp */ |
| 826 | 911 | regmap_write(es8326->regmap, ES8326_CLK_DIV_CPC, 0x89); |
| @@ -828,14 +913,15 @@ static int es8326_resume(struct snd_soc_component *component) · 1 unmodified line | ||
| 828 | 913 | /* clock manager reset release */ |
| 829 | 914 | regmap_write(es8326->regmap, ES8326_RESET, 0x17); |
| 830 | 915 | /* set headphone detection as half scan mode */ |
| 831 | − regmap_write(es8326->regmap, ES8326_HP_MISC, 0x30); | |
| 916 | + regmap_write(es8326->regmap, ES8326_HP_MISC, 0x3d); | |
| 832 | 917 | regmap_write(es8326->regmap, ES8326_PULLUP_CTL, 0x00); |
| 833 | 918 | |
| 834 | 919 | /* enable headphone driver */ |
| 920 | + regmap_write(es8326->regmap, ES8326_HP_VOL, 0xc4); | |
| 835 | 921 | regmap_write(es8326->regmap, ES8326_HP_DRIVER, 0xa7); |
| 836 | 922 | usleep_range(2000, 5000); |
| 837 | − regmap_write(es8326->regmap, ES8326_HP_DRIVER_REF, 0xa3); | |
| 838 | − regmap_write(es8326->regmap, ES8326_HP_DRIVER_REF, 0xb3); | |
| 923 | + regmap_write(es8326->regmap, ES8326_HP_DRIVER_REF, 0x23); | |
| 924 | + regmap_write(es8326->regmap, ES8326_HP_DRIVER_REF, 0x33); | |
| 839 | 925 | regmap_write(es8326->regmap, ES8326_HP_DRIVER, 0xa1); |
| 840 | 926 | |
| 841 | 927 | regmap_write(es8326->regmap, ES8326_CLK_INV, 0x00); |
| @@ -844,6 +930,8 @@ static int es8326_resume(struct snd_soc_component *component) · 2 unmodified lines | ||
| 844 | 930 | regmap_write(es8326->regmap, ES8326_CLK_CAL_TIME, 0x00); |
| 845 | 931 | /* calibrate for B version */ |
| 846 | 932 | es8326_calibrate(component); |
| 933 | + regmap_write(es8326->regmap, ES8326_DAC_CROSSTALK, 0xaa); | |
| 934 | + regmap_write(es8326->regmap, ES8326_DAC_RAMPRATE, 0x00); | |
| 847 | 935 | /* turn off headphone out */ |
| 848 | 936 | regmap_write(es8326->regmap, ES8326_HP_CAL, 0x00); |
| 849 | 937 | /* set ADC and DAC in low power mode */ |
| @@ -856,6 +944,14 @@ static int es8326_resume(struct snd_soc_component *component) · 6 unmodified lines | ||
| 856 | 944 | regmap_write(es8326->regmap, ES8326_DAC_DSM, 0x08); |
| 857 | 945 | regmap_write(es8326->regmap, ES8326_DAC_VPPSCALE, 0x15); |
| 858 | 946 | |
| 947 | + regmap_write(es8326->regmap, ES8326_HPDET_TYPE, 0x80 | | |
| 948 | + ((es8326->version == ES8326_VERSION_B) ? | |
| 949 | + (ES8326_HP_DET_SRC_PIN9 | es8326->jack_pol) : | |
| 950 | + (ES8326_HP_DET_SRC_PIN9 | es8326->jack_pol | 0x04))); | |
| 951 | + usleep_range(5000, 10000); | |
| 952 | + es8326_enable_micbias(es8326->component); | |
| 953 | + usleep_range(50000, 70000); | |
| 954 | + regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x00); | |
| 859 | 955 | regmap_write(es8326->regmap, ES8326_INT_SOURCE, |
| 860 | 956 | (ES8326_INT_SRC_PIN9 | ES8326_INT_SRC_BUTTON)); |
| 861 | 957 | regmap_write(es8326->regmap, ES8326_INTOUT_IO, |
| @@ -864,7 +960,7 @@ static int es8326_resume(struct snd_soc_component *component) · 2 unmodified lines | ||
| 864 | 960 | (ES8326_IO_DMIC_CLK << ES8326_SDINOUT1_SHIFT)); |
| 865 | 961 | regmap_write(es8326->regmap, ES8326_SDINOUT23_IO, ES8326_IO_INPUT); |
| 866 | 962 | |
| 867 | − regmap_write(es8326->regmap, ES8326_ANA_PDN, 0x3b); | |
| 963 | + regmap_write(es8326->regmap, ES8326_ANA_PDN, 0x00); | |
| 868 | 964 | regmap_write(es8326->regmap, ES8326_RESET, ES8326_CSM_ON); |
| 869 | 965 | regmap_update_bits(es8326->regmap, ES8326_PGAGAIN, ES8326_MIC_SEL_MASK, |
| 870 | 966 | ES8326_MIC1_SEL); |
| @@ -872,11 +968,7 @@ static int es8326_resume(struct snd_soc_component *component) · 1 unmodified line | ||
| 872 | 968 | regmap_update_bits(es8326->regmap, ES8326_DAC_MUTE, ES8326_MUTE_MASK, |
| 873 | 969 | ES8326_MUTE); |
| 874 | 970 | |
| 875 | − regmap_write(es8326->regmap, ES8326_HPDET_TYPE, 0x80 | | |
| 876 | − ((es8326->version == ES8326_VERSION_B) ? | |
| 877 | − (ES8326_HP_DET_SRC_PIN9 | es8326->jack_pol) : | |
| 878 | − (ES8326_HP_DET_SRC_PIN9 | es8326->jack_pol | 0x04))); | |
| 879 | − regmap_write(es8326->regmap, ES8326_HP_VOL, 0x11); | |
| 971 | + regmap_write(es8326->regmap, ES8326_ADC_MUTE, 0x0f); | |
| 880 | 972 | |
| 881 | 973 | es8326->jack_remove_retry = 0; |
| 882 | 974 | es8326->hp = 0; |
| @@ -72,6 +72,7 @@ · 71 unmodified lines | ||
| 72 | 72 | #define ES8326_DAC_VOL 0x50 |
| 73 | 73 | #define ES8326_DRC_RECOVERY 0x53 |
| 74 | 74 | #define ES8326_DRC_WINSIZE 0x54 |
| 75 | +#define ES8326_DAC_CROSSTALK 0x55 | |
| 75 | 76 | #define ES8326_HPJACK_TIMER 0x56 |
| 76 | 77 | #define ES8326_HPDET_TYPE 0x57 |
| 77 | 78 | #define ES8326_INT_SOURCE 0x58 |
| @@ -100,7 +101,7 @@ · 22 unmodified lines | ||
| 100 | 101 | #define ES8326_MUTE (3 << 0) |
| 101 | 102 | |
| 102 | 103 | /* ES8326_CLK_CTL */ |
| 103 | −#define ES8326_CLK_ON (0x7f << 0) | |
| 104 | +#define ES8326_CLK_ON (0x7e << 0) | |
| 104 | 105 | #define ES8326_CLK_OFF (0 << 0) |
| 105 | 106 | |
| 106 | 107 | /* ES8326_CLK_INV */ |
| @@ -1584,7 +1584,6 @@ static int wsa_macro_enable_interpolator(struct snd_soc_dapm_widget *w, · 1583 unmodified lines | ||
| 1584 | 1584 | u16 gain_reg; |
| 1585 | 1585 | u16 reg; |
| 1586 | 1586 | int val; |
| 1587 | − int offset_val = 0; | |
| 1588 | 1587 | struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); |
| 1589 | 1588 | |
| 1590 | 1589 | if (w->shift == WSA_MACRO_COMP1) { |
| @@ -1623,10 +1622,8 @@ static int wsa_macro_enable_interpolator(struct snd_soc_dapm_widget *w, · 32 unmodified lines | ||
| 1623 | 1622 | CDC_WSA_RX1_RX_PATH_MIX_SEC0, |
| 1624 | 1623 | CDC_WSA_RX_PGA_HALF_DB_MASK, |
| 1625 | 1624 | CDC_WSA_RX_PGA_HALF_DB_ENABLE); |
| 1626 | − offset_val = -2; | |
| 1627 | 1625 | } |
| 1628 | 1626 | val = snd_soc_component_read(component, gain_reg); |
| 1629 | − val += offset_val; | |
| 1630 | 1627 | snd_soc_component_write(component, gain_reg, val); |
| 1631 | 1628 | wsa_macro_config_ear_spkr_gain(component, wsa, |
| 1632 | 1629 | event, gain_reg); |
| @@ -1654,10 +1651,6 @@ static int wsa_macro_enable_interpolator(struct snd_soc_dapm_widget *w, · 21 unmodified lines | ||
| 1654 | 1651 | CDC_WSA_RX1_RX_PATH_MIX_SEC0, |
| 1655 | 1652 | CDC_WSA_RX_PGA_HALF_DB_MASK, |
| 1656 | 1653 | CDC_WSA_RX_PGA_HALF_DB_DISABLE); |
| 1657 | − offset_val = 2; | |
| 1658 | − val = snd_soc_component_read(component, gain_reg); | |
| 1659 | − val += offset_val; | |
| 1660 | − snd_soc_component_write(component, gain_reg, val); | |
| 1661 | 1654 | } |
| 1662 | 1655 | wsa_macro_config_ear_spkr_gain(component, wsa, |
| 1663 | 1656 | event, gain_reg); |
| @@ -3033,7 +3033,6 @@ static int wcd9335_codec_enable_mix_path(struct snd_soc_dapm_widget *w, · 3032 unmodified lines | ||
| 3033 | 3033 | { |
| 3034 | 3034 | struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm); |
| 3035 | 3035 | u16 gain_reg; |
| 3036 | − int offset_val = 0; | |
| 3037 | 3036 | int val = 0; |
| 3038 | 3037 | |
| 3039 | 3038 | switch (w->reg) { |
| @@ -3073,7 +3072,6 @@ static int wcd9335_codec_enable_mix_path(struct snd_soc_dapm_widget *w, · 33 unmodified lines | ||
| 3073 | 3072 | switch (event) { |
| 3074 | 3073 | case SND_SOC_DAPM_POST_PMU: |
| 3075 | 3074 | val = snd_soc_component_read(comp, gain_reg); |
| 3076 | − val += offset_val; | |
| 3077 | 3075 | snd_soc_component_write(comp, gain_reg, val); |
| 3078 | 3076 | break; |
| 3079 | 3077 | case SND_SOC_DAPM_POST_PMD: |
| @@ -3294,7 +3292,6 @@ static int wcd9335_codec_enable_interpolator(struct snd_soc_dapm_widget *w, · 214 unmodified lines | ||
| 3294 | 3292 | u16 gain_reg; |
| 3295 | 3293 | u16 reg; |
| 3296 | 3294 | int val; |
| 3297 | − int offset_val = 0; | |
| 3298 | 3295 | |
| 3299 | 3296 | if (!(snd_soc_dapm_widget_name_cmp(w, "RX INT0 INTERP"))) { |
| 3300 | 3297 | reg = WCD9335_CDC_RX0_RX_PATH_CTL; |
| @@ -3337,7 +3334,6 @@ static int wcd9335_codec_enable_interpolator(struct snd_soc_dapm_widget *w, · 36 unmodified lines | ||
| 3337 | 3334 | case SND_SOC_DAPM_POST_PMU: |
| 3338 | 3335 | wcd9335_config_compander(comp, w->shift, event); |
| 3339 | 3336 | val = snd_soc_component_read(comp, gain_reg); |
| 3340 | − val += offset_val; | |
| 3341 | 3337 | snd_soc_component_write(comp, gain_reg, val); |
| 3342 | 3338 | break; |
| 3343 | 3339 | case SND_SOC_DAPM_POST_PMD: |
| @@ -13,7 +13,6 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/of.h> |
| 14 | 14 | #include <linux/platform_device.h> |
| 15 | 15 | #include <linux/regmap.h> |
| 16 | −#include <linux/regulator/consumer.h> | |
| 17 | 16 | #include <linux/slab.h> |
| 18 | 17 | #include <linux/slimbus.h> |
| 19 | 18 | #include <sound/pcm_params.h> |
| @@ -210,7 +210,7 @@ struct wcd938x_priv { · 209 unmodified lines | ||
| 210 | 210 | }; |
| 211 | 211 | |
| 212 | 212 | static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(ear_pa_gain, 600, -1800); |
| 213 | −static const DECLARE_TLV_DB_SCALE(line_gain, -3000, 150, -3000); | |
| 213 | +static const DECLARE_TLV_DB_SCALE(line_gain, -3000, 150, 0); | |
| 214 | 214 | static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(analog_gain, 0, 3000); |
| 215 | 215 | |
| 216 | 216 | struct wcd938x_mbhc_zdet_param { |
| @@ -3587,10 +3587,8 @@ static int wcd938x_probe(struct platform_device *pdev) · 3370 unmodified lines | ||
| 3587 | 3587 | mutex_init(&wcd938x->micb_lock); |
| 3588 | 3588 | |
| 3589 | 3589 | ret = wcd938x_populate_dt_data(wcd938x, dev); |
| 3590 | − if (ret) { | |
| 3591 | − dev_err(dev, "%s: Fail to obtain platform data\n", __func__); | |
| 3592 | − return -EINVAL; | |
| 3593 | − } | |
| 3590 | + if (ret) | |
| 3591 | + return ret; | |
| 3594 | 3592 | |
| 3595 | 3593 | ret = wcd938x_add_slave_components(wcd938x, dev, &match); |
| 3596 | 3594 | if (ret) |
| @@ -739,19 +739,25 @@ static int wm_adsp_request_firmware_file(struct wm_adsp *dsp, · 738 unmodified lines | ||
| 739 | 739 | const char *filetype) |
| 740 | 740 | { |
| 741 | 741 | struct cs_dsp *cs_dsp = &dsp->cs_dsp; |
| 742 | + const char *fwf; | |
| 742 | 743 | char *s, c; |
| 743 | 744 | int ret = 0; |
| 744 | 745 | |
| 746 | + if (dsp->fwf_name) | |
| 747 | + fwf = dsp->fwf_name; | |
| 748 | + else | |
| 749 | + fwf = dsp->cs_dsp.name; | |
| 750 | + | |
| 745 | 751 | if (system_name && asoc_component_prefix) |
| 746 | 752 | *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s-%s.%s", dir, dsp->part, |
| 747 | − dsp->fwf_name, wm_adsp_fw[dsp->fw].file, system_name, | |
| 753 | + fwf, wm_adsp_fw[dsp->fw].file, system_name, | |
| 748 | 754 | asoc_component_prefix, filetype); |
| 749 | 755 | else if (system_name) |
| 750 | 756 | *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s.%s", dir, dsp->part, |
| 751 | − dsp->fwf_name, wm_adsp_fw[dsp->fw].file, system_name, | |
| 757 | + fwf, wm_adsp_fw[dsp->fw].file, system_name, | |
| 752 | 758 | filetype); |
| 753 | 759 | else |
| 754 | − *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s.%s", dir, dsp->part, dsp->fwf_name, | |
| 760 | + *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s.%s", dir, dsp->part, fwf, | |
| 755 | 761 | wm_adsp_fw[dsp->fw].file, filetype); |
| 756 | 762 | |
| 757 | 763 | if (*filename == NULL) |
| @@ -823,6 +829,23 @@ static int wm_adsp_request_firmware_files(struct wm_adsp *dsp, · 65 unmodified lines | ||
| 823 | 829 | } |
| 824 | 830 | } |
| 825 | 831 | |
| 832 | + /* Check system-specific bin without wmfw before falling back to generic */ | |
| 833 | + if (dsp->wmfw_optional && system_name) { | |
| 834 | + if (asoc_component_prefix) | |
| 835 | + wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, | |
| 836 | + cirrus_dir, system_name, | |
| 837 | + asoc_component_prefix, "bin"); | |
| 838 | + | |
| 839 | + if (!*coeff_firmware) | |
| 840 | + wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, | |
| 841 | + cirrus_dir, system_name, | |
| 842 | + NULL, "bin"); | |
| 843 | + | |
| 844 | + if (*coeff_firmware) | |
| 845 | + return 0; | |
| 846 | + } | |
| 847 | + | |
| 848 | + /* Check legacy location */ | |
| 826 | 849 | if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, |
| 827 | 850 | "", NULL, NULL, "wmfw")) { |
| 828 | 851 | wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, |
| @@ -830,62 +853,28 @@ static int wm_adsp_request_firmware_files(struct wm_adsp *dsp, · 1 unmodified line | ||
| 830 | 853 | return 0; |
| 831 | 854 | } |
| 832 | 855 | |
| 856 | + /* Fall back to generic wmfw and optional matching bin */ | |
| 833 | 857 | ret = wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, |
| 834 | 858 | cirrus_dir, NULL, NULL, "wmfw"); |
| 835 | − if (!ret) { | |
| 859 | + if (!ret || dsp->wmfw_optional) { | |
| 836 | 860 | wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, |
| 837 | 861 | cirrus_dir, NULL, NULL, "bin"); |
| 838 | 862 | return 0; |
| 839 | 863 | } |
| 840 | 864 | |
| 841 | − if (dsp->wmfw_optional) { | |
| 842 | − if (system_name) { | |
| 843 | − if (asoc_component_prefix) | |
| 844 | − wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, | |
| 845 | − cirrus_dir, system_name, | |
| 846 | − asoc_component_prefix, "bin"); | |
| 847 | − | |
| 848 | − if (!*coeff_firmware) | |
| 849 | − wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, | |
| 850 | − cirrus_dir, system_name, | |
| 851 | − NULL, "bin"); | |
| 852 | − } | |
| 853 | − | |
| 854 | − if (!*coeff_firmware) | |
| 855 | − wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, | |
| 856 | − "", NULL, NULL, "bin"); | |
| 857 | − | |
| 858 | − if (!*coeff_firmware) | |
| 859 | − wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, | |
| 860 | − cirrus_dir, NULL, NULL, "bin"); | |
| 861 | − | |
| 862 | − return 0; | |
| 863 | − } | |
| 864 | − | |
| 865 | 865 | adsp_err(dsp, "Failed to request firmware <%s>%s-%s-%s<-%s<%s>>.wmfw\n", |
| 866 | − cirrus_dir, dsp->part, dsp->fwf_name, wm_adsp_fw[dsp->fw].file, | |
| 867 | − system_name, asoc_component_prefix); | |
| 866 | + cirrus_dir, dsp->part, | |
| 867 | + dsp->fwf_name ? dsp->fwf_name : dsp->cs_dsp.name, | |
| 868 | + wm_adsp_fw[dsp->fw].file, system_name, asoc_component_prefix); | |
| 868 | 869 | |
| 869 | 870 | return -ENOENT; |
| 870 | 871 | } |
| 871 | 872 | |
| 872 | 873 | static int wm_adsp_common_init(struct wm_adsp *dsp) |
| 873 | 874 | { |
| 874 | − char *p; | |
| 875 | − | |
| 876 | 875 | INIT_LIST_HEAD(&dsp->compr_list); |
| 877 | 876 | INIT_LIST_HEAD(&dsp->buffer_list); |
| 878 | 877 | |
| 879 | − if (!dsp->fwf_name) { | |
| 880 | − p = devm_kstrdup(dsp->cs_dsp.dev, dsp->cs_dsp.name, GFP_KERNEL); | |
| 881 | − if (!p) | |
| 882 | − return -ENOMEM; | |
| 883 | − | |
| 884 | − dsp->fwf_name = p; | |
| 885 | − for (; *p != 0; ++p) | |
| 886 | − *p = tolower(*p); | |
| 887 | − } | |
| 888 | − | |
| 889 | 878 | return 0; |
| 890 | 879 | } |
| 891 | 880 | |
| @@ -1098,7 +1098,11 @@ static int wsa_dev_mode_put(struct snd_kcontrol *kcontrol, · 1097 unmodified lines | ||
| 1098 | 1098 | return 1; |
| 1099 | 1099 | } |
| 1100 | 1100 | |
| 1101 | −static const DECLARE_TLV_DB_SCALE(pa_gain, -300, 150, -300); | |
| 1101 | +static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(pa_gain, | |
| 1102 | + 0, 14, TLV_DB_SCALE_ITEM(-300, 0, 0), | |
| 1103 | + 15, 29, TLV_DB_SCALE_ITEM(-300, 150, 0), | |
| 1104 | + 30, 31, TLV_DB_SCALE_ITEM(1800, 0, 0), | |
| 1105 | +); | |
| 1102 | 1106 | |
| 1103 | 1107 | static int wsa883x_get_swr_port(struct snd_kcontrol *kcontrol, |
| 1104 | 1108 | struct snd_ctl_elem_value *ucontrol) |
| @@ -32,12 +32,14 @@ static int sc8280xp_snd_init(struct snd_soc_pcm_runtime *rtd) · 31 unmodified lines | ||
| 32 | 32 | case WSA_CODEC_DMA_RX_0: |
| 33 | 33 | case WSA_CODEC_DMA_RX_1: |
| 34 | 34 | /* |
| 35 | − * set limit of 0dB on Digital Volume for Speakers, | |
| 36 | − * this can prevent damage of speakers to some extent without | |
| 37 | − * active speaker protection | |
| 35 | + * Set limit of -3 dB on Digital Volume and 0 dB on PA Volume | |
| 36 | + * to reduce the risk of speaker damage until we have active | |
| 37 | + * speaker protection in place. | |
| 38 | 38 | */ |
| 39 | − snd_soc_limit_volume(card, "WSA_RX0 Digital Volume", 84); | |
| 40 | − snd_soc_limit_volume(card, "WSA_RX1 Digital Volume", 84); | |
| 39 | + snd_soc_limit_volume(card, "WSA_RX0 Digital Volume", 81); | |
| 40 | + snd_soc_limit_volume(card, "WSA_RX1 Digital Volume", 81); | |
| 41 | + snd_soc_limit_volume(card, "SpkrLeft PA Volume", 17); | |
| 42 | + snd_soc_limit_volume(card, "SpkrRight PA Volume", 17); | |
| 41 | 43 | break; |
| 42 | 44 | default: |
| 43 | 45 | break; |
| @@ -1037,7 +1037,7 @@ component_dai_empty: · 1036 unmodified lines | ||
| 1037 | 1037 | return -EINVAL; |
| 1038 | 1038 | } |
| 1039 | 1039 | |
| 1040 | −#define MAX_DEFAULT_CH_MAP_SIZE 7 | |
| 1040 | +#define MAX_DEFAULT_CH_MAP_SIZE 8 | |
| 1041 | 1041 | static struct snd_soc_dai_link_ch_map default_ch_map_sync[MAX_DEFAULT_CH_MAP_SIZE] = { |
| 1042 | 1042 | { .cpu = 0, .codec = 0 }, |
| 1043 | 1043 | { .cpu = 1, .codec = 1 }, |
| @@ -1046,6 +1046,7 @@ static struct snd_soc_dai_link_ch_map default_ch_map_sync[MAX_DEFAULT_CH_MAP_SIZ · 2 unmodified lines | ||
| 1046 | 1046 | { .cpu = 4, .codec = 4 }, |
| 1047 | 1047 | { .cpu = 5, .codec = 5 }, |
| 1048 | 1048 | { .cpu = 6, .codec = 6 }, |
| 1049 | + { .cpu = 7, .codec = 7 }, | |
| 1049 | 1050 | }; |
| 1050 | 1051 | static struct snd_soc_dai_link_ch_map default_ch_map_1cpu[MAX_DEFAULT_CH_MAP_SIZE] = { |
| 1051 | 1052 | { .cpu = 0, .codec = 0 }, |
| @@ -1055,6 +1056,7 @@ static struct snd_soc_dai_link_ch_map default_ch_map_1cpu[MAX_DEFAULT_CH_MAP_SIZ · 3 unmodified lines | ||
| 1055 | 1056 | { .cpu = 0, .codec = 4 }, |
| 1056 | 1057 | { .cpu = 0, .codec = 5 }, |
| 1057 | 1058 | { .cpu = 0, .codec = 6 }, |
| 1059 | + { .cpu = 0, .codec = 7 }, | |
| 1058 | 1060 | }; |
| 1059 | 1061 | static struct snd_soc_dai_link_ch_map default_ch_map_1codec[MAX_DEFAULT_CH_MAP_SIZE] = { |
| 1060 | 1062 | { .cpu = 0, .codec = 0 }, |
| @@ -1064,6 +1066,7 @@ static struct snd_soc_dai_link_ch_map default_ch_map_1codec[MAX_DEFAULT_CH_MAP_S · 3 unmodified lines | ||
| 1064 | 1066 | { .cpu = 4, .codec = 0 }, |
| 1065 | 1067 | { .cpu = 5, .codec = 0 }, |
| 1066 | 1068 | { .cpu = 6, .codec = 0 }, |
| 1069 | + { .cpu = 7, .codec = 0 }, | |
| 1067 | 1070 | }; |
| 1068 | 1071 | static int snd_soc_compensate_channel_connection_map(struct snd_soc_card *card, |
| 1069 | 1072 | struct snd_soc_dai_link *dai_link) |
| @@ -577,6 +577,11 @@ static const struct of_device_id sun4i_spdif_of_match[] = { · 576 unmodified lines | ||
| 577 | 577 | .compatible = "allwinner,sun50i-h6-spdif", |
| 578 | 578 | .data = &sun50i_h6_spdif_quirks, |
| 579 | 579 | }, |
| 580 | + { | |
| 581 | + .compatible = "allwinner,sun50i-h616-spdif", | |
| 582 | + /* Essentially the same as the H6, but without RX */ | |
| 583 | + .data = &sun50i_h6_spdif_quirks, | |
| 584 | + }, | |
| 580 | 585 | { /* sentinel */ } |
| 581 | 586 | }; |
| 582 | 587 | MODULE_DEVICE_TABLE(of, sun4i_spdif_of_match); |
| @@ -261,6 +261,8 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, · 260 unmodified lines | ||
| 261 | 261 | int ret, i, cur, err, pins, clock_id; |
| 262 | 262 | const u8 *sources; |
| 263 | 263 | int proto = fmt->protocol; |
| 264 | + bool readable, writeable; | |
| 265 | + u32 bmControls; | |
| 264 | 266 | |
| 265 | 267 | entity_id &= 0xff; |
| 266 | 268 | |
| @@ -292,11 +294,27 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, · 25 unmodified lines | ||
| 292 | 294 | sources = GET_VAL(selector, proto, baCSourceID); |
| 293 | 295 | cur = 0; |
| 294 | 296 | |
| 297 | + if (proto == UAC_VERSION_3) | |
| 298 | + bmControls = le32_to_cpu(*(__le32 *)(&selector->v3.baCSourceID[0] + pins)); | |
| 299 | + else | |
| 300 | + bmControls = *(__u8 *)(&selector->v2.baCSourceID[0] + pins); | |
| 301 | + | |
| 302 | + readable = uac_v2v3_control_is_readable(bmControls, | |
| 303 | + UAC2_CX_CLOCK_SELECTOR); | |
| 304 | + writeable = uac_v2v3_control_is_writeable(bmControls, | |
| 305 | + UAC2_CX_CLOCK_SELECTOR); | |
| 306 | + | |
| 295 | 307 | if (pins == 1) { |
| 296 | 308 | ret = 1; |
| 297 | 309 | goto find_source; |
| 298 | 310 | } |
| 299 | 311 | |
| 312 | + /* for now just warn about buggy device */ | |
| 313 | + if (!readable) | |
| 314 | + usb_audio_warn(chip, | |
| 315 | + "%s(): clock selector control is not readable, id %d\n", | |
| 316 | + __func__, clock_id); | |
| 317 | + | |
| 300 | 318 | /* the entity ID we are looking at is a selector. |
| 301 | 319 | * find out what it currently selects */ |
| 302 | 320 | ret = uac_clock_selector_get_val(chip, clock_id); |
| @@ -325,17 +343,29 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, · 22 unmodified lines | ||
| 325 | 343 | visited, validate); |
| 326 | 344 | if (ret > 0) { |
| 327 | 345 | /* Skip setting clock selector again for some devices */ |
| 328 | − if (chip->quirk_flags & QUIRK_FLAG_SKIP_CLOCK_SELECTOR) | |
| 346 | + if (chip->quirk_flags & QUIRK_FLAG_SKIP_CLOCK_SELECTOR || | |
| 347 | + !writeable) | |
| 329 | 348 | return ret; |
| 330 | 349 | err = uac_clock_selector_set_val(chip, entity_id, cur); |
| 331 | − if (err < 0) | |
| 350 | + if (err < 0) { | |
| 351 | + if (pins == 1) { | |
| 352 | + usb_audio_dbg(chip, | |
| 353 | + "%s(): selector returned an error, " | |
| 354 | + "assuming a firmware bug, id %d, ret %d\n", | |
| 355 | + __func__, clock_id, err); | |
| 356 | + return ret; | |
| 357 | + } | |
| 332 | 358 | return err; |
| 359 | + } | |
| 333 | 360 | } |
| 334 | 361 | |
| 335 | 362 | if (!validate || ret > 0 || !chip->autoclock) |
| 336 | 363 | return ret; |
| 337 | 364 | |
| 338 | 365 | find_others: |
| 366 | + if (!writeable) | |
| 367 | + return -ENXIO; | |
| 368 | + | |
| 339 | 369 | /* The current clock source is invalid, try others. */ |
| 340 | 370 | for (i = 1; i <= pins; i++) { |
| 341 | 371 | if (i == cur) |
| @@ -470,9 +470,11 @@ static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip, · 469 unmodified lines | ||
| 470 | 470 | int clock) |
| 471 | 471 | { |
| 472 | 472 | struct usb_device *dev = chip->dev; |
| 473 | + struct usb_host_interface *alts; | |
| 473 | 474 | unsigned int *table; |
| 474 | 475 | unsigned int nr_rates; |
| 475 | 476 | int i, err; |
| 477 | + u32 bmControls; | |
| 476 | 478 | |
| 477 | 479 | /* performing the rate verification may lead to unexpected USB bus |
| 478 | 480 | * behavior afterwards by some unknown reason. Do this only for the |
| @@ -481,6 +483,24 @@ static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip, · 2 unmodified lines | ||
| 481 | 483 | if (!(chip->quirk_flags & QUIRK_FLAG_VALIDATE_RATES)) |
| 482 | 484 | return 0; /* don't perform the validation as default */ |
| 483 | 485 | |
| 486 | + alts = snd_usb_get_host_interface(chip, fp->iface, fp->altsetting); | |
| 487 | + if (!alts) | |
| 488 | + return 0; | |
| 489 | + | |
| 490 | + if (fp->protocol == UAC_VERSION_3) { | |
| 491 | + struct uac3_as_header_descriptor *as = snd_usb_find_csint_desc( | |
| 492 | + alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); | |
| 493 | + bmControls = le32_to_cpu(as->bmControls); | |
| 494 | + } else { | |
| 495 | + struct uac2_as_header_descriptor *as = snd_usb_find_csint_desc( | |
| 496 | + alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); | |
| 497 | + bmControls = as->bmControls; | |
| 498 | + } | |
| 499 | + | |
| 500 | + if (!uac_v2v3_control_is_readable(bmControls, | |
| 501 | + UAC2_AS_VAL_ALT_SETTINGS)) | |
| 502 | + return 0; | |
| 503 | + | |
| 484 | 504 | table = kcalloc(fp->nr_rates, sizeof(*table), GFP_KERNEL); |
| 485 | 505 | if (!table) |
| 486 | 506 | return -ENOMEM; |
| @@ -1085,7 +1085,7 @@ int snd_usb_midi_v2_create(struct snd_usb_audio *chip, · 1084 unmodified lines | ||
| 1085 | 1085 | } |
| 1086 | 1086 | if ((quirk && quirk->type != QUIRK_MIDI_STANDARD_INTERFACE) || |
| 1087 | 1087 | iface->num_altsetting < 2) { |
| 1088 | − usb_audio_info(chip, "Quirk or no altest; falling back to MIDI 1.0\n"); | |
| 1088 | + usb_audio_info(chip, "Quirk or no altset; falling back to MIDI 1.0\n"); | |
| 1089 | 1089 | goto fallback_to_midi1; |
| 1090 | 1090 | } |
| 1091 | 1091 | hostif = &iface->altsetting[1]; |
| @@ -2031,10 +2031,14 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { · 2030 unmodified lines | ||
| 2031 | 2031 | QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR), |
| 2032 | 2032 | DEVICE_FLG(0x0499, 0x1509, /* Steinberg UR22 */ |
| 2033 | 2033 | QUIRK_FLAG_GENERIC_IMPLICIT_FB), |
| 2034 | + DEVICE_FLG(0x0499, 0x3108, /* Yamaha YIT-W12TX */ | |
| 2035 | + QUIRK_FLAG_GET_SAMPLE_RATE), | |
| 2034 | 2036 | DEVICE_FLG(0x04d8, 0xfeea, /* Benchmark DAC1 Pre */ |
| 2035 | 2037 | QUIRK_FLAG_GET_SAMPLE_RATE), |
| 2036 | 2038 | DEVICE_FLG(0x04e8, 0xa051, /* Samsung USBC Headset (AKG) */ |
| 2037 | 2039 | QUIRK_FLAG_SKIP_CLOCK_SELECTOR | QUIRK_FLAG_CTL_MSG_DELAY_5M), |
| 2040 | + DEVICE_FLG(0x0525, 0xa4ad, /* Hamedal C20 usb camero */ | |
| 2041 | + QUIRK_FLAG_IFACE_SKIP_CLOSE), | |
| 2038 | 2042 | DEVICE_FLG(0x054c, 0x0b8c, /* Sony WALKMAN NW-A45 DAC */ |
| 2039 | 2043 | QUIRK_FLAG_SET_IFACE_FIRST), |
| 2040 | 2044 | DEVICE_FLG(0x0556, 0x0014, /* Phoenix Audio TMX320VC */ |
| @@ -2073,14 +2077,22 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { · 32 unmodified lines | ||
| 2073 | 2077 | QUIRK_FLAG_GENERIC_IMPLICIT_FB), |
| 2074 | 2078 | DEVICE_FLG(0x0763, 0x2031, /* M-Audio Fast Track C600 */ |
| 2075 | 2079 | QUIRK_FLAG_GENERIC_IMPLICIT_FB), |
| 2080 | + DEVICE_FLG(0x07fd, 0x000b, /* MOTU M Series 2nd hardware revision */ | |
| 2081 | + QUIRK_FLAG_CTL_MSG_DELAY_1M), | |
| 2076 | 2082 | DEVICE_FLG(0x08bb, 0x2702, /* LineX FM Transmitter */ |
| 2077 | 2083 | QUIRK_FLAG_IGNORE_CTL_ERROR), |
| 2078 | 2084 | DEVICE_FLG(0x0951, 0x16ad, /* Kingston HyperX */ |
| 2079 | 2085 | QUIRK_FLAG_CTL_MSG_DELAY_1M), |
| 2080 | 2086 | DEVICE_FLG(0x0b0e, 0x0349, /* Jabra 550a */ |
| 2081 | 2087 | QUIRK_FLAG_CTL_MSG_DELAY_1M), |
| 2088 | + DEVICE_FLG(0x0ecb, 0x205c, /* JBL Quantum610 Wireless */ | |
| 2089 | + QUIRK_FLAG_FIXED_RATE), | |
| 2090 | + DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */ | |
| 2091 | + QUIRK_FLAG_FIXED_RATE), | |
| 2082 | 2092 | DEVICE_FLG(0x0fd9, 0x0008, /* Hauppauge HVR-950Q */ |
| 2083 | 2093 | QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), |
| 2094 | + DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */ | |
| 2095 | + QUIRK_FLAG_GET_SAMPLE_RATE), | |
| 2084 | 2096 | DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */ |
| 2085 | 2097 | QUIRK_FLAG_GET_SAMPLE_RATE), |
| 2086 | 2098 | DEVICE_FLG(0x1397, 0x0507, /* Behringer UMC202HD */ |
| @@ -2113,6 +2125,10 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { · 26 unmodified lines | ||
| 2113 | 2125 | QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY), |
| 2114 | 2126 | DEVICE_FLG(0x1901, 0x0191, /* GE B850V3 CP2114 audio interface */ |
| 2115 | 2127 | QUIRK_FLAG_GET_SAMPLE_RATE), |
| 2128 | + DEVICE_FLG(0x19f7, 0x0035, /* RODE NT-USB+ */ | |
| 2129 | + QUIRK_FLAG_GET_SAMPLE_RATE), | |
| 2130 | + DEVICE_FLG(0x1bcf, 0x2283, /* NexiGo N930AF FHD Webcam */ | |
| 2131 | + QUIRK_FLAG_GET_SAMPLE_RATE), | |
| 2116 | 2132 | DEVICE_FLG(0x2040, 0x7200, /* Hauppauge HVR-950Q */ |
| 2117 | 2133 | QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), |
| 2118 | 2134 | DEVICE_FLG(0x2040, 0x7201, /* Hauppauge HVR-950Q-MXL */ |
| @@ -2155,6 +2171,12 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { · 36 unmodified lines | ||
| 2155 | 2171 | QUIRK_FLAG_IGNORE_CTL_ERROR), |
| 2156 | 2172 | DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */ |
| 2157 | 2173 | QUIRK_FLAG_GET_SAMPLE_RATE), |
| 2174 | + DEVICE_FLG(0x2b53, 0x0023, /* Fiero SC-01 (firmware v1.0.0 @ 48 kHz) */ | |
| 2175 | + QUIRK_FLAG_GENERIC_IMPLICIT_FB), | |
| 2176 | + DEVICE_FLG(0x2b53, 0x0024, /* Fiero SC-01 (firmware v1.0.0 @ 96 kHz) */ | |
| 2177 | + QUIRK_FLAG_GENERIC_IMPLICIT_FB), | |
| 2178 | + DEVICE_FLG(0x2b53, 0x0031, /* Fiero SC-01 (firmware v1.1.0) */ | |
| 2179 | + QUIRK_FLAG_GENERIC_IMPLICIT_FB), | |
| 2158 | 2180 | DEVICE_FLG(0x30be, 0x0101, /* Schiit Hel */ |
| 2159 | 2181 | QUIRK_FLAG_IGNORE_CTL_ERROR), |
| 2160 | 2182 | DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */ |
| @@ -2163,22 +2185,6 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { · 2 unmodified lines | ||
| 2163 | 2185 | QUIRK_FLAG_ALIGN_TRANSFER), |
| 2164 | 2186 | DEVICE_FLG(0x534d, 0x2109, /* MacroSilicon MS2109 */ |
| 2165 | 2187 | QUIRK_FLAG_ALIGN_TRANSFER), |
| 2166 | − DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */ | |
| 2167 | − QUIRK_FLAG_GET_SAMPLE_RATE), | |
| 2168 | − DEVICE_FLG(0x2b53, 0x0023, /* Fiero SC-01 (firmware v1.0.0 @ 48 kHz) */ | |
| 2169 | − QUIRK_FLAG_GENERIC_IMPLICIT_FB), | |
| 2170 | − DEVICE_FLG(0x2b53, 0x0024, /* Fiero SC-01 (firmware v1.0.0 @ 96 kHz) */ | |
| 2171 | − QUIRK_FLAG_GENERIC_IMPLICIT_FB), | |
| 2172 | − DEVICE_FLG(0x2b53, 0x0031, /* Fiero SC-01 (firmware v1.1.0) */ | |
| 2173 | − QUIRK_FLAG_GENERIC_IMPLICIT_FB), | |
| 2174 | − DEVICE_FLG(0x0525, 0xa4ad, /* Hamedal C20 usb camero */ | |
| 2175 | − QUIRK_FLAG_IFACE_SKIP_CLOSE), | |
| 2176 | − DEVICE_FLG(0x0ecb, 0x205c, /* JBL Quantum610 Wireless */ | |
| 2177 | − QUIRK_FLAG_FIXED_RATE), | |
| 2178 | − DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */ | |
| 2179 | − QUIRK_FLAG_FIXED_RATE), | |
| 2180 | − DEVICE_FLG(0x1bcf, 0x2283, /* NexiGo N930AF FHD Webcam */ | |
| 2181 | − QUIRK_FLAG_GET_SAMPLE_RATE), | |
| 2182 | 2188 | |
| 2183 | 2189 | /* Vendor matches */ |
| 2184 | 2190 | VENDOR_FLG(0x045e, /* MS Lifecam */ |
| @@ -91,8 +91,6 @@ static void virtsnd_event_notify_cb(struct virtqueue *vqueue) · 90 unmodified lines | ||
| 91 | 91 | virtsnd_event_dispatch(snd, event); |
| 92 | 92 | virtsnd_event_send(vqueue, event, true, GFP_ATOMIC); |
| 93 | 93 | } |
| 94 | − if (unlikely(virtqueue_is_broken(vqueue))) | |
| 95 | − break; | |
| 96 | 94 | } while (!virtqueue_enable_cb(vqueue)); |
| 97 | 95 | spin_unlock_irqrestore(&queue->lock, flags); |
| 98 | 96 | } |
| @@ -303,8 +303,6 @@ void virtsnd_ctl_notify_cb(struct virtqueue *vqueue) · 302 unmodified lines | ||
| 303 | 303 | virtqueue_disable_cb(vqueue); |
| 304 | 304 | while ((msg = virtqueue_get_buf(vqueue, &length))) |
| 305 | 305 | virtsnd_ctl_msg_complete(msg); |
| 306 | − if (unlikely(virtqueue_is_broken(vqueue))) | |
| 307 | − break; | |
| 308 | 306 | } while (!virtqueue_enable_cb(vqueue)); |
| 309 | 307 | spin_unlock_irqrestore(&queue->lock, flags); |
| 310 | 308 | } |
| @@ -358,8 +358,6 @@ static inline void virtsnd_pcm_notify_cb(struct virtio_snd_queue *queue) · 357 unmodified lines | ||
| 358 | 358 | virtqueue_disable_cb(queue->vqueue); |
| 359 | 359 | while ((msg = virtqueue_get_buf(queue->vqueue, &written_bytes))) |
| 360 | 360 | virtsnd_pcm_msg_complete(msg, written_bytes); |
| 361 | − if (unlikely(virtqueue_is_broken(queue->vqueue))) | |
| 362 | − break; | |
| 363 | 361 | } while (!virtqueue_enable_cb(queue->vqueue)); |
| 364 | 362 | spin_unlock_irqrestore(&queue->lock, flags); |
| 365 | 363 | } |
| @@ -198,6 +198,7 @@ · 197 unmodified lines | ||
| 198 | 198 | #define X86_FEATURE_CAT_L3 ( 7*32+ 4) /* Cache Allocation Technology L3 */ |
| 199 | 199 | #define X86_FEATURE_CAT_L2 ( 7*32+ 5) /* Cache Allocation Technology L2 */ |
| 200 | 200 | #define X86_FEATURE_CDP_L3 ( 7*32+ 6) /* Code and Data Prioritization L3 */ |
| 201 | +#define X86_FEATURE_TDX_HOST_PLATFORM ( 7*32+ 7) /* Platform supports being a TDX host */ | |
| 201 | 202 | #define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */ |
| 202 | 203 | #define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */ |
| 203 | 204 | #define X86_FEATURE_XCOMPACTED ( 7*32+10) /* "" Use compacted XSTATE (XSAVES or XSAVEC) */ |
| @@ -308,10 +309,14 @@ · 104 unmodified lines | ||
| 308 | 309 | #define X86_FEATURE_SMBA (11*32+21) /* "" Slow Memory Bandwidth Allocation */ |
| 309 | 310 | #define X86_FEATURE_BMEC (11*32+22) /* "" Bandwidth Monitoring Event Configuration */ |
| 310 | 311 | #define X86_FEATURE_USER_SHSTK (11*32+23) /* Shadow stack support for user mode applications */ |
| 311 | − | |
| 312 | 312 | #define X86_FEATURE_SRSO (11*32+24) /* "" AMD BTB untrain RETs */ |
| 313 | 313 | #define X86_FEATURE_SRSO_ALIAS (11*32+25) /* "" AMD BTB untrain RETs through aliasing */ |
| 314 | 314 | #define X86_FEATURE_IBPB_ON_VMEXIT (11*32+26) /* "" Issue an IBPB only on VMEXIT */ |
| 315 | +#define X86_FEATURE_APIC_MSRS_FENCE (11*32+27) /* "" IA32_TSC_DEADLINE and X2APIC MSRs need fencing */ | |
| 316 | +#define X86_FEATURE_ZEN2 (11*32+28) /* "" CPU based on Zen2 microarchitecture */ | |
| 317 | +#define X86_FEATURE_ZEN3 (11*32+29) /* "" CPU based on Zen3 microarchitecture */ | |
| 318 | +#define X86_FEATURE_ZEN4 (11*32+30) /* "" CPU based on Zen4 microarchitecture */ | |
| 319 | +#define X86_FEATURE_ZEN1 (11*32+31) /* "" CPU based on Zen1 microarchitecture */ | |
| 315 | 320 | |
| 316 | 321 | /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */ |
| 317 | 322 | #define X86_FEATURE_AVX_VNNI (12*32+ 4) /* AVX VNNI instructions */ |
| @@ -495,6 +500,7 @@ · 177 unmodified lines | ||
| 495 | 500 | #define X86_BUG_EIBRS_PBRSB X86_BUG(28) /* EIBRS is vulnerable to Post Barrier RSB Predictions */ |
| 496 | 501 | #define X86_BUG_SMT_RSB X86_BUG(29) /* CPU is vulnerable to Cross-Thread Return Address Predictions */ |
| 497 | 502 | #define X86_BUG_GDS X86_BUG(30) /* CPU is affected by Gather Data Sampling */ |
| 503 | +#define X86_BUG_TDX_PW_MCE X86_BUG(31) /* CPU may incur #MC if non-TD software does partial write to TDX private memory */ | |
| 498 | 504 | |
| 499 | 505 | /* BUG word 2 */ |
| 500 | 506 | #define X86_BUG_SRSO X86_BUG(1*32 + 0) /* AMD SRSO bug */ |
| @@ -237,6 +237,11 @@ · 236 unmodified lines | ||
| 237 | 237 | #define LBR_INFO_CYCLES 0xffff |
| 238 | 238 | #define LBR_INFO_BR_TYPE_OFFSET 56 |
| 239 | 239 | #define LBR_INFO_BR_TYPE (0xfull << LBR_INFO_BR_TYPE_OFFSET) |
| 240 | +#define LBR_INFO_BR_CNTR_OFFSET 32 | |
| 241 | +#define LBR_INFO_BR_CNTR_NUM 4 | |
| 242 | +#define LBR_INFO_BR_CNTR_BITS 2 | |
| 243 | +#define LBR_INFO_BR_CNTR_MASK GENMASK_ULL(LBR_INFO_BR_CNTR_BITS - 1, 0) | |
| 244 | +#define LBR_INFO_BR_CNTR_FULL_MASK GENMASK_ULL(LBR_INFO_BR_CNTR_NUM * LBR_INFO_BR_CNTR_BITS - 1, 0) | |
| 240 | 245 | |
| 241 | 246 | #define MSR_ARCH_LBR_CTL 0x000014ce |
| 242 | 247 | #define ARCH_LBR_CTL_LBREN BIT(0) |
| @@ -536,6 +541,9 @@ · 293 unmodified lines | ||
| 536 | 541 | #define MSR_RELOAD_PMC0 0x000014c1 |
| 537 | 542 | #define MSR_RELOAD_FIXED_CTR0 0x00001309 |
| 538 | 543 | |
| 544 | +/* KeyID partitioning between MKTME and TDX */ | |
| 545 | +#define MSR_IA32_MKTME_KEYID_PARTITIONING 0x00000087 | |
| 546 | + | |
| 539 | 547 | /* |
| 540 | 548 | * AMD64 MSRs. Not complete. See the architecture manual for a more |
| 541 | 549 | * complete list. |
| @@ -562,4 +562,7 @@ struct kvm_pmu_event_filter { · 561 unmodified lines | ||
| 562 | 562 | /* x86-specific KVM_EXIT_HYPERCALL flags. */ |
| 563 | 563 | #define KVM_EXIT_HYPERCALL_LONG_MODE BIT(0) |
| 564 | 564 | |
| 565 | +#define KVM_X86_DEFAULT_VM 0 | |
| 566 | +#define KVM_X86_SW_PROTECTED_VM 1 | |
| 567 | + | |
| 565 | 568 | #endif /* _ASM_X86_KVM_H */ |
| @@ -1,11 +1,11 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | 2 | /* Copyright 2002 Andi Kleen */ |
| 3 | 3 | |
| 4 | +#include <linux/export.h> | |
| 4 | 5 | #include <linux/linkage.h> |
| 5 | 6 | #include <asm/errno.h> |
| 6 | 7 | #include <asm/cpufeatures.h> |
| 7 | 8 | #include <asm/alternative.h> |
| 8 | −#include <asm/export.h> | |
| 9 | 9 | |
| 10 | 10 | .section .noinstr.text, "ax" |
| 11 | 11 | |
| @@ -39,7 +39,7 @@ SYM_TYPED_FUNC_START(__memcpy) · 27 unmodified lines | ||
| 39 | 39 | SYM_FUNC_END(__memcpy) |
| 40 | 40 | EXPORT_SYMBOL(__memcpy) |
| 41 | 41 | |
| 42 | −SYM_FUNC_ALIAS(memcpy, __memcpy) | |
| 42 | +SYM_FUNC_ALIAS_MEMFUNC(memcpy, __memcpy) | |
| 43 | 43 | EXPORT_SYMBOL(memcpy) |
| 44 | 44 | |
| 45 | 45 | SYM_FUNC_START_LOCAL(memcpy_orig) |
| @@ -1,10 +1,10 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | 2 | /* Copyright 2002 Andi Kleen, SuSE Labs */ |
| 3 | 3 | |
| 4 | +#include <linux/export.h> | |
| 4 | 5 | #include <linux/linkage.h> |
| 5 | 6 | #include <asm/cpufeatures.h> |
| 6 | 7 | #include <asm/alternative.h> |
| 7 | −#include <asm/export.h> | |
| 8 | 8 | |
| 9 | 9 | .section .noinstr.text, "ax" |
| 10 | 10 | |
| @@ -40,7 +40,7 @@ SYM_FUNC_START(__memset) · 29 unmodified lines | ||
| 40 | 40 | SYM_FUNC_END(__memset) |
| 41 | 41 | EXPORT_SYMBOL(__memset) |
| 42 | 42 | |
| 43 | −SYM_FUNC_ALIAS(memset, __memset) | |
| 43 | +SYM_FUNC_ALIAS_MEMFUNC(memset, __memset) | |
| 44 | 44 | EXPORT_SYMBOL(memset) |
| 45 | 45 | |
| 46 | 46 | SYM_FUNC_START_LOCAL(memset_orig) |
| @@ -105,9 +105,9 @@ static inline u32 get_unaligned_le24(const void *p) · 104 unmodified lines | ||
| 105 | 105 | |
| 106 | 106 | static inline void __put_unaligned_be24(const u32 val, u8 *p) |
| 107 | 107 | { |
| 108 | − *p++ = val >> 16; | |
| 109 | − *p++ = val >> 8; | |
| 110 | − *p++ = val; | |
| 108 | + *p++ = (val >> 16) & 0xff; | |
| 109 | + *p++ = (val >> 8) & 0xff; | |
| 110 | + *p++ = val & 0xff; | |
| 111 | 111 | } |
| 112 | 112 | |
| 113 | 113 | static inline void put_unaligned_be24(const u32 val, void *p) |
| @@ -117,9 +117,9 @@ static inline void put_unaligned_be24(const u32 val, void *p) · 3 unmodified lines | ||
| 117 | 117 | |
| 118 | 118 | static inline void __put_unaligned_le24(const u32 val, u8 *p) |
| 119 | 119 | { |
| 120 | − *p++ = val; | |
| 121 | − *p++ = val >> 8; | |
| 122 | − *p++ = val >> 16; | |
| 120 | + *p++ = val & 0xff; | |
| 121 | + *p++ = (val >> 8) & 0xff; | |
| 122 | + *p++ = (val >> 16) & 0xff; | |
| 123 | 123 | } |
| 124 | 124 | |
| 125 | 125 | static inline void put_unaligned_le24(const u32 val, void *p) |
| @@ -129,12 +129,12 @@ static inline void put_unaligned_le24(const u32 val, void *p) · 3 unmodified lines | ||
| 129 | 129 | |
| 130 | 130 | static inline void __put_unaligned_be48(const u64 val, u8 *p) |
| 131 | 131 | { |
| 132 | − *p++ = val >> 40; | |
| 133 | − *p++ = val >> 32; | |
| 134 | − *p++ = val >> 24; | |
| 135 | − *p++ = val >> 16; | |
| 136 | − *p++ = val >> 8; | |
| 137 | − *p++ = val; | |
| 132 | + *p++ = (val >> 40) & 0xff; | |
| 133 | + *p++ = (val >> 32) & 0xff; | |
| 134 | + *p++ = (val >> 24) & 0xff; | |
| 135 | + *p++ = (val >> 16) & 0xff; | |
| 136 | + *p++ = (val >> 8) & 0xff; | |
| 137 | + *p++ = val & 0xff; | |
| 138 | 138 | } |
| 139 | 139 | |
| 140 | 140 | static inline void put_unaligned_be48(const u64 val, void *p) |
| @@ -829,8 +829,21 @@ __SYSCALL(__NR_futex_wait, sys_futex_wait) · 828 unmodified lines | ||
| 829 | 829 | #define __NR_futex_requeue 456 |
| 830 | 830 | __SYSCALL(__NR_futex_requeue, sys_futex_requeue) |
| 831 | 831 | |
| 832 | +#define __NR_statmount 457 | |
| 833 | +__SYSCALL(__NR_statmount, sys_statmount) | |
| 834 | + | |
| 835 | +#define __NR_listmount 458 | |
| 836 | +__SYSCALL(__NR_listmount, sys_listmount) | |
| 837 | + | |
| 838 | +#define __NR_lsm_get_self_attr 459 | |
| 839 | +__SYSCALL(__NR_lsm_get_self_attr, sys_lsm_get_self_attr) | |
| 840 | +#define __NR_lsm_set_self_attr 460 | |
| 841 | +__SYSCALL(__NR_lsm_set_self_attr, sys_lsm_set_self_attr) | |
| 842 | +#define __NR_lsm_list_modules 461 | |
| 843 | +__SYSCALL(__NR_lsm_list_modules, sys_lsm_list_modules) | |
| 844 | + | |
| 832 | 845 | #undef __NR_syscalls |
| 833 | −#define __NR_syscalls 457 | |
| 846 | +#define __NR_syscalls 462 | |
| 834 | 847 | |
| 835 | 848 | /* |
| 836 | 849 | * 32 bit systems traditionally used different |
| @@ -713,7 +713,8 @@ struct drm_gem_open { · 712 unmodified lines | ||
| 713 | 713 | /** |
| 714 | 714 | * DRM_CAP_ASYNC_PAGE_FLIP |
| 715 | 715 | * |
| 716 | − * If set to 1, the driver supports &DRM_MODE_PAGE_FLIP_ASYNC. | |
| 716 | + * If set to 1, the driver supports &DRM_MODE_PAGE_FLIP_ASYNC for legacy | |
| 717 | + * page-flips. | |
| 717 | 718 | */ |
| 718 | 719 | #define DRM_CAP_ASYNC_PAGE_FLIP 0x7 |
| 719 | 720 | /** |
| @@ -773,6 +774,13 @@ struct drm_gem_open { · 53 unmodified lines | ||
| 773 | 774 | * :ref:`drm_sync_objects`. |
| 774 | 775 | */ |
| 775 | 776 | #define DRM_CAP_SYNCOBJ_TIMELINE 0x14 |
| 777 | +/** | |
| 778 | + * DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP | |
| 779 | + * | |
| 780 | + * If set to 1, the driver supports &DRM_MODE_PAGE_FLIP_ASYNC for atomic | |
| 781 | + * commits. | |
| 782 | + */ | |
| 783 | +#define DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP 0x15 | |
| 776 | 784 | |
| 777 | 785 | /* DRM_IOCTL_GET_CAP ioctl argument type */ |
| 778 | 786 | struct drm_get_cap { |
| @@ -842,6 +850,31 @@ struct drm_get_cap { · 63 unmodified lines | ||
| 842 | 850 | */ |
| 843 | 851 | #define DRM_CLIENT_CAP_WRITEBACK_CONNECTORS 5 |
| 844 | 852 | |
| 853 | +/** | |
| 854 | + * DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT | |
| 855 | + * | |
| 856 | + * Drivers for para-virtualized hardware (e.g. vmwgfx, qxl, virtio and | |
| 857 | + * virtualbox) have additional restrictions for cursor planes (thus | |
| 858 | + * making cursor planes on those drivers not truly universal,) e.g. | |
| 859 | + * they need cursor planes to act like one would expect from a mouse | |
| 860 | + * cursor and have correctly set hotspot properties. | |
| 861 | + * If this client cap is not set the DRM core will hide cursor plane on | |
| 862 | + * those virtualized drivers because not setting it implies that the | |
| 863 | + * client is not capable of dealing with those extra restictions. | |
| 864 | + * Clients which do set cursor hotspot and treat the cursor plane | |
| 865 | + * like a mouse cursor should set this property. | |
| 866 | + * The client must enable &DRM_CLIENT_CAP_ATOMIC first. | |
| 867 | + * | |
| 868 | + * Setting this property on drivers which do not special case | |
| 869 | + * cursor planes (i.e. non-virtualized drivers) will return | |
| 870 | + * EOPNOTSUPP, which can be used by userspace to gauge | |
| 871 | + * requirements of the hardware/drivers they're running on. | |
| 872 | + * | |
| 873 | + * This capability is always supported for atomic-capable virtualized | |
| 874 | + * drivers starting from kernel version 6.6. | |
| 875 | + */ | |
| 876 | +#define DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT 6 | |
| 877 | + | |
| 845 | 878 | /* DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ |
| 846 | 879 | struct drm_set_client_cap { |
| 847 | 880 | __u64 capability; |
| @@ -893,6 +926,7 @@ struct drm_syncobj_transfer { · 45 unmodified lines | ||
| 893 | 926 | #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0) |
| 894 | 927 | #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1) |
| 895 | 928 | #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE (1 << 2) /* wait for time point to become available */ |
| 929 | +#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE (1 << 3) /* set fence deadline to deadline_nsec */ | |
| 896 | 930 | struct drm_syncobj_wait { |
| 897 | 931 | __u64 handles; |
| 898 | 932 | /* absolute timeout */ |
| @@ -901,6 +935,14 @@ struct drm_syncobj_wait { · 2 unmodified lines | ||
| 901 | 935 | __u32 flags; |
| 902 | 936 | __u32 first_signaled; /* only valid when not waiting all */ |
| 903 | 937 | __u32 pad; |
| 938 | + /** | |
| 939 | + * @deadline_nsec - fence deadline hint | |
| 940 | + * | |
| 941 | + * Deadline hint, in absolute CLOCK_MONOTONIC, to set on backing | |
| 942 | + * fence(s) if the DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE flag is | |
| 943 | + * set. | |
| 944 | + */ | |
| 945 | + __u64 deadline_nsec; | |
| 904 | 946 | }; |
| 905 | 947 | |
| 906 | 948 | struct drm_syncobj_timeline_wait { |
| @@ -913,6 +955,14 @@ struct drm_syncobj_timeline_wait { · 6 unmodified lines | ||
| 913 | 955 | __u32 flags; |
| 914 | 956 | __u32 first_signaled; /* only valid when not waiting all */ |
| 915 | 957 | __u32 pad; |
| 958 | + /** | |
| 959 | + * @deadline_nsec - fence deadline hint | |
| 960 | + * | |
| 961 | + * Deadline hint, in absolute CLOCK_MONOTONIC, to set on backing | |
| 962 | + * fence(s) if the DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE flag is | |
| 963 | + * set. | |
| 964 | + */ | |
| 965 | + __u64 deadline_nsec; | |
| 916 | 966 | }; |
| 917 | 967 | |
| 918 | 968 | /** |
| @@ -1218,6 +1268,26 @@ extern "C" { · 299 unmodified lines | ||
| 1218 | 1268 | |
| 1219 | 1269 | #define DRM_IOCTL_SYNCOBJ_EVENTFD DRM_IOWR(0xCF, struct drm_syncobj_eventfd) |
| 1220 | 1270 | |
| 1271 | +/** | |
| 1272 | + * DRM_IOCTL_MODE_CLOSEFB - Close a framebuffer. | |
| 1273 | + * | |
| 1274 | + * This closes a framebuffer previously added via ADDFB/ADDFB2. The IOCTL | |
| 1275 | + * argument is a framebuffer object ID. | |
| 1276 | + * | |
| 1277 | + * This IOCTL is similar to &DRM_IOCTL_MODE_RMFB, except it doesn't disable | |
| 1278 | + * planes and CRTCs. As long as the framebuffer is used by a plane, it's kept | |
| 1279 | + * alive. When the plane no longer uses the framebuffer (because the | |
| 1280 | + * framebuffer is replaced with another one, or the plane is disabled), the | |
| 1281 | + * framebuffer is cleaned up. | |
| 1282 | + * | |
| 1283 | + * This is useful to implement flicker-free transitions between two processes. | |
| 1284 | + * | |
| 1285 | + * Depending on the threat model, user-space may want to ensure that the | |
| 1286 | + * framebuffer doesn't expose any sensitive user information: closed | |
| 1287 | + * framebuffers attached to a plane can be read back by the next DRM master. | |
| 1288 | + */ | |
| 1289 | +#define DRM_IOCTL_MODE_CLOSEFB DRM_IOWR(0xD0, struct drm_mode_closefb) | |
| 1290 | + | |
| 1221 | 1291 | /* |
| 1222 | 1292 | * Device specific ioctls should only be in their respective headers |
| 1223 | 1293 | * The device specific ioctl range is from 0x40 to 0x9f. |
| @@ -693,7 +693,7 @@ typedef struct drm_i915_irq_wait { · 692 unmodified lines | ||
| 693 | 693 | #define I915_PARAM_HAS_EXEC_FENCE 44 |
| 694 | 694 | |
| 695 | 695 | /* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to capture |
| 696 | − * user specified bufffers for post-mortem debugging of GPU hangs. See | |
| 696 | + * user-specified buffers for post-mortem debugging of GPU hangs. See | |
| 697 | 697 | * EXEC_OBJECT_CAPTURE. |
| 698 | 698 | */ |
| 699 | 699 | #define I915_PARAM_HAS_EXEC_CAPTURE 45 |
| @@ -1606,7 +1606,7 @@ struct drm_i915_gem_busy { · 906 unmodified lines | ||
| 1606 | 1606 | * is accurate. |
| 1607 | 1607 | * |
| 1608 | 1608 | * The returned dword is split into two fields to indicate both |
| 1609 | − * the engine classess on which the object is being read, and the | |
| 1609 | + * the engine classes on which the object is being read, and the | |
| 1610 | 1610 | * engine class on which it is currently being written (if any). |
| 1611 | 1611 | * |
| 1612 | 1612 | * The low word (bits 0:15) indicate if the object is being written |
| @@ -1815,7 +1815,7 @@ struct drm_i915_gem_madvise { · 202 unmodified lines | ||
| 1815 | 1815 | __u32 handle; |
| 1816 | 1816 | |
| 1817 | 1817 | /* Advice: either the buffer will be needed again in the near future, |
| 1818 | − * or wont be and could be discarded under memory pressure. | |
| 1818 | + * or won't be and could be discarded under memory pressure. | |
| 1819 | 1819 | */ |
| 1820 | 1820 | __u32 madv; |
| 1821 | 1821 | |
| @@ -3246,7 +3246,7 @@ struct drm_i915_query_topology_info { · 1424 unmodified lines | ||
| 3246 | 3246 | * // enough to hold our array of engines. The kernel will fill out the |
| 3247 | 3247 | * // item.length for us, which is the number of bytes we need. |
| 3248 | 3248 | * // |
| 3249 | − * // Alternatively a large buffer can be allocated straight away enabling | |
| 3249 | + * // Alternatively a large buffer can be allocated straightaway enabling | |
| 3250 | 3250 | * // querying in one pass, in which case item.length should contain the |
| 3251 | 3251 | * // length of the provided buffer. |
| 3252 | 3252 | * err = ioctl(fd, DRM_IOCTL_I915_QUERY, &query); |
| @@ -3256,7 +3256,7 @@ struct drm_i915_query_topology_info { · 3 unmodified lines | ||
| 3256 | 3256 | * // Now that we allocated the required number of bytes, we call the ioctl |
| 3257 | 3257 | * // again, this time with the data_ptr pointing to our newly allocated |
| 3258 | 3258 | * // blob, which the kernel can then populate with info on all engines. |
| 3259 | − * item.data_ptr = (uintptr_t)&info, | |
| 3259 | + * item.data_ptr = (uintptr_t)&info; | |
| 3260 | 3260 | * |
| 3261 | 3261 | * err = ioctl(fd, DRM_IOCTL_I915_QUERY, &query); |
| 3262 | 3262 | * if (err) ... |
| @@ -3286,7 +3286,7 @@ struct drm_i915_query_topology_info { · 23 unmodified lines | ||
| 3286 | 3286 | /** |
| 3287 | 3287 | * struct drm_i915_engine_info |
| 3288 | 3288 | * |
| 3289 | − * Describes one engine and it's capabilities as known to the driver. | |
| 3289 | + * Describes one engine and its capabilities as known to the driver. | |
| 3290 | 3290 | */ |
| 3291 | 3291 | struct drm_i915_engine_info { |
| 3292 | 3292 | /** @engine: Engine class and instance. */ |
| @@ -116,5 +116,8 @@ · 115 unmodified lines | ||
| 116 | 116 | #define AT_HANDLE_FID AT_REMOVEDIR /* file handle is needed to |
| 117 | 117 | compare object identity and may not |
| 118 | 118 | be usable to open_by_handle_at(2) */ |
| 119 | +#if defined(__KERNEL__) | |
| 120 | +#define AT_GETATTR_NOSEC 0x80000000 | |
| 121 | +#endif | |
| 119 | 122 | |
| 120 | 123 | #endif /* _UAPI_LINUX_FCNTL_H */ |
| @@ -16,76 +16,6 @@ · 15 unmodified lines | ||
| 16 | 16 | |
| 17 | 17 | #define KVM_API_VERSION 12 |
| 18 | 18 | |
| 19 | −/* *** Deprecated interfaces *** */ | |
| 20 | − | |
| 21 | −#define KVM_TRC_SHIFT 16 | |
| 22 | − | |
| 23 | −#define KVM_TRC_ENTRYEXIT (1 << KVM_TRC_SHIFT) | |
| 24 | −#define KVM_TRC_HANDLER (1 << (KVM_TRC_SHIFT + 1)) | |
| 25 | − | |
| 26 | −#define KVM_TRC_VMENTRY (KVM_TRC_ENTRYEXIT + 0x01) | |
| 27 | −#define KVM_TRC_VMEXIT (KVM_TRC_ENTRYEXIT + 0x02) | |
| 28 | −#define KVM_TRC_PAGE_FAULT (KVM_TRC_HANDLER + 0x01) | |
| 29 | − | |
| 30 | −#define KVM_TRC_HEAD_SIZE 12 | |
| 31 | −#define KVM_TRC_CYCLE_SIZE 8 | |
| 32 | −#define KVM_TRC_EXTRA_MAX 7 | |
| 33 | − | |
| 34 | −#define KVM_TRC_INJ_VIRQ (KVM_TRC_HANDLER + 0x02) | |
| 35 | −#define KVM_TRC_REDELIVER_EVT (KVM_TRC_HANDLER + 0x03) | |
| 36 | −#define KVM_TRC_PEND_INTR (KVM_TRC_HANDLER + 0x04) | |
| 37 | −#define KVM_TRC_IO_READ (KVM_TRC_HANDLER + 0x05) | |
| 38 | −#define KVM_TRC_IO_WRITE (KVM_TRC_HANDLER + 0x06) | |
| 39 | −#define KVM_TRC_CR_READ (KVM_TRC_HANDLER + 0x07) | |
| 40 | −#define KVM_TRC_CR_WRITE (KVM_TRC_HANDLER + 0x08) | |
| 41 | −#define KVM_TRC_DR_READ (KVM_TRC_HANDLER + 0x09) | |
| 42 | −#define KVM_TRC_DR_WRITE (KVM_TRC_HANDLER + 0x0A) | |
| 43 | −#define KVM_TRC_MSR_READ (KVM_TRC_HANDLER + 0x0B) | |
| 44 | −#define KVM_TRC_MSR_WRITE (KVM_TRC_HANDLER + 0x0C) | |
| 45 | −#define KVM_TRC_CPUID (KVM_TRC_HANDLER + 0x0D) | |
| 46 | −#define KVM_TRC_INTR (KVM_TRC_HANDLER + 0x0E) | |
| 47 | −#define KVM_TRC_NMI (KVM_TRC_HANDLER + 0x0F) | |
| 48 | −#define KVM_TRC_VMMCALL (KVM_TRC_HANDLER + 0x10) | |
| 49 | −#define KVM_TRC_HLT (KVM_TRC_HANDLER + 0x11) | |
| 50 | −#define KVM_TRC_CLTS (KVM_TRC_HANDLER + 0x12) | |
| 51 | −#define KVM_TRC_LMSW (KVM_TRC_HANDLER + 0x13) | |
| 52 | −#define KVM_TRC_APIC_ACCESS (KVM_TRC_HANDLER + 0x14) | |
| 53 | −#define KVM_TRC_TDP_FAULT (KVM_TRC_HANDLER + 0x15) | |
| 54 | −#define KVM_TRC_GTLB_WRITE (KVM_TRC_HANDLER + 0x16) | |
| 55 | −#define KVM_TRC_STLB_WRITE (KVM_TRC_HANDLER + 0x17) | |
| 56 | −#define KVM_TRC_STLB_INVAL (KVM_TRC_HANDLER + 0x18) | |
| 57 | −#define KVM_TRC_PPC_INSTR (KVM_TRC_HANDLER + 0x19) | |
| 58 | − | |
| 59 | −struct kvm_user_trace_setup { | |
| 60 | − __u32 buf_size; | |
| 61 | − __u32 buf_nr; | |
| 62 | −}; | |
| 63 | − | |
| 64 | −#define __KVM_DEPRECATED_MAIN_W_0x06 \ | |
| 65 | − _IOW(KVMIO, 0x06, struct kvm_user_trace_setup) | |
| 66 | −#define __KVM_DEPRECATED_MAIN_0x07 _IO(KVMIO, 0x07) | |
| 67 | −#define __KVM_DEPRECATED_MAIN_0x08 _IO(KVMIO, 0x08) | |
| 68 | − | |
| 69 | −#define __KVM_DEPRECATED_VM_R_0x70 _IOR(KVMIO, 0x70, struct kvm_assigned_irq) | |
| 70 | − | |
| 71 | −struct kvm_breakpoint { | |
| 72 | − __u32 enabled; | |
| 73 | − __u32 padding; | |
| 74 | − __u64 address; | |
| 75 | −}; | |
| 76 | − | |
| 77 | −struct kvm_debug_guest { | |
| 78 | − __u32 enabled; | |
| 79 | − __u32 pad; | |
| 80 | − struct kvm_breakpoint breakpoints[4]; | |
| 81 | − __u32 singlestep; | |
| 82 | −}; | |
| 83 | − | |
| 84 | −#define __KVM_DEPRECATED_VCPU_W_0x87 _IOW(KVMIO, 0x87, struct kvm_debug_guest) | |
| 85 | − | |
| 86 | −/* *** End of deprecated interfaces *** */ | |
| 87 | − | |
| 88 | − | |
| 89 | 19 | /* for KVM_SET_USER_MEMORY_REGION */ |
| 90 | 20 | struct kvm_userspace_memory_region { |
| 91 | 21 | __u32 slot; |
| @@ -95,6 +25,19 @@ struct kvm_userspace_memory_region { · 3 unmodified lines | ||
| 95 | 25 | __u64 userspace_addr; /* start of the userspace allocated memory */ |
| 96 | 26 | }; |
| 97 | 27 | |
| 28 | +/* for KVM_SET_USER_MEMORY_REGION2 */ | |
| 29 | +struct kvm_userspace_memory_region2 { | |
| 30 | + __u32 slot; | |
| 31 | + __u32 flags; | |
| 32 | + __u64 guest_phys_addr; | |
| 33 | + __u64 memory_size; | |
| 34 | + __u64 userspace_addr; | |
| 35 | + __u64 guest_memfd_offset; | |
| 36 | + __u32 guest_memfd; | |
| 37 | + __u32 pad1; | |
| 38 | + __u64 pad2[14]; | |
| 39 | +}; | |
| 40 | + | |
| 98 | 41 | /* |
| 99 | 42 | * The bit 0 ~ bit 15 of kvm_userspace_memory_region::flags are visible for |
| 100 | 43 | * userspace, other bits are reserved for kvm internal use which are defined |
| @@ -102,6 +45,7 @@ struct kvm_userspace_memory_region { · 1 unmodified line | ||
| 102 | 45 | */ |
| 103 | 46 | #define KVM_MEM_LOG_DIRTY_PAGES (1UL << 0) |
| 104 | 47 | #define KVM_MEM_READONLY (1UL << 1) |
| 48 | +#define KVM_MEM_GUEST_MEMFD (1UL << 2) | |
| 105 | 49 | |
| 106 | 50 | /* for KVM_IRQ_LINE */ |
| 107 | 51 | struct kvm_irq_level { |
| @@ -265,6 +209,7 @@ struct kvm_xen_exit { · 157 unmodified lines | ||
| 265 | 209 | #define KVM_EXIT_RISCV_CSR 36 |
| 266 | 210 | #define KVM_EXIT_NOTIFY 37 |
| 267 | 211 | #define KVM_EXIT_LOONGARCH_IOCSR 38 |
| 212 | +#define KVM_EXIT_MEMORY_FAULT 39 | |
| 268 | 213 | |
| 269 | 214 | /* For KVM_EXIT_INTERNAL_ERROR */ |
| 270 | 215 | /* Emulate instruction failed. */ |
| @@ -518,6 +463,13 @@ struct kvm_run { · 247 unmodified lines | ||
| 518 | 463 | #define KVM_NOTIFY_CONTEXT_INVALID (1 << 0) |
| 519 | 464 | __u32 flags; |
| 520 | 465 | } notify; |
| 466 | + /* KVM_EXIT_MEMORY_FAULT */ | |
| 467 | + struct { | |
| 468 | +#define KVM_MEMORY_EXIT_FLAG_PRIVATE (1ULL << 3) | |
| 469 | + __u64 flags; | |
| 470 | + __u64 gpa; | |
| 471 | + __u64 size; | |
| 472 | + } memory_fault; | |
| 521 | 473 | /* Fix the size of the union. */ |
| 522 | 474 | char padding[256]; |
| 523 | 475 | }; |
| @@ -945,9 +897,6 @@ struct kvm_ppc_resize_hpt { · 421 unmodified lines | ||
| 945 | 897 | */ |
| 946 | 898 | #define KVM_GET_VCPU_MMAP_SIZE _IO(KVMIO, 0x04) /* in bytes */ |
| 947 | 899 | #define KVM_GET_SUPPORTED_CPUID _IOWR(KVMIO, 0x05, struct kvm_cpuid2) |
| 948 | −#define KVM_TRACE_ENABLE __KVM_DEPRECATED_MAIN_W_0x06 | |
| 949 | −#define KVM_TRACE_PAUSE __KVM_DEPRECATED_MAIN_0x07 | |
| 950 | −#define KVM_TRACE_DISABLE __KVM_DEPRECATED_MAIN_0x08 | |
| 951 | 900 | #define KVM_GET_EMULATED_CPUID _IOWR(KVMIO, 0x09, struct kvm_cpuid2) |
| 952 | 901 | #define KVM_GET_MSR_FEATURE_INDEX_LIST _IOWR(KVMIO, 0x0a, struct kvm_msr_list) |
| 953 | 902 | |
| @@ -1201,6 +1150,11 @@ struct kvm_ppc_resize_hpt { · 247 unmodified lines | ||
| 1201 | 1150 | #define KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE 228 |
| 1202 | 1151 | #define KVM_CAP_ARM_SUPPORTED_BLOCK_SIZES 229 |
| 1203 | 1152 | #define KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES 230 |
| 1153 | +#define KVM_CAP_USER_MEMORY2 231 | |
| 1154 | +#define KVM_CAP_MEMORY_FAULT_INFO 232 | |
| 1155 | +#define KVM_CAP_MEMORY_ATTRIBUTES 233 | |
| 1156 | +#define KVM_CAP_GUEST_MEMFD 234 | |
| 1157 | +#define KVM_CAP_VM_TYPES 235 | |
| 1204 | 1158 | |
| 1205 | 1159 | #ifdef KVM_CAP_IRQ_ROUTING |
| 1206 | 1160 | |
| @@ -1291,6 +1245,7 @@ struct kvm_x86_mce { · 84 unmodified lines | ||
| 1291 | 1245 | #define KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL (1 << 4) |
| 1292 | 1246 | #define KVM_XEN_HVM_CONFIG_EVTCHN_SEND (1 << 5) |
| 1293 | 1247 | #define KVM_XEN_HVM_CONFIG_RUNSTATE_UPDATE_FLAG (1 << 6) |
| 1248 | +#define KVM_XEN_HVM_CONFIG_PVCLOCK_TSC_UNSTABLE (1 << 7) | |
| 1294 | 1249 | |
| 1295 | 1250 | struct kvm_xen_hvm_config { |
| 1296 | 1251 | __u32 flags; |
| @@ -1483,6 +1438,8 @@ struct kvm_vfio_spapr_tce { · 186 unmodified lines | ||
| 1483 | 1438 | struct kvm_userspace_memory_region) |
| 1484 | 1439 | #define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47) |
| 1485 | 1440 | #define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO, 0x48, __u64) |
| 1441 | +#define KVM_SET_USER_MEMORY_REGION2 _IOW(KVMIO, 0x49, \ | |
| 1442 | + struct kvm_userspace_memory_region2) | |
| 1486 | 1443 | |
| 1487 | 1444 | /* enable ucontrol for s390 */ |
| 1488 | 1445 | struct kvm_s390_ucas_mapping { |
| @@ -1507,20 +1464,8 @@ struct kvm_s390_ucas_mapping { · 18 unmodified lines | ||
| 1507 | 1464 | _IOW(KVMIO, 0x67, struct kvm_coalesced_mmio_zone) |
| 1508 | 1465 | #define KVM_UNREGISTER_COALESCED_MMIO \ |
| 1509 | 1466 | _IOW(KVMIO, 0x68, struct kvm_coalesced_mmio_zone) |
| 1510 | −#define KVM_ASSIGN_PCI_DEVICE _IOR(KVMIO, 0x69, \ | |
| 1511 | − struct kvm_assigned_pci_dev) | |
| 1512 | 1467 | #define KVM_SET_GSI_ROUTING _IOW(KVMIO, 0x6a, struct kvm_irq_routing) |
| 1513 | −/* deprecated, replaced by KVM_ASSIGN_DEV_IRQ */ | |
| 1514 | −#define KVM_ASSIGN_IRQ __KVM_DEPRECATED_VM_R_0x70 | |
| 1515 | −#define KVM_ASSIGN_DEV_IRQ _IOW(KVMIO, 0x70, struct kvm_assigned_irq) | |
| 1516 | 1468 | #define KVM_REINJECT_CONTROL _IO(KVMIO, 0x71) |
| 1517 | −#define KVM_DEASSIGN_PCI_DEVICE _IOW(KVMIO, 0x72, \ | |
| 1518 | − struct kvm_assigned_pci_dev) | |
| 1519 | −#define KVM_ASSIGN_SET_MSIX_NR _IOW(KVMIO, 0x73, \ | |
| 1520 | − struct kvm_assigned_msix_nr) | |
| 1521 | −#define KVM_ASSIGN_SET_MSIX_ENTRY _IOW(KVMIO, 0x74, \ | |
| 1522 | − struct kvm_assigned_msix_entry) | |
| 1523 | −#define KVM_DEASSIGN_DEV_IRQ _IOW(KVMIO, 0x75, struct kvm_assigned_irq) | |
| 1524 | 1469 | #define KVM_IRQFD _IOW(KVMIO, 0x76, struct kvm_irqfd) |
| 1525 | 1470 | #define KVM_CREATE_PIT2 _IOW(KVMIO, 0x77, struct kvm_pit_config) |
| 1526 | 1471 | #define KVM_SET_BOOT_CPU_ID _IO(KVMIO, 0x78) |
| @@ -1537,9 +1482,6 @@ struct kvm_s390_ucas_mapping { · 10 unmodified lines | ||
| 1537 | 1482 | * KVM_CAP_VM_TSC_CONTROL to set defaults for a VM */ |
| 1538 | 1483 | #define KVM_SET_TSC_KHZ _IO(KVMIO, 0xa2) |
| 1539 | 1484 | #define KVM_GET_TSC_KHZ _IO(KVMIO, 0xa3) |
| 1540 | −/* Available with KVM_CAP_PCI_2_3 */ | |
| 1541 | −#define KVM_ASSIGN_SET_INTX_MASK _IOW(KVMIO, 0xa4, \ | |
| 1542 | − struct kvm_assigned_pci_dev) | |
| 1543 | 1485 | /* Available with KVM_CAP_SIGNAL_MSI */ |
| 1544 | 1486 | #define KVM_SIGNAL_MSI _IOW(KVMIO, 0xa5, struct kvm_msi) |
| 1545 | 1487 | /* Available with KVM_CAP_PPC_GET_SMMU_INFO */ |
| @@ -1592,8 +1534,6 @@ struct kvm_s390_ucas_mapping { · 46 unmodified lines | ||
| 1592 | 1534 | #define KVM_SET_SREGS _IOW(KVMIO, 0x84, struct kvm_sregs) |
| 1593 | 1535 | #define KVM_TRANSLATE _IOWR(KVMIO, 0x85, struct kvm_translation) |
| 1594 | 1536 | #define KVM_INTERRUPT _IOW(KVMIO, 0x86, struct kvm_interrupt) |
| 1595 | −/* KVM_DEBUG_GUEST is no longer supported, use KVM_SET_GUEST_DEBUG instead */ | |
| 1596 | −#define KVM_DEBUG_GUEST __KVM_DEPRECATED_VCPU_W_0x87 | |
| 1597 | 1537 | #define KVM_GET_MSRS _IOWR(KVMIO, 0x88, struct kvm_msrs) |
| 1598 | 1538 | #define KVM_SET_MSRS _IOW(KVMIO, 0x89, struct kvm_msrs) |
| 1599 | 1539 | #define KVM_SET_CPUID _IOW(KVMIO, 0x8a, struct kvm_cpuid) |
| @@ -2267,4 +2207,24 @@ struct kvm_s390_zpci_op { · 667 unmodified lines | ||
| 2267 | 2207 | /* flags for kvm_s390_zpci_op->u.reg_aen.flags */ |
| 2268 | 2208 | #define KVM_S390_ZPCIOP_REGAEN_HOST (1 << 0) |
| 2269 | 2209 | |
| 2210 | +/* Available with KVM_CAP_MEMORY_ATTRIBUTES */ | |
| 2211 | +#define KVM_SET_MEMORY_ATTRIBUTES _IOW(KVMIO, 0xd2, struct kvm_memory_attributes) | |
| 2212 | + | |
| 2213 | +struct kvm_memory_attributes { | |
| 2214 | + __u64 address; | |
| 2215 | + __u64 size; | |
| 2216 | + __u64 attributes; | |
| 2217 | + __u64 flags; | |
| 2218 | +}; | |
| 2219 | + | |
| 2220 | +#define KVM_MEMORY_ATTRIBUTE_PRIVATE (1ULL << 3) | |
| 2221 | + | |
| 2222 | +#define KVM_CREATE_GUEST_MEMFD _IOWR(KVMIO, 0xd4, struct kvm_create_guest_memfd) | |
| 2223 | + | |
| 2224 | +struct kvm_create_guest_memfd { | |
| 2225 | + __u64 size; | |
| 2226 | + __u64 flags; | |
| 2227 | + __u64 reserved[6]; | |
| 2228 | +}; | |
| 2229 | + | |
| 2270 | 2230 | #endif /* __LINUX_KVM_H */ |
| @@ -138,4 +138,74 @@ struct mount_attr { · 137 unmodified lines | ||
| 138 | 138 | /* List of all mount_attr versions. */ |
| 139 | 139 | #define MOUNT_ATTR_SIZE_VER0 32 /* sizeof first published struct */ |
| 140 | 140 | |
| 141 | + | |
| 142 | +/* | |
| 143 | + * Structure for getting mount/superblock/filesystem info with statmount(2). | |
| 144 | + * | |
| 145 | + * The interface is similar to statx(2): individual fields or groups can be | |
| 146 | + * selected with the @mask argument of statmount(). Kernel will set the @mask | |
| 147 | + * field according to the supported fields. | |
| 148 | + * | |
| 149 | + * If string fields are selected, then the caller needs to pass a buffer that | |
| 150 | + * has space after the fixed part of the structure. Nul terminated strings are | |
| 151 | + * copied there and offsets relative to @str are stored in the relevant fields. | |
| 152 | + * If the buffer is too small, then EOVERFLOW is returned. The actually used | |
| 153 | + * size is returned in @size. | |
| 154 | + */ | |
| 155 | +struct statmount { | |
| 156 | + __u32 size; /* Total size, including strings */ | |
| 157 | + __u32 __spare1; | |
| 158 | + __u64 mask; /* What results were written */ | |
| 159 | + __u32 sb_dev_major; /* Device ID */ | |
| 160 | + __u32 sb_dev_minor; | |
| 161 | + __u64 sb_magic; /* ..._SUPER_MAGIC */ | |
| 162 | + __u32 sb_flags; /* SB_{RDONLY,SYNCHRONOUS,DIRSYNC,LAZYTIME} */ | |
| 163 | + __u32 fs_type; /* [str] Filesystem type */ | |
| 164 | + __u64 mnt_id; /* Unique ID of mount */ | |
| 165 | + __u64 mnt_parent_id; /* Unique ID of parent (for root == mnt_id) */ | |
| 166 | + __u32 mnt_id_old; /* Reused IDs used in proc/.../mountinfo */ | |
| 167 | + __u32 mnt_parent_id_old; | |
| 168 | + __u64 mnt_attr; /* MOUNT_ATTR_... */ | |
| 169 | + __u64 mnt_propagation; /* MS_{SHARED,SLAVE,PRIVATE,UNBINDABLE} */ | |
| 170 | + __u64 mnt_peer_group; /* ID of shared peer group */ | |
| 171 | + __u64 mnt_master; /* Mount receives propagation from this ID */ | |
| 172 | + __u64 propagate_from; /* Propagation from in current namespace */ | |
| 173 | + __u32 mnt_root; /* [str] Root of mount relative to root of fs */ | |
| 174 | + __u32 mnt_point; /* [str] Mountpoint relative to current root */ | |
| 175 | + __u64 __spare2[50]; | |
| 176 | + char str[]; /* Variable size part containing strings */ | |
| 177 | +}; | |
| 178 | + | |
| 179 | +/* | |
| 180 | + * Structure for passing mount ID and miscellaneous parameters to statmount(2) | |
| 181 | + * and listmount(2). | |
| 182 | + * | |
| 183 | + * For statmount(2) @param represents the request mask. | |
| 184 | + * For listmount(2) @param represents the last listed mount id (or zero). | |
| 185 | + */ | |
| 186 | +struct mnt_id_req { | |
| 187 | + __u32 size; | |
| 188 | + __u32 spare; | |
| 189 | + __u64 mnt_id; | |
| 190 | + __u64 param; | |
| 191 | +}; | |
| 192 | + | |
| 193 | +/* List of all mnt_id_req versions. */ | |
| 194 | +#define MNT_ID_REQ_SIZE_VER0 24 /* sizeof first published struct */ | |
| 195 | + | |
| 196 | +/* | |
| 197 | + * @mask bits for statmount(2) | |
| 198 | + */ | |
| 199 | +#define STATMOUNT_SB_BASIC 0x00000001U /* Want/got sb_... */ | |
| 200 | +#define STATMOUNT_MNT_BASIC 0x00000002U /* Want/got mnt_... */ | |
| 201 | +#define STATMOUNT_PROPAGATE_FROM 0x00000004U /* Want/got propagate_from */ | |
| 202 | +#define STATMOUNT_MNT_ROOT 0x00000008U /* Want/got mnt_root */ | |
| 203 | +#define STATMOUNT_MNT_POINT 0x00000010U /* Want/got mnt_point */ | |
| 204 | +#define STATMOUNT_FS_TYPE 0x00000020U /* Want/got fs_type */ | |
| 205 | + | |
| 206 | +/* | |
| 207 | + * Special @mnt_id values that can be passed to listmount | |
| 208 | + */ | |
| 209 | +#define LSMT_ROOT 0xffffffffffffffff /* root mount */ | |
| 210 | + | |
| 141 | 211 | #endif /* _UAPI_LINUX_MOUNT_H */ |
| @@ -154,6 +154,7 @@ struct statx { · 153 unmodified lines | ||
| 154 | 154 | #define STATX_BTIME 0x00000800U /* Want/got stx_btime */ |
| 155 | 155 | #define STATX_MNT_ID 0x00001000U /* Got stx_mnt_id */ |
| 156 | 156 | #define STATX_DIOALIGN 0x00002000U /* Want/got direct I/O alignment info */ |
| 157 | +#define STATX_MNT_ID_UNIQUE 0x00004000U /* Want/got extended stx_mount_id */ | |
| 157 | 158 | |
| 158 | 159 | #define STATX__RESERVED 0x80000000U /* Reserved for future struct statx expansion */ |
| 159 | 160 | |
| @@ -47,6 +47,10 @@ Print PMU events and metrics limited to the specific PMU name. · 46 unmodified lines | ||
| 47 | 47 | --json:: |
| 48 | 48 | Output in JSON format. |
| 49 | 49 | |
| 50 | +-o:: | |
| 51 | +--output=:: | |
| 52 | + Output file name. By default output is written to stdout. | |
| 53 | + | |
| 50 | 54 | [[EVENT_MODIFIERS]] |
| 51 | 55 | EVENT MODIFIERS |
| 52 | 56 | --------------- |
| @@ -236,6 +236,16 @@ else · 235 unmodified lines | ||
| 236 | 236 | SHELLCHECK := $(shell which shellcheck 2> /dev/null) |
| 237 | 237 | endif |
| 238 | 238 | |
| 239 | +# shellcheck is using in tools/perf/tests/Build with option -a/--check-sourced ( | |
| 240 | +# introduced in v0.4.7) and -S/--severity (introduced in v0.6.0). So make the | |
| 241 | +# minimal shellcheck version as v0.6.0. | |
| 242 | +ifneq ($(SHELLCHECK),) | |
| 243 | + ifeq ($(shell expr $(shell $(SHELLCHECK) --version | grep version: | \ | |
| 244 | + sed -e 's/.\+ \([0-9]\+\).\([0-9]\+\).\([0-9]\+\)/\1\2\3/g') \< 060), 1) | |
| 245 | + SHELLCHECK := | |
| 246 | + endif | |
| 247 | +endif | |
| 248 | + | |
| 239 | 249 | export srctree OUTPUT RM CC CXX LD AR CFLAGS CXXFLAGS V BISON FLEX AWK |
| 240 | 250 | export HOSTCC HOSTLD HOSTAR HOSTCFLAGS SHELLCHECK |
| 241 | 251 | |
| @@ -30,6 +30,8 @@ · 29 unmodified lines | ||
| 30 | 30 | * functions. |
| 31 | 31 | */ |
| 32 | 32 | struct print_state { |
| 33 | + /** @fp: File to write output to. */ | |
| 34 | + FILE *fp; | |
| 33 | 35 | /** |
| 34 | 36 | * @pmu_glob: Optionally restrict PMU and metric matching to PMU or |
| 35 | 37 | * debugfs subsystem name. |
| @@ -66,13 +68,15 @@ static void default_print_start(void *ps) · 30 unmodified lines | ||
| 66 | 68 | { |
| 67 | 69 | struct print_state *print_state = ps; |
| 68 | 70 | |
| 69 | − if (!print_state->name_only && pager_in_use()) | |
| 70 | − printf("\nList of pre-defined events (to be used in -e or -M):\n\n"); | |
| 71 | + if (!print_state->name_only && pager_in_use()) { | |
| 72 | + fprintf(print_state->fp, | |
| 73 | + "\nList of pre-defined events (to be used in -e or -M):\n\n"); | |
| 74 | + } | |
| 71 | 75 | } |
| 72 | 76 | |
| 73 | 77 | static void default_print_end(void *print_state __maybe_unused) {} |
| 74 | 78 | |
| 75 | −static void wordwrap(const char *s, int start, int max, int corr) | |
| 79 | +static void wordwrap(FILE *fp, const char *s, int start, int max, int corr) | |
| 76 | 80 | { |
| 77 | 81 | int column = start; |
| 78 | 82 | int n; |
| @@ -82,10 +86,10 @@ static void wordwrap(const char *s, int start, int max, int corr) · 3 unmodified lines | ||
| 82 | 86 | int wlen = strcspn(s, " \t\n"); |
| 83 | 87 | |
| 84 | 88 | if ((column + wlen >= max && column > start) || saw_newline) { |
| 85 | − printf("\n%*s", start, ""); | |
| 89 | + fprintf(fp, "\n%*s", start, ""); | |
| 86 | 90 | column = start + corr; |
| 87 | 91 | } |
| 88 | − n = printf("%s%.*s", column > start ? " " : "", wlen, s); | |
| 92 | + n = fprintf(fp, "%s%.*s", column > start ? " " : "", wlen, s); | |
| 89 | 93 | if (n <= 0) |
| 90 | 94 | break; |
| 91 | 95 | saw_newline = s[wlen] == '\n'; |
| @@ -104,6 +108,7 @@ static void default_print_event(void *ps, const char *pmu_name, const char *topi · 12 unmodified lines | ||
| 104 | 108 | { |
| 105 | 109 | struct print_state *print_state = ps; |
| 106 | 110 | int pos; |
| 111 | + FILE *fp = print_state->fp; | |
| 107 | 112 | |
| 108 | 113 | if (deprecated && !print_state->deprecated) |
| 109 | 114 | return; |
| @@ -119,30 +124,30 @@ static void default_print_event(void *ps, const char *pmu_name, const char *topi · 9 unmodified lines | ||
| 119 | 124 | |
| 120 | 125 | if (print_state->name_only) { |
| 121 | 126 | if (event_alias && strlen(event_alias)) |
| 122 | − printf("%s ", event_alias); | |
| 127 | + fprintf(fp, "%s ", event_alias); | |
| 123 | 128 | else |
| 124 | − printf("%s ", event_name); | |
| 129 | + fprintf(fp, "%s ", event_name); | |
| 125 | 130 | return; |
| 126 | 131 | } |
| 127 | 132 | |
| 128 | 133 | if (strcmp(print_state->last_topic, topic ?: "")) { |
| 129 | 134 | if (topic) |
| 130 | − printf("\n%s:\n", topic); | |
| 135 | + fprintf(fp, "\n%s:\n", topic); | |
| 131 | 136 | zfree(&print_state->last_topic); |
| 132 | 137 | print_state->last_topic = strdup(topic ?: ""); |
| 133 | 138 | } |
| 134 | 139 | |
| 135 | 140 | if (event_alias && strlen(event_alias)) |
| 136 | − pos = printf(" %s OR %s", event_name, event_alias); | |
| 141 | + pos = fprintf(fp, " %s OR %s", event_name, event_alias); | |
| 137 | 142 | else |
| 138 | − pos = printf(" %s", event_name); | |
| 143 | + pos = fprintf(fp, " %s", event_name); | |
| 139 | 144 | |
| 140 | 145 | if (!topic && event_type_desc) { |
| 141 | 146 | for (; pos < 53; pos++) |
| 142 | − putchar(' '); | |
| 143 | − printf("[%s]\n", event_type_desc); | |
| 147 | + fputc(' ', fp); | |
| 148 | + fprintf(fp, "[%s]\n", event_type_desc); | |
| 144 | 149 | } else |
| 145 | − putchar('\n'); | |
| 150 | + fputc('\n', fp); | |
| 146 | 151 | |
| 147 | 152 | if (desc && print_state->desc) { |
| 148 | 153 | char *desc_with_unit = NULL; |
| @@ -155,22 +160,22 @@ static void default_print_event(void *ps, const char *pmu_name, const char *topi · 6 unmodified lines | ||
| 155 | 160 | ? "%s. Unit: %s" : "%s Unit: %s", |
| 156 | 161 | desc, pmu_name); |
| 157 | 162 | } |
| 158 | − printf("%*s", 8, "["); | |
| 159 | − wordwrap(desc_len > 0 ? desc_with_unit : desc, 8, pager_get_columns(), 0); | |
| 160 | − printf("]\n"); | |
| 163 | + fprintf(fp, "%*s", 8, "["); | |
| 164 | + wordwrap(fp, desc_len > 0 ? desc_with_unit : desc, 8, pager_get_columns(), 0); | |
| 165 | + fprintf(fp, "]\n"); | |
| 161 | 166 | free(desc_with_unit); |
| 162 | 167 | } |
| 163 | 168 | long_desc = long_desc ?: desc; |
| 164 | 169 | if (long_desc && print_state->long_desc) { |
| 165 | − printf("%*s", 8, "["); | |
| 166 | − wordwrap(long_desc, 8, pager_get_columns(), 0); | |
| 167 | − printf("]\n"); | |
| 170 | + fprintf(fp, "%*s", 8, "["); | |
| 171 | + wordwrap(fp, long_desc, 8, pager_get_columns(), 0); | |
| 172 | + fprintf(fp, "]\n"); | |
| 168 | 173 | } |
| 169 | 174 | |
| 170 | 175 | if (print_state->detailed && encoding_desc) { |
| 171 | − printf("%*s", 8, ""); | |
| 172 | − wordwrap(encoding_desc, 8, pager_get_columns(), 0); | |
| 173 | − putchar('\n'); | |
| 176 | + fprintf(fp, "%*s", 8, ""); | |
| 177 | + wordwrap(fp, encoding_desc, 8, pager_get_columns(), 0); | |
| 178 | + fputc('\n', fp); | |
| 174 | 179 | } |
| 175 | 180 | } |
| 176 | 181 | |
| @@ -184,6 +189,7 @@ static void default_print_metric(void *ps, · 7 unmodified lines | ||
| 184 | 189 | const char *unit __maybe_unused) |
| 185 | 190 | { |
| 186 | 191 | struct print_state *print_state = ps; |
| 192 | + FILE *fp = print_state->fp; | |
| 187 | 193 | |
| 188 | 194 | if (print_state->event_glob && |
| 189 | 195 | (!print_state->metrics || !name || !strglobmatch(name, print_state->event_glob)) && |
| @@ -192,27 +198,27 @@ static void default_print_metric(void *ps, · 2 unmodified lines | ||
| 192 | 198 | |
| 193 | 199 | if (!print_state->name_only && !print_state->last_metricgroups) { |
| 194 | 200 | if (print_state->metricgroups) { |
| 195 | − printf("\nMetric Groups:\n"); | |
| 201 | + fprintf(fp, "\nMetric Groups:\n"); | |
| 196 | 202 | if (!print_state->metrics) |
| 197 | − putchar('\n'); | |
| 203 | + fputc('\n', fp); | |
| 198 | 204 | } else { |
| 199 | − printf("\nMetrics:\n\n"); | |
| 205 | + fprintf(fp, "\nMetrics:\n\n"); | |
| 200 | 206 | } |
| 201 | 207 | } |
| 202 | 208 | if (!print_state->last_metricgroups || |
| 203 | 209 | strcmp(print_state->last_metricgroups, group ?: "")) { |
| 204 | 210 | if (group && print_state->metricgroups) { |
| 205 | 211 | if (print_state->name_only) |
| 206 | − printf("%s ", group); | |
| 212 | + fprintf(fp, "%s ", group); | |
| 207 | 213 | else if (print_state->metrics) { |
| 208 | 214 | const char *gdesc = describe_metricgroup(group); |
| 209 | 215 | |
| 210 | 216 | if (gdesc) |
| 211 | − printf("\n%s: [%s]\n", group, gdesc); | |
| 217 | + fprintf(fp, "\n%s: [%s]\n", group, gdesc); | |
| 212 | 218 | else |
| 213 | − printf("\n%s:\n", group); | |
| 219 | + fprintf(fp, "\n%s:\n", group); | |
| 214 | 220 | } else |
| 215 | − printf("%s\n", group); | |
| 221 | + fprintf(fp, "%s\n", group); | |
| 216 | 222 | } |
| 217 | 223 | zfree(&print_state->last_metricgroups); |
| 218 | 224 | print_state->last_metricgroups = strdup(group ?: ""); |
| @@ -223,53 +229,59 @@ static void default_print_metric(void *ps, · 4 unmodified lines | ||
| 223 | 229 | if (print_state->name_only) { |
| 224 | 230 | if (print_state->metrics && |
| 225 | 231 | !strlist__has_entry(print_state->visited_metrics, name)) { |
| 226 | − printf("%s ", name); | |
| 232 | + fprintf(fp, "%s ", name); | |
| 227 | 233 | strlist__add(print_state->visited_metrics, name); |
| 228 | 234 | } |
| 229 | 235 | return; |
| 230 | 236 | } |
| 231 | − printf(" %s\n", name); | |
| 237 | + fprintf(fp, " %s\n", name); | |
| 232 | 238 | |
| 233 | 239 | if (desc && print_state->desc) { |
| 234 | − printf("%*s", 8, "["); | |
| 235 | − wordwrap(desc, 8, pager_get_columns(), 0); | |
| 236 | − printf("]\n"); | |
| 240 | + fprintf(fp, "%*s", 8, "["); | |
| 241 | + wordwrap(fp, desc, 8, pager_get_columns(), 0); | |
| 242 | + fprintf(fp, "]\n"); | |
| 237 | 243 | } |
| 238 | 244 | if (long_desc && print_state->long_desc) { |
| 239 | − printf("%*s", 8, "["); | |
| 240 | − wordwrap(long_desc, 8, pager_get_columns(), 0); | |
| 241 | − printf("]\n"); | |
| 245 | + fprintf(fp, "%*s", 8, "["); | |
| 246 | + wordwrap(fp, long_desc, 8, pager_get_columns(), 0); | |
| 247 | + fprintf(fp, "]\n"); | |
| 242 | 248 | } |
| 243 | 249 | if (expr && print_state->detailed) { |
| 244 | − printf("%*s", 8, "["); | |
| 245 | − wordwrap(expr, 8, pager_get_columns(), 0); | |
| 246 | − printf("]\n"); | |
| 250 | + fprintf(fp, "%*s", 8, "["); | |
| 251 | + wordwrap(fp, expr, 8, pager_get_columns(), 0); | |
| 252 | + fprintf(fp, "]\n"); | |
| 247 | 253 | } |
| 248 | 254 | if (threshold && print_state->detailed) { |
| 249 | − printf("%*s", 8, "["); | |
| 250 | − wordwrap(threshold, 8, pager_get_columns(), 0); | |
| 251 | − printf("]\n"); | |
| 255 | + fprintf(fp, "%*s", 8, "["); | |
| 256 | + wordwrap(fp, threshold, 8, pager_get_columns(), 0); | |
| 257 | + fprintf(fp, "]\n"); | |
| 252 | 258 | } |
| 253 | 259 | } |
| 254 | 260 | |
| 255 | 261 | struct json_print_state { |
| 262 | + /** @fp: File to write output to. */ | |
| 263 | + FILE *fp; | |
| 256 | 264 | /** Should a separator be printed prior to the next item? */ |
| 257 | 265 | bool need_sep; |
| 258 | 266 | }; |
| 259 | 267 | |
| 260 | −static void json_print_start(void *print_state __maybe_unused) | |
| 268 | +static void json_print_start(void *ps) | |
| 261 | 269 | { |
| 262 | − printf("[\n"); | |
| 270 | + struct json_print_state *print_state = ps; | |
| 271 | + FILE *fp = print_state->fp; | |
| 272 | + | |
| 273 | + fprintf(fp, "[\n"); | |
| 263 | 274 | } |
| 264 | 275 | |
| 265 | 276 | static void json_print_end(void *ps) |
| 266 | 277 | { |
| 267 | 278 | struct json_print_state *print_state = ps; |
| 279 | + FILE *fp = print_state->fp; | |
| 268 | 280 | |
| 269 | − printf("%s]\n", print_state->need_sep ? "\n" : ""); | |
| 281 | + fprintf(fp, "%s]\n", print_state->need_sep ? "\n" : ""); | |
| 270 | 282 | } |
| 271 | 283 | |
| 272 | −static void fix_escape_printf(struct strbuf *buf, const char *fmt, ...) | |
| 284 | +static void fix_escape_fprintf(FILE *fp, struct strbuf *buf, const char *fmt, ...) | |
| 273 | 285 | { |
| 274 | 286 | va_list args; |
| 275 | 287 | |
| @@ -318,7 +330,7 @@ static void fix_escape_printf(struct strbuf *buf, const char *fmt, ...) · 42 unmodified lines | ||
| 318 | 330 | } |
| 319 | 331 | } |
| 320 | 332 | va_end(args); |
| 321 | − fputs(buf->buf, stdout); | |
| 333 | + fputs(buf->buf, fp); | |
| 322 | 334 | } |
| 323 | 335 | |
| 324 | 336 | static void json_print_event(void *ps, const char *pmu_name, const char *topic, |
| @@ -330,60 +342,71 @@ static void json_print_event(void *ps, const char *pmu_name, const char *topic, · 5 unmodified lines | ||
| 330 | 342 | { |
| 331 | 343 | struct json_print_state *print_state = ps; |
| 332 | 344 | bool need_sep = false; |
| 345 | + FILE *fp = print_state->fp; | |
| 333 | 346 | struct strbuf buf; |
| 334 | 347 | |
| 335 | 348 | strbuf_init(&buf, 0); |
| 336 | − printf("%s{\n", print_state->need_sep ? ",\n" : ""); | |
| 349 | + fprintf(fp, "%s{\n", print_state->need_sep ? ",\n" : ""); | |
| 337 | 350 | print_state->need_sep = true; |
| 338 | 351 | if (pmu_name) { |
| 339 | − fix_escape_printf(&buf, "\t\"Unit\": \"%S\"", pmu_name); | |
| 352 | + fix_escape_fprintf(fp, &buf, "\t\"Unit\": \"%S\"", pmu_name); | |
| 340 | 353 | need_sep = true; |
| 341 | 354 | } |
| 342 | 355 | if (topic) { |
| 343 | − fix_escape_printf(&buf, "%s\t\"Topic\": \"%S\"", need_sep ? ",\n" : "", topic); | |
| 356 | + fix_escape_fprintf(fp, &buf, "%s\t\"Topic\": \"%S\"", | |
| 357 | + need_sep ? ",\n" : "", | |
| 358 | + topic); | |
| 344 | 359 | need_sep = true; |
| 345 | 360 | } |
| 346 | 361 | if (event_name) { |
| 347 | − fix_escape_printf(&buf, "%s\t\"EventName\": \"%S\"", need_sep ? ",\n" : "", | |
| 348 | − event_name); | |
| 362 | + fix_escape_fprintf(fp, &buf, "%s\t\"EventName\": \"%S\"", | |
| 363 | + need_sep ? ",\n" : "", | |
| 364 | + event_name); | |
| 349 | 365 | need_sep = true; |
| 350 | 366 | } |
| 351 | 367 | if (event_alias && strlen(event_alias)) { |
| 352 | − fix_escape_printf(&buf, "%s\t\"EventAlias\": \"%S\"", need_sep ? ",\n" : "", | |
| 353 | − event_alias); | |
| 368 | + fix_escape_fprintf(fp, &buf, "%s\t\"EventAlias\": \"%S\"", | |
| 369 | + need_sep ? ",\n" : "", | |
| 370 | + event_alias); | |
| 354 | 371 | need_sep = true; |
| 355 | 372 | } |
| 356 | 373 | if (scale_unit && strlen(scale_unit)) { |
| 357 | − fix_escape_printf(&buf, "%s\t\"ScaleUnit\": \"%S\"", need_sep ? ",\n" : "", | |
| 358 | − scale_unit); | |
| 374 | + fix_escape_fprintf(fp, &buf, "%s\t\"ScaleUnit\": \"%S\"", | |
| 375 | + need_sep ? ",\n" : "", | |
| 376 | + scale_unit); | |
| 359 | 377 | need_sep = true; |
| 360 | 378 | } |
| 361 | 379 | if (event_type_desc) { |
| 362 | − fix_escape_printf(&buf, "%s\t\"EventType\": \"%S\"", need_sep ? ",\n" : "", | |
| 363 | − event_type_desc); | |
| 380 | + fix_escape_fprintf(fp, &buf, "%s\t\"EventType\": \"%S\"", | |
| 381 | + need_sep ? ",\n" : "", | |
| 382 | + event_type_desc); | |
| 364 | 383 | need_sep = true; |
| 365 | 384 | } |
| 366 | 385 | if (deprecated) { |
| 367 | − fix_escape_printf(&buf, "%s\t\"Deprecated\": \"%S\"", need_sep ? ",\n" : "", | |
| 368 | − deprecated ? "1" : "0"); | |
| 386 | + fix_escape_fprintf(fp, &buf, "%s\t\"Deprecated\": \"%S\"", | |
| 387 | + need_sep ? ",\n" : "", | |
| 388 | + deprecated ? "1" : "0"); | |
| 369 | 389 | need_sep = true; |
| 370 | 390 | } |
| 371 | 391 | if (desc) { |
| 372 | − fix_escape_printf(&buf, "%s\t\"BriefDescription\": \"%S\"", need_sep ? ",\n" : "", | |
| 373 | − desc); | |
| 392 | + fix_escape_fprintf(fp, &buf, "%s\t\"BriefDescription\": \"%S\"", | |
| 393 | + need_sep ? ",\n" : "", | |
| 394 | + desc); | |
| 374 | 395 | need_sep = true; |
| 375 | 396 | } |
| 376 | 397 | if (long_desc) { |
| 377 | − fix_escape_printf(&buf, "%s\t\"PublicDescription\": \"%S\"", need_sep ? ",\n" : "", | |
| 378 | − long_desc); | |
| 398 | + fix_escape_fprintf(fp, &buf, "%s\t\"PublicDescription\": \"%S\"", | |
| 399 | + need_sep ? ",\n" : "", | |
| 400 | + long_desc); | |
| 379 | 401 | need_sep = true; |
| 380 | 402 | } |
| 381 | 403 | if (encoding_desc) { |
| 382 | − fix_escape_printf(&buf, "%s\t\"Encoding\": \"%S\"", need_sep ? ",\n" : "", | |
| 383 | − encoding_desc); | |
| 404 | + fix_escape_fprintf(fp, &buf, "%s\t\"Encoding\": \"%S\"", | |
| 405 | + need_sep ? ",\n" : "", | |
| 406 | + encoding_desc); | |
| 384 | 407 | need_sep = true; |
| 385 | 408 | } |
| 386 | − printf("%s}", need_sep ? "\n" : ""); | |
| 409 | + fprintf(fp, "%s}", need_sep ? "\n" : ""); | |
| 387 | 410 | strbuf_release(&buf); |
| 388 | 411 | } |
| 389 | 412 | |
| @@ -394,43 +417,53 @@ static void json_print_metric(void *ps __maybe_unused, const char *group, · 4 unmodified lines | ||
| 394 | 417 | { |
| 395 | 418 | struct json_print_state *print_state = ps; |
| 396 | 419 | bool need_sep = false; |
| 420 | + FILE *fp = print_state->fp; | |
| 397 | 421 | struct strbuf buf; |
| 398 | 422 | |
| 399 | 423 | strbuf_init(&buf, 0); |
| 400 | − printf("%s{\n", print_state->need_sep ? ",\n" : ""); | |
| 424 | + fprintf(fp, "%s{\n", print_state->need_sep ? ",\n" : ""); | |
| 401 | 425 | print_state->need_sep = true; |
| 402 | 426 | if (group) { |
| 403 | − fix_escape_printf(&buf, "\t\"MetricGroup\": \"%S\"", group); | |
| 427 | + fix_escape_fprintf(fp, &buf, "\t\"MetricGroup\": \"%S\"", group); | |
| 404 | 428 | need_sep = true; |
| 405 | 429 | } |
| 406 | 430 | if (name) { |
| 407 | − fix_escape_printf(&buf, "%s\t\"MetricName\": \"%S\"", need_sep ? ",\n" : "", name); | |
| 431 | + fix_escape_fprintf(fp, &buf, "%s\t\"MetricName\": \"%S\"", | |
| 432 | + need_sep ? ",\n" : "", | |
| 433 | + name); | |
| 408 | 434 | need_sep = true; |
| 409 | 435 | } |
| 410 | 436 | if (expr) { |
| 411 | − fix_escape_printf(&buf, "%s\t\"MetricExpr\": \"%S\"", need_sep ? ",\n" : "", expr); | |
| 437 | + fix_escape_fprintf(fp, &buf, "%s\t\"MetricExpr\": \"%S\"", | |
| 438 | + need_sep ? ",\n" : "", | |
| 439 | + expr); | |
| 412 | 440 | need_sep = true; |
| 413 | 441 | } |
| 414 | 442 | if (threshold) { |
| 415 | − fix_escape_printf(&buf, "%s\t\"MetricThreshold\": \"%S\"", need_sep ? ",\n" : "", | |
| 416 | − threshold); | |
| 443 | + fix_escape_fprintf(fp, &buf, "%s\t\"MetricThreshold\": \"%S\"", | |
| 444 | + need_sep ? ",\n" : "", | |
| 445 | + threshold); | |
| 417 | 446 | need_sep = true; |
| 418 | 447 | } |
| 419 | 448 | if (unit) { |
| 420 | − fix_escape_printf(&buf, "%s\t\"ScaleUnit\": \"%S\"", need_sep ? ",\n" : "", unit); | |
| 449 | + fix_escape_fprintf(fp, &buf, "%s\t\"ScaleUnit\": \"%S\"", | |
| 450 | + need_sep ? ",\n" : "", | |
| 451 | + unit); | |
| 421 | 452 | need_sep = true; |
| 422 | 453 | } |
| 423 | 454 | if (desc) { |
| 424 | − fix_escape_printf(&buf, "%s\t\"BriefDescription\": \"%S\"", need_sep ? ",\n" : "", | |
| 425 | − desc); | |
| 455 | + fix_escape_fprintf(fp, &buf, "%s\t\"BriefDescription\": \"%S\"", | |
| 456 | + need_sep ? ",\n" : "", | |
| 457 | + desc); | |
| 426 | 458 | need_sep = true; |
| 427 | 459 | } |
| 428 | 460 | if (long_desc) { |
| 429 | − fix_escape_printf(&buf, "%s\t\"PublicDescription\": \"%S\"", need_sep ? ",\n" : "", | |
| 430 | − long_desc); | |
| 461 | + fix_escape_fprintf(fp, &buf, "%s\t\"PublicDescription\": \"%S\"", | |
| 462 | + need_sep ? ",\n" : "", | |
| 463 | + long_desc); | |
| 431 | 464 | need_sep = true; |
| 432 | 465 | } |
| 433 | − printf("%s}", need_sep ? "\n" : ""); | |
| 466 | + fprintf(fp, "%s}", need_sep ? "\n" : ""); | |
| 434 | 467 | strbuf_release(&buf); |
| 435 | 468 | } |
| 436 | 469 | |
| @@ -449,8 +482,12 @@ static bool default_skip_duplicate_pmus(void *ps) · 12 unmodified lines | ||
| 449 | 482 | int cmd_list(int argc, const char **argv) |
| 450 | 483 | { |
| 451 | 484 | int i, ret = 0; |
| 452 | − struct print_state default_ps = {}; | |
| 453 | − struct print_state json_ps = {}; | |
| 485 | + struct print_state default_ps = { | |
| 486 | + .fp = stdout, | |
| 487 | + }; | |
| 488 | + struct print_state json_ps = { | |
| 489 | + .fp = stdout, | |
| 490 | + }; | |
| 454 | 491 | void *ps = &default_ps; |
| 455 | 492 | struct print_callbacks print_cb = { |
| 456 | 493 | .print_start = default_print_start, |
| @@ -461,6 +498,7 @@ int cmd_list(int argc, const char **argv) · 4 unmodified lines | ||
| 461 | 498 | }; |
| 462 | 499 | const char *cputype = NULL; |
| 463 | 500 | const char *unit_name = NULL; |
| 501 | + const char *output_path = NULL; | |
| 464 | 502 | bool json = false; |
| 465 | 503 | struct option list_options[] = { |
| 466 | 504 | OPT_BOOLEAN(0, "raw-dump", &default_ps.name_only, "Dump raw events"), |
| @@ -471,6 +509,7 @@ int cmd_list(int argc, const char **argv) · 4 unmodified lines | ||
| 471 | 509 | "Print longer event descriptions."), |
| 472 | 510 | OPT_BOOLEAN(0, "details", &default_ps.detailed, |
| 473 | 511 | "Print information on the perf event names and expressions used internally by events."), |
| 512 | + OPT_STRING('o', "output", &output_path, "file", "output file name"), | |
| 474 | 513 | OPT_BOOLEAN(0, "deprecated", &default_ps.deprecated, |
| 475 | 514 | "Print deprecated events."), |
| 476 | 515 | OPT_STRING(0, "cputype", &cputype, "cpu type", |
| @@ -497,6 +536,11 @@ int cmd_list(int argc, const char **argv) · 20 unmodified lines | ||
| 497 | 536 | argc = parse_options(argc, argv, list_options, list_usage, |
| 498 | 537 | PARSE_OPT_STOP_AT_NON_OPTION); |
| 499 | 538 | |
| 539 | + if (output_path) { | |
| 540 | + default_ps.fp = fopen(output_path, "w"); | |
| 541 | + json_ps.fp = default_ps.fp; | |
| 542 | + } | |
| 543 | + | |
| 500 | 544 | setup_pager(); |
| 501 | 545 | |
| 502 | 546 | if (!default_ps.name_only) |
| @@ -618,5 +662,8 @@ out: · 115 unmodified lines | ||
| 618 | 662 | free(default_ps.last_topic); |
| 619 | 663 | free(default_ps.last_metricgroups); |
| 620 | 664 | strlist__delete(default_ps.visited_metrics); |
| 665 | + if (output_path) | |
| 666 | + fclose(default_ps.fp); | |
| 667 | + | |
| 621 | 668 | return ret; |
| 622 | 669 | } |
| @@ -4080,8 +4080,8 @@ int cmd_record(int argc, const char **argv) · 4079 unmodified lines | ||
| 4080 | 4080 | } |
| 4081 | 4081 | |
| 4082 | 4082 | if (rec->switch_output.num_files) { |
| 4083 | − rec->switch_output.filenames = calloc(sizeof(char *), | |
| 4084 | − rec->switch_output.num_files); | |
| 4083 | + rec->switch_output.filenames = calloc(rec->switch_output.num_files, | |
| 4084 | + sizeof(char *)); | |
| 4085 | 4085 | if (!rec->switch_output.filenames) { |
| 4086 | 4086 | err = -EINVAL; |
| 4087 | 4087 | goto out_opts; |
| @@ -357,7 +357,7 @@ static void perf_top__print_sym_table(struct perf_top *top) · 356 unmodified lines | ||
| 357 | 357 | |
| 358 | 358 | static void prompt_integer(int *target, const char *msg) |
| 359 | 359 | { |
| 360 | − char *buf = malloc(0), *p; | |
| 360 | + char *buf = NULL, *p; | |
| 361 | 361 | size_t dummy = 0; |
| 362 | 362 | int tmp; |
| 363 | 363 | |
| @@ -114,7 +114,7 @@ · 113 unmodified lines | ||
| 114 | 114 | }, |
| 115 | 115 | { |
| 116 | 116 | "BriefDescription": "Counts the number of issue slots that were not consumed by the backend due to certain allocation restrictions.", |
| 117 | − "MetricExpr": "TOPDOWN_BE_BOUND.ALLOC_RESTRICTIONS / tma_info_core_slots", | |
| 117 | + "MetricExpr": "cpu_atom@TOPDOWN_BE_BOUND.ALLOC_RESTRICTIONS@ / tma_info_core_slots", | |
| 118 | 118 | "MetricGroup": "TopdownL3;tma_L3_group;tma_resource_bound_group", |
| 119 | 119 | "MetricName": "tma_alloc_restriction", |
| 120 | 120 | "MetricThreshold": "tma_alloc_restriction > 0.1", |
| @@ -124,7 +124,7 @@ · 3 unmodified lines | ||
| 124 | 124 | { |
| 125 | 125 | "BriefDescription": "Counts the total number of issue slots that were not consumed by the backend due to backend stalls", |
| 126 | 126 | "DefaultMetricgroupName": "TopdownL1", |
| 127 | − "MetricExpr": "TOPDOWN_BE_BOUND.ALL / tma_info_core_slots", | |
| 127 | + "MetricExpr": "cpu_atom@TOPDOWN_BE_BOUND.ALL@ / tma_info_core_slots", | |
| 128 | 128 | "MetricGroup": "Default;TopdownL1;tma_L1_group", |
| 129 | 129 | "MetricName": "tma_backend_bound", |
| 130 | 130 | "MetricThreshold": "tma_backend_bound > 0.1", |
| @@ -169,7 +169,7 @@ · 38 unmodified lines | ||
| 169 | 169 | }, |
| 170 | 170 | { |
| 171 | 171 | "BriefDescription": "Counts the number of issue slots that were not delivered by the frontend due to BACLEARS, which occurs when the Branch Target Buffer (BTB) prediction or lack thereof, was corrected by a later branch predictor in the frontend", |
| 172 | − "MetricExpr": "TOPDOWN_FE_BOUND.BRANCH_DETECT / tma_info_core_slots", | |
| 172 | + "MetricExpr": "cpu_atom@TOPDOWN_FE_BOUND.BRANCH_DETECT@ / tma_info_core_slots", | |
| 173 | 173 | "MetricGroup": "TopdownL3;tma_L3_group;tma_fetch_latency_group", |
| 174 | 174 | "MetricName": "tma_branch_detect", |
| 175 | 175 | "MetricThreshold": "tma_branch_detect > 0.05", |
| @@ -179,7 +179,7 @@ · 3 unmodified lines | ||
| 179 | 179 | }, |
| 180 | 180 | { |
| 181 | 181 | "BriefDescription": "Counts the number of issue slots that were not consumed by the backend due to branch mispredicts.", |
| 182 | − "MetricExpr": "TOPDOWN_BAD_SPECULATION.MISPREDICT / tma_info_core_slots", | |
| 182 | + "MetricExpr": "cpu_atom@TOPDOWN_BAD_SPECULATION.MISPREDICT@ / tma_info_core_slots", | |
| 183 | 183 | "MetricGroup": "TopdownL2;tma_L2_group;tma_bad_speculation_group", |
| 184 | 184 | "MetricName": "tma_branch_mispredicts", |
| 185 | 185 | "MetricThreshold": "tma_branch_mispredicts > 0.05", |
| @@ -189,7 +189,7 @@ · 3 unmodified lines | ||
| 189 | 189 | }, |
| 190 | 190 | { |
| 191 | 191 | "BriefDescription": "Counts the number of issue slots that were not delivered by the frontend due to BTCLEARS, which occurs when the Branch Target Buffer (BTB) predicts a taken branch.", |
| 192 | − "MetricExpr": "TOPDOWN_FE_BOUND.BRANCH_RESTEER / tma_info_core_slots", | |
| 192 | + "MetricExpr": "cpu_atom@TOPDOWN_FE_BOUND.BRANCH_RESTEER@ / tma_info_core_slots", | |
| 193 | 193 | "MetricGroup": "TopdownL3;tma_L3_group;tma_fetch_latency_group", |
| 194 | 194 | "MetricName": "tma_branch_resteer", |
| 195 | 195 | "MetricThreshold": "tma_branch_resteer > 0.05", |
| @@ -198,7 +198,7 @@ · 2 unmodified lines | ||
| 198 | 198 | }, |
| 199 | 199 | { |
| 200 | 200 | "BriefDescription": "Counts the number of issue slots that were not delivered by the frontend due to the microcode sequencer (MS).", |
| 201 | − "MetricExpr": "TOPDOWN_FE_BOUND.CISC / tma_info_core_slots", | |
| 201 | + "MetricExpr": "cpu_atom@TOPDOWN_FE_BOUND.CISC@ / tma_info_core_slots", | |
| 202 | 202 | "MetricGroup": "TopdownL3;tma_L3_group;tma_fetch_bandwidth_group", |
| 203 | 203 | "MetricName": "tma_cisc", |
| 204 | 204 | "MetricThreshold": "tma_cisc > 0.05", |
| @@ -217,7 +217,7 @@ · 12 unmodified lines | ||
| 217 | 217 | }, |
| 218 | 218 | { |
| 219 | 219 | "BriefDescription": "Counts the number of issue slots that were not delivered by the frontend due to decode stalls.", |
| 220 | − "MetricExpr": "TOPDOWN_FE_BOUND.DECODE / tma_info_core_slots", | |
| 220 | + "MetricExpr": "cpu_atom@TOPDOWN_FE_BOUND.DECODE@ / tma_info_core_slots", | |
| 221 | 221 | "MetricGroup": "TopdownL3;tma_L3_group;tma_fetch_bandwidth_group", |
| 222 | 222 | "MetricName": "tma_decode", |
| 223 | 223 | "MetricThreshold": "tma_decode > 0.05", |
| @@ -235,7 +235,6 @@ · 11 unmodified lines | ||
| 235 | 235 | }, |
| 236 | 236 | { |
| 237 | 237 | "BriefDescription": "Counts the number of cycles the core is stalled due to a demand load miss which hit in DRAM or MMIO (Non-DRAM).", |
| 238 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 239 | 238 | "MetricExpr": "cpu_atom@MEM_BOUND_STALLS.LOAD_DRAM_HIT@ / tma_info_core_clks - max((cpu_atom@MEM_BOUND_STALLS.LOAD@ - cpu_atom@LD_HEAD.L1_MISS_AT_RET@) / tma_info_core_clks, 0) * cpu_atom@MEM_BOUND_STALLS.LOAD_DRAM_HIT@ / cpu_atom@MEM_BOUND_STALLS.LOAD@", |
| 240 | 239 | "MetricGroup": "TopdownL3;tma_L3_group;tma_memory_bound_group", |
| 241 | 240 | "MetricName": "tma_dram_bound", |
| @@ -245,7 +244,7 @@ · 3 unmodified lines | ||
| 245 | 244 | }, |
| 246 | 245 | { |
| 247 | 246 | "BriefDescription": "Counts the number of issue slots that were not consumed by the backend due to a machine clear classified as a fast nuke due to memory ordering, memory disambiguation and memory renaming.", |
| 248 | − "MetricExpr": "TOPDOWN_BAD_SPECULATION.FASTNUKE / tma_info_core_slots", | |
| 247 | + "MetricExpr": "cpu_atom@TOPDOWN_BAD_SPECULATION.FASTNUKE@ / tma_info_core_slots", | |
| 249 | 248 | "MetricGroup": "TopdownL3;tma_L3_group;tma_machine_clears_group", |
| 250 | 249 | "MetricName": "tma_fast_nuke", |
| 251 | 250 | "MetricThreshold": "tma_fast_nuke > 0.05", |
| @@ -254,7 +253,7 @@ · 2 unmodified lines | ||
| 254 | 253 | }, |
| 255 | 254 | { |
| 256 | 255 | "BriefDescription": "Counts the number of issue slots that were not delivered by the frontend due to frontend bandwidth restrictions due to decode, predecode, cisc, and other limitations.", |
| 257 | − "MetricExpr": "TOPDOWN_FE_BOUND.FRONTEND_BANDWIDTH / tma_info_core_slots", | |
| 256 | + "MetricExpr": "cpu_atom@TOPDOWN_FE_BOUND.FRONTEND_BANDWIDTH@ / tma_info_core_slots", | |
| 258 | 257 | "MetricGroup": "TopdownL2;tma_L2_group;tma_frontend_bound_group", |
| 259 | 258 | "MetricName": "tma_fetch_bandwidth", |
| 260 | 259 | "MetricThreshold": "tma_fetch_bandwidth > 0.1", |
| @@ -264,7 +263,7 @@ · 3 unmodified lines | ||
| 264 | 263 | }, |
| 265 | 264 | { |
| 266 | 265 | "BriefDescription": "Counts the number of issue slots that were not delivered by the frontend due to frontend bandwidth restrictions due to decode, predecode, cisc, and other limitations.", |
| 267 | − "MetricExpr": "TOPDOWN_FE_BOUND.FRONTEND_LATENCY / tma_info_core_slots", | |
| 266 | + "MetricExpr": "cpu_atom@TOPDOWN_FE_BOUND.FRONTEND_LATENCY@ / tma_info_core_slots", | |
| 268 | 267 | "MetricGroup": "TopdownL2;tma_L2_group;tma_frontend_bound_group", |
| 269 | 268 | "MetricName": "tma_fetch_latency", |
| 270 | 269 | "MetricThreshold": "tma_fetch_latency > 0.15", |
| @@ -283,7 +282,7 @@ · 12 unmodified lines | ||
| 283 | 282 | }, |
| 284 | 283 | { |
| 285 | 284 | "BriefDescription": "Counts the number of floating point divide operations per uop.", |
| 286 | − "MetricExpr": "UOPS_RETIRED.FPDIV / tma_info_core_slots", | |
| 285 | + "MetricExpr": "cpu_atom@UOPS_RETIRED.FPDIV@ / tma_info_core_slots", | |
| 287 | 286 | "MetricGroup": "TopdownL3;tma_L3_group;tma_base_group", |
| 288 | 287 | "MetricName": "tma_fpdiv_uops", |
| 289 | 288 | "MetricThreshold": "tma_fpdiv_uops > 0.2", |
| @@ -293,7 +292,7 @@ · 3 unmodified lines | ||
| 293 | 292 | { |
| 294 | 293 | "BriefDescription": "Counts the number of issue slots that were not consumed by the backend due to frontend stalls.", |
| 295 | 294 | "DefaultMetricgroupName": "TopdownL1", |
| 296 | − "MetricExpr": "TOPDOWN_FE_BOUND.ALL / tma_info_core_slots", | |
| 295 | + "MetricExpr": "cpu_atom@TOPDOWN_FE_BOUND.ALL@ / tma_info_core_slots", | |
| 297 | 296 | "MetricGroup": "Default;TopdownL1;tma_L1_group", |
| 298 | 297 | "MetricName": "tma_frontend_bound", |
| 299 | 298 | "MetricThreshold": "tma_frontend_bound > 0.2", |
| @@ -303,7 +302,7 @@ · 3 unmodified lines | ||
| 303 | 302 | }, |
| 304 | 303 | { |
| 305 | 304 | "BriefDescription": "Counts the number of issue slots that were not delivered by the frontend due to instruction cache misses.", |
| 306 | − "MetricExpr": "TOPDOWN_FE_BOUND.ICACHE / tma_info_core_slots", | |
| 305 | + "MetricExpr": "cpu_atom@TOPDOWN_FE_BOUND.ICACHE@ / tma_info_core_slots", | |
| 307 | 306 | "MetricGroup": "TopdownL3;tma_L3_group;tma_fetch_latency_group", |
| 308 | 307 | "MetricName": "tma_icache_misses", |
| 309 | 308 | "MetricThreshold": "tma_icache_misses > 0.05", |
| @@ -330,7 +329,7 @@ · 20 unmodified lines | ||
| 330 | 329 | }, |
| 331 | 330 | { |
| 332 | 331 | "BriefDescription": "Instructions Per Cycle", |
| 333 | − "MetricExpr": "INST_RETIRED.ANY / tma_info_core_clks", | |
| 332 | + "MetricExpr": "cpu_atom@INST_RETIRED.ANY@ / tma_info_core_clks", | |
| 334 | 333 | "MetricName": "tma_info_core_ipc", |
| 335 | 334 | "Unit": "cpu_atom" |
| 336 | 335 | }, |
| @@ -342,7 +341,7 @@ · 5 unmodified lines | ||
| 342 | 341 | }, |
| 343 | 342 | { |
| 344 | 343 | "BriefDescription": "Uops Per Instruction", |
| 345 | − "MetricExpr": "UOPS_RETIRED.ALL / INST_RETIRED.ANY", | |
| 344 | + "MetricExpr": "cpu_atom@UOPS_RETIRED.ALL@ / INST_RETIRED.ANY", | |
| 346 | 345 | "MetricName": "tma_info_core_upi", |
| 347 | 346 | "Unit": "cpu_atom" |
| 348 | 347 | }, |
| @@ -366,13 +365,13 @@ · 17 unmodified lines | ||
| 366 | 365 | }, |
| 367 | 366 | { |
| 368 | 367 | "BriefDescription": "Ratio of all branches which mispredict", |
| 369 | − "MetricExpr": "BR_MISP_RETIRED.ALL_BRANCHES / BR_INST_RETIRED.ALL_BRANCHES", | |
| 368 | + "MetricExpr": "cpu_atom@BR_MISP_RETIRED.ALL_BRANCHES@ / BR_INST_RETIRED.ALL_BRANCHES", | |
| 370 | 369 | "MetricName": "tma_info_inst_mix_branch_mispredict_ratio", |
| 371 | 370 | "Unit": "cpu_atom" |
| 372 | 371 | }, |
| 373 | 372 | { |
| 374 | 373 | "BriefDescription": "Ratio between Mispredicted branches and unknown branches", |
| 375 | − "MetricExpr": "BR_MISP_RETIRED.ALL_BRANCHES / BACLEARS.ANY", | |
| 374 | + "MetricExpr": "cpu_atom@BR_MISP_RETIRED.ALL_BRANCHES@ / BACLEARS.ANY", | |
| 376 | 375 | "MetricName": "tma_info_inst_mix_branch_mispredict_to_unknown_branch_ratio", |
| 377 | 376 | "Unit": "cpu_atom" |
| 378 | 377 | }, |
| @@ -390,61 +389,61 @@ · 11 unmodified lines | ||
| 390 | 389 | }, |
| 391 | 390 | { |
| 392 | 391 | "BriefDescription": "Instructions per Branch (lower number means higher occurrence rate)", |
| 393 | − "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.ALL_BRANCHES", | |
| 392 | + "MetricExpr": "cpu_atom@INST_RETIRED.ANY@ / BR_INST_RETIRED.ALL_BRANCHES", | |
| 394 | 393 | "MetricName": "tma_info_inst_mix_ipbranch", |
| 395 | 394 | "Unit": "cpu_atom" |
| 396 | 395 | }, |
| 397 | 396 | { |
| 398 | 397 | "BriefDescription": "Instruction per (near) call (lower number means higher occurrence rate)", |
| 399 | − "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.CALL", | |
| 398 | + "MetricExpr": "cpu_atom@INST_RETIRED.ANY@ / BR_INST_RETIRED.CALL", | |
| 400 | 399 | "MetricName": "tma_info_inst_mix_ipcall", |
| 401 | 400 | "Unit": "cpu_atom" |
| 402 | 401 | }, |
| 403 | 402 | { |
| 404 | 403 | "BriefDescription": "Instructions per Far Branch", |
| 405 | − "MetricExpr": "INST_RETIRED.ANY / (cpu_atom@BR_INST_RETIRED.FAR_BRANCH@ / 2)", | |
| 404 | + "MetricExpr": "cpu_atom@INST_RETIRED.ANY@ / (cpu_atom@BR_INST_RETIRED.FAR_BRANCH@ / 2)", | |
| 406 | 405 | "MetricName": "tma_info_inst_mix_ipfarbranch", |
| 407 | 406 | "Unit": "cpu_atom" |
| 408 | 407 | }, |
| 409 | 408 | { |
| 410 | 409 | "BriefDescription": "Instructions per Load", |
| 411 | − "MetricExpr": "INST_RETIRED.ANY / MEM_UOPS_RETIRED.ALL_LOADS", | |
| 410 | + "MetricExpr": "cpu_atom@INST_RETIRED.ANY@ / MEM_UOPS_RETIRED.ALL_LOADS", | |
| 412 | 411 | "MetricName": "tma_info_inst_mix_ipload", |
| 413 | 412 | "Unit": "cpu_atom" |
| 414 | 413 | }, |
| 415 | 414 | { |
| 416 | 415 | "BriefDescription": "Instructions per retired conditional Branch Misprediction where the branch was not taken", |
| 417 | − "MetricExpr": "INST_RETIRED.ANY / (cpu_atom@BR_MISP_RETIRED.COND@ - cpu_atom@BR_MISP_RETIRED.COND_TAKEN@)", | |
| 416 | + "MetricExpr": "cpu_atom@INST_RETIRED.ANY@ / (cpu_atom@BR_MISP_RETIRED.COND@ - cpu_atom@BR_MISP_RETIRED.COND_TAKEN@)", | |
| 418 | 417 | "MetricName": "tma_info_inst_mix_ipmisp_cond_ntaken", |
| 419 | 418 | "Unit": "cpu_atom" |
| 420 | 419 | }, |
| 421 | 420 | { |
| 422 | 421 | "BriefDescription": "Instructions per retired conditional Branch Misprediction where the branch was taken", |
| 423 | − "MetricExpr": "INST_RETIRED.ANY / BR_MISP_RETIRED.COND_TAKEN", | |
| 422 | + "MetricExpr": "cpu_atom@INST_RETIRED.ANY@ / BR_MISP_RETIRED.COND_TAKEN", | |
| 424 | 423 | "MetricName": "tma_info_inst_mix_ipmisp_cond_taken", |
| 425 | 424 | "Unit": "cpu_atom" |
| 426 | 425 | }, |
| 427 | 426 | { |
| 428 | 427 | "BriefDescription": "Instructions per retired indirect call or jump Branch Misprediction", |
| 429 | − "MetricExpr": "INST_RETIRED.ANY / BR_MISP_RETIRED.INDIRECT", | |
| 428 | + "MetricExpr": "cpu_atom@INST_RETIRED.ANY@ / BR_MISP_RETIRED.INDIRECT", | |
| 430 | 429 | "MetricName": "tma_info_inst_mix_ipmisp_indirect", |
| 431 | 430 | "Unit": "cpu_atom" |
| 432 | 431 | }, |
| 433 | 432 | { |
| 434 | 433 | "BriefDescription": "Instructions per retired return Branch Misprediction", |
| 435 | − "MetricExpr": "INST_RETIRED.ANY / BR_MISP_RETIRED.RETURN", | |
| 434 | + "MetricExpr": "cpu_atom@INST_RETIRED.ANY@ / BR_MISP_RETIRED.RETURN", | |
| 436 | 435 | "MetricName": "tma_info_inst_mix_ipmisp_ret", |
| 437 | 436 | "Unit": "cpu_atom" |
| 438 | 437 | }, |
| 439 | 438 | { |
| 440 | 439 | "BriefDescription": "Instructions per retired Branch Misprediction", |
| 441 | − "MetricExpr": "INST_RETIRED.ANY / BR_MISP_RETIRED.ALL_BRANCHES", | |
| 440 | + "MetricExpr": "cpu_atom@INST_RETIRED.ANY@ / BR_MISP_RETIRED.ALL_BRANCHES", | |
| 442 | 441 | "MetricName": "tma_info_inst_mix_ipmispredict", |
| 443 | 442 | "Unit": "cpu_atom" |
| 444 | 443 | }, |
| 445 | 444 | { |
| 446 | 445 | "BriefDescription": "Instructions per Store", |
| 447 | − "MetricExpr": "INST_RETIRED.ANY / MEM_UOPS_RETIRED.ALL_STORES", | |
| 446 | + "MetricExpr": "cpu_atom@INST_RETIRED.ANY@ / MEM_UOPS_RETIRED.ALL_STORES", | |
| 448 | 447 | "MetricName": "tma_info_inst_mix_ipstore", |
| 449 | 448 | "Unit": "cpu_atom" |
| 450 | 449 | }, |
| @@ -480,19 +479,19 @@ · 29 unmodified lines | ||
| 480 | 479 | }, |
| 481 | 480 | { |
| 482 | 481 | "BriefDescription": "Cycle cost per DRAM hit", |
| 483 | − "MetricExpr": "MEM_BOUND_STALLS.LOAD_DRAM_HIT / MEM_LOAD_UOPS_RETIRED.DRAM_HIT", | |
| 482 | + "MetricExpr": "cpu_atom@MEM_BOUND_STALLS.LOAD_DRAM_HIT@ / MEM_LOAD_UOPS_RETIRED.DRAM_HIT", | |
| 484 | 483 | "MetricName": "tma_info_memory_cycles_per_demand_load_dram_hit", |
| 485 | 484 | "Unit": "cpu_atom" |
| 486 | 485 | }, |
| 487 | 486 | { |
| 488 | 487 | "BriefDescription": "Cycle cost per L2 hit", |
| 489 | − "MetricExpr": "MEM_BOUND_STALLS.LOAD_L2_HIT / MEM_LOAD_UOPS_RETIRED.L2_HIT", | |
| 488 | + "MetricExpr": "cpu_atom@MEM_BOUND_STALLS.LOAD_L2_HIT@ / MEM_LOAD_UOPS_RETIRED.L2_HIT", | |
| 490 | 489 | "MetricName": "tma_info_memory_cycles_per_demand_load_l2_hit", |
| 491 | 490 | "Unit": "cpu_atom" |
| 492 | 491 | }, |
| 493 | 492 | { |
| 494 | 493 | "BriefDescription": "Cycle cost per LLC hit", |
| 495 | − "MetricExpr": "MEM_BOUND_STALLS.LOAD_LLC_HIT / MEM_LOAD_UOPS_RETIRED.L3_HIT", | |
| 494 | + "MetricExpr": "cpu_atom@MEM_BOUND_STALLS.LOAD_LLC_HIT@ / MEM_LOAD_UOPS_RETIRED.L3_HIT", | |
| 496 | 495 | "MetricName": "tma_info_memory_cycles_per_demand_load_l3_hit", |
| 497 | 496 | "Unit": "cpu_atom" |
| 498 | 497 | }, |
| @@ -504,7 +503,7 @@ · 5 unmodified lines | ||
| 504 | 503 | }, |
| 505 | 504 | { |
| 506 | 505 | "BriefDescription": "Average CPU Utilization", |
| 507 | − "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC / TSC", | |
| 506 | + "MetricExpr": "cpu_atom@CPU_CLK_UNHALTED.REF_TSC@ / TSC", | |
| 508 | 507 | "MetricName": "tma_info_system_cpu_utilization", |
| 509 | 508 | "Unit": "cpu_atom" |
| 510 | 509 | }, |
| @@ -524,7 +523,7 @@ · 13 unmodified lines | ||
| 524 | 523 | }, |
| 525 | 524 | { |
| 526 | 525 | "BriefDescription": "Counts the number of issue slots that were not delivered by the frontend due to Instruction Table Lookaside Buffer (ITLB) misses.", |
| 527 | − "MetricExpr": "TOPDOWN_FE_BOUND.ITLB / tma_info_core_slots", | |
| 526 | + "MetricExpr": "cpu_atom@TOPDOWN_FE_BOUND.ITLB@ / tma_info_core_slots", | |
| 528 | 527 | "MetricGroup": "TopdownL3;tma_L3_group;tma_fetch_latency_group", |
| 529 | 528 | "MetricName": "tma_itlb_misses", |
| 530 | 529 | "MetricThreshold": "tma_itlb_misses > 0.05", |
| @@ -533,7 +532,7 @@ · 2 unmodified lines | ||
| 533 | 532 | }, |
| 534 | 533 | { |
| 535 | 534 | "BriefDescription": "Counts the number of cycles that the oldest load of the load buffer is stalled at retirement due to a load block.", |
| 536 | − "MetricExpr": "LD_HEAD.L1_BOUND_AT_RET / tma_info_core_clks", | |
| 535 | + "MetricExpr": "cpu_atom@LD_HEAD.L1_BOUND_AT_RET@ / tma_info_core_clks", | |
| 537 | 536 | "MetricGroup": "TopdownL3;tma_L3_group;tma_memory_bound_group", |
| 538 | 537 | "MetricName": "tma_l1_bound", |
| 539 | 538 | "MetricThreshold": "tma_l1_bound > 0.1", |
| @@ -542,7 +541,6 @@ · 2 unmodified lines | ||
| 542 | 541 | }, |
| 543 | 542 | { |
| 544 | 543 | "BriefDescription": "Counts the number of cycles a core is stalled due to a demand load which hit in the L2 Cache.", |
| 545 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 546 | 544 | "MetricExpr": "cpu_atom@MEM_BOUND_STALLS.LOAD_L2_HIT@ / tma_info_core_clks - max((cpu_atom@MEM_BOUND_STALLS.LOAD@ - cpu_atom@LD_HEAD.L1_MISS_AT_RET@) / tma_info_core_clks, 0) * cpu_atom@MEM_BOUND_STALLS.LOAD_L2_HIT@ / cpu_atom@MEM_BOUND_STALLS.LOAD@", |
| 547 | 545 | "MetricGroup": "TopdownL3;tma_L3_group;tma_memory_bound_group", |
| 548 | 546 | "MetricName": "tma_l2_bound", |
| @@ -552,7 +550,6 @@ · 3 unmodified lines | ||
| 552 | 550 | }, |
| 553 | 551 | { |
| 554 | 552 | "BriefDescription": "Counts the number of cycles a core is stalled due to a demand load which hit in the Last Level Cache (LLC) or other core with HITE/F/M.", |
| 555 | − "MetricConstraint": "NO_GROUP_EVENTS_NMI", | |
| 556 | 553 | "MetricExpr": "cpu_atom@MEM_BOUND_STALLS.LOAD_LLC_HIT@ / tma_info_core_clks - max((cpu_atom@MEM_BOUND_STALLS.LOAD@ - cpu_atom@LD_HEAD.L1_MISS_AT_RET@) / tma_info_core_clks, 0) * cpu_atom@MEM_BOUND_STALLS.LOAD_LLC_HIT@ / cpu_atom@MEM_BOUND_STALLS.LOAD@", |
| 557 | 554 | "MetricGroup": "TopdownL3;tma_L3_group;tma_memory_bound_group", |
| 558 | 555 | "MetricName": "tma_l3_bound", |
| @@ -571,7 +568,7 @@ · 12 unmodified lines | ||
| 571 | 568 | }, |
| 572 | 569 | { |
| 573 | 570 | "BriefDescription": "Counts the total number of issue slots that were not consumed by the backend because allocation is stalled due to a machine clear (nuke) of any kind including memory ordering and memory disambiguation.", |
| 574 | − "MetricExpr": "TOPDOWN_BAD_SPECULATION.MACHINE_CLEARS / tma_info_core_slots", | |
| 571 | + "MetricExpr": "cpu_atom@TOPDOWN_BAD_SPECULATION.MACHINE_CLEARS@ / tma_info_core_slots", | |
| 575 | 572 | "MetricGroup": "TopdownL2;tma_L2_group;tma_bad_speculation_group", |
| 576 | 573 | "MetricName": "tma_machine_clears", |
| 577 | 574 | "MetricThreshold": "tma_machine_clears > 0.05", |
| @@ -581,7 +578,7 @@ · 3 unmodified lines | ||
| 581 | 578 | }, |
| 582 | 579 | { |
| 583 | 580 | "BriefDescription": "Counts the number of issue slots that were not consumed by the backend due to memory reservation stalls in which a scheduler is not able to accept uops.", |
| 584 | − "MetricExpr": "TOPDOWN_BE_BOUND.MEM_SCHEDULER / tma_info_core_slots", | |
| 581 | + "MetricExpr": "cpu_atom@TOPDOWN_BE_BOUND.MEM_SCHEDULER@ / tma_info_core_slots", | |
| 585 | 582 | "MetricGroup": "TopdownL3;tma_L3_group;tma_resource_bound_group", |
| 586 | 583 | "MetricName": "tma_mem_scheduler", |
| 587 | 584 | "MetricThreshold": "tma_mem_scheduler > 0.1", |
| @@ -590,7 +587,7 @@ · 2 unmodified lines | ||
| 590 | 587 | }, |
| 591 | 588 | { |
| 592 | 589 | "BriefDescription": "Counts the number of cycles the core is stalled due to stores or loads.", |
| 593 | − "MetricExpr": "min(cpu_atom@TOPDOWN_BE_BOUND.ALL@ / tma_info_core_slots, cpu_atom@LD_HEAD.ANY_AT_RET@ / tma_info_core_clks + tma_store_bound)", | |
| 590 | + "MetricExpr": "min(tma_backend_bound, cpu_atom@LD_HEAD.ANY_AT_RET@ / tma_info_core_clks + tma_store_bound)", | |
| 594 | 591 | "MetricGroup": "TopdownL2;tma_L2_group;tma_backend_bound_group", |
| 595 | 592 | "MetricName": "tma_memory_bound", |
| 596 | 593 | "MetricThreshold": "tma_memory_bound > 0.2", |
| @@ -609,7 +606,7 @@ · 12 unmodified lines | ||
| 609 | 606 | }, |
| 610 | 607 | { |
| 611 | 608 | "BriefDescription": "Counts the number of uops that are from the complex flows issued by the micro-sequencer (MS)", |
| 612 | − "MetricExpr": "UOPS_RETIRED.MS / tma_info_core_slots", | |
| 609 | + "MetricExpr": "cpu_atom@UOPS_RETIRED.MS@ / tma_info_core_slots", | |
| 613 | 610 | "MetricGroup": "TopdownL2;tma_L2_group;tma_retiring_group", |
| 614 | 611 | "MetricName": "tma_ms_uops", |
| 615 | 612 | "MetricThreshold": "tma_ms_uops > 0.05", |
| @@ -620,7 +617,7 @@ · 4 unmodified lines | ||
| 620 | 617 | }, |
| 621 | 618 | { |
| 622 | 619 | "BriefDescription": "Counts the number of issue slots that were not consumed by the backend due to IEC or FPC RAT stalls, which can be due to FIQ or IEC reservation stalls in which the integer, floating point or SIMD scheduler is not able to accept uops.", |
| 623 | − "MetricExpr": "TOPDOWN_BE_BOUND.NON_MEM_SCHEDULER / tma_info_core_slots", | |
| 620 | + "MetricExpr": "cpu_atom@TOPDOWN_BE_BOUND.NON_MEM_SCHEDULER@ / tma_info_core_slots", | |
| 624 | 621 | "MetricGroup": "TopdownL3;tma_L3_group;tma_resource_bound_group", |
| 625 | 622 | "MetricName": "tma_non_mem_scheduler", |
| 626 | 623 | "MetricThreshold": "tma_non_mem_scheduler > 0.1", |
| @@ -629,7 +626,7 @@ · 2 unmodified lines | ||
| 629 | 626 | }, |
| 630 | 627 | { |
| 631 | 628 | "BriefDescription": "Counts the number of issue slots that were not consumed by the backend due to a machine clear (slow nuke).", |
| 632 | − "MetricExpr": "TOPDOWN_BAD_SPECULATION.NUKE / tma_info_core_slots", | |
| 629 | + "MetricExpr": "cpu_atom@TOPDOWN_BAD_SPECULATION.NUKE@ / tma_info_core_slots", | |
| 633 | 630 | "MetricGroup": "TopdownL3;tma_L3_group;tma_machine_clears_group", |
| 634 | 631 | "MetricName": "tma_nuke", |
| 635 | 632 | "MetricThreshold": "tma_nuke > 0.05", |
| @@ -638,7 +635,7 @@ · 2 unmodified lines | ||
| 638 | 635 | }, |
| 639 | 636 | { |
| 640 | 637 | "BriefDescription": "Counts the number of issue slots that were not delivered by the frontend due to other common frontend stalls not categorized.", |
| 641 | − "MetricExpr": "TOPDOWN_FE_BOUND.OTHER / tma_info_core_slots", | |
| 638 | + "MetricExpr": "cpu_atom@TOPDOWN_FE_BOUND.OTHER@ / tma_info_core_slots", | |
| 642 | 639 | "MetricGroup": "TopdownL3;tma_L3_group;tma_fetch_bandwidth_group", |
| 643 | 640 | "MetricName": "tma_other_fb", |
| 644 | 641 | "MetricThreshold": "tma_other_fb > 0.05", |
| @@ -647,7 +644,7 @@ · 2 unmodified lines | ||
| 647 | 644 | }, |
| 648 | 645 | { |
| 649 | 646 | "BriefDescription": "Counts the number of cycles that the oldest load of the load buffer is stalled at retirement due to a number of other load blocks.", |
| 650 | − "MetricExpr": "LD_HEAD.OTHER_AT_RET / tma_info_core_clks", | |
| 647 | + "MetricExpr": "cpu_atom@LD_HEAD.OTHER_AT_RET@ / tma_info_core_clks", | |
| 651 | 648 | "MetricGroup": "TopdownL4;tma_L4_group;tma_l1_bound_group", |
| 652 | 649 | "MetricName": "tma_other_l1", |
| 653 | 650 | "MetricThreshold": "tma_other_l1 > 0.05", |
| @@ -683,7 +680,7 @@ · 29 unmodified lines | ||
| 683 | 680 | }, |
| 684 | 681 | { |
| 685 | 682 | "BriefDescription": "Counts the number of issue slots that were not delivered by the frontend due to wrong predecodes.", |
| 686 | − "MetricExpr": "TOPDOWN_FE_BOUND.PREDECODE / tma_info_core_slots", | |
| 683 | + "MetricExpr": "cpu_atom@TOPDOWN_FE_BOUND.PREDECODE@ / tma_info_core_slots", | |
| 687 | 684 | "MetricGroup": "TopdownL3;tma_L3_group;tma_fetch_bandwidth_group", |
| 688 | 685 | "MetricName": "tma_predecode", |
| 689 | 686 | "MetricThreshold": "tma_predecode > 0.05", |
| @@ -692,7 +689,7 @@ · 2 unmodified lines | ||
| 692 | 689 | }, |
| 693 | 690 | { |
| 694 | 691 | "BriefDescription": "Counts the number of issue slots that were not consumed by the backend due to the physical register file unable to accept an entry (marble stalls).", |
| 695 | − "MetricExpr": "TOPDOWN_BE_BOUND.REGISTER / tma_info_core_slots", | |
| 692 | + "MetricExpr": "cpu_atom@TOPDOWN_BE_BOUND.REGISTER@ / tma_info_core_slots", | |
| 696 | 693 | "MetricGroup": "TopdownL3;tma_L3_group;tma_resource_bound_group", |
| 697 | 694 | "MetricName": "tma_register", |
| 698 | 695 | "MetricThreshold": "tma_register > 0.1", |
| @@ -701,7 +698,7 @@ · 2 unmodified lines | ||
| 701 | 698 | }, |
| 702 | 699 | { |
| 703 | 700 | "BriefDescription": "Counts the number of issue slots that were not consumed by the backend due to the reorder buffer being full (ROB stalls).", |
| 704 | − "MetricExpr": "TOPDOWN_BE_BOUND.REORDER_BUFFER / tma_info_core_slots", | |
| 701 | + "MetricExpr": "cpu_atom@TOPDOWN_BE_BOUND.REORDER_BUFFER@ / tma_info_core_slots", | |
| 705 | 702 | "MetricGroup": "TopdownL3;tma_L3_group;tma_resource_bound_group", |
| 706 | 703 | "MetricName": "tma_reorder_buffer", |
| 707 | 704 | "MetricThreshold": "tma_reorder_buffer > 0.1", |
| @@ -722,7 +719,7 @@ · 14 unmodified lines | ||
| 722 | 719 | { |
| 723 | 720 | "BriefDescription": "Counts the number of issue slots that result in retirement slots.", |
| 724 | 721 | "DefaultMetricgroupName": "TopdownL1", |
| 725 | − "MetricExpr": "TOPDOWN_RETIRING.ALL / tma_info_core_slots", | |
| 722 | + "MetricExpr": "cpu_atom@TOPDOWN_RETIRING.ALL@ / tma_info_core_slots", | |
| 726 | 723 | "MetricGroup": "Default;TopdownL1;tma_L1_group", |
| 727 | 724 | "MetricName": "tma_retiring", |
| 728 | 725 | "MetricThreshold": "tma_retiring > 0.75", |
| @@ -741,7 +738,7 @@ · 12 unmodified lines | ||
| 741 | 738 | }, |
| 742 | 739 | { |
| 743 | 740 | "BriefDescription": "Counts the number of issue slots that were not consumed by the backend due to scoreboards from the instruction queue (IQ), jump execution unit (JEU), or microcode sequencer (MS).", |
| 744 | − "MetricExpr": "TOPDOWN_BE_BOUND.SERIALIZATION / tma_info_core_slots", | |
| 741 | + "MetricExpr": "cpu_atom@TOPDOWN_BE_BOUND.SERIALIZATION@ / tma_info_core_slots", | |
| 745 | 742 | "MetricGroup": "TopdownL3;tma_L3_group;tma_resource_bound_group", |
| 746 | 743 | "MetricName": "tma_serialization", |
| 747 | 744 | "MetricThreshold": "tma_serialization > 0.1", |
| @@ -768,7 +765,7 @@ · 20 unmodified lines | ||
| 768 | 765 | }, |
| 769 | 766 | { |
| 770 | 767 | "BriefDescription": "Counts the number of cycles that the oldest load of the load buffer is stalled at retirement due to a first level TLB miss.", |
| 771 | − "MetricExpr": "LD_HEAD.DTLB_MISS_AT_RET / tma_info_core_clks", | |
| 768 | + "MetricExpr": "cpu_atom@LD_HEAD.DTLB_MISS_AT_RET@ / tma_info_core_clks", | |
| 772 | 769 | "MetricGroup": "TopdownL4;tma_L4_group;tma_l1_bound_group", |
| 773 | 770 | "MetricName": "tma_stlb_hit", |
| 774 | 771 | "MetricThreshold": "tma_stlb_hit > 0.05", |
| @@ -777,7 +774,7 @@ · 2 unmodified lines | ||
| 777 | 774 | }, |
| 778 | 775 | { |
| 779 | 776 | "BriefDescription": "Counts the number of cycles that the oldest load of the load buffer is stalled at retirement due to a second level TLB miss requiring a page walk.", |
| 780 | − "MetricExpr": "LD_HEAD.PGWALK_AT_RET / tma_info_core_clks", | |
| 777 | + "MetricExpr": "cpu_atom@LD_HEAD.PGWALK_AT_RET@ / tma_info_core_clks", | |
| 781 | 778 | "MetricGroup": "TopdownL4;tma_L4_group;tma_l1_bound_group", |
| 782 | 779 | "MetricName": "tma_stlb_miss", |
| 783 | 780 | "MetricThreshold": "tma_stlb_miss > 0.05", |
| @@ -795,8 +792,7 @@ · 11 unmodified lines | ||
| 795 | 792 | }, |
| 796 | 793 | { |
| 797 | 794 | "BriefDescription": "Counts the number of cycles that the oldest load of the load buffer is stalled at retirement due to a store forward block.", |
| 798 | − "MetricConstraint": "NO_GROUP_EVENTS_NMI", | |
| 799 | − "MetricExpr": "LD_HEAD.ST_ADDR_AT_RET / tma_info_core_clks", | |
| 795 | + "MetricExpr": "cpu_atom@LD_HEAD.ST_ADDR_AT_RET@ / tma_info_core_clks", | |
| 800 | 796 | "MetricGroup": "TopdownL4;tma_L4_group;tma_l1_bound_group", |
| 801 | 797 | "MetricName": "tma_store_fwd_blk", |
| 802 | 798 | "MetricThreshold": "tma_store_fwd_blk > 0.05", |
| @@ -875,7 +871,7 @@ · 72 unmodified lines | ||
| 875 | 871 | }, |
| 876 | 872 | { |
| 877 | 873 | "BriefDescription": "This metric represents fraction of cycles the CPU was stalled due to Branch Resteers", |
| 878 | − "MetricExpr": "INT_MISC.CLEAR_RESTEER_CYCLES / tma_info_thread_clks + tma_unknown_branches", | |
| 874 | + "MetricExpr": "cpu_core@INT_MISC.CLEAR_RESTEER_CYCLES@ / tma_info_thread_clks + tma_unknown_branches", | |
| 879 | 875 | "MetricGroup": "FetchLat;TopdownL3;tma_L3_group;tma_fetch_latency_group", |
| 880 | 876 | "MetricName": "tma_branch_resteers", |
| 881 | 877 | "MetricThreshold": "tma_branch_resteers > 0.05 & (tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15)", |
| @@ -905,7 +901,6 @@ · 23 unmodified lines | ||
| 905 | 901 | }, |
| 906 | 902 | { |
| 907 | 903 | "BriefDescription": "This metric estimates fraction of cycles while the memory subsystem was handling synchronizations due to contested accesses", |
| 908 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 909 | 904 | "MetricExpr": "(25 * tma_info_system_average_frequency * (cpu_core@MEM_LOAD_L3_HIT_RETIRED.XSNP_FWD@ * (cpu_core@OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HITM@ / (cpu_core@OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HITM@ + cpu_core@OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD@))) + 24 * tma_info_system_average_frequency * cpu_core@MEM_LOAD_L3_HIT_RETIRED.XSNP_MISS@) * (1 + cpu_core@MEM_LOAD_RETIRED.FB_HIT@ / cpu_core@MEM_LOAD_RETIRED.L1_MISS@ / 2) / tma_info_thread_clks", |
| 910 | 905 | "MetricGroup": "DataSharing;Offcore;Snoop;TopdownL4;tma_L4_group;tma_issueSyncxn;tma_l3_bound_group", |
| 911 | 906 | "MetricName": "tma_contested_accesses", |
| @@ -927,7 +922,6 @@ · 15 unmodified lines | ||
| 927 | 922 | }, |
| 928 | 923 | { |
| 929 | 924 | "BriefDescription": "This metric estimates fraction of cycles while the memory subsystem was handling synchronizations due to data-sharing accesses", |
| 930 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 931 | 925 | "MetricExpr": "24 * tma_info_system_average_frequency * (cpu_core@MEM_LOAD_L3_HIT_RETIRED.XSNP_NO_FWD@ + cpu_core@MEM_LOAD_L3_HIT_RETIRED.XSNP_FWD@ * (1 - cpu_core@OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HITM@ / (cpu_core@OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HITM@ + cpu_core@OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD@))) * (1 + cpu_core@MEM_LOAD_RETIRED.FB_HIT@ / cpu_core@MEM_LOAD_RETIRED.L1_MISS@ / 2) / tma_info_thread_clks", |
| 932 | 926 | "MetricGroup": "Offcore;Snoop;TopdownL4;tma_L4_group;tma_issueSyncxn;tma_l3_bound_group", |
| 933 | 927 | "MetricName": "tma_data_sharing", |
| @@ -948,7 +942,7 @@ · 14 unmodified lines | ||
| 948 | 942 | }, |
| 949 | 943 | { |
| 950 | 944 | "BriefDescription": "This metric represents fraction of cycles where the Divider unit was active", |
| 951 | − "MetricExpr": "ARITH.DIV_ACTIVE / tma_info_thread_clks", | |
| 945 | + "MetricExpr": "cpu_core@ARITH.DIV_ACTIVE@ / tma_info_thread_clks", | |
| 952 | 946 | "MetricGroup": "TopdownL3;tma_L3_group;tma_core_bound_group", |
| 953 | 947 | "MetricName": "tma_divider", |
| 954 | 948 | "MetricThreshold": "tma_divider > 0.2 & (tma_core_bound > 0.1 & tma_backend_bound > 0.2)", |
| @@ -958,7 +952,6 @@ · 3 unmodified lines | ||
| 958 | 952 | }, |
| 959 | 953 | { |
| 960 | 954 | "BriefDescription": "This metric estimates how often the CPU was stalled on accesses to external memory (DRAM) by loads", |
| 961 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 962 | 955 | "MetricExpr": "cpu_core@MEMORY_ACTIVITY.STALLS_L3_MISS@ / tma_info_thread_clks", |
| 963 | 956 | "MetricGroup": "MemoryBound;TmaL3mem;TopdownL3;tma_L3_group;tma_memory_bound_group", |
| 964 | 957 | "MetricName": "tma_dram_bound", |
| @@ -979,7 +972,7 @@ · 14 unmodified lines | ||
| 979 | 972 | }, |
| 980 | 973 | { |
| 981 | 974 | "BriefDescription": "This metric represents fraction of cycles the CPU was stalled due to switches from DSB to MITE pipelines", |
| 982 | − "MetricExpr": "DSB2MITE_SWITCHES.PENALTY_CYCLES / tma_info_thread_clks", | |
| 975 | + "MetricExpr": "cpu_core@DSB2MITE_SWITCHES.PENALTY_CYCLES@ / tma_info_thread_clks", | |
| 983 | 976 | "MetricGroup": "DSBmiss;FetchLat;TopdownL3;tma_L3_group;tma_fetch_latency_group;tma_issueFB", |
| 984 | 977 | "MetricName": "tma_dsb_switches", |
| 985 | 978 | "MetricThreshold": "tma_dsb_switches > 0.05 & (tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15)", |
| @@ -1019,7 +1012,7 @@ · 33 unmodified lines | ||
| 1019 | 1012 | }, |
| 1020 | 1013 | { |
| 1021 | 1014 | "BriefDescription": "This metric does a *rough estimation* of how often L1D Fill Buffer unavailability limited additional L1D miss memory access requests to proceed", |
| 1022 | − "MetricExpr": "L1D_PEND_MISS.FB_FULL / tma_info_thread_clks", | |
| 1015 | + "MetricExpr": "cpu_core@L1D_PEND_MISS.FB_FULL@ / tma_info_thread_clks", | |
| 1023 | 1016 | "MetricGroup": "MemoryBW;TopdownL4;tma_L4_group;tma_issueBW;tma_issueSL;tma_issueSmSt;tma_l1_bound_group", |
| 1024 | 1017 | "MetricName": "tma_fb_full", |
| 1025 | 1018 | "MetricThreshold": "tma_fb_full > 0.3", |
| @@ -1154,7 +1147,7 @@ · 128 unmodified lines | ||
| 1154 | 1147 | }, |
| 1155 | 1148 | { |
| 1156 | 1149 | "BriefDescription": "This metric represents fraction of cycles the CPU was stalled due to instruction cache misses", |
| 1157 | − "MetricExpr": "ICACHE_DATA.STALLS / tma_info_thread_clks", | |
| 1150 | + "MetricExpr": "cpu_core@ICACHE_DATA.STALLS@ / tma_info_thread_clks", | |
| 1158 | 1151 | "MetricGroup": "BigFoot;FetchLat;IcMiss;TopdownL3;tma_L3_group;tma_fetch_latency_group", |
| 1159 | 1152 | "MetricName": "tma_icache_misses", |
| 1160 | 1153 | "MetricThreshold": "tma_icache_misses > 0.05 & (tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15)", |
| @@ -1164,7 +1157,6 @@ · 3 unmodified lines | ||
| 1164 | 1157 | }, |
| 1165 | 1158 | { |
| 1166 | 1159 | "BriefDescription": "Branch Misprediction Cost: Fraction of TMA slots wasted per non-speculative branch misprediction (retired JEClear)", |
| 1167 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 1168 | 1160 | "MetricExpr": "(tma_branch_mispredicts + tma_fetch_latency * tma_mispredicts_resteers / (tma_branch_resteers + tma_dsb_switches + tma_icache_misses + tma_itlb_misses + tma_lcp + tma_ms_switches)) * tma_info_thread_slots / BR_MISP_RETIRED.ALL_BRANCHES", |
| 1169 | 1161 | "MetricGroup": "Bad;BrMispredicts;tma_issueBM", |
| 1170 | 1162 | "MetricName": "tma_info_bad_spec_branch_misprediction_cost", |
| @@ -1173,7 +1165,7 @@ · 2 unmodified lines | ||
| 1173 | 1165 | }, |
| 1174 | 1166 | { |
| 1175 | 1167 | "BriefDescription": "Instructions per retired mispredicts for conditional non-taken branches (lower number means higher occurrence rate).", |
| 1176 | − "MetricExpr": "INST_RETIRED.ANY / BR_MISP_RETIRED.COND_NTAKEN", | |
| 1168 | + "MetricExpr": "cpu_core@INST_RETIRED.ANY@ / BR_MISP_RETIRED.COND_NTAKEN", | |
| 1177 | 1169 | "MetricGroup": "Bad;BrMispredicts", |
| 1178 | 1170 | "MetricName": "tma_info_bad_spec_ipmisp_cond_ntaken", |
| 1179 | 1171 | "MetricThreshold": "tma_info_bad_spec_ipmisp_cond_ntaken < 200", |
| @@ -1181,7 +1173,7 @@ · 1 unmodified line | ||
| 1181 | 1173 | }, |
| 1182 | 1174 | { |
| 1183 | 1175 | "BriefDescription": "Instructions per retired mispredicts for conditional taken branches (lower number means higher occurrence rate).", |
| 1184 | − "MetricExpr": "INST_RETIRED.ANY / BR_MISP_RETIRED.COND_TAKEN", | |
| 1176 | + "MetricExpr": "cpu_core@INST_RETIRED.ANY@ / BR_MISP_RETIRED.COND_TAKEN", | |
| 1185 | 1177 | "MetricGroup": "Bad;BrMispredicts", |
| 1186 | 1178 | "MetricName": "tma_info_bad_spec_ipmisp_cond_taken", |
| 1187 | 1179 | "MetricThreshold": "tma_info_bad_spec_ipmisp_cond_taken < 200", |
| @@ -1197,7 +1189,7 @@ · 9 unmodified lines | ||
| 1197 | 1189 | }, |
| 1198 | 1190 | { |
| 1199 | 1191 | "BriefDescription": "Instructions per retired mispredicts for return branches (lower number means higher occurrence rate).", |
| 1200 | − "MetricExpr": "INST_RETIRED.ANY / BR_MISP_RETIRED.RET", | |
| 1192 | + "MetricExpr": "cpu_core@INST_RETIRED.ANY@ / BR_MISP_RETIRED.RET", | |
| 1201 | 1193 | "MetricGroup": "Bad;BrMispredicts", |
| 1202 | 1194 | "MetricName": "tma_info_bad_spec_ipmisp_ret", |
| 1203 | 1195 | "MetricThreshold": "tma_info_bad_spec_ipmisp_ret < 500", |
| @@ -1205,7 +1197,7 @@ · 1 unmodified line | ||
| 1205 | 1197 | }, |
| 1206 | 1198 | { |
| 1207 | 1199 | "BriefDescription": "Number of Instructions per non-speculative Branch Misprediction (JEClear) (lower number means higher occurrence rate)", |
| 1208 | − "MetricExpr": "INST_RETIRED.ANY / BR_MISP_RETIRED.ALL_BRANCHES", | |
| 1200 | + "MetricExpr": "cpu_core@INST_RETIRED.ANY@ / BR_MISP_RETIRED.ALL_BRANCHES", | |
| 1209 | 1201 | "MetricGroup": "Bad;BadSpec;BrMispredicts", |
| 1210 | 1202 | "MetricName": "tma_info_bad_spec_ipmispredict", |
| 1211 | 1203 | "MetricThreshold": "tma_info_bad_spec_ipmispredict < 200", |
| @@ -1213,7 +1205,6 @@ · 1 unmodified line | ||
| 1213 | 1205 | }, |
| 1214 | 1206 | { |
| 1215 | 1207 | "BriefDescription": "Probability of Core Bound bottleneck hidden by SMT-profiling artifacts", |
| 1216 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 1217 | 1208 | "MetricExpr": "(100 * (1 - tma_core_bound / tma_ports_utilization if tma_core_bound < tma_ports_utilization else 1) if tma_info_system_smt_2t_utilization > 0.5 else 0)", |
| 1218 | 1209 | "MetricGroup": "Cor;SMT", |
| 1219 | 1210 | "MetricName": "tma_info_botlnk_l0_core_bound_likely", |
| @@ -1222,7 +1213,6 @@ · 2 unmodified lines | ||
| 1222 | 1213 | }, |
| 1223 | 1214 | { |
| 1224 | 1215 | "BriefDescription": "Total pipeline cost of DSB (uop cache) misses - subset of the Instruction_Fetch_BW Bottleneck", |
| 1225 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 1226 | 1216 | "MetricExpr": "100 * (tma_fetch_latency * tma_dsb_switches / (tma_branch_resteers + tma_dsb_switches + tma_icache_misses + tma_itlb_misses + tma_lcp + tma_ms_switches) + tma_fetch_bandwidth * tma_mite / (tma_dsb + tma_lsd + tma_mite))", |
| 1227 | 1217 | "MetricGroup": "DSBmiss;Fed;tma_issueFB", |
| 1228 | 1218 | "MetricName": "tma_info_botlnk_l2_dsb_misses", |
| @@ -1232,7 +1222,6 @@ · 3 unmodified lines | ||
| 1232 | 1222 | }, |
| 1233 | 1223 | { |
| 1234 | 1224 | "BriefDescription": "Total pipeline cost of Instruction Cache misses - subset of the Big_Code Bottleneck", |
| 1235 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 1236 | 1225 | "MetricExpr": "100 * (tma_fetch_latency * tma_icache_misses / (tma_branch_resteers + tma_dsb_switches + tma_icache_misses + tma_itlb_misses + tma_lcp + tma_ms_switches))", |
| 1237 | 1226 | "MetricGroup": "Fed;FetchLat;IcMiss;tma_issueFL", |
| 1238 | 1227 | "MetricName": "tma_info_botlnk_l2_ic_misses", |
| @@ -1242,7 +1231,6 @@ · 3 unmodified lines | ||
| 1242 | 1231 | }, |
| 1243 | 1232 | { |
| 1244 | 1233 | "BriefDescription": "Total pipeline cost of instruction fetch related bottlenecks by large code footprint programs (i-side cache; TLB and BTB misses)", |
| 1245 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 1246 | 1234 | "MetricExpr": "100 * tma_fetch_latency * (tma_itlb_misses + tma_icache_misses + tma_unknown_branches) / (tma_branch_resteers + tma_dsb_switches + tma_icache_misses + tma_itlb_misses + tma_lcp + tma_ms_switches)", |
| 1247 | 1235 | "MetricGroup": "BigFoot;Fed;Frontend;IcMiss;MemoryTLB;tma_issueBC", |
| 1248 | 1236 | "MetricName": "tma_info_bottleneck_big_code", |
| @@ -1261,7 +1249,6 @@ · 12 unmodified lines | ||
| 1261 | 1249 | }, |
| 1262 | 1250 | { |
| 1263 | 1251 | "BriefDescription": "Total pipeline cost of instruction fetch bandwidth related bottlenecks", |
| 1264 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 1265 | 1252 | "MetricExpr": "100 * (tma_frontend_bound - tma_fetch_latency * tma_mispredicts_resteers / (tma_branch_resteers + tma_dsb_switches + tma_icache_misses + tma_itlb_misses + tma_lcp + tma_ms_switches)) - tma_info_bottleneck_big_code", |
| 1266 | 1253 | "MetricGroup": "Fed;FetchBW;Frontend", |
| 1267 | 1254 | "MetricName": "tma_info_bottleneck_instruction_fetch_bw", |
| @@ -1270,7 +1257,6 @@ · 2 unmodified lines | ||
| 1270 | 1257 | }, |
| 1271 | 1258 | { |
| 1272 | 1259 | "BriefDescription": "Total pipeline cost of (external) Memory Bandwidth related bottlenecks", |
| 1273 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 1274 | 1260 | "MetricExpr": "100 * tma_memory_bound * (tma_dram_bound / (tma_dram_bound + tma_l1_bound + tma_l2_bound + tma_l3_bound + tma_store_bound) * (tma_mem_bandwidth / (tma_mem_bandwidth + tma_mem_latency)) + tma_l3_bound / (tma_dram_bound + tma_l1_bound + tma_l2_bound + tma_l3_bound + tma_store_bound) * (tma_sq_full / (tma_contested_accesses + tma_data_sharing + tma_l3_hit_latency + tma_sq_full))) + tma_l1_bound / (tma_dram_bound + tma_l1_bound + tma_l2_bound + tma_l3_bound + tma_store_bound) * (tma_fb_full / (tma_dtlb_load + tma_fb_full + tma_lock_latency + tma_split_loads + tma_store_fwd_blk))", |
| 1275 | 1261 | "MetricGroup": "Mem;MemoryBW;Offcore;tma_issueBW", |
| 1276 | 1262 | "MetricName": "tma_info_bottleneck_memory_bandwidth", |
| @@ -1280,7 +1266,6 @@ · 3 unmodified lines | ||
| 1280 | 1266 | }, |
| 1281 | 1267 | { |
| 1282 | 1268 | "BriefDescription": "Total pipeline cost of Memory Address Translation related bottlenecks (data-side TLBs)", |
| 1283 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 1284 | 1269 | "MetricExpr": "100 * tma_memory_bound * (tma_l1_bound / max(tma_memory_bound, tma_dram_bound + tma_l1_bound + tma_l2_bound + tma_l3_bound + tma_store_bound) * (tma_dtlb_load / max(tma_l1_bound, tma_dtlb_load + tma_fb_full + tma_lock_latency + tma_split_loads + tma_store_fwd_blk)) + tma_store_bound / (tma_dram_bound + tma_l1_bound + tma_l2_bound + tma_l3_bound + tma_store_bound) * (tma_dtlb_store / (tma_dtlb_store + tma_false_sharing + tma_split_stores + tma_store_latency + tma_streaming_stores)))", |
| 1285 | 1270 | "MetricGroup": "Mem;MemoryTLB;Offcore;tma_issueTLB", |
| 1286 | 1271 | "MetricName": "tma_info_bottleneck_memory_data_tlbs", |
| @@ -1290,7 +1275,6 @@ · 3 unmodified lines | ||
| 1290 | 1275 | }, |
| 1291 | 1276 | { |
| 1292 | 1277 | "BriefDescription": "Total pipeline cost of Memory Latency related bottlenecks (external memory and off-core caches)", |
| 1293 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 1294 | 1278 | "MetricExpr": "100 * tma_memory_bound * (tma_dram_bound / (tma_dram_bound + tma_l1_bound + tma_l2_bound + tma_l3_bound + tma_store_bound) * (tma_mem_latency / (tma_mem_bandwidth + tma_mem_latency)) + tma_l3_bound / (tma_dram_bound + tma_l1_bound + tma_l2_bound + tma_l3_bound + tma_store_bound) * (tma_l3_hit_latency / (tma_contested_accesses + tma_data_sharing + tma_l3_hit_latency + tma_sq_full)) + tma_l2_bound / (tma_dram_bound + tma_l1_bound + tma_l2_bound + tma_l3_bound + tma_store_bound))", |
| 1295 | 1279 | "MetricGroup": "Mem;MemoryLat;Offcore;tma_issueLat", |
| 1296 | 1280 | "MetricName": "tma_info_bottleneck_memory_latency", |
| @@ -1300,7 +1284,6 @@ · 3 unmodified lines | ||
| 1300 | 1284 | }, |
| 1301 | 1285 | { |
| 1302 | 1286 | "BriefDescription": "Total pipeline cost of Branch Misprediction related bottlenecks", |
| 1303 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 1304 | 1287 | "MetricExpr": "100 * (tma_branch_mispredicts + tma_fetch_latency * tma_mispredicts_resteers / (tma_branch_resteers + tma_dsb_switches + tma_icache_misses + tma_itlb_misses + tma_lcp + tma_ms_switches))", |
| 1305 | 1288 | "MetricGroup": "Bad;BadSpec;BrMispredicts;tma_issueBM", |
| 1306 | 1289 | "MetricName": "tma_info_bottleneck_mispredictions", |
| @@ -1317,14 +1300,14 @@ · 10 unmodified lines | ||
| 1317 | 1300 | }, |
| 1318 | 1301 | { |
| 1319 | 1302 | "BriefDescription": "Fraction of branches that are non-taken conditionals", |
| 1320 | − "MetricExpr": "BR_INST_RETIRED.COND_NTAKEN / BR_INST_RETIRED.ALL_BRANCHES", | |
| 1303 | + "MetricExpr": "cpu_core@BR_INST_RETIRED.COND_NTAKEN@ / BR_INST_RETIRED.ALL_BRANCHES", | |
| 1321 | 1304 | "MetricGroup": "Bad;Branches;CodeGen;PGO", |
| 1322 | 1305 | "MetricName": "tma_info_branches_cond_nt", |
| 1323 | 1306 | "Unit": "cpu_core" |
| 1324 | 1307 | }, |
| 1325 | 1308 | { |
| 1326 | 1309 | "BriefDescription": "Fraction of branches that are taken conditionals", |
| 1327 | − "MetricExpr": "BR_INST_RETIRED.COND_TAKEN / BR_INST_RETIRED.ALL_BRANCHES", | |
| 1310 | + "MetricExpr": "cpu_core@BR_INST_RETIRED.COND_TAKEN@ / BR_INST_RETIRED.ALL_BRANCHES", | |
| 1328 | 1311 | "MetricGroup": "Bad;Branches;CodeGen;PGO", |
| 1329 | 1312 | "MetricName": "tma_info_branches_cond_tk", |
| 1330 | 1313 | "Unit": "cpu_core" |
| @@ -1352,7 +1335,7 @@ · 21 unmodified lines | ||
| 1352 | 1335 | }, |
| 1353 | 1336 | { |
| 1354 | 1337 | "BriefDescription": "Instructions Per Cycle across hyper-threads (per physical core)", |
| 1355 | − "MetricExpr": "INST_RETIRED.ANY / tma_info_core_core_clks", | |
| 1338 | + "MetricExpr": "cpu_core@INST_RETIRED.ANY@ / tma_info_core_core_clks", | |
| 1356 | 1339 | "MetricGroup": "Ret;SMT;TmaL1;tma_L1_group", |
| 1357 | 1340 | "MetricName": "tma_info_core_coreipc", |
| 1358 | 1341 | "Unit": "cpu_core" |
| @@ -1374,14 +1357,14 @@ · 15 unmodified lines | ||
| 1374 | 1357 | }, |
| 1375 | 1358 | { |
| 1376 | 1359 | "BriefDescription": "Instruction-Level-Parallelism (average number of uops executed when there is execution) per-core", |
| 1377 | − "MetricExpr": "UOPS_EXECUTED.THREAD / (cpu_core@UOPS_EXECUTED.CORE_CYCLES_GE_1@ / 2 if #SMT_on else cpu_core@UOPS_EXECUTED.CORE_CYCLES_GE_1@)", | |
| 1360 | + "MetricExpr": "cpu_core@UOPS_EXECUTED.THREAD@ / (cpu_core@UOPS_EXECUTED.CORE_CYCLES_GE_1@ / 2 if #SMT_on else cpu_core@UOPS_EXECUTED.CORE_CYCLES_GE_1@)", | |
| 1378 | 1361 | "MetricGroup": "Backend;Cor;Pipeline;PortsUtil", |
| 1379 | 1362 | "MetricName": "tma_info_core_ilp", |
| 1380 | 1363 | "Unit": "cpu_core" |
| 1381 | 1364 | }, |
| 1382 | 1365 | { |
| 1383 | 1366 | "BriefDescription": "Fraction of Uops delivered by the DSB (aka Decoded ICache; or Uop Cache)", |
| 1384 | − "MetricExpr": "IDQ.DSB_UOPS / cpu_core@UOPS_ISSUED.ANY@", | |
| 1367 | + "MetricExpr": "cpu_core@IDQ.DSB_UOPS@ / cpu_core@UOPS_ISSUED.ANY@", | |
| 1385 | 1368 | "MetricGroup": "DSB;Fed;FetchBW;tma_issueFB", |
| 1386 | 1369 | "MetricName": "tma_info_frontend_dsb_coverage", |
| 1387 | 1370 | "MetricThreshold": "tma_info_frontend_dsb_coverage < 0.7 & tma_info_thread_ipc / 6 > 0.35", |
| @@ -1390,28 +1373,28 @@ · 2 unmodified lines | ||
| 1390 | 1373 | }, |
| 1391 | 1374 | { |
| 1392 | 1375 | "BriefDescription": "Average number of cycles of a switch from the DSB fetch-unit to MITE fetch unit - see DSB_Switches tree node for details.", |
| 1393 | − "MetricExpr": "DSB2MITE_SWITCHES.PENALTY_CYCLES / cpu_core@DSB2MITE_SWITCHES.PENALTY_CYCLES\\,cmask\\=1\\,edge@", | |
| 1376 | + "MetricExpr": "cpu_core@DSB2MITE_SWITCHES.PENALTY_CYCLES@ / cpu_core@DSB2MITE_SWITCHES.PENALTY_CYCLES\\,cmask\\=1\\,edge@", | |
| 1394 | 1377 | "MetricGroup": "DSBmiss", |
| 1395 | 1378 | "MetricName": "tma_info_frontend_dsb_switch_cost", |
| 1396 | 1379 | "Unit": "cpu_core" |
| 1397 | 1380 | }, |
| 1398 | 1381 | { |
| 1399 | 1382 | "BriefDescription": "Average number of Uops issued by front-end when it issued something", |
| 1400 | − "MetricExpr": "UOPS_ISSUED.ANY / cpu_core@UOPS_ISSUED.ANY\\,cmask\\=1@", | |
| 1383 | + "MetricExpr": "cpu_core@UOPS_ISSUED.ANY@ / cpu_core@UOPS_ISSUED.ANY\\,cmask\\=1@", | |
| 1401 | 1384 | "MetricGroup": "Fed;FetchBW", |
| 1402 | 1385 | "MetricName": "tma_info_frontend_fetch_upc", |
| 1403 | 1386 | "Unit": "cpu_core" |
| 1404 | 1387 | }, |
| 1405 | 1388 | { |
| 1406 | 1389 | "BriefDescription": "Average Latency for L1 instruction cache misses", |
| 1407 | − "MetricExpr": "ICACHE_DATA.STALLS / cpu_core@ICACHE_DATA.STALLS\\,cmask\\=1\\,edge@", | |
| 1390 | + "MetricExpr": "cpu_core@ICACHE_DATA.STALLS@ / cpu_core@ICACHE_DATA.STALLS\\,cmask\\=1\\,edge@", | |
| 1408 | 1391 | "MetricGroup": "Fed;FetchLat;IcMiss", |
| 1409 | 1392 | "MetricName": "tma_info_frontend_icache_miss_latency", |
| 1410 | 1393 | "Unit": "cpu_core" |
| 1411 | 1394 | }, |
| 1412 | 1395 | { |
| 1413 | 1396 | "BriefDescription": "Instructions per non-speculative DSB miss (lower number means higher occurrence rate)", |
| 1414 | − "MetricExpr": "INST_RETIRED.ANY / FRONTEND_RETIRED.ANY_DSB_MISS", | |
| 1397 | + "MetricExpr": "cpu_core@INST_RETIRED.ANY@ / FRONTEND_RETIRED.ANY_DSB_MISS", | |
| 1415 | 1398 | "MetricGroup": "DSBmiss;Fed", |
| 1416 | 1399 | "MetricName": "tma_info_frontend_ipdsb_miss_ret", |
| 1417 | 1400 | "MetricThreshold": "tma_info_frontend_ipdsb_miss_ret < 50", |
| @@ -1440,14 +1423,14 @@ · 22 unmodified lines | ||
| 1440 | 1423 | }, |
| 1441 | 1424 | { |
| 1442 | 1425 | "BriefDescription": "Fraction of Uops delivered by the LSD (Loop Stream Detector; aka Loop Cache)", |
| 1443 | − "MetricExpr": "LSD.UOPS / cpu_core@UOPS_ISSUED.ANY@", | |
| 1426 | + "MetricExpr": "cpu_core@LSD.UOPS@ / cpu_core@UOPS_ISSUED.ANY@", | |
| 1444 | 1427 | "MetricGroup": "Fed;LSD", |
| 1445 | 1428 | "MetricName": "tma_info_frontend_lsd_coverage", |
| 1446 | 1429 | "Unit": "cpu_core" |
| 1447 | 1430 | }, |
| 1448 | 1431 | { |
| 1449 | 1432 | "BriefDescription": "Branch instructions per taken branch.", |
| 1450 | − "MetricExpr": "BR_INST_RETIRED.ALL_BRANCHES / BR_INST_RETIRED.NEAR_TAKEN", | |
| 1433 | + "MetricExpr": "cpu_core@BR_INST_RETIRED.ALL_BRANCHES@ / BR_INST_RETIRED.NEAR_TAKEN", | |
| 1451 | 1434 | "MetricGroup": "Branches;Fed;PGO", |
| 1452 | 1435 | "MetricName": "tma_info_inst_mix_bptkbranch", |
| 1453 | 1436 | "Unit": "cpu_core" |
| @@ -1462,7 +1445,7 @@ · 8 unmodified lines | ||
| 1462 | 1445 | }, |
| 1463 | 1446 | { |
| 1464 | 1447 | "BriefDescription": "Instructions per FP Arithmetic instruction (lower number means higher occurrence rate)", |
| 1465 | − "MetricExpr": "INST_RETIRED.ANY / (cpu_core@FP_ARITH_INST_RETIRED.SCALAR_SINGLE\\,umask\\=0x03@ + cpu_core@FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE\\,umask\\=0x3c@)", | |
| 1448 | + "MetricExpr": "cpu_core@INST_RETIRED.ANY@ / (cpu_core@FP_ARITH_INST_RETIRED.SCALAR_SINGLE\\,umask\\=0x03@ + cpu_core@FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE\\,umask\\=0x3c@)", | |
| 1466 | 1449 | "MetricGroup": "Flops;InsType", |
| 1467 | 1450 | "MetricName": "tma_info_inst_mix_iparith", |
| 1468 | 1451 | "MetricThreshold": "tma_info_inst_mix_iparith < 10", |
| @@ -1471,7 +1454,7 @@ · 2 unmodified lines | ||
| 1471 | 1454 | }, |
| 1472 | 1455 | { |
| 1473 | 1456 | "BriefDescription": "Instructions per FP Arithmetic AVX/SSE 128-bit instruction (lower number means higher occurrence rate)", |
| 1474 | − "MetricExpr": "INST_RETIRED.ANY / (cpu_core@FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE@ + cpu_core@FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE@)", | |
| 1457 | + "MetricExpr": "cpu_core@INST_RETIRED.ANY@ / (cpu_core@FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE@ + cpu_core@FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE@)", | |
| 1475 | 1458 | "MetricGroup": "Flops;FpVector;InsType", |
| 1476 | 1459 | "MetricName": "tma_info_inst_mix_iparith_avx128", |
| 1477 | 1460 | "MetricThreshold": "tma_info_inst_mix_iparith_avx128 < 10", |
| @@ -1480,7 +1463,7 @@ · 2 unmodified lines | ||
| 1480 | 1463 | }, |
| 1481 | 1464 | { |
| 1482 | 1465 | "BriefDescription": "Instructions per FP Arithmetic AVX* 256-bit instruction (lower number means higher occurrence rate)", |
| 1483 | − "MetricExpr": "INST_RETIRED.ANY / (cpu_core@FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE@ + cpu_core@FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE@)", | |
| 1466 | + "MetricExpr": "cpu_core@INST_RETIRED.ANY@ / (cpu_core@FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE@ + cpu_core@FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE@)", | |
| 1484 | 1467 | "MetricGroup": "Flops;FpVector;InsType", |
| 1485 | 1468 | "MetricName": "tma_info_inst_mix_iparith_avx256", |
| 1486 | 1469 | "MetricThreshold": "tma_info_inst_mix_iparith_avx256 < 10", |
| @@ -1489,7 +1472,7 @@ · 2 unmodified lines | ||
| 1489 | 1472 | }, |
| 1490 | 1473 | { |
| 1491 | 1474 | "BriefDescription": "Instructions per FP Arithmetic Scalar Double-Precision instruction (lower number means higher occurrence rate)", |
| 1492 | − "MetricExpr": "INST_RETIRED.ANY / FP_ARITH_INST_RETIRED.SCALAR_DOUBLE", | |
| 1475 | + "MetricExpr": "cpu_core@INST_RETIRED.ANY@ / FP_ARITH_INST_RETIRED.SCALAR_DOUBLE", | |
| 1493 | 1476 | "MetricGroup": "Flops;FpScalar;InsType", |
| 1494 | 1477 | "MetricName": "tma_info_inst_mix_iparith_scalar_dp", |
| 1495 | 1478 | "MetricThreshold": "tma_info_inst_mix_iparith_scalar_dp < 10", |
| @@ -1498,7 +1481,7 @@ · 2 unmodified lines | ||
| 1498 | 1481 | }, |
| 1499 | 1482 | { |
| 1500 | 1483 | "BriefDescription": "Instructions per FP Arithmetic Scalar Single-Precision instruction (lower number means higher occurrence rate)", |
| 1501 | − "MetricExpr": "INST_RETIRED.ANY / FP_ARITH_INST_RETIRED.SCALAR_SINGLE", | |
| 1484 | + "MetricExpr": "cpu_core@INST_RETIRED.ANY@ / FP_ARITH_INST_RETIRED.SCALAR_SINGLE", | |
| 1502 | 1485 | "MetricGroup": "Flops;FpScalar;InsType", |
| 1503 | 1486 | "MetricName": "tma_info_inst_mix_iparith_scalar_sp", |
| 1504 | 1487 | "MetricThreshold": "tma_info_inst_mix_iparith_scalar_sp < 10", |
| @@ -1507,7 +1490,7 @@ · 2 unmodified lines | ||
| 1507 | 1490 | }, |
| 1508 | 1491 | { |
| 1509 | 1492 | "BriefDescription": "Instructions per Branch (lower number means higher occurrence rate)", |
| 1510 | − "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.ALL_BRANCHES", | |
| 1493 | + "MetricExpr": "cpu_core@INST_RETIRED.ANY@ / BR_INST_RETIRED.ALL_BRANCHES", | |
| 1511 | 1494 | "MetricGroup": "Branches;Fed;InsType", |
| 1512 | 1495 | "MetricName": "tma_info_inst_mix_ipbranch", |
| 1513 | 1496 | "MetricThreshold": "tma_info_inst_mix_ipbranch < 8", |
| @@ -1515,7 +1498,7 @@ · 1 unmodified line | ||
| 1515 | 1498 | }, |
| 1516 | 1499 | { |
| 1517 | 1500 | "BriefDescription": "Instructions per (near) call (lower number means higher occurrence rate)", |
| 1518 | − "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.NEAR_CALL", | |
| 1501 | + "MetricExpr": "cpu_core@INST_RETIRED.ANY@ / BR_INST_RETIRED.NEAR_CALL", | |
| 1519 | 1502 | "MetricGroup": "Branches;Fed;PGO", |
| 1520 | 1503 | "MetricName": "tma_info_inst_mix_ipcall", |
| 1521 | 1504 | "MetricThreshold": "tma_info_inst_mix_ipcall < 200", |
| @@ -1523,7 +1506,7 @@ · 1 unmodified line | ||
| 1523 | 1506 | }, |
| 1524 | 1507 | { |
| 1525 | 1508 | "BriefDescription": "Instructions per Floating Point (FP) Operation (lower number means higher occurrence rate)", |
| 1526 | − "MetricExpr": "INST_RETIRED.ANY / (cpu_core@FP_ARITH_INST_RETIRED.SCALAR_SINGLE@ + cpu_core@FP_ARITH_INST_RETIRED.SCALAR_DOUBLE@ + 2 * cpu_core@FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE@ + 4 * (cpu_core@FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE@ + cpu_core@FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE@) + 8 * cpu_core@FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE@)", | |
| 1509 | + "MetricExpr": "cpu_core@INST_RETIRED.ANY@ / (cpu_core@FP_ARITH_INST_RETIRED.SCALAR_SINGLE@ + cpu_core@FP_ARITH_INST_RETIRED.SCALAR_DOUBLE@ + 2 * cpu_core@FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE@ + 4 * (cpu_core@FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE@ + cpu_core@FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE@) + 8 * cpu_core@FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE@)", | |
| 1527 | 1510 | "MetricGroup": "Flops;InsType", |
| 1528 | 1511 | "MetricName": "tma_info_inst_mix_ipflop", |
| 1529 | 1512 | "MetricThreshold": "tma_info_inst_mix_ipflop < 10", |
| @@ -1531,7 +1514,7 @@ · 1 unmodified line | ||
| 1531 | 1514 | }, |
| 1532 | 1515 | { |
| 1533 | 1516 | "BriefDescription": "Instructions per Load (lower number means higher occurrence rate)", |
| 1534 | − "MetricExpr": "INST_RETIRED.ANY / MEM_INST_RETIRED.ALL_LOADS", | |
| 1517 | + "MetricExpr": "cpu_core@INST_RETIRED.ANY@ / MEM_INST_RETIRED.ALL_LOADS", | |
| 1535 | 1518 | "MetricGroup": "InsType", |
| 1536 | 1519 | "MetricName": "tma_info_inst_mix_ipload", |
| 1537 | 1520 | "MetricThreshold": "tma_info_inst_mix_ipload < 3", |
| @@ -1539,7 +1522,7 @@ · 1 unmodified line | ||
| 1539 | 1522 | }, |
| 1540 | 1523 | { |
| 1541 | 1524 | "BriefDescription": "Instructions per Store (lower number means higher occurrence rate)", |
| 1542 | − "MetricExpr": "INST_RETIRED.ANY / MEM_INST_RETIRED.ALL_STORES", | |
| 1525 | + "MetricExpr": "cpu_core@INST_RETIRED.ANY@ / MEM_INST_RETIRED.ALL_STORES", | |
| 1543 | 1526 | "MetricGroup": "InsType", |
| 1544 | 1527 | "MetricName": "tma_info_inst_mix_ipstore", |
| 1545 | 1528 | "MetricThreshold": "tma_info_inst_mix_ipstore < 8", |
| @@ -1547,7 +1530,7 @@ · 1 unmodified line | ||
| 1547 | 1530 | }, |
| 1548 | 1531 | { |
| 1549 | 1532 | "BriefDescription": "Instructions per Software prefetch instruction (of any type: NTA/T0/T1/T2/Prefetch) (lower number means higher occurrence rate)", |
| 1550 | − "MetricExpr": "INST_RETIRED.ANY / cpu_core@SW_PREFETCH_ACCESS.T0\\,umask\\=0xF@", | |
| 1533 | + "MetricExpr": "cpu_core@INST_RETIRED.ANY@ / cpu_core@SW_PREFETCH_ACCESS.T0\\,umask\\=0xF@", | |
| 1551 | 1534 | "MetricGroup": "Prefetches", |
| 1552 | 1535 | "MetricName": "tma_info_inst_mix_ipswpf", |
| 1553 | 1536 | "MetricThreshold": "tma_info_inst_mix_ipswpf < 100", |
| @@ -1555,7 +1538,7 @@ · 1 unmodified line | ||
| 1555 | 1538 | }, |
| 1556 | 1539 | { |
| 1557 | 1540 | "BriefDescription": "Instruction per taken branch", |
| 1558 | − "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.NEAR_TAKEN", | |
| 1541 | + "MetricExpr": "cpu_core@INST_RETIRED.ANY@ / BR_INST_RETIRED.NEAR_TAKEN", | |
| 1559 | 1542 | "MetricGroup": "Branches;Fed;FetchBW;Frontend;PGO;tma_issueFB", |
| 1560 | 1543 | "MetricName": "tma_info_inst_mix_iptb", |
| 1561 | 1544 | "MetricThreshold": "tma_info_inst_mix_iptb < 13", |
| @@ -1655,14 +1638,14 @@ · 93 unmodified lines | ||
| 1655 | 1638 | }, |
| 1656 | 1639 | { |
| 1657 | 1640 | "BriefDescription": "Actual Average Latency for L1 data-cache miss demand load operations (in core cycles)", |
| 1658 | − "MetricExpr": "L1D_PEND_MISS.PENDING / MEM_LOAD_COMPLETED.L1_MISS_ANY", | |
| 1641 | + "MetricExpr": "cpu_core@L1D_PEND_MISS.PENDING@ / MEM_LOAD_COMPLETED.L1_MISS_ANY", | |
| 1659 | 1642 | "MetricGroup": "Mem;MemoryBound;MemoryLat", |
| 1660 | 1643 | "MetricName": "tma_info_memory_load_miss_real_latency", |
| 1661 | 1644 | "Unit": "cpu_core" |
| 1662 | 1645 | }, |
| 1663 | 1646 | { |
| 1664 | 1647 | "BriefDescription": "Memory-Level-Parallelism (average number of L1 miss demand load when there is at least one such miss", |
| 1665 | − "MetricExpr": "L1D_PEND_MISS.PENDING / L1D_PEND_MISS.PENDING_CYCLES", | |
| 1648 | + "MetricExpr": "cpu_core@L1D_PEND_MISS.PENDING@ / L1D_PEND_MISS.PENDING_CYCLES", | |
| 1666 | 1649 | "MetricGroup": "Mem;MemoryBW;MemoryBound", |
| 1667 | 1650 | "MetricName": "tma_info_memory_mlp", |
| 1668 | 1651 | "PublicDescription": "Memory-Level-Parallelism (average number of L1 miss demand load when there is at least one such miss. Per-Logical Processor)", |
| @@ -1670,28 +1653,28 @@ · 1 unmodified line | ||
| 1670 | 1653 | }, |
| 1671 | 1654 | { |
| 1672 | 1655 | "BriefDescription": "Average Parallel L2 cache miss data reads", |
| 1673 | − "MetricExpr": "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD / OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD", | |
| 1656 | + "MetricExpr": "cpu_core@OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD@ / OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD", | |
| 1674 | 1657 | "MetricGroup": "Memory_BW;Offcore", |
| 1675 | 1658 | "MetricName": "tma_info_memory_oro_data_l2_mlp", |
| 1676 | 1659 | "Unit": "cpu_core" |
| 1677 | 1660 | }, |
| 1678 | 1661 | { |
| 1679 | 1662 | "BriefDescription": "Average Latency for L2 cache miss demand Loads", |
| 1680 | − "MetricExpr": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD / OFFCORE_REQUESTS.DEMAND_DATA_RD", | |
| 1663 | + "MetricExpr": "cpu_core@OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD@ / OFFCORE_REQUESTS.DEMAND_DATA_RD", | |
| 1681 | 1664 | "MetricGroup": "Memory_Lat;Offcore", |
| 1682 | 1665 | "MetricName": "tma_info_memory_oro_load_l2_miss_latency", |
| 1683 | 1666 | "Unit": "cpu_core" |
| 1684 | 1667 | }, |
| 1685 | 1668 | { |
| 1686 | 1669 | "BriefDescription": "Average Parallel L2 cache miss demand Loads", |
| 1687 | − "MetricExpr": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD / cpu_core@OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD\\,cmask\\=1@", | |
| 1670 | + "MetricExpr": "cpu_core@OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD@ / cpu_core@OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD\\,cmask\\=1@", | |
| 1688 | 1671 | "MetricGroup": "Memory_BW;Offcore", |
| 1689 | 1672 | "MetricName": "tma_info_memory_oro_load_l2_mlp", |
| 1690 | 1673 | "Unit": "cpu_core" |
| 1691 | 1674 | }, |
| 1692 | 1675 | { |
| 1693 | 1676 | "BriefDescription": "Average Latency for L3 cache miss demand Loads", |
| 1694 | − "MetricExpr": "OFFCORE_REQUESTS_OUTSTANDING.L3_MISS_DEMAND_DATA_RD / OFFCORE_REQUESTS.L3_MISS_DEMAND_DATA_RD", | |
| 1677 | + "MetricExpr": "cpu_core@OFFCORE_REQUESTS_OUTSTANDING.L3_MISS_DEMAND_DATA_RD@ / OFFCORE_REQUESTS.L3_MISS_DEMAND_DATA_RD", | |
| 1695 | 1678 | "MetricGroup": "Memory_Lat;Offcore", |
| 1696 | 1679 | "MetricName": "tma_info_memory_oro_load_l3_miss_latency", |
| 1697 | 1680 | "Unit": "cpu_core" |
| @@ -1755,14 +1738,14 @@ · 57 unmodified lines | ||
| 1755 | 1738 | }, |
| 1756 | 1739 | { |
| 1757 | 1740 | "BriefDescription": "Instruction-Level-Parallelism (average number of uops executed when there is execution) per-thread", |
| 1758 | − "MetricExpr": "UOPS_EXECUTED.THREAD / cpu_core@UOPS_EXECUTED.THREAD\\,cmask\\=1@", | |
| 1741 | + "MetricExpr": "cpu_core@UOPS_EXECUTED.THREAD@ / cpu_core@UOPS_EXECUTED.THREAD\\,cmask\\=1@", | |
| 1759 | 1742 | "MetricGroup": "Cor;Pipeline;PortsUtil;SMT", |
| 1760 | 1743 | "MetricName": "tma_info_pipeline_execute", |
| 1761 | 1744 | "Unit": "cpu_core" |
| 1762 | 1745 | }, |
| 1763 | 1746 | { |
| 1764 | 1747 | "BriefDescription": "Instructions per a microcode Assist invocation", |
| 1765 | − "MetricExpr": "INST_RETIRED.ANY / cpu_core@ASSISTS.ANY\\,umask\\=0x1B@", | |
| 1748 | + "MetricExpr": "cpu_core@INST_RETIRED.ANY@ / cpu_core@ASSISTS.ANY\\,umask\\=0x1B@", | |
| 1766 | 1749 | "MetricGroup": "Pipeline;Ret;Retire", |
| 1767 | 1750 | "MetricName": "tma_info_pipeline_ipassist", |
| 1768 | 1751 | "MetricThreshold": "tma_info_pipeline_ipassist < 100e3", |
| @@ -1778,7 +1761,7 @@ · 9 unmodified lines | ||
| 1778 | 1761 | }, |
| 1779 | 1762 | { |
| 1780 | 1763 | "BriefDescription": "Estimated fraction of retirement-cycles dealing with repeat instructions", |
| 1781 | − "MetricExpr": "INST_RETIRED.REP_ITERATION / cpu_core@UOPS_RETIRED.SLOTS\\,cmask\\=1@", | |
| 1764 | + "MetricExpr": "cpu_core@INST_RETIRED.REP_ITERATION@ / cpu_core@UOPS_RETIRED.SLOTS\\,cmask\\=1@", | |
| 1782 | 1765 | "MetricGroup": "Pipeline;Ret", |
| 1783 | 1766 | "MetricName": "tma_info_pipeline_strings_cycles", |
| 1784 | 1767 | "MetricThreshold": "tma_info_pipeline_strings_cycles > 0.1", |
| @@ -1793,7 +1776,7 @@ · 8 unmodified lines | ||
| 1793 | 1776 | }, |
| 1794 | 1777 | { |
| 1795 | 1778 | "BriefDescription": "Average CPU Utilization", |
| 1796 | − "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC / TSC", | |
| 1779 | + "MetricExpr": "cpu_core@CPU_CLK_UNHALTED.REF_TSC@ / TSC", | |
| 1797 | 1780 | "MetricGroup": "HPC;Summary", |
| 1798 | 1781 | "MetricName": "tma_info_system_cpu_utilization", |
| 1799 | 1782 | "Unit": "cpu_core" |
| @@ -1816,7 +1799,7 @@ · 16 unmodified lines | ||
| 1816 | 1799 | }, |
| 1817 | 1800 | { |
| 1818 | 1801 | "BriefDescription": "Instructions per Far Branch ( Far Branches apply upon transition from application to operating system, handling interrupts, exceptions) [lower number means higher occurrence rate]", |
| 1819 | − "MetricExpr": "INST_RETIRED.ANY / cpu_core@BR_INST_RETIRED.FAR_BRANCH@u", | |
| 1802 | + "MetricExpr": "cpu_core@INST_RETIRED.ANY@ / cpu_core@BR_INST_RETIRED.FAR_BRANCH@u", | |
| 1820 | 1803 | "MetricGroup": "Branches;OS", |
| 1821 | 1804 | "MetricName": "tma_info_system_ipfarbranch", |
| 1822 | 1805 | "MetricThreshold": "tma_info_system_ipfarbranch < 1e6", |
| @@ -1847,6 +1830,7 @@ · 24 unmodified lines | ||
| 1847 | 1830 | }, |
| 1848 | 1831 | { |
| 1849 | 1832 | "BriefDescription": "Average latency of data read request to external memory (in nanoseconds)", |
| 1833 | + "MetricConstraint": "NO_GROUP_EVENTS", | |
| 1850 | 1834 | "MetricExpr": "(UNC_ARB_TRK_OCCUPANCY.RD + UNC_ARB_DAT_OCCUPANCY.RD) / UNC_ARB_TRK_REQUESTS.RD", |
| 1851 | 1835 | "MetricGroup": "Mem;MemoryLat;SoC", |
| 1852 | 1836 | "MetricName": "tma_info_system_mem_read_latency", |
| @@ -1855,6 +1839,7 @@ · 2 unmodified lines | ||
| 1855 | 1839 | }, |
| 1856 | 1840 | { |
| 1857 | 1841 | "BriefDescription": "Average latency of all requests to external memory (in Uncore cycles)", |
| 1842 | + "MetricConstraint": "NO_GROUP_EVENTS", | |
| 1858 | 1843 | "MetricExpr": "(UNC_ARB_TRK_OCCUPANCY.ALL + UNC_ARB_DAT_OCCUPANCY.RD) / UNC_ARB_TRK_REQUESTS.ALL", |
| 1859 | 1844 | "MetricGroup": "Mem;SoC", |
| 1860 | 1845 | "MetricName": "tma_info_system_mem_request_latency", |
| @@ -1897,7 +1882,7 @@ · 36 unmodified lines | ||
| 1897 | 1882 | }, |
| 1898 | 1883 | { |
| 1899 | 1884 | "BriefDescription": "The ratio of Executed- by Issued-Uops", |
| 1900 | − "MetricExpr": "UOPS_EXECUTED.THREAD / UOPS_ISSUED.ANY", | |
| 1885 | + "MetricExpr": "cpu_core@UOPS_EXECUTED.THREAD@ / UOPS_ISSUED.ANY", | |
| 1901 | 1886 | "MetricGroup": "Cor;Pipeline", |
| 1902 | 1887 | "MetricName": "tma_info_thread_execute_per_issue", |
| 1903 | 1888 | "PublicDescription": "The ratio of Executed- by Issued-Uops. Ratio > 1 suggests high rate of uop micro-fusions. Ratio < 1 suggest high rate of \"execute\" at rename stage.", |
| @@ -1905,7 +1890,7 @@ · 1 unmodified line | ||
| 1905 | 1890 | }, |
| 1906 | 1891 | { |
| 1907 | 1892 | "BriefDescription": "Instructions Per Cycle (per Logical Processor)", |
| 1908 | − "MetricExpr": "INST_RETIRED.ANY / tma_info_thread_clks", | |
| 1893 | + "MetricExpr": "cpu_core@INST_RETIRED.ANY@ / tma_info_thread_clks", | |
| 1909 | 1894 | "MetricGroup": "Ret;Summary", |
| 1910 | 1895 | "MetricName": "tma_info_thread_ipc", |
| 1911 | 1896 | "Unit": "cpu_core" |
| @@ -1972,7 +1957,7 @@ · 60 unmodified lines | ||
| 1972 | 1957 | }, |
| 1973 | 1958 | { |
| 1974 | 1959 | "BriefDescription": "This metric represents fraction of cycles the CPU was stalled due to Instruction TLB (ITLB) misses", |
| 1975 | − "MetricExpr": "ICACHE_TAG.STALLS / tma_info_thread_clks", | |
| 1960 | + "MetricExpr": "cpu_core@ICACHE_TAG.STALLS@ / tma_info_thread_clks", | |
| 1976 | 1961 | "MetricGroup": "BigFoot;FetchLat;MemoryTLB;TopdownL3;tma_L3_group;tma_fetch_latency_group", |
| 1977 | 1962 | "MetricName": "tma_itlb_misses", |
| 1978 | 1963 | "MetricThreshold": "tma_itlb_misses > 0.05 & (tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15)", |
| @@ -1992,7 +1977,6 @@ · 13 unmodified lines | ||
| 1992 | 1977 | }, |
| 1993 | 1978 | { |
| 1994 | 1979 | "BriefDescription": "This metric estimates how often the CPU was stalled due to L2 cache accesses by loads", |
| 1995 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 1996 | 1980 | "MetricExpr": "(cpu_core@MEMORY_ACTIVITY.STALLS_L1D_MISS@ - cpu_core@MEMORY_ACTIVITY.STALLS_L2_MISS@) / tma_info_thread_clks", |
| 1997 | 1981 | "MetricGroup": "CacheMisses;MemoryBound;TmaL3mem;TopdownL3;tma_L3_group;tma_memory_bound_group", |
| 1998 | 1982 | "MetricName": "tma_l2_bound", |
| @@ -2003,7 +1987,6 @@ · 4 unmodified lines | ||
| 2003 | 1987 | }, |
| 2004 | 1988 | { |
| 2005 | 1989 | "BriefDescription": "This metric estimates how often the CPU was stalled due to loads accesses to L3 cache or contended with a sibling Core", |
| 2006 | − "MetricConstraint": "NO_GROUP_EVENTS_NMI", | |
| 2007 | 1990 | "MetricExpr": "(cpu_core@MEMORY_ACTIVITY.STALLS_L2_MISS@ - cpu_core@MEMORY_ACTIVITY.STALLS_L3_MISS@) / tma_info_thread_clks", |
| 2008 | 1991 | "MetricGroup": "CacheMisses;MemoryBound;TmaL3mem;TopdownL3;tma_L3_group;tma_memory_bound_group", |
| 2009 | 1992 | "MetricName": "tma_l3_bound", |
| @@ -2024,7 +2007,7 @@ · 14 unmodified lines | ||
| 2024 | 2007 | }, |
| 2025 | 2008 | { |
| 2026 | 2009 | "BriefDescription": "This metric represents fraction of cycles CPU was stalled due to Length Changing Prefixes (LCPs)", |
| 2027 | − "MetricExpr": "DECODE.LCP / tma_info_thread_clks", | |
| 2010 | + "MetricExpr": "cpu_core@DECODE.LCP@ / tma_info_thread_clks", | |
| 2028 | 2011 | "MetricGroup": "FetchLat;TopdownL3;tma_L3_group;tma_fetch_latency_group;tma_issueFB", |
| 2029 | 2012 | "MetricName": "tma_lcp", |
| 2030 | 2013 | "MetricThreshold": "tma_lcp > 0.05 & (tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15)", |
| @@ -2045,7 +2028,7 @@ · 14 unmodified lines | ||
| 2045 | 2028 | }, |
| 2046 | 2029 | { |
| 2047 | 2030 | "BriefDescription": "This metric represents Core fraction of cycles CPU dispatched uops on execution port for Load operations", |
| 2048 | − "MetricExpr": "UOPS_DISPATCHED.PORT_2_3_10 / (3 * tma_info_core_core_clks)", | |
| 2031 | + "MetricExpr": "cpu_core@UOPS_DISPATCHED.PORT_2_3_10@ / (3 * tma_info_core_core_clks)", | |
| 2049 | 2032 | "MetricGroup": "TopdownL5;tma_L5_group;tma_ports_utilized_3m_group", |
| 2050 | 2033 | "MetricName": "tma_load_op_utilization", |
| 2051 | 2034 | "MetricThreshold": "tma_load_op_utilization > 0.6", |
| @@ -2064,7 +2047,7 @@ · 12 unmodified lines | ||
| 2064 | 2047 | }, |
| 2065 | 2048 | { |
| 2066 | 2049 | "BriefDescription": "This metric estimates the fraction of cycles where the Second-level TLB (STLB) was missed by load accesses, performing a hardware page walk", |
| 2067 | − "MetricExpr": "DTLB_LOAD_MISSES.WALK_ACTIVE / tma_info_thread_clks", | |
| 2050 | + "MetricExpr": "cpu_core@DTLB_LOAD_MISSES.WALK_ACTIVE@ / tma_info_thread_clks", | |
| 2068 | 2051 | "MetricGroup": "MemoryTLB;TopdownL5;tma_L5_group;tma_dtlb_load_group", |
| 2069 | 2052 | "MetricName": "tma_load_stlb_miss", |
| 2070 | 2053 | "MetricThreshold": "tma_load_stlb_miss > 0.05 & (tma_dtlb_load > 0.1 & (tma_l1_bound > 0.1 & (tma_memory_bound > 0.2 & tma_backend_bound > 0.2)))", |
| @@ -2073,7 +2056,6 @@ · 2 unmodified lines | ||
| 2073 | 2056 | }, |
| 2074 | 2057 | { |
| 2075 | 2058 | "BriefDescription": "This metric represents fraction of cycles the CPU spent handling cache misses due to lock operations", |
| 2076 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 2077 | 2059 | "MetricExpr": "(16 * max(0, cpu_core@MEM_INST_RETIRED.LOCK_LOADS@ - cpu_core@L2_RQSTS.ALL_RFO@) + cpu_core@MEM_INST_RETIRED.LOCK_LOADS@ / cpu_core@MEM_INST_RETIRED.ALL_STORES@ * (10 * cpu_core@L2_RQSTS.RFO_HIT@ + min(cpu_core@CPU_CLK_UNHALTED.THREAD@, cpu_core@OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO@))) / tma_info_thread_clks", |
| 2078 | 2060 | "MetricGroup": "Offcore;TopdownL4;tma_L4_group;tma_issueRFO;tma_l1_bound_group", |
| 2079 | 2061 | "MetricName": "tma_lock_latency", |
| @@ -2136,6 +2118,7 @@ · 56 unmodified lines | ||
| 2136 | 2118 | }, |
| 2137 | 2119 | { |
| 2138 | 2120 | "BriefDescription": "This metric represents fraction of cycles the CPU was stalled due to LFENCE Instructions.", |
| 2121 | + "MetricConstraint": "NO_GROUP_EVENTS_NMI", | |
| 2139 | 2122 | "MetricExpr": "13 * cpu_core@MISC2_RETIRED.LFENCE@ / tma_info_thread_clks", |
| 2140 | 2123 | "MetricGroup": "TopdownL6;tma_L6_group;tma_serializing_operation_group", |
| 2141 | 2124 | "MetricName": "tma_memory_fence", |
| @@ -2145,7 +2128,6 @@ · 3 unmodified lines | ||
| 2145 | 2128 | }, |
| 2146 | 2129 | { |
| 2147 | 2130 | "BriefDescription": "This metric represents fraction of slots where the CPU was retiring memory operations -- uops for memory load or store accesses.", |
| 2148 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 2149 | 2131 | "MetricExpr": "tma_light_operations * cpu_core@MEM_UOP_RETIRED.ANY@ / (tma_retiring * tma_info_thread_slots)", |
| 2150 | 2132 | "MetricGroup": "Pipeline;TopdownL3;tma_L3_group;tma_light_operations_group", |
| 2151 | 2133 | "MetricName": "tma_memory_operations", |
| @@ -2155,7 +2137,7 @@ · 3 unmodified lines | ||
| 2155 | 2137 | }, |
| 2156 | 2138 | { |
| 2157 | 2139 | "BriefDescription": "This metric represents fraction of slots the CPU was retiring uops fetched by the Microcode Sequencer (MS) unit", |
| 2158 | − "MetricExpr": "UOPS_RETIRED.MS / tma_info_thread_slots", | |
| 2140 | + "MetricExpr": "cpu_core@UOPS_RETIRED.MS@ / tma_info_thread_slots", | |
| 2159 | 2141 | "MetricGroup": "MicroSeq;TopdownL3;tma_L3_group;tma_heavy_operations_group;tma_issueMC;tma_issueMS", |
| 2160 | 2142 | "MetricName": "tma_microcode_sequencer", |
| 2161 | 2143 | "MetricThreshold": "tma_microcode_sequencer > 0.05 & tma_heavy_operations > 0.1", |
| @@ -2225,7 +2207,6 @@ · 63 unmodified lines | ||
| 2225 | 2207 | }, |
| 2226 | 2208 | { |
| 2227 | 2209 | "BriefDescription": "This metric represents the remaining light uops fraction the CPU has executed - remaining means not covered by other sibling nodes", |
| 2228 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 2229 | 2210 | "MetricExpr": "max(0, tma_light_operations - (tma_fp_arith + tma_int_operations + tma_memory_operations + tma_fused_instructions + tma_non_fused_branches + tma_nop_instructions))", |
| 2230 | 2211 | "MetricGroup": "Pipeline;TopdownL3;tma_L3_group;tma_light_operations_group", |
| 2231 | 2212 | "MetricName": "tma_other_light_ops", |
| @@ -2246,7 +2227,7 @@ · 14 unmodified lines | ||
| 2246 | 2227 | }, |
| 2247 | 2228 | { |
| 2248 | 2229 | "BriefDescription": "This metric represents Core fraction of cycles CPU dispatched uops on execution port 0 ([SNB+] ALU; [HSW+] ALU and 2nd branch)", |
| 2249 | − "MetricExpr": "UOPS_DISPATCHED.PORT_0 / tma_info_core_core_clks", | |
| 2230 | + "MetricExpr": "cpu_core@UOPS_DISPATCHED.PORT_0@ / tma_info_core_core_clks", | |
| 2250 | 2231 | "MetricGroup": "Compute;TopdownL6;tma_L6_group;tma_alu_op_utilization_group;tma_issue2P", |
| 2251 | 2232 | "MetricName": "tma_port_0", |
| 2252 | 2233 | "MetricThreshold": "tma_port_0 > 0.6", |
| @@ -2256,7 +2237,7 @@ · 3 unmodified lines | ||
| 2256 | 2237 | }, |
| 2257 | 2238 | { |
| 2258 | 2239 | "BriefDescription": "This metric represents Core fraction of cycles CPU dispatched uops on execution port 1 (ALU)", |
| 2259 | − "MetricExpr": "UOPS_DISPATCHED.PORT_1 / tma_info_core_core_clks", | |
| 2240 | + "MetricExpr": "cpu_core@UOPS_DISPATCHED.PORT_1@ / tma_info_core_core_clks", | |
| 2260 | 2241 | "MetricGroup": "TopdownL6;tma_L6_group;tma_alu_op_utilization_group;tma_issue2P", |
| 2261 | 2242 | "MetricName": "tma_port_1", |
| 2262 | 2243 | "MetricThreshold": "tma_port_1 > 0.6", |
| @@ -2266,7 +2247,7 @@ · 3 unmodified lines | ||
| 2266 | 2247 | }, |
| 2267 | 2248 | { |
| 2268 | 2249 | "BriefDescription": "This metric represents Core fraction of cycles CPU dispatched uops on execution port 6 ([HSW+]Primary Branch and simple ALU)", |
| 2269 | − "MetricExpr": "UOPS_DISPATCHED.PORT_6 / tma_info_core_core_clks", | |
| 2250 | + "MetricExpr": "cpu_core@UOPS_DISPATCHED.PORT_6@ / tma_info_core_core_clks", | |
| 2270 | 2251 | "MetricGroup": "TopdownL6;tma_L6_group;tma_alu_op_utilization_group;tma_issue2P", |
| 2271 | 2252 | "MetricName": "tma_port_6", |
| 2272 | 2253 | "MetricThreshold": "tma_port_6 > 0.6", |
| @@ -2296,7 +2277,7 @@ · 23 unmodified lines | ||
| 2296 | 2277 | }, |
| 2297 | 2278 | { |
| 2298 | 2279 | "BriefDescription": "This metric represents fraction of cycles where the CPU executed total of 1 uop per cycle on all execution ports (Logical Processor cycles since ICL, Physical Core cycles otherwise)", |
| 2299 | − "MetricExpr": "EXE_ACTIVITY.1_PORTS_UTIL / tma_info_thread_clks", | |
| 2280 | + "MetricExpr": "cpu_core@EXE_ACTIVITY.1_PORTS_UTIL@ / tma_info_thread_clks", | |
| 2300 | 2281 | "MetricGroup": "PortsUtil;TopdownL4;tma_L4_group;tma_issueL1;tma_ports_utilization_group", |
| 2301 | 2282 | "MetricName": "tma_ports_utilized_1", |
| 2302 | 2283 | "MetricThreshold": "tma_ports_utilized_1 > 0.2 & (tma_ports_utilization > 0.15 & (tma_core_bound > 0.1 & tma_backend_bound > 0.2))", |
| @@ -2306,7 +2287,8 @@ · 3 unmodified lines | ||
| 2306 | 2287 | }, |
| 2307 | 2288 | { |
| 2308 | 2289 | "BriefDescription": "This metric represents fraction of cycles CPU executed total of 2 uops per cycle on all execution ports (Logical Processor cycles since ICL, Physical Core cycles otherwise)", |
| 2309 | − "MetricExpr": "EXE_ACTIVITY.2_PORTS_UTIL / tma_info_thread_clks", | |
| 2290 | + "MetricConstraint": "NO_GROUP_EVENTS_NMI", | |
| 2291 | + "MetricExpr": "cpu_core@EXE_ACTIVITY.2_PORTS_UTIL@ / tma_info_thread_clks", | |
| 2310 | 2292 | "MetricGroup": "PortsUtil;TopdownL4;tma_L4_group;tma_issue2P;tma_ports_utilization_group", |
| 2311 | 2293 | "MetricName": "tma_ports_utilized_2", |
| 2312 | 2294 | "MetricThreshold": "tma_ports_utilized_2 > 0.15 & (tma_ports_utilization > 0.15 & (tma_core_bound > 0.1 & tma_backend_bound > 0.2))", |
| @@ -2316,7 +2298,8 @@ · 3 unmodified lines | ||
| 2316 | 2298 | }, |
| 2317 | 2299 | { |
| 2318 | 2300 | "BriefDescription": "This metric represents fraction of cycles CPU executed total of 3 or more uops per cycle on all execution ports (Logical Processor cycles since ICL, Physical Core cycles otherwise)", |
| 2319 | − "MetricExpr": "UOPS_EXECUTED.CYCLES_GE_3 / tma_info_thread_clks", | |
| 2301 | + "MetricConstraint": "NO_GROUP_EVENTS_NMI", | |
| 2302 | + "MetricExpr": "cpu_core@UOPS_EXECUTED.CYCLES_GE_3@ / tma_info_thread_clks", | |
| 2320 | 2303 | "MetricGroup": "PortsUtil;TopdownL4;tma_L4_group;tma_ports_utilization_group", |
| 2321 | 2304 | "MetricName": "tma_ports_utilized_3m", |
| 2322 | 2305 | "MetricThreshold": "tma_ports_utilized_3m > 0.7 & (tma_ports_utilization > 0.15 & (tma_core_bound > 0.1 & tma_backend_bound > 0.2))", |
| @@ -2338,7 +2321,7 @@ · 15 unmodified lines | ||
| 2338 | 2321 | }, |
| 2339 | 2322 | { |
| 2340 | 2323 | "BriefDescription": "This metric represents fraction of cycles the CPU issue-pipeline was stalled due to serializing operations", |
| 2341 | − "MetricExpr": "RESOURCE_STALLS.SCOREBOARD / tma_info_thread_clks", | |
| 2324 | + "MetricExpr": "cpu_core@RESOURCE_STALLS.SCOREBOARD@ / tma_info_thread_clks", | |
| 2342 | 2325 | "MetricGroup": "PortsUtil;TopdownL5;tma_L5_group;tma_issueSO;tma_ports_utilized_0_group", |
| 2343 | 2326 | "MetricName": "tma_serializing_operation", |
| 2344 | 2327 | "MetricThreshold": "tma_serializing_operation > 0.1 & (tma_ports_utilized_0 > 0.2 & (tma_ports_utilization > 0.15 & (tma_core_bound > 0.1 & tma_backend_bound > 0.2)))", |
| @@ -2348,7 +2331,7 @@ · 3 unmodified lines | ||
| 2348 | 2331 | }, |
| 2349 | 2332 | { |
| 2350 | 2333 | "BriefDescription": "This metric represents Shuffle (cross \"vector lane\" data transfers) uops fraction the CPU has retired.", |
| 2351 | − "MetricExpr": "INT_VEC_RETIRED.SHUFFLES / (tma_retiring * tma_info_thread_slots)", | |
| 2334 | + "MetricExpr": "cpu_core@INT_VEC_RETIRED.SHUFFLES@ / (tma_retiring * tma_info_thread_slots)", | |
| 2352 | 2335 | "MetricGroup": "HPC;Pipeline;TopdownL4;tma_L4_group;tma_int_operations_group", |
| 2353 | 2336 | "MetricName": "tma_shuffles", |
| 2354 | 2337 | "MetricThreshold": "tma_shuffles > 0.1 & (tma_int_operations > 0.1 & tma_light_operations > 0.6)", |
| @@ -2357,7 +2340,8 @@ · 2 unmodified lines | ||
| 2357 | 2340 | }, |
| 2358 | 2341 | { |
| 2359 | 2342 | "BriefDescription": "This metric represents fraction of cycles the CPU was stalled due to PAUSE Instructions", |
| 2360 | − "MetricExpr": "CPU_CLK_UNHALTED.PAUSE / tma_info_thread_clks", | |
| 2343 | + "MetricConstraint": "NO_GROUP_EVENTS_NMI", | |
| 2344 | + "MetricExpr": "cpu_core@CPU_CLK_UNHALTED.PAUSE@ / tma_info_thread_clks", | |
| 2361 | 2345 | "MetricGroup": "TopdownL6;tma_L6_group;tma_serializing_operation_group", |
| 2362 | 2346 | "MetricName": "tma_slow_pause", |
| 2363 | 2347 | "MetricThreshold": "tma_slow_pause > 0.05 & (tma_serializing_operation > 0.1 & (tma_ports_utilized_0 > 0.2 & (tma_ports_utilization > 0.15 & (tma_core_bound > 0.1 & tma_backend_bound > 0.2))))", |
| @@ -2377,8 +2361,7 @@ · 13 unmodified lines | ||
| 2377 | 2361 | }, |
| 2378 | 2362 | { |
| 2379 | 2363 | "BriefDescription": "This metric represents rate of split store accesses", |
| 2380 | − "MetricConstraint": "NO_GROUP_EVENTS_NMI", | |
| 2381 | − "MetricExpr": "MEM_INST_RETIRED.SPLIT_STORES / tma_info_core_core_clks", | |
| 2364 | + "MetricExpr": "cpu_core@MEM_INST_RETIRED.SPLIT_STORES@ / tma_info_core_core_clks", | |
| 2382 | 2365 | "MetricGroup": "TopdownL4;tma_L4_group;tma_issueSpSt;tma_store_bound_group", |
| 2383 | 2366 | "MetricName": "tma_split_stores", |
| 2384 | 2367 | "MetricThreshold": "tma_split_stores > 0.2 & (tma_store_bound > 0.2 & (tma_memory_bound > 0.2 & tma_backend_bound > 0.2))", |
| @@ -2398,7 +2381,7 @@ · 13 unmodified lines | ||
| 2398 | 2381 | }, |
| 2399 | 2382 | { |
| 2400 | 2383 | "BriefDescription": "This metric estimates how often CPU was stalled due to RFO store memory accesses; RFO store issue a read-for-ownership request before the write", |
| 2401 | − "MetricExpr": "EXE_ACTIVITY.BOUND_ON_STORES / tma_info_thread_clks", | |
| 2384 | + "MetricExpr": "cpu_core@EXE_ACTIVITY.BOUND_ON_STORES@ / tma_info_thread_clks", | |
| 2402 | 2385 | "MetricGroup": "MemoryBound;TmaL3mem;TopdownL3;tma_L3_group;tma_memory_bound_group", |
| 2403 | 2386 | "MetricName": "tma_store_bound", |
| 2404 | 2387 | "MetricThreshold": "tma_store_bound > 0.2 & (tma_memory_bound > 0.2 & tma_backend_bound > 0.2)", |
| @@ -2408,7 +2391,6 @@ · 3 unmodified lines | ||
| 2408 | 2391 | }, |
| 2409 | 2392 | { |
| 2410 | 2393 | "BriefDescription": "This metric roughly estimates fraction of cycles when the memory subsystem had loads blocked since they could not forward data from earlier (in program order) overlapping stores", |
| 2411 | − "MetricConstraint": "NO_GROUP_EVENTS_NMI", | |
| 2412 | 2394 | "MetricExpr": "13 * cpu_core@LD_BLOCKS.STORE_FORWARD@ / tma_info_thread_clks", |
| 2413 | 2395 | "MetricGroup": "TopdownL4;tma_L4_group;tma_l1_bound_group", |
| 2414 | 2396 | "MetricName": "tma_store_fwd_blk", |
| @@ -2448,7 +2430,7 @@ · 33 unmodified lines | ||
| 2448 | 2430 | }, |
| 2449 | 2431 | { |
| 2450 | 2432 | "BriefDescription": "This metric estimates the fraction of cycles where the STLB was missed by store accesses, performing a hardware page walk", |
| 2451 | − "MetricExpr": "DTLB_STORE_MISSES.WALK_ACTIVE / tma_info_core_core_clks", | |
| 2433 | + "MetricExpr": "cpu_core@DTLB_STORE_MISSES.WALK_ACTIVE@ / tma_info_core_core_clks", | |
| 2452 | 2434 | "MetricGroup": "MemoryTLB;TopdownL5;tma_L5_group;tma_dtlb_store_group", |
| 2453 | 2435 | "MetricName": "tma_store_stlb_miss", |
| 2454 | 2436 | "MetricThreshold": "tma_store_stlb_miss > 0.05 & (tma_dtlb_store > 0.05 & (tma_store_bound > 0.2 & (tma_memory_bound > 0.2 & tma_backend_bound > 0.2)))", |
| @@ -2467,7 +2449,7 @@ · 12 unmodified lines | ||
| 2467 | 2449 | }, |
| 2468 | 2450 | { |
| 2469 | 2451 | "BriefDescription": "This metric represents fraction of cycles the CPU was stalled due to new branch address clears", |
| 2470 | − "MetricExpr": "INT_MISC.UNKNOWN_BRANCH_CYCLES / tma_info_thread_clks", | |
| 2452 | + "MetricExpr": "cpu_core@INT_MISC.UNKNOWN_BRANCH_CYCLES@ / tma_info_thread_clks", | |
| 2471 | 2453 | "MetricGroup": "BigFoot;FetchLat;TopdownL4;tma_L4_group;tma_branch_resteers_group", |
| 2472 | 2454 | "MetricName": "tma_unknown_branches", |
| 2473 | 2455 | "MetricThreshold": "tma_unknown_branches > 0.05 & (tma_branch_resteers > 0.05 & (tma_fetch_latency > 0.1 & tma_frontend_bound > 0.15))", |
| @@ -195,7 +195,6 @@ · 194 unmodified lines | ||
| 195 | 195 | }, |
| 196 | 196 | { |
| 197 | 197 | "BriefDescription": "Counts the number of cycles the core is stalled due to a demand load miss which hit in DRAM or MMIO (Non-DRAM).", |
| 198 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 199 | 198 | "MetricExpr": "MEM_BOUND_STALLS.LOAD_DRAM_HIT / tma_info_core_clks - max((MEM_BOUND_STALLS.LOAD - LD_HEAD.L1_MISS_AT_RET) / tma_info_core_clks, 0) * MEM_BOUND_STALLS.LOAD_DRAM_HIT / MEM_BOUND_STALLS.LOAD", |
| 200 | 199 | "MetricGroup": "TopdownL3;tma_L3_group;tma_memory_bound_group", |
| 201 | 200 | "MetricName": "tma_dram_bound", |
| @@ -457,7 +456,6 @@ · 255 unmodified lines | ||
| 457 | 456 | }, |
| 458 | 457 | { |
| 459 | 458 | "BriefDescription": "Counts the number of cycles a core is stalled due to a demand load which hit in the L2 Cache.", |
| 460 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 461 | 459 | "MetricExpr": "MEM_BOUND_STALLS.LOAD_L2_HIT / tma_info_core_clks - max((MEM_BOUND_STALLS.LOAD - LD_HEAD.L1_MISS_AT_RET) / tma_info_core_clks, 0) * MEM_BOUND_STALLS.LOAD_L2_HIT / MEM_BOUND_STALLS.LOAD", |
| 462 | 460 | "MetricGroup": "TopdownL3;tma_L3_group;tma_memory_bound_group", |
| 463 | 461 | "MetricName": "tma_l2_bound", |
| @@ -466,7 +464,6 @@ · 2 unmodified lines | ||
| 466 | 464 | }, |
| 467 | 465 | { |
| 468 | 466 | "BriefDescription": "Counts the number of cycles a core is stalled due to a demand load which hit in the Last Level Cache (LLC) or other core with HITE/F/M.", |
| 469 | − "MetricConstraint": "NO_GROUP_EVENTS_NMI", | |
| 470 | 467 | "MetricExpr": "MEM_BOUND_STALLS.LOAD_LLC_HIT / tma_info_core_clks - max((MEM_BOUND_STALLS.LOAD - LD_HEAD.L1_MISS_AT_RET) / tma_info_core_clks, 0) * MEM_BOUND_STALLS.LOAD_LLC_HIT / MEM_BOUND_STALLS.LOAD", |
| 471 | 468 | "MetricGroup": "TopdownL3;tma_L3_group;tma_memory_bound_group", |
| 472 | 469 | "MetricName": "tma_l3_bound", |
| @@ -683,7 +680,6 @@ · 210 unmodified lines | ||
| 683 | 680 | }, |
| 684 | 681 | { |
| 685 | 682 | "BriefDescription": "Counts the number of cycles that the oldest load of the load buffer is stalled at retirement due to a store forward block.", |
| 686 | − "MetricConstraint": "NO_GROUP_EVENTS_NMI", | |
| 687 | 683 | "MetricExpr": "LD_HEAD.ST_ADDR_AT_RET / tma_info_core_clks", |
| 688 | 684 | "MetricGroup": "TopdownL4;tma_L4_group;tma_l1_bound_group", |
| 689 | 685 | "MetricName": "tma_store_fwd_blk", |
| @@ -400,7 +400,6 @@ · 399 unmodified lines | ||
| 400 | 400 | }, |
| 401 | 401 | { |
| 402 | 402 | "BriefDescription": "This metric estimates fraction of cycles while the memory subsystem was handling synchronizations due to contested accesses", |
| 403 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 404 | 403 | "MetricExpr": "(76 * tma_info_system_average_frequency * (MEM_LOAD_L3_HIT_RETIRED.XSNP_FWD * (OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HITM / (OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HITM + OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD))) + 75.5 * tma_info_system_average_frequency * MEM_LOAD_L3_HIT_RETIRED.XSNP_MISS) * (1 + MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS / 2) / tma_info_thread_clks", |
| 405 | 404 | "MetricGroup": "DataSharing;Offcore;Snoop;TopdownL4;tma_L4_group;tma_issueSyncxn;tma_l3_bound_group", |
| 406 | 405 | "MetricName": "tma_contested_accesses", |
| @@ -421,7 +420,6 @@ · 14 unmodified lines | ||
| 421 | 420 | }, |
| 422 | 421 | { |
| 423 | 422 | "BriefDescription": "This metric estimates fraction of cycles while the memory subsystem was handling synchronizations due to data-sharing accesses", |
| 424 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 425 | 423 | "MetricExpr": "75.5 * tma_info_system_average_frequency * (MEM_LOAD_L3_HIT_RETIRED.XSNP_NO_FWD + MEM_LOAD_L3_HIT_RETIRED.XSNP_FWD * (1 - OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HITM / (OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HITM + OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD))) * (1 + MEM_LOAD_RETIRED.FB_HIT / MEM_LOAD_RETIRED.L1_MISS / 2) / tma_info_thread_clks", |
| 426 | 424 | "MetricGroup": "Offcore;Snoop;TopdownL4;tma_L4_group;tma_issueSyncxn;tma_l3_bound_group", |
| 427 | 425 | "MetricName": "tma_data_sharing", |
| @@ -449,7 +447,6 @@ · 21 unmodified lines | ||
| 449 | 447 | }, |
| 450 | 448 | { |
| 451 | 449 | "BriefDescription": "This metric estimates how often the CPU was stalled on accesses to external memory (DRAM) by loads", |
| 452 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 453 | 450 | "MetricExpr": "(MEMORY_ACTIVITY.STALLS_L3_MISS / tma_info_thread_clks - tma_pmm_bound if #has_pmem > 0 else MEMORY_ACTIVITY.STALLS_L3_MISS / tma_info_thread_clks)", |
| 454 | 451 | "MetricGroup": "MemoryBound;TmaL3mem;TopdownL3;tma_L3_group;tma_memory_bound_group", |
| 455 | 452 | "MetricName": "tma_dram_bound", |
| @@ -656,7 +653,6 @@ · 200 unmodified lines | ||
| 656 | 653 | }, |
| 657 | 654 | { |
| 658 | 655 | "BriefDescription": "Branch Misprediction Cost: Fraction of TMA slots wasted per non-speculative branch misprediction (retired JEClear)", |
| 659 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 660 | 656 | "MetricExpr": "(tma_branch_mispredicts + tma_fetch_latency * tma_mispredicts_resteers / (tma_branch_resteers + tma_dsb_switches + tma_icache_misses + tma_itlb_misses + tma_lcp + tma_ms_switches)) * tma_info_thread_slots / BR_MISP_RETIRED.ALL_BRANCHES", |
| 661 | 657 | "MetricGroup": "Bad;BrMispredicts;tma_issueBM", |
| 662 | 658 | "MetricName": "tma_info_bad_spec_branch_misprediction_cost", |
| @@ -699,7 +695,6 @@ · 36 unmodified lines | ||
| 699 | 695 | }, |
| 700 | 696 | { |
| 701 | 697 | "BriefDescription": "Probability of Core Bound bottleneck hidden by SMT-profiling artifacts", |
| 702 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 703 | 698 | "MetricExpr": "(100 * (1 - tma_core_bound / tma_ports_utilization if tma_core_bound < tma_ports_utilization else 1) if tma_info_system_smt_2t_utilization > 0.5 else 0)", |
| 704 | 699 | "MetricGroup": "Cor;SMT", |
| 705 | 700 | "MetricName": "tma_info_botlnk_l0_core_bound_likely", |
| @@ -707,7 +702,6 @@ · 1 unmodified line | ||
| 707 | 702 | }, |
| 708 | 703 | { |
| 709 | 704 | "BriefDescription": "Total pipeline cost of DSB (uop cache) misses - subset of the Instruction_Fetch_BW Bottleneck", |
| 710 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 711 | 705 | "MetricExpr": "100 * (tma_fetch_latency * tma_dsb_switches / (tma_branch_resteers + tma_dsb_switches + tma_icache_misses + tma_itlb_misses + tma_lcp + tma_ms_switches) + tma_fetch_bandwidth * tma_mite / (tma_dsb + tma_mite))", |
| 712 | 706 | "MetricGroup": "DSBmiss;Fed;tma_issueFB", |
| 713 | 707 | "MetricName": "tma_info_botlnk_l2_dsb_misses", |
| @@ -716,7 +710,6 @@ · 2 unmodified lines | ||
| 716 | 710 | }, |
| 717 | 711 | { |
| 718 | 712 | "BriefDescription": "Total pipeline cost of Instruction Cache misses - subset of the Big_Code Bottleneck", |
| 719 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 720 | 713 | "MetricExpr": "100 * (tma_fetch_latency * tma_icache_misses / (tma_branch_resteers + tma_dsb_switches + tma_icache_misses + tma_itlb_misses + tma_lcp + tma_ms_switches))", |
| 721 | 714 | "MetricGroup": "Fed;FetchLat;IcMiss;tma_issueFL", |
| 722 | 715 | "MetricName": "tma_info_botlnk_l2_ic_misses", |
| @@ -725,7 +718,6 @@ · 2 unmodified lines | ||
| 725 | 718 | }, |
| 726 | 719 | { |
| 727 | 720 | "BriefDescription": "Total pipeline cost of instruction fetch related bottlenecks by large code footprint programs (i-side cache; TLB and BTB misses)", |
| 728 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 729 | 721 | "MetricExpr": "100 * tma_fetch_latency * (tma_itlb_misses + tma_icache_misses + tma_unknown_branches) / (tma_branch_resteers + tma_dsb_switches + tma_icache_misses + tma_itlb_misses + tma_lcp + tma_ms_switches)", |
| 730 | 722 | "MetricGroup": "BigFoot;Fed;Frontend;IcMiss;MemoryTLB;tma_issueBC", |
| 731 | 723 | "MetricName": "tma_info_bottleneck_big_code", |
| @@ -742,7 +734,6 @@ · 10 unmodified lines | ||
| 742 | 734 | }, |
| 743 | 735 | { |
| 744 | 736 | "BriefDescription": "Total pipeline cost of instruction fetch bandwidth related bottlenecks", |
| 745 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 746 | 737 | "MetricExpr": "100 * (tma_frontend_bound - tma_fetch_latency * tma_mispredicts_resteers / (tma_branch_resteers + tma_dsb_switches + tma_icache_misses + tma_itlb_misses + tma_lcp + tma_ms_switches)) - tma_info_bottleneck_big_code", |
| 747 | 738 | "MetricGroup": "Fed;FetchBW;Frontend", |
| 748 | 739 | "MetricName": "tma_info_bottleneck_instruction_fetch_bw", |
| @@ -750,7 +741,6 @@ · 1 unmodified line | ||
| 750 | 741 | }, |
| 751 | 742 | { |
| 752 | 743 | "BriefDescription": "Total pipeline cost of (external) Memory Bandwidth related bottlenecks", |
| 753 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 754 | 744 | "MetricExpr": "100 * tma_memory_bound * (tma_dram_bound / (tma_dram_bound + tma_l1_bound + tma_l2_bound + tma_l3_bound + tma_pmm_bound + tma_store_bound) * (tma_mem_bandwidth / (tma_mem_bandwidth + tma_mem_latency)) + tma_l3_bound / (tma_dram_bound + tma_l1_bound + tma_l2_bound + tma_l3_bound + tma_pmm_bound + tma_store_bound) * (tma_sq_full / (tma_contested_accesses + tma_data_sharing + tma_l3_hit_latency + tma_sq_full))) + tma_l1_bound / (tma_dram_bound + tma_l1_bound + tma_l2_bound + tma_l3_bound + tma_pmm_bound + tma_store_bound) * (tma_fb_full / (tma_dtlb_load + tma_fb_full + tma_lock_latency + tma_split_loads + tma_store_fwd_blk))", |
| 755 | 745 | "MetricGroup": "Mem;MemoryBW;Offcore;tma_issueBW", |
| 756 | 746 | "MetricName": "tma_info_bottleneck_memory_bandwidth", |
| @@ -759,7 +749,6 @@ · 2 unmodified lines | ||
| 759 | 749 | }, |
| 760 | 750 | { |
| 761 | 751 | "BriefDescription": "Total pipeline cost of Memory Address Translation related bottlenecks (data-side TLBs)", |
| 762 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 763 | 752 | "MetricExpr": "100 * tma_memory_bound * (tma_l1_bound / max(tma_memory_bound, tma_dram_bound + tma_l1_bound + tma_l2_bound + tma_l3_bound + tma_pmm_bound + tma_store_bound) * (tma_dtlb_load / max(tma_l1_bound, tma_dtlb_load + tma_fb_full + tma_lock_latency + tma_split_loads + tma_store_fwd_blk)) + tma_store_bound / (tma_dram_bound + tma_l1_bound + tma_l2_bound + tma_l3_bound + tma_pmm_bound + tma_store_bound) * (tma_dtlb_store / (tma_dtlb_store + tma_false_sharing + tma_split_stores + tma_store_latency + tma_streaming_stores)))", |
| 764 | 753 | "MetricGroup": "Mem;MemoryTLB;Offcore;tma_issueTLB", |
| 765 | 754 | "MetricName": "tma_info_bottleneck_memory_data_tlbs", |
| @@ -768,7 +757,6 @@ · 2 unmodified lines | ||
| 768 | 757 | }, |
| 769 | 758 | { |
| 770 | 759 | "BriefDescription": "Total pipeline cost of Memory Latency related bottlenecks (external memory and off-core caches)", |
| 771 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 772 | 760 | "MetricExpr": "100 * tma_memory_bound * (tma_dram_bound / (tma_dram_bound + tma_l1_bound + tma_l2_bound + tma_l3_bound + tma_pmm_bound + tma_store_bound) * (tma_mem_latency / (tma_mem_bandwidth + tma_mem_latency)) + tma_l3_bound / (tma_dram_bound + tma_l1_bound + tma_l2_bound + tma_l3_bound + tma_pmm_bound + tma_store_bound) * (tma_l3_hit_latency / (tma_contested_accesses + tma_data_sharing + tma_l3_hit_latency + tma_sq_full)) + tma_l2_bound / (tma_dram_bound + tma_l1_bound + tma_l2_bound + tma_l3_bound + tma_pmm_bound + tma_store_bound))", |
| 773 | 761 | "MetricGroup": "Mem;MemoryLat;Offcore;tma_issueLat", |
| 774 | 762 | "MetricName": "tma_info_bottleneck_memory_latency", |
| @@ -777,7 +765,6 @@ · 2 unmodified lines | ||
| 777 | 765 | }, |
| 778 | 766 | { |
| 779 | 767 | "BriefDescription": "Total pipeline cost of Branch Misprediction related bottlenecks", |
| 780 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 781 | 768 | "MetricExpr": "100 * (tma_branch_mispredicts + tma_fetch_latency * tma_mispredicts_resteers / (tma_branch_resteers + tma_dsb_switches + tma_icache_misses + tma_itlb_misses + tma_lcp + tma_ms_switches))", |
| 782 | 769 | "MetricGroup": "Bad;BadSpec;BrMispredicts;tma_issueBM", |
| 783 | 770 | "MetricName": "tma_info_bottleneck_mispredictions", |
| @@ -1301,6 +1288,7 @@ · 517 unmodified lines | ||
| 1301 | 1288 | }, |
| 1302 | 1289 | { |
| 1303 | 1290 | "BriefDescription": "Average latency of data read request to external memory (in nanoseconds)", |
| 1291 | + "MetricConstraint": "NO_GROUP_EVENTS", | |
| 1304 | 1292 | "MetricExpr": "1e9 * (UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD / UNC_CHA_TOR_INSERTS.IA_MISS_DRD) / (tma_info_system_socket_clks / duration_time)", |
| 1305 | 1293 | "MetricGroup": "Mem;MemoryLat;SoC", |
| 1306 | 1294 | "MetricName": "tma_info_system_mem_read_latency", |
| @@ -1455,7 +1443,6 @@ · 148 unmodified lines | ||
| 1455 | 1443 | }, |
| 1456 | 1444 | { |
| 1457 | 1445 | "BriefDescription": "This metric estimates how often the CPU was stalled due to L2 cache accesses by loads", |
| 1458 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 1459 | 1446 | "MetricExpr": "(MEMORY_ACTIVITY.STALLS_L1D_MISS - MEMORY_ACTIVITY.STALLS_L2_MISS) / tma_info_thread_clks", |
| 1460 | 1447 | "MetricGroup": "CacheMisses;MemoryBound;TmaL3mem;TopdownL3;tma_L3_group;tma_memory_bound_group", |
| 1461 | 1448 | "MetricName": "tma_l2_bound", |
| @@ -1465,7 +1452,6 @@ · 3 unmodified lines | ||
| 1465 | 1452 | }, |
| 1466 | 1453 | { |
| 1467 | 1454 | "BriefDescription": "This metric estimates how often the CPU was stalled due to loads accesses to L3 cache or contended with a sibling Core", |
| 1468 | − "MetricConstraint": "NO_GROUP_EVENTS_NMI", | |
| 1469 | 1455 | "MetricExpr": "(MEMORY_ACTIVITY.STALLS_L2_MISS - MEMORY_ACTIVITY.STALLS_L3_MISS) / tma_info_thread_clks", |
| 1470 | 1456 | "MetricGroup": "CacheMisses;MemoryBound;TmaL3mem;TopdownL3;tma_L3_group;tma_memory_bound_group", |
| 1471 | 1457 | "MetricName": "tma_l3_bound", |
| @@ -1538,7 +1524,6 @@ · 66 unmodified lines | ||
| 1538 | 1524 | }, |
| 1539 | 1525 | { |
| 1540 | 1526 | "BriefDescription": "This metric represents fraction of cycles the CPU spent handling cache misses due to lock operations", |
| 1541 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 1542 | 1527 | "MetricExpr": "(16 * max(0, MEM_INST_RETIRED.LOCK_LOADS - L2_RQSTS.ALL_RFO) + MEM_INST_RETIRED.LOCK_LOADS / MEM_INST_RETIRED.ALL_STORES * (10 * L2_RQSTS.RFO_HIT + min(CPU_CLK_UNHALTED.THREAD, OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO))) / tma_info_thread_clks", |
| 1543 | 1528 | "MetricGroup": "Offcore;TopdownL4;tma_L4_group;tma_issueRFO;tma_l1_bound_group", |
| 1544 | 1529 | "MetricName": "tma_lock_latency", |
| @@ -1596,6 +1581,7 @@ · 51 unmodified lines | ||
| 1596 | 1581 | }, |
| 1597 | 1582 | { |
| 1598 | 1583 | "BriefDescription": "This metric represents fraction of cycles the CPU was stalled due to LFENCE Instructions.", |
| 1584 | + "MetricConstraint": "NO_GROUP_EVENTS_NMI", | |
| 1599 | 1585 | "MetricExpr": "13 * MISC2_RETIRED.LFENCE / tma_info_thread_clks", |
| 1600 | 1586 | "MetricGroup": "TopdownL6;tma_L6_group;tma_serializing_operation_group", |
| 1601 | 1587 | "MetricName": "tma_memory_fence", |
| @@ -1604,7 +1590,6 @@ · 2 unmodified lines | ||
| 1604 | 1590 | }, |
| 1605 | 1591 | { |
| 1606 | 1592 | "BriefDescription": "This metric represents fraction of slots where the CPU was retiring memory operations -- uops for memory load or store accesses.", |
| 1607 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 1608 | 1593 | "MetricExpr": "tma_light_operations * MEM_UOP_RETIRED.ANY / (tma_retiring * tma_info_thread_slots)", |
| 1609 | 1594 | "MetricGroup": "Pipeline;TopdownL3;tma_L3_group;tma_light_operations_group", |
| 1610 | 1595 | "MetricName": "tma_memory_operations", |
| @@ -1676,7 +1661,6 @@ · 65 unmodified lines | ||
| 1676 | 1661 | }, |
| 1677 | 1662 | { |
| 1678 | 1663 | "BriefDescription": "This metric represents the remaining light uops fraction the CPU has executed - remaining means not covered by other sibling nodes", |
| 1679 | − "MetricConstraint": "NO_GROUP_EVENTS", | |
| 1680 | 1664 | "MetricExpr": "max(0, tma_light_operations - (tma_fp_arith + tma_int_operations + tma_memory_operations + tma_fused_instructions + tma_non_fused_branches + tma_nop_instructions))", |
| 1681 | 1665 | "MetricGroup": "Pipeline;TopdownL3;tma_L3_group;tma_light_operations_group", |
| 1682 | 1666 | "MetricName": "tma_other_light_ops", |
| @@ -1758,6 +1742,7 @@ · 75 unmodified lines | ||
| 1758 | 1742 | }, |
| 1759 | 1743 | { |
| 1760 | 1744 | "BriefDescription": "This metric represents fraction of cycles CPU executed total of 2 uops per cycle on all execution ports (Logical Processor cycles since ICL, Physical Core cycles otherwise)", |
| 1745 | + "MetricConstraint": "NO_GROUP_EVENTS_NMI", | |
| 1761 | 1746 | "MetricExpr": "EXE_ACTIVITY.2_PORTS_UTIL / tma_info_thread_clks", |
| 1762 | 1747 | "MetricGroup": "PortsUtil;TopdownL4;tma_L4_group;tma_issue2P;tma_ports_utilization_group", |
| 1763 | 1748 | "MetricName": "tma_ports_utilized_2", |
| @@ -1767,6 +1752,7 @@ · 3 unmodified lines | ||
| 1767 | 1752 | }, |
| 1768 | 1753 | { |
| 1769 | 1754 | "BriefDescription": "This metric represents fraction of cycles CPU executed total of 3 or more uops per cycle on all execution ports (Logical Processor cycles since ICL, Physical Core cycles otherwise)", |
| 1755 | + "MetricConstraint": "NO_GROUP_EVENTS_NMI", | |
| 1770 | 1756 | "MetricExpr": "UOPS_EXECUTED.CYCLES_GE_3 / tma_info_thread_clks", |
| 1771 | 1757 | "MetricGroup": "PortsUtil;TopdownL4;tma_L4_group;tma_ports_utilization_group", |
| 1772 | 1758 | "MetricName": "tma_ports_utilized_3m", |
| @@ -1822,6 +1808,7 @@ · 49 unmodified lines | ||
| 1822 | 1808 | }, |
| 1823 | 1809 | { |
| 1824 | 1810 | "BriefDescription": "This metric represents fraction of cycles the CPU was stalled due to PAUSE Instructions", |
| 1811 | + "MetricConstraint": "NO_GROUP_EVENTS_NMI", | |
| 1825 | 1812 | "MetricExpr": "CPU_CLK_UNHALTED.PAUSE / tma_info_thread_clks", |
| 1826 | 1813 | "MetricGroup": "TopdownL6;tma_L6_group;tma_serializing_operation_group", |
| 1827 | 1814 | "MetricName": "tma_slow_pause", |
| @@ -1840,7 +1827,6 @@ · 12 unmodified lines | ||
| 1840 | 1827 | }, |
| 1841 | 1828 | { |
| 1842 | 1829 | "BriefDescription": "This metric represents rate of split store accesses", |
| 1843 | − "MetricConstraint": "NO_GROUP_EVENTS_NMI", | |
| 1844 | 1830 | "MetricExpr": "MEM_INST_RETIRED.SPLIT_STORES / tma_info_core_core_clks", |
| 1845 | 1831 | "MetricGroup": "TopdownL4;tma_L4_group;tma_issueSpSt;tma_store_bound_group", |
| 1846 | 1832 | "MetricName": "tma_split_stores", |
| @@ -1868,7 +1854,6 @@ · 21 unmodified lines | ||
| 1868 | 1854 | }, |
| 1869 | 1855 | { |
| 1870 | 1856 | "BriefDescription": "This metric roughly estimates fraction of cycles when the memory subsystem had loads blocked since they could not forward data from earlier (in program order) overlapping stores", |
| 1871 | − "MetricConstraint": "NO_GROUP_EVENTS_NMI", | |
| 1872 | 1857 | "MetricExpr": "13 * LD_BLOCKS.STORE_FORWARD / tma_info_thread_clks", |
| 1873 | 1858 | "MetricGroup": "TopdownL4;tma_L4_group;tma_l1_bound_group", |
| 1874 | 1859 | "MetricName": "tma_store_fwd_blk", |
| @@ -414,16 +414,30 @@ EOF · 413 unmodified lines | ||
| 414 | 414 | # start daemon |
| 415 | 415 | daemon_start ${config} test |
| 416 | 416 | |
| 417 | − # send 2 signals | |
| 418 | − perf daemon signal --config ${config} --session test | |
| 419 | − perf daemon signal --config ${config} | |
| 420 | − | |
| 421 | − # stop daemon | |
| 422 | − daemon_exit ${config} | |
| 423 | − | |
| 424 | − # count is 2 perf.data for signals and 1 for perf record finished | |
| 425 | − count=`ls ${base}/session-test/*perf.data* | wc -l` | |
| 426 | − if [ ${count} -ne 3 ]; then | |
| 417 | + # send 2 signals then exit. Do this in a loop watching the number of | |
| 418 | + # files to avoid races. If the loop retries more than 600 times then | |
| 419 | + # give up. | |
| 420 | + local retries=0 | |
| 421 | + local signals=0 | |
| 422 | + local success=0 | |
| 423 | + while [ ${retries} -lt 600 ] && [ ${success} -eq 0 ]; do | |
| 424 | + local files | |
| 425 | + files=`ls ${base}/session-test/*perf.data* 2> /dev/null | wc -l` | |
| 426 | + if [ ${signals} -eq 0 ]; then | |
| 427 | + perf daemon signal --config ${config} --session test | |
| 428 | + signals=1 | |
| 429 | + elif [ ${signals} -eq 1 ] && [ $files -ge 1 ]; then | |
| 430 | + perf daemon signal --config ${config} | |
| 431 | + signals=2 | |
| 432 | + elif [ ${signals} -eq 2 ] && [ $files -ge 2 ]; then | |
| 433 | + daemon_exit ${config} | |
| 434 | + signals=3 | |
| 435 | + elif [ ${signals} -eq 3 ] && [ $files -ge 3 ]; then | |
| 436 | + success=1 | |
| 437 | + fi | |
| 438 | + retries=$((${retries} +1)) | |
| 439 | + done | |
| 440 | + if [ ${success} -eq 0 ]; then | |
| 427 | 441 | error=1 |
| 428 | 442 | echo "FAILED: perf data no generated" |
| 429 | 443 | fi |
| @@ -3,17 +3,32 @@ · 2 unmodified lines | ||
| 3 | 3 | # SPDX-License-Identifier: GPL-2.0 |
| 4 | 4 | |
| 5 | 5 | set -e |
| 6 | −err=0 | |
| 7 | 6 | |
| 8 | 7 | shelldir=$(dirname "$0") |
| 9 | 8 | # shellcheck source=lib/setup_python.sh |
| 10 | 9 | . "${shelldir}"/lib/setup_python.sh |
| 11 | 10 | |
| 11 | +list_output=$(mktemp /tmp/__perf_test.list_output.json.XXXXX) | |
| 12 | + | |
| 13 | +cleanup() { | |
| 14 | + rm -f "${list_output}" | |
| 15 | + | |
| 16 | + trap - EXIT TERM INT | |
| 17 | +} | |
| 18 | + | |
| 19 | +trap_cleanup() { | |
| 20 | + cleanup | |
| 21 | + exit 1 | |
| 22 | +} | |
| 23 | +trap trap_cleanup EXIT TERM INT | |
| 24 | + | |
| 12 | 25 | test_list_json() { |
| 13 | 26 | echo "Json output test" |
| 14 | − perf list -j | $PYTHON -m json.tool | |
| 27 | + perf list -j -o "${list_output}" | |
| 28 | + $PYTHON -m json.tool "${list_output}" | |
| 15 | 29 | echo "Json output test [Success]" |
| 16 | 30 | } |
| 17 | 31 | |
| 18 | 32 | test_list_json |
| 19 | −exit $err | |
| 33 | +cleanup | |
| 34 | +exit 0 | |
| @@ -36,8 +36,7 @@ test_db() · 35 unmodified lines | ||
| 36 | 36 | echo "DB test" |
| 37 | 37 | |
| 38 | 38 | # Check if python script is supported |
| 39 | − libpython=$(perf version --build-options | grep python | grep -cv OFF) | |
| 40 | − if [ "${libpython}" != "1" ] ; then | |
| 39 | + if perf version --build-options | grep python | grep -q OFF ; then | |
| 41 | 40 | echo "SKIP: python scripting is not supported" |
| 42 | 41 | err=2 |
| 43 | 42 | return |
| @@ -54,7 +53,14 @@ def sample_table(*args): · 10 unmodified lines | ||
| 54 | 53 | def call_path_table(*args): |
| 55 | 54 | print(f'call_path_table({args}') |
| 56 | 55 | _end_of_file_ |
| 57 | − perf record -g -o "${perfdatafile}" true | |
| 56 | + case $(uname -m) | |
| 57 | + in s390x) | |
| 58 | + cmd_flags="--call-graph dwarf -e cpu-clock";; | |
| 59 | + *) | |
| 60 | + cmd_flags="-g";; | |
| 61 | + esac | |
| 62 | + | |
| 63 | + perf record $cmd_flags -o "${perfdatafile}" true | |
| 58 | 64 | perf script -i "${perfdatafile}" -s "${db_test}" |
| 59 | 65 | echo "DB test [Success]" |
| 60 | 66 | } |
| @@ -67,6 +67,7 @@ size_t syscall_arg__scnprintf_statx_mask(char *bf, size_t size, struct syscall_a · 66 unmodified lines | ||
| 67 | 67 | P_FLAG(BTIME); |
| 68 | 68 | P_FLAG(MNT_ID); |
| 69 | 69 | P_FLAG(DIOALIGN); |
| 70 | + P_FLAG(MNT_ID_UNIQUE); | |
| 70 | 71 | |
| 71 | 72 | #undef P_FLAG |
| 72 | 73 | |
| @@ -103,7 +103,14 @@ struct evlist *evlist__new_default(void) · 102 unmodified lines | ||
| 103 | 103 | err = parse_event(evlist, can_profile_kernel ? "cycles:P" : "cycles:Pu"); |
| 104 | 104 | if (err) { |
| 105 | 105 | evlist__delete(evlist); |
| 106 | − evlist = NULL; | |
| 106 | + return NULL; | |
| 107 | + } | |
| 108 | + | |
| 109 | + if (evlist->core.nr_entries > 1) { | |
| 110 | + struct evsel *evsel; | |
| 111 | + | |
| 112 | + evlist__for_each_entry(evlist, evsel) | |
| 113 | + evsel__set_sample_id(evsel, /*can_sample_identifier=*/false); | |
| 107 | 114 | } |
| 108 | 115 | |
| 109 | 116 | return evlist; |
| @@ -491,8 +491,8 @@ static int hist_entry__init(struct hist_entry *he, · 490 unmodified lines | ||
| 491 | 491 | } |
| 492 | 492 | |
| 493 | 493 | if (symbol_conf.res_sample) { |
| 494 | − he->res_samples = calloc(sizeof(struct res_sample), | |
| 495 | − symbol_conf.res_sample); | |
| 494 | + he->res_samples = calloc(symbol_conf.res_sample, | |
| 495 | + sizeof(struct res_sample)); | |
| 496 | 496 | if (!he->res_samples) |
| 497 | 497 | goto err_srcline; |
| 498 | 498 | } |
| @@ -115,6 +115,10 @@ · 114 unmodified lines | ||
| 115 | 115 | SYM_ALIAS(alias, name, SYM_T_FUNC, SYM_L_WEAK) |
| 116 | 116 | #endif |
| 117 | 117 | |
| 118 | +#ifndef SYM_FUNC_ALIAS_MEMFUNC | |
| 119 | +#define SYM_FUNC_ALIAS_MEMFUNC SYM_FUNC_ALIAS | |
| 120 | +#endif | |
| 121 | + | |
| 118 | 122 | // In the kernel sources (include/linux/cfi_types.h), this has a different |
| 119 | 123 | // definition when CONFIG_CFI_CLANG is used, for tools/ just use the !clang |
| 120 | 124 | // definition: |
| @@ -286,7 +286,7 @@ static int setup_metric_events(const char *pmu, struct hashmap *ids, · 285 unmodified lines | ||
| 286 | 286 | *out_metric_events = NULL; |
| 287 | 287 | ids_size = hashmap__size(ids); |
| 288 | 288 | |
| 289 | − metric_events = calloc(sizeof(void *), ids_size + 1); | |
| 289 | + metric_events = calloc(ids_size + 1, sizeof(void *)); | |
| 290 | 290 | if (!metric_events) |
| 291 | 291 | return -ENOMEM; |
| 292 | 292 | |
| @@ -66,7 +66,7 @@ void print_tracepoint_events(const struct print_callbacks *print_cb __maybe_unus · 65 unmodified lines | ||
| 66 | 66 | |
| 67 | 67 | put_tracing_file(events_path); |
| 68 | 68 | if (events_fd < 0) { |
| 69 | − printf("Error: failed to open tracing events directory\n"); | |
| 69 | + pr_err("Error: failed to open tracing events directory\n"); | |
| 70 | 70 | return; |
| 71 | 71 | } |
| 72 | 72 | |
| @@ -1055,11 +1055,11 @@ int perf_event__synthesize_threads(struct perf_tool *tool, · 1054 unmodified lines | ||
| 1055 | 1055 | if (thread_nr > n) |
| 1056 | 1056 | thread_nr = n; |
| 1057 | 1057 | |
| 1058 | − synthesize_threads = calloc(sizeof(pthread_t), thread_nr); | |
| 1058 | + synthesize_threads = calloc(thread_nr, sizeof(pthread_t)); | |
| 1059 | 1059 | if (synthesize_threads == NULL) |
| 1060 | 1060 | goto free_dirent; |
| 1061 | 1061 | |
| 1062 | − args = calloc(sizeof(*args), thread_nr); | |
| 1062 | + args = calloc(thread_nr, sizeof(*args)); | |
| 1063 | 1063 | if (args == NULL) |
| 1064 | 1064 | goto free_threads; |
| 1065 | 1065 | |
| @@ -49,15 +49,42 @@ bool filter_reg(__u64 reg) · 48 unmodified lines | ||
| 49 | 49 | case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_SVPBMT: |
| 50 | 50 | case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZBA: |
| 51 | 51 | case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZBB: |
| 52 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZBC: | |
| 53 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZBKB: | |
| 54 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZBKC: | |
| 55 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZBKX: | |
| 52 | 56 | case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZBS: |
| 57 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZFA: | |
| 58 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZFH: | |
| 59 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZFHMIN: | |
| 53 | 60 | case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICBOM: |
| 54 | 61 | case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICBOZ: |
| 55 | 62 | case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICNTR: |
| 56 | 63 | case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICOND: |
| 57 | 64 | case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZICSR: |
| 58 | 65 | case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZIFENCEI: |
| 66 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZIHINTNTL: | |
| 59 | 67 | case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZIHINTPAUSE: |
| 60 | 68 | case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZIHPM: |
| 69 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZKND: | |
| 70 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZKNE: | |
| 71 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZKNH: | |
| 72 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZKR: | |
| 73 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZKSED: | |
| 74 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZKSH: | |
| 75 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZKT: | |
| 76 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVBB: | |
| 77 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVBC: | |
| 78 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVFH: | |
| 79 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVFHMIN: | |
| 80 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVKB: | |
| 81 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVKG: | |
| 82 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVKNED: | |
| 83 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVKNHA: | |
| 84 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVKNHB: | |
| 85 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVKSED: | |
| 86 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVKSH: | |
| 87 | + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZVKT: | |
| 61 | 88 | /* |
| 62 | 89 | * Like ISA_EXT registers, SBI_EXT registers are only visible when the |
| 63 | 90 | * host supports them and disabling them does not affect the visibility |
| @@ -394,15 +421,42 @@ static const char *isa_ext_single_id_to_str(__u64 reg_off) · 330 unmodified lines | ||
| 394 | 421 | KVM_ISA_EXT_ARR(SVPBMT), |
| 395 | 422 | KVM_ISA_EXT_ARR(ZBA), |
| 396 | 423 | KVM_ISA_EXT_ARR(ZBB), |
| 424 | + KVM_ISA_EXT_ARR(ZBC), | |
| 425 | + KVM_ISA_EXT_ARR(ZBKB), | |
| 426 | + KVM_ISA_EXT_ARR(ZBKC), | |
| 427 | + KVM_ISA_EXT_ARR(ZBKX), | |
| 397 | 428 | KVM_ISA_EXT_ARR(ZBS), |
| 429 | + KVM_ISA_EXT_ARR(ZFA), | |
| 430 | + KVM_ISA_EXT_ARR(ZFH), | |
| 431 | + KVM_ISA_EXT_ARR(ZFHMIN), | |
| 398 | 432 | KVM_ISA_EXT_ARR(ZICBOM), |
| 399 | 433 | KVM_ISA_EXT_ARR(ZICBOZ), |
| 400 | 434 | KVM_ISA_EXT_ARR(ZICNTR), |
| 401 | 435 | KVM_ISA_EXT_ARR(ZICOND), |
| 402 | 436 | KVM_ISA_EXT_ARR(ZICSR), |
| 403 | 437 | KVM_ISA_EXT_ARR(ZIFENCEI), |
| 438 | + KVM_ISA_EXT_ARR(ZIHINTNTL), | |
| 404 | 439 | KVM_ISA_EXT_ARR(ZIHINTPAUSE), |
| 405 | 440 | KVM_ISA_EXT_ARR(ZIHPM), |
| 441 | + KVM_ISA_EXT_ARR(ZKND), | |
| 442 | + KVM_ISA_EXT_ARR(ZKNE), | |
| 443 | + KVM_ISA_EXT_ARR(ZKNH), | |
| 444 | + KVM_ISA_EXT_ARR(ZKR), | |
| 445 | + KVM_ISA_EXT_ARR(ZKSED), | |
| 446 | + KVM_ISA_EXT_ARR(ZKSH), | |
| 447 | + KVM_ISA_EXT_ARR(ZKT), | |
| 448 | + KVM_ISA_EXT_ARR(ZVBB), | |
| 449 | + KVM_ISA_EXT_ARR(ZVBC), | |
| 450 | + KVM_ISA_EXT_ARR(ZVFH), | |
| 451 | + KVM_ISA_EXT_ARR(ZVFHMIN), | |
| 452 | + KVM_ISA_EXT_ARR(ZVKB), | |
| 453 | + KVM_ISA_EXT_ARR(ZVKG), | |
| 454 | + KVM_ISA_EXT_ARR(ZVKNED), | |
| 455 | + KVM_ISA_EXT_ARR(ZVKNHA), | |
| 456 | + KVM_ISA_EXT_ARR(ZVKNHB), | |
| 457 | + KVM_ISA_EXT_ARR(ZVKSED), | |
| 458 | + KVM_ISA_EXT_ARR(ZVKSH), | |
| 459 | + KVM_ISA_EXT_ARR(ZVKT), | |
| 406 | 460 | }; |
| 407 | 461 | |
| 408 | 462 | if (reg_off >= ARRAY_SIZE(kvm_isa_ext_reg_name)) |
| @@ -888,15 +942,42 @@ KVM_ISA_EXT_SIMPLE_CONFIG(svnapot, SVNAPOT); · 479 unmodified lines | ||
| 888 | 942 | KVM_ISA_EXT_SIMPLE_CONFIG(svpbmt, SVPBMT); |
| 889 | 943 | KVM_ISA_EXT_SIMPLE_CONFIG(zba, ZBA); |
| 890 | 944 | KVM_ISA_EXT_SIMPLE_CONFIG(zbb, ZBB); |
| 945 | +KVM_ISA_EXT_SIMPLE_CONFIG(zbc, ZBC); | |
| 946 | +KVM_ISA_EXT_SIMPLE_CONFIG(zbkb, ZBKB); | |
| 947 | +KVM_ISA_EXT_SIMPLE_CONFIG(zbkc, ZBKC); | |
| 948 | +KVM_ISA_EXT_SIMPLE_CONFIG(zbkx, ZBKX); | |
| 891 | 949 | KVM_ISA_EXT_SIMPLE_CONFIG(zbs, ZBS); |
| 950 | +KVM_ISA_EXT_SIMPLE_CONFIG(zfa, ZFA); | |
| 951 | +KVM_ISA_EXT_SIMPLE_CONFIG(zfh, ZFH); | |
| 952 | +KVM_ISA_EXT_SIMPLE_CONFIG(zfhmin, ZFHMIN); | |
| 892 | 953 | KVM_ISA_EXT_SUBLIST_CONFIG(zicbom, ZICBOM); |
| 893 | 954 | KVM_ISA_EXT_SUBLIST_CONFIG(zicboz, ZICBOZ); |
| 894 | 955 | KVM_ISA_EXT_SIMPLE_CONFIG(zicntr, ZICNTR); |
| 895 | 956 | KVM_ISA_EXT_SIMPLE_CONFIG(zicond, ZICOND); |
| 896 | 957 | KVM_ISA_EXT_SIMPLE_CONFIG(zicsr, ZICSR); |
| 897 | 958 | KVM_ISA_EXT_SIMPLE_CONFIG(zifencei, ZIFENCEI); |
| 959 | +KVM_ISA_EXT_SIMPLE_CONFIG(zihintntl, ZIHINTNTL); | |
| 898 | 960 | KVM_ISA_EXT_SIMPLE_CONFIG(zihintpause, ZIHINTPAUSE); |
| 899 | 961 | KVM_ISA_EXT_SIMPLE_CONFIG(zihpm, ZIHPM); |
| 962 | +KVM_ISA_EXT_SIMPLE_CONFIG(zknd, ZKND); | |
| 963 | +KVM_ISA_EXT_SIMPLE_CONFIG(zkne, ZKNE); | |
| 964 | +KVM_ISA_EXT_SIMPLE_CONFIG(zknh, ZKNH); | |
| 965 | +KVM_ISA_EXT_SIMPLE_CONFIG(zkr, ZKR); | |
| 966 | +KVM_ISA_EXT_SIMPLE_CONFIG(zksed, ZKSED); | |
| 967 | +KVM_ISA_EXT_SIMPLE_CONFIG(zksh, ZKSH); | |
| 968 | +KVM_ISA_EXT_SIMPLE_CONFIG(zkt, ZKT); | |
| 969 | +KVM_ISA_EXT_SIMPLE_CONFIG(zvbb, ZVBB); | |
| 970 | +KVM_ISA_EXT_SIMPLE_CONFIG(zvbc, ZVBC); | |
| 971 | +KVM_ISA_EXT_SIMPLE_CONFIG(zvfh, ZVFH); | |
| 972 | +KVM_ISA_EXT_SIMPLE_CONFIG(zvfhmin, ZVFHMIN); | |
| 973 | +KVM_ISA_EXT_SIMPLE_CONFIG(zvkb, ZVKB); | |
| 974 | +KVM_ISA_EXT_SIMPLE_CONFIG(zvkg, ZVKG); | |
| 975 | +KVM_ISA_EXT_SIMPLE_CONFIG(zvkned, ZVKNED); | |
| 976 | +KVM_ISA_EXT_SIMPLE_CONFIG(zvknha, ZVKNHA); | |
| 977 | +KVM_ISA_EXT_SIMPLE_CONFIG(zvknhb, ZVKNHB); | |
| 978 | +KVM_ISA_EXT_SIMPLE_CONFIG(zvksed, ZVKSED); | |
| 979 | +KVM_ISA_EXT_SIMPLE_CONFIG(zvksh, ZVKSH); | |
| 980 | +KVM_ISA_EXT_SIMPLE_CONFIG(zvkt, ZVKT); | |
| 900 | 981 | |
| 901 | 982 | struct vcpu_reg_list *vcpu_configs[] = { |
| 902 | 983 | &config_sbi_base, |
| @@ -914,14 +995,41 @@ struct vcpu_reg_list *vcpu_configs[] = { · 11 unmodified lines | ||
| 914 | 995 | &config_svpbmt, |
| 915 | 996 | &config_zba, |
| 916 | 997 | &config_zbb, |
| 998 | + &config_zbc, | |
| 999 | + &config_zbkb, | |
| 1000 | + &config_zbkc, | |
| 1001 | + &config_zbkx, | |
| 917 | 1002 | &config_zbs, |
| 1003 | + &config_zfa, | |
| 1004 | + &config_zfh, | |
| 1005 | + &config_zfhmin, | |
| 918 | 1006 | &config_zicbom, |
| 919 | 1007 | &config_zicboz, |
| 920 | 1008 | &config_zicntr, |
| 921 | 1009 | &config_zicond, |
| 922 | 1010 | &config_zicsr, |
| 923 | 1011 | &config_zifencei, |
| 1012 | + &config_zihintntl, | |
| 924 | 1013 | &config_zihintpause, |
| 925 | 1014 | &config_zihpm, |
| 1015 | + &config_zknd, | |
| 1016 | + &config_zkne, | |
| 1017 | + &config_zknh, | |
| 1018 | + &config_zkr, | |
| 1019 | + &config_zksed, | |
| 1020 | + &config_zksh, | |
| 1021 | + &config_zkt, | |
| 1022 | + &config_zvbb, | |
| 1023 | + &config_zvbc, | |
| 1024 | + &config_zvfh, | |
| 1025 | + &config_zvfhmin, | |
| 1026 | + &config_zvkb, | |
| 1027 | + &config_zvkg, | |
| 1028 | + &config_zvkned, | |
| 1029 | + &config_zvknha, | |
| 1030 | + &config_zvknhb, | |
| 1031 | + &config_zvksed, | |
| 1032 | + &config_zvksh, | |
| 1033 | + &config_zvkt, | |
| 926 | 1034 | }; |
| 927 | 1035 | int vcpu_configs_n = ARRAY_SIZE(vcpu_configs); |
| @@ -122,7 +122,9 @@ do_netperf() { · 121 unmodified lines | ||
| 122 | 122 | local netns=$1 |
| 123 | 123 | |
| 124 | 124 | [ "$NF" = "6" ] && serip=$SERVER_IP6 |
| 125 | − ip net exec $netns netperf -$NF -t TCP_STREAM -H $serip 2>&1 >/dev/null | |
| 125 | + | |
| 126 | + # use large write to be sure to generate big tcp packets | |
| 127 | + ip net exec $netns netperf -$NF -t TCP_STREAM -l 1 -H $serip -- -m 262144 2>&1 >/dev/null | |
| 126 | 128 | } |
| 127 | 129 | |
| 128 | 130 | do_test() { |
| @@ -89,7 +89,7 @@ for ovr in setsock cmsg both diff; do · 88 unmodified lines | ||
| 89 | 89 | check_result $? 0 "TCLASS $prot $ovr - pass" |
| 90 | 90 | |
| 91 | 91 | while [ -d /proc/$BG ]; do |
| 92 | − $NSEXE ./cmsg_sender -6 -p u $TGT6 1234 | |
| 92 | + $NSEXE ./cmsg_sender -6 -p $p $m $((TOS2)) $TGT6 1234 | |
| 93 | 93 | done |
| 94 | 94 | |
| 95 | 95 | tcpdump -r $TMPF -v 2>&1 | grep "class $TOS2" >> /dev/null |
| @@ -126,7 +126,7 @@ for ovr in setsock cmsg both diff; do · 30 unmodified lines | ||
| 126 | 126 | check_result $? 0 "HOPLIMIT $prot $ovr - pass" |
| 127 | 127 | |
| 128 | 128 | while [ -d /proc/$BG ]; do |
| 129 | − $NSEXE ./cmsg_sender -6 -p u $TGT6 1234 | |
| 129 | + $NSEXE ./cmsg_sender -6 -p $p $m $LIM $TGT6 1234 | |
| 130 | 130 | done |
| 131 | 131 | |
| 132 | 132 | tcpdump -r $TMPF -v 2>&1 | grep "hlim $LIM[^0-9]" >> /dev/null |
| @@ -199,6 +199,7 @@ · 198 unmodified lines | ||
| 199 | 199 | # Same as above but with IPv6 |
| 200 | 200 | |
| 201 | 201 | source lib.sh |
| 202 | +source net_helper.sh | |
| 202 | 203 | |
| 203 | 204 | PAUSE_ON_FAIL=no |
| 204 | 205 | VERBOSE=0 |
| @@ -1336,13 +1337,15 @@ test_pmtu_ipvX_over_bridged_vxlanY_or_geneveY_exception() { · 1131 unmodified lines | ||
| 1336 | 1337 | TCPDST="TCP:[${dst}]:50000" |
| 1337 | 1338 | fi |
| 1338 | 1339 | ${ns_b} socat -T 3 -u -6 TCP-LISTEN:50000 STDOUT > $tmpoutfile & |
| 1340 | + local socat_pid=$! | |
| 1339 | 1341 | |
| 1340 | − sleep 1 | |
| 1342 | + wait_local_port_listen ${NS_B} 50000 tcp | |
| 1341 | 1343 | |
| 1342 | 1344 | dd if=/dev/zero status=none bs=1M count=1 | ${target} socat -T 3 -u STDIN $TCPDST,connect-timeout=3 |
| 1343 | 1345 | |
| 1344 | 1346 | size=$(du -sb $tmpoutfile) |
| 1345 | 1347 | size=${size%%/tmp/*} |
| 1348 | + wait ${socat_pid} | |
| 1346 | 1349 | |
| 1347 | 1350 | [ $size -ne 1048576 ] && err "File size $size mismatches exepcted value in locally bridged vxlan test" && return 1 |
| 1348 | 1351 | done |
| @@ -1954,6 +1957,13 @@ check_command() { · 605 unmodified lines | ||
| 1954 | 1957 | return 0 |
| 1955 | 1958 | } |
| 1956 | 1959 | |
| 1960 | +check_running() { | |
| 1961 | + pid=${1} | |
| 1962 | + cmd=${2} | |
| 1963 | + | |
| 1964 | + [ "$(cat /proc/${pid}/cmdline 2>/dev/null | tr -d '\0')" = "{cmd}" ] | |
| 1965 | +} | |
| 1966 | + | |
| 1957 | 1967 | test_cleanup_vxlanX_exception() { |
| 1958 | 1968 | outer="${1}" |
| 1959 | 1969 | encap="vxlan" |
| @@ -1984,11 +1994,12 @@ test_cleanup_vxlanX_exception() { · 24 unmodified lines | ||
| 1984 | 1994 | |
| 1985 | 1995 | ${ns_a} ip link del dev veth_A-R1 & |
| 1986 | 1996 | iplink_pid=$! |
| 1987 | − sleep 1 | |
| 1988 | − if [ "$(cat /proc/${iplink_pid}/cmdline 2>/dev/null | tr -d '\0')" = "iplinkdeldevveth_A-R1" ]; then | |
| 1989 | − err " can't delete veth device in a timely manner, PMTU dst likely leaked" | |
| 1990 | − return 1 | |
| 1991 | − fi | |
| 1997 | + for i in $(seq 1 20); do | |
| 1998 | + check_running ${iplink_pid} "iplinkdeldevveth_A-R1" || return 0 | |
| 1999 | + sleep 0.1 | |
| 2000 | + done | |
| 2001 | + err " can't delete veth device in a timely manner, PMTU dst likely leaked" | |
| 2002 | + return 1 | |
| 1992 | 2003 | } |
| 1993 | 2004 | |
| 1994 | 2005 | test_cleanup_ipv6_exception() { |
| @@ -440,7 +440,6 @@ kci_test_encap_vxlan() · 439 unmodified lines | ||
| 440 | 440 | local ret=0 |
| 441 | 441 | vxlan="test-vxlan0" |
| 442 | 442 | vlan="test-vlan0" |
| 443 | − testns="$1" | |
| 444 | 443 | run_cmd ip -netns "$testns" link add "$vxlan" type vxlan id 42 group 239.1.1.1 \ |
| 445 | 444 | dev "$devdummy" dstport 4789 |
| 446 | 445 | if [ $? -ne 0 ]; then |
| @@ -485,7 +484,6 @@ kci_test_encap_fou() · 38 unmodified lines | ||
| 485 | 484 | { |
| 486 | 485 | local ret=0 |
| 487 | 486 | name="test-fou" |
| 488 | − testns="$1" | |
| 489 | 487 | run_cmd_grep 'Usage: ip fou' ip fou help |
| 490 | 488 | if [ $? -ne 0 ];then |
| 491 | 489 | end_test "SKIP: fou: iproute2 too old" |
| @@ -526,8 +524,8 @@ kci_test_encap() · 34 unmodified lines | ||
| 526 | 524 | run_cmd ip -netns "$testns" link set lo up |
| 527 | 525 | run_cmd ip -netns "$testns" link add name "$devdummy" type dummy |
| 528 | 526 | run_cmd ip -netns "$testns" link set "$devdummy" up |
| 529 | − run_cmd kci_test_encap_vxlan "$testns" | |
| 530 | − run_cmd kci_test_encap_fou "$testns" | |
| 527 | + run_cmd kci_test_encap_vxlan | |
| 528 | + run_cmd kci_test_encap_fou | |
| 531 | 529 | |
| 532 | 530 | ip netns del "$testns" |
| 533 | 531 | return $ret |
| @@ -110,9 +110,9 @@ static void try_accept(const char *tst_name, unsigned int port, · 109 unmodified lines | ||
| 110 | 110 | test_tcp_ao_counters_cmp(tst_name, &ao_cnt1, &ao_cnt2, cnt_expected); |
| 111 | 111 | |
| 112 | 112 | out: |
| 113 | − synchronize_threads(); /* close() */ | |
| 113 | + synchronize_threads(); /* test_kill_sk() */ | |
| 114 | 114 | if (sk > 0) |
| 115 | − close(sk); | |
| 115 | + test_kill_sk(sk); | |
| 116 | 116 | } |
| 117 | 117 | |
| 118 | 118 | static void server_add_routes(void) |
| @@ -302,10 +302,10 @@ static void try_connect(const char *tst_name, unsigned int port, · 183 unmodified lines | ||
| 302 | 302 | test_ok("%s: connected", tst_name); |
| 303 | 303 | |
| 304 | 304 | out: |
| 305 | − synchronize_threads(); /* close() */ | |
| 305 | + synchronize_threads(); /* test_kill_sk() */ | |
| 306 | 306 | /* _test_connect_socket() cleans up on failure */ |
| 307 | 307 | if (ret > 0) |
| 308 | − close(sk); | |
| 308 | + test_kill_sk(sk); | |
| 309 | 309 | } |
| 310 | 310 | |
| 311 | 311 | #define PREINSTALL_MD5_FIRST BIT(0) |
| @@ -486,10 +486,10 @@ static void try_to_add(const char *tst_name, unsigned int port, · 174 unmodified lines | ||
| 486 | 486 | } |
| 487 | 487 | |
| 488 | 488 | out: |
| 489 | − synchronize_threads(); /* close() */ | |
| 489 | + synchronize_threads(); /* test_kill_sk() */ | |
| 490 | 490 | /* _test_connect_socket() cleans up on failure */ |
| 491 | 491 | if (ret > 0) |
| 492 | − close(sk); | |
| 492 | + test_kill_sk(sk); | |
| 493 | 493 | } |
| 494 | 494 | |
| 495 | 495 | static void client_add_ip(union tcp_addr *client, const char *ip) |
| @@ -39,6 +39,10 @@ create_ns() { · 38 unmodified lines | ||
| 39 | 39 | for ns in $NS_SRC $NS_DST; do |
| 40 | 40 | ip netns add $ns |
| 41 | 41 | ip -n $ns link set dev lo up |
| 42 | + | |
| 43 | + # disable route solicitations to decrease 'noise' traffic | |
| 44 | + ip netns exec $ns sysctl -qw net.ipv6.conf.default.router_solicitations=0 | |
| 45 | + ip netns exec $ns sysctl -qw net.ipv6.conf.all.router_solicitations=0 | |
| 42 | 46 | done |
| 43 | 47 | |
| 44 | 48 | ip link add name veth$SRC type veth peer name veth$DST |
| @@ -80,6 +84,12 @@ create_vxlan_pair() { · 35 unmodified lines | ||
| 80 | 84 | create_vxlan_endpoint $BASE$ns veth$ns $BM_NET_V6$((3 - $ns)) vxlan6$ns 6 |
| 81 | 85 | ip -n $BASE$ns addr add dev vxlan6$ns $OL_NET_V6$ns/24 nodad |
| 82 | 86 | done |
| 87 | + | |
| 88 | + # preload neighbur cache, do avoid some noisy traffic | |
| 89 | + local addr_dst=$(ip -j -n $BASE$DST link show dev vxlan6$DST |jq -r '.[]["address"]') | |
| 90 | + local addr_src=$(ip -j -n $BASE$SRC link show dev vxlan6$SRC |jq -r '.[]["address"]') | |
| 91 | + ip -n $BASE$DST neigh add dev vxlan6$DST lladdr $addr_src $OL_NET_V6$SRC | |
| 92 | + ip -n $BASE$SRC neigh add dev vxlan6$SRC lladdr $addr_dst $OL_NET_V6$DST | |
| 83 | 93 | } |
| 84 | 94 | |
| 85 | 95 | is_ipv6() { |
| @@ -119,7 +129,7 @@ run_test() { · 33 unmodified lines | ||
| 119 | 129 | # not enable GRO |
| 120 | 130 | ip netns exec $NS_DST $ipt -A INPUT -p udp --dport 4789 |
| 121 | 131 | ip netns exec $NS_DST $ipt -A INPUT -p udp --dport 8000 |
| 122 | − ip netns exec $NS_DST ./udpgso_bench_rx -C 1000 -R 10 -n 10 -l 1300 $rx_args & | |
| 132 | + ip netns exec $NS_DST ./udpgso_bench_rx -C 2000 -R 100 -n 10 -l 1300 $rx_args & | |
| 123 | 133 | local spid=$! |
| 124 | 134 | wait_local_port_listen "$NS_DST" 8000 udp |
| 125 | 135 | ip netns exec $NS_SRC ./udpgso_bench_tx $family -M 1 -s 13000 -S 1300 -D $dst |
| @@ -168,7 +178,7 @@ run_bench() { · 42 unmodified lines | ||
| 168 | 178 | # bind the sender and the receiver to different CPUs to try |
| 169 | 179 | # get reproducible results |
| 170 | 180 | ip netns exec $NS_DST bash -c "echo 2 > /sys/class/net/veth$DST/queues/rx-0/rps_cpus" |
| 171 | − ip netns exec $NS_DST taskset 0x2 ./udpgso_bench_rx -C 1000 -R 10 & | |
| 181 | + ip netns exec $NS_DST taskset 0x2 ./udpgso_bench_rx -C 2000 -R 100 & | |
| 172 | 182 | local spid=$! |
| 173 | 183 | wait_local_port_listen "$NS_DST" 8000 udp |
| 174 | 184 | ip netns exec $NS_SRC taskset 0x1 ./udpgso_bench_tx $family -l 3 -S 1300 -D $dst |
| @@ -375,7 +375,7 @@ static void do_recv(void) · 374 unmodified lines | ||
| 375 | 375 | do_flush_udp(fd); |
| 376 | 376 | |
| 377 | 377 | tnow = gettimeofday_ms(); |
| 378 | − if (tnow > treport) { | |
| 378 | + if (!cfg_expected_pkt_nr && tnow > treport) { | |
| 379 | 379 | if (packets) |
| 380 | 380 | fprintf(stderr, |
| 381 | 381 | "%s rx: %6lu MB/s %8lu calls/s\n", |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include "../kselftest_harness.h" |
| 14 | 14 | |
| 15 | 15 | #define TEST_ZONE_ID 123 |
| 16 | −#define CTA_FILTER_F_CTA_TUPLE_ZONE (1 << 2) | |
| 16 | +#define NF_CT_DEFAULT_ZONE_ID 0 | |
| 17 | 17 | |
| 18 | 18 | static int reply_counter; |
| 19 | 19 | |
| @@ -336,6 +336,9 @@ FIXTURE_SETUP(conntrack_dump_flush) · 316 unmodified lines | ||
| 336 | 336 | ret = conntrack_data_generate_v4(self->sock, 0xf4f4f4f4, 0xf5f5f5f5, |
| 337 | 337 | TEST_ZONE_ID + 2); |
| 338 | 338 | EXPECT_EQ(ret, 0); |
| 339 | + ret = conntrack_data_generate_v4(self->sock, 0xf6f6f6f6, 0xf7f7f7f7, | |
| 340 | + NF_CT_DEFAULT_ZONE_ID); | |
| 341 | + EXPECT_EQ(ret, 0); | |
| 339 | 342 | |
| 340 | 343 | src = (struct in6_addr) {{ |
| 341 | 344 | .__u6_addr32 = { |
| @@ -395,6 +398,26 @@ FIXTURE_SETUP(conntrack_dump_flush) · 53 unmodified lines | ||
| 395 | 398 | TEST_ZONE_ID + 2); |
| 396 | 399 | EXPECT_EQ(ret, 0); |
| 397 | 400 | |
| 401 | + src = (struct in6_addr) {{ | |
| 402 | + .__u6_addr32 = { | |
| 403 | + 0xb80d0120, | |
| 404 | + 0x00000000, | |
| 405 | + 0x00000000, | |
| 406 | + 0x07000000 | |
| 407 | + } | |
| 408 | + }}; | |
| 409 | + dst = (struct in6_addr) {{ | |
| 410 | + .__u6_addr32 = { | |
| 411 | + 0xb80d0120, | |
| 412 | + 0x00000000, | |
| 413 | + 0x00000000, | |
| 414 | + 0x08000000 | |
| 415 | + } | |
| 416 | + }}; | |
| 417 | + ret = conntrack_data_generate_v6(self->sock, src, dst, | |
| 418 | + NF_CT_DEFAULT_ZONE_ID); | |
| 419 | + EXPECT_EQ(ret, 0); | |
| 420 | + | |
| 398 | 421 | ret = conntracK_count_zone(self->sock, TEST_ZONE_ID); |
| 399 | 422 | EXPECT_GE(ret, 2); |
| 400 | 423 | if (ret > 2) |
| @@ -425,6 +448,24 @@ TEST_F(conntrack_dump_flush, test_flush_by_zone) · 24 unmodified lines | ||
| 425 | 448 | EXPECT_EQ(ret, 2); |
| 426 | 449 | ret = conntracK_count_zone(self->sock, TEST_ZONE_ID + 2); |
| 427 | 450 | EXPECT_EQ(ret, 2); |
| 451 | + ret = conntracK_count_zone(self->sock, NF_CT_DEFAULT_ZONE_ID); | |
| 452 | + EXPECT_EQ(ret, 2); | |
| 453 | +} | |
| 454 | + | |
| 455 | +TEST_F(conntrack_dump_flush, test_flush_by_zone_default) | |
| 456 | +{ | |
| 457 | + int ret; | |
| 458 | + | |
| 459 | + ret = conntrack_flush_zone(self->sock, NF_CT_DEFAULT_ZONE_ID); | |
| 460 | + EXPECT_EQ(ret, 0); | |
| 461 | + ret = conntracK_count_zone(self->sock, TEST_ZONE_ID); | |
| 462 | + EXPECT_EQ(ret, 2); | |
| 463 | + ret = conntracK_count_zone(self->sock, TEST_ZONE_ID + 1); | |
| 464 | + EXPECT_EQ(ret, 2); | |
| 465 | + ret = conntracK_count_zone(self->sock, TEST_ZONE_ID + 2); | |
| 466 | + EXPECT_EQ(ret, 2); | |
| 467 | + ret = conntracK_count_zone(self->sock, NF_CT_DEFAULT_ZONE_ID); | |
| 468 | + EXPECT_EQ(ret, 0); | |
| 428 | 469 | } |
| 429 | 470 | |
| 430 | 471 | TEST_HARNESS_MAIN |