GKI (arm64) relevant 75 out of 419 changes, affecting 91 files +700/-30438a1aa02b9exec: fix up /proc/pid/comm in the execveat(AT_EMPTY_PATH) case [2 files, +29/-4]e5ff8d825dsched: Don't try to catch up excess steal time. [1 file, +4/-2]404e5fd918printk: Fix signed integer overflow when defining LOG_BUF_LEN_MAX [1 file, +1/-1]b006aadf72drm/connector: add mutex to protect ELD from concurrent access [3 files, +11/-1]22a1a75818ring-buffer: Make reading page consistent with the code logic [1 file, +3/-1]5c2b1d9386tun: fix group permission check [1 file, +9/-5]f4b8bac3cfmmc: core: Respect quirk_max_rate for non-UHS SDIO card [1 file, +2/-0]e557b15ea2HID: multitouch: Add quirk for Hantick 5288 touchpad [1 file, +5/-0]adcb8ce68dHID: Wacom: Add PCI Wacom device support [1 file, +5/-0]ebb90f23f0Bluetooth: MGMT: Fix slab-use-after-free Read in mgmt_remove_adv_monitor_sync [1 file, +11/-1]c257c15845tipc: re-order conditions in tipc_crypto_key_rcv() [1 file, +2/-2]90778f31efASoC: soc-pcm: don't use soc_pcm_ret() on .prepare callback [1 file, +28/-4]33a4a9f54aInput: allocate keycode for phone linking [1 file, +1/-0]57e07d10b3sched/fair: Fix inaccurate h_nr_runnable accounting with delayed dequeue [1 file, +19/-0]bc85817e6bnvme: handle connectivity loss in nvme_set_queue_count [1 file, +7/-1]5eba53a9eanvme: make nvme_tls_attrs_group static [1 file, +1/-1]83ebf741aaudp: gso: do not drop small packets when PMTU reduces [3 files, +30/-4]3139a7024eethtool: rss: fix hiding unsupported fields in dumps [1 file, +2/-1]e40cb34b7fpfifo_tail_enqueue: Drop new packet when sch->limit == 0 [1 file, +3/-0]6312555249netem: Update sch->q.qlen before qdisc_tree_reduce_backlog() [1 file, +1/-1]e36364d5d4tun: revert fix group permission check [1 file, +5/-9]181b23ca2enet: sched: Fix truncation of offloaded action statistics [1 file, +1/-1]ac7b5f3e4ddrm/client: Handle tiled displays better [1 file, +9/-0]f735c9d4dcfs/proc: do_task_stat: Fix ESP not readable during coredump [1 file, +1/-1]5a6520493carm64/kvm: Configure HYP TCR.PS/DS based on host stage1 [1 file, +4/-4]c66e5205fdarm64/sme: Move storage of reg_smidr to __cpuinfo_store_cpu() [2 files, +10/-13]e5251ae5d3arm64/mm: Reduce PA space to 48 bits when LPA2 is not enabled [3 files, +11/-7]de3ffeb212KVM: arm64: timer: Always evaluate the need for a soft timer [1 file, +1/-3]f2f805ada6KVM: Explicitly verify target vCPU is online in kvm_get_vcpu() [1 file, +9/-0]691218a50cBluetooth: L2CAP: handle NULL sock pointer in l2cap_sock_alloc [1 file, +2/-1]ddfc234761Bluetooth: L2CAP: accept zero as a special value for MTU auto-selection [1 file, +2/-2]5a262628f4seccomp: passthrough uretprobe systemcall without filtering [1 file, +12/-0]2ce09aabe0blk-cgroup: Fix class @block_class's subsystem refcount leakage [1 file, +1/-0]ae959ab075scsi: ufs: core: Fix the HIGH/LOW_TEMP Bit Definitions [1 file, +2/-2]45ad3c7d62of: Correct child specifier used as input of the 2nd nexus node [1 file, +1/-1]e62c630810of: address: Fix empty resource handling in __of_address_resource_bounds() [1 file, +5/-7]4e4b3d4926of: Fix of_find_node_opts_by_path() handling of alias+path+options [1 file, +3/-3]5b91440ebeof: reserved-memory: Fix using wrong number of cells to get property 'alignment' [1 file, +2/-2]ed0ad04c68ring-buffer: Do not allow events in NMI with generic atomic64 cmpxchg() [1 file, +7/-2]d0b81ea5a5dm-crypt: don't update io->sector after kcryptd_crypt_write_io_submit() [1 file, +3/-11]68a25ceb11dm-crypt: track tag_offset in convert_context [1 file, +7/-6]68f16d3034block: don't revert iter for -EIOCBQUEUED [1 file, +3/-2]0a14a2b841Revert "media: uvcvideo: Require entities to have a non-zero unique ID" [1 file, +27/-43]3d17a4bbf2PCI: endpoint: Finish virtual EP removal in pci_epf_remove_vepf() [1 file, +1/-0]36786d1a45PCI: dwc: ep: Write BAR_MASK before iATU registers in pci_epc_set_bar() [1 file, +15/-13]b5cacfd067PCI: dwc: ep: Prevent changing BAR size/flags in pci_epc_set_bar() [1 file, +21/-1]9fbac83100nvme-pci: Add TUXEDO InfinityFlex to Samsung sleep quirk [1 file, +2/-1]2c4cda456envme-pci: Add TUXEDO IBP Gen9 to Samsung sleep quirk [1 file, +1/-0]0c77c0d754scsi: ufs: core: Fix use-after free in init error and remove paths [4 files, +30/-32]8db25d4c4ascsi: core: Do not retry I/Os during depopulation [1 file, +7/-2]c287f18f64rv: Reset per-task monitors also for idle tasks [1 file, +4/-0]e456a88bddhrtimers: Force migrate away hrtimers queued after CPUHP_AP_HRTIMERS_DYING [2 files, +83/-21]2a54e8f118kfence: skip __GFP_THISNODE allocations on NUMA systems [1 file, +2/-0]b64b773087soc: qcom: smem_state: fix missing of_node_put in error path [1 file, +2/-1]5100391acamedia: mc: fix endpoint iteration [1 file, +1/-1]d2eac8b14amedia: uvcvideo: Fix crash during unbind if gpio unit is in use [2 files, +22/-7]4f534dd576media: uvcvideo: Fix event flags in uvc_ctrl_send_events [1 file, +2/-2]ac7737ed9amedia: uvcvideo: Support partial control reads [1 file, +21/-0]34fb9eb31dmedia: uvcvideo: Only save async fh if success [1 file, +11/-7]e8a650dbc7media: uvcvideo: Remove redundant NULL assignment [1 file, +1/-3]438bda062bmedia: uvcvideo: Remove dangling pointers [3 files, +67/-3]a403eca86cmm: gup: fix infinite loop within __get_longterm_locked [1 file, +4/-10]4b69308314mm/vmscan: accumulate nr_demoted for accurate demotion statistics [1 file, +4/-3]4491159774mm/compaction: fix UBSAN shift-out-of-bounds warning [1 file, +2/-1]2c3109dcdanvmem: core: improve range check for nvmem_cell_write() [1 file, +2/-0]35ae7910c3io_uring: fix multishots with selected buffers [1 file, +2/-0]be985aea92io_uring/net: don't retry connect operation on EPOLLERR [2 files, +7/-0]e398619920i3c: master: Fix missing 'ret' assignment in set_speed() [1 file, +1/-1]8b4120b3e0misc: misc_minor_alloc to use ida for all dynamic/misc dynamic minors [1 file, +30/-9]19fc795e9dmaple_tree: simplify split calculation [1 file, +6/-17]8441aea464ptp: Ensure info->enable callback is always set [1 file, +8/-0]c6dd70e5b4timers/migration: Fix off-by-one root mis-connection [1 file, +9/-1]45439a8b11fs: prepend statmount.mnt_opts string with security_sb_mnt_opts() [1 file, +4/-0]7db0365ee6fs: fix adding security options to statmount.mnt_opt [1 file, +14/-15]d49c64c1d7statmount: let unset strings be empty [1 file, +12/-4] Changes in 6.12.14 irqchip/lan966x-oic: Make CONFIG_LAN966X_OIC depend on CONFIG_MCHP_LAN966X_PCI btrfs: fix assertion failure when splitting ordered extent after transaction abort btrfs: do not output error message if a qgroup has been already cleaned up btrfs: fix use-after-free when attempting to join an aborted transaction arm64/mm: Ensure adequate HUGE_MAX_HSTATE exec: fix up /proc/pid/comm in the execveat(AT_EMPTY_PATH) case s390/stackleak: Use exrl instead of ex in __stackleak_poison() btrfs: fix data race when accessing the inode's disk_i_size at btrfs_drop_extents() btrfs: convert BUG_ON in btrfs_reloc_cow_block() to proper error handling sched: Don't try to catch up excess steal time. x86: Convert unreachable() to BUG() locking/ww_mutex/test: Use swap() macro lockdep: Fix upper limit for LOCKDEP_*_BITS configs x86/amd_nb: Restrict init function to AMD-based systems drm/virtio: New fence for every plane update drm: Add panel backlight quirks drm: panel-backlight-quirks: Add Framework 13 matte panel drm: panel-backlight-quirks: Add Framework 13 glossy and 2.8k panels nvkm/gsp: correctly advance the read pointer of GSP message queue nvkm: correctly calculate the available space of the GSP cmdq buffer drm/tests: hdmi: handle empty modes in find_preferred_mode() drm/tests: hdmi: return meaningful value from set_connector_edid() drm/amd/display: Populate chroma prefetch parameters, DET buffer fix drm/amd/display: Overwriting dualDPP UBF values before usage printk: Fix signed integer overflow when defining LOG_BUF_LEN_MAX drm/connector: add mutex to protect ELD from concurrent access drm/bridge: anx7625: use eld_mutex to protect access to connector->eld drm/bridge: ite-it66121: use eld_mutex to protect access to connector->eld drm/amd/display: use eld_mutex to protect access to connector->eld drm/exynos: hdmi: use eld_mutex to protect access to connector->eld drm/radeon: use eld_mutex to protect access to connector->eld drm/sti: hdmi: use eld_mutex to protect access to connector->eld drm/vc4: hdmi: use eld_mutex to protect access to connector->eld drm/amd/display: Fix Mode Cutoff in DSC Passthrough to DP2.1 Monitor drm/amdgpu: Don't enable sdma 4.4.5 CTXEMPTY interrupt drm/amdkfd: Queue interrupt work to different CPU drm/bridge: it6505: Change definition MAX_HDCP_DOWN_STREAM_COUNT drm/bridge: it6505: fix HDCP Bstatus check drm/bridge: it6505: fix HDCP encryption when R0 ready drm/bridge: it6505: fix HDCP CTS compare V matching drm/bridge: it6505: fix HDCP CTS KSV list wait timer safesetid: check size of policy writes drm/amd/display: Increase sanitizer frame larger than limit when compile testing with clang drm/amd/display: Limit Scaling Ratio on DCN3.01 ring-buffer: Make reading page consistent with the code logic wifi: rtw89: add crystal_cap check to avoid setting as overflow value tun: fix group permission check mmc: core: Respect quirk_max_rate for non-UHS SDIO card mmc: sdhci-esdhc-imx: enable 'SDHCI_QUIRK_NO_LED' quirk for S32G wifi: brcmsmac: add gain range check to wlc_phy_iqcal_gainparams_nphy() tomoyo: don't emit warning in tomoyo_write_control() mfd: lpc_ich: Add another Gemini Lake ISA bridge PCI device-id wifi: rtw88: add __packed attribute to efuse layout struct clk: qcom: Make GCC_8150 depend on QCOM_GDSC HID: multitouch: Add quirk for Hantick 5288 touchpad HID: Wacom: Add PCI Wacom device support net/mlx5: use do_aux_work for PHC overflow checks wifi: brcmfmac: Check the return value of of_property_read_string_index() wifi: iwlwifi: pcie: Add support for new device ids wifi: iwlwifi: avoid memory leak i2c: Force ELAN06FA touchpad I2C bus freq to 100KHz APEI: GHES: Have GHES honor the panic= setting Bluetooth: btusb: Add new VID/PID 13d3/3610 for MT7922 Bluetooth: btusb: Add new VID/PID 13d3/3628 for MT7925 Bluetooth: MGMT: Fix slab-use-after-free Read in mgmt_remove_adv_monitor_sync net: wwan: iosm: Fix hibernation by re-binding the driver around it HID: hid-asus: Disable OOBE mode on the ProArt P16 mmc: sdhci-msm: Correctly set the load for the regulator octeon_ep: update tx/rx stats locally for persistence octeon_ep_vf: update tx/rx stats locally for persistence tipc: re-order conditions in tipc_crypto_key_rcv() selftests/net/ipsec: Fix Null pointer dereference in rtattr_pack() net: ethernet: ti: am65-cpsw: ensure proper channel cleanup in error path ASoC: SOF: Intel: hda-dai: Ensure DAI widget is valid during params x86/kexec: Allocate PGD for x86_64 transition page tables separately ASoC: Intel: sof_sdw: Correct quirk for Lenovo Yoga Slim 7 iommu/arm-smmu-qcom: add sdm670 adreno iommu compatible iommu/arm-smmu-v3: Clean up more on probe failure platform/x86: int3472: Check for adev == NULL platform/x86: acer-wmi: Add support for Acer PH14-51 ASoC: soc-pcm: don't use soc_pcm_ret() on .prepare callback platform/x86: acer-wmi: Add support for Acer Predator PH16-72 ASoC: amd: Add ACPI dependency to fix build error Input: allocate keycode for phone linking platform/x86: acer-wmi: add support for Acer Nitro AN515-58 platform/x86: acer-wmi: Ignore AC events KVM: PPC: e500: Mark "struct page" dirty in kvmppc_e500_shadow_map() KVM: PPC: e500: Mark "struct page" pfn accessed before dropping mmu_lock KVM: PPC: e500: Use __kvm_faultin_pfn() to handle page faults KVM: e500: always restore irqs drm/amdgpu: Fix Circular Locking Dependency in AMDGPU GFX Isolation xfs: report realtime block quota limits on realtime directories xfs: don't over-report free space or inodes in statvfs tty: xilinx_uartps: split sysrq handling tty: Permit some TIOCL_SETSEL modes without CAP_SYS_ADMIN platform/x86: serdev_helpers: Check for serial_ctrl_uid == NULL sched/fair: Fix inaccurate h_nr_runnable accounting with delayed dequeue nvme: handle connectivity loss in nvme_set_queue_count firmware: iscsi_ibft: fix ISCSI_IBFT Kconfig entry gpu: drm_dp_cec: fix broken CEC adapter properties check ice: put Rx buffers after being done with current frame ice: gather page_count()'s of each frag right before XDP prog call ice: stop storing XDP verdict within ice_rx_buf nvme: make nvme_tls_attrs_group static nvme-fc: use ctrl state getter net: bcmgenet: Correct overlaying of PHY and MAC Wake-on-LAN ice: Add check for devm_kzalloc() vmxnet3: Fix tx queue race condition with XDP tg3: Disable tg3 PCIe AER on system reboot udp: gso: do not drop small packets when PMTU reduces drm/i915/dp: fix the Adaptive sync Operation mode for SDP ethtool: rss: fix hiding unsupported fields in dumps rxrpc: Fix the rxrpc_connection attend queue handling gpio: pca953x: Improve interrupt support net: atlantic: fix warning during hot unplug net: rose: lock the socket in rose_bind() gpio: sim: lock hog configfs items if present x86/xen: fix xen_hypercall_hvm() to not clobber %rbx x86/xen: add FRAME_END to xen_hypercall_hvm() ACPI: property: Fix return value for nval == 0 in acpi_data_prop_read() pfifo_tail_enqueue: Drop new packet when sch->limit == 0 netem: Update sch->q.qlen before qdisc_tree_reduce_backlog() tun: revert fix group permission check net: sched: Fix truncation of offloaded action statistics rxrpc: Fix call state set to not include the SERVER_SECURING state cpufreq: fix using cpufreq-dt as module cpufreq: s3c64xx: Fix compilation warning leds: lp8860: Write full EEPROM, not only half of it ALSA: hda/realtek: Enable Mute LED on HP Laptop 14s-fq1xxx cifs: Remove intermediate object of failed create SFU call drm/modeset: Handle tiled displays in pan_display_atomic. drm/client: Handle tiled displays better smb: client: fix order of arguments of tracepoints smb: client: change lease epoch type from unsigned int to __u16 md: reintroduce md-linear s390/futex: Fix FUTEX_OP_ANDN implementation arm64: Filter out SVE hwcaps when FEAT_SVE isn't implemented m68k: vga: Fix I/O defines fs/proc: do_task_stat: Fix ESP not readable during coredump binfmt_flat: Fix integer overflow bug on 32 bit systems accel/ivpu: Fix Qemu crash when running in passthrough arm64/kvm: Configure HYP TCR.PS/DS based on host stage1 arm64/mm: Override PARange for !LPA2 and use it consistently arm64/sme: Move storage of reg_smidr to __cpuinfo_store_cpu() arm64/mm: Reduce PA space to 48 bits when LPA2 is not enabled KVM: arm64: timer: Always evaluate the need for a soft timer drm/rockchip: cdn-dp: Use drm_connector_helper_hpd_irq_event() arm64: dts: rockchip: increase gmac rx_delay on rk3399-puma remoteproc: omap: Handle ARM dma_iommu_mapping KVM: Explicitly verify target vCPU is online in kvm_get_vcpu() kvm: defer huge page recovery vhost task to later KVM: s390: vsie: fix some corner-cases when grabbing vsie pages ksmbd: fix integer overflows on 32 bit systems drm/amd/display: Optimize cursor position updates drm/amd/pm: Mark MM activity as unsupported drm/amd/amdgpu: change the config of cgcg on gfx12 drm/amdkfd: only flush the validate MES contex drm/amdkfd: Block per-queue reset when halt_if_hws_hang=1 Revert "drm/amd/display: Use HW lock mgr for PSR1" drm/i915/guc: Debug print LRC state entries only if the context is pinned drm/i915: Fix page cleanup on DMA remap failure drm/komeda: Add check for komeda_get_layer_fourcc_list() drm/xe/devcoredump: Move exec queue snapshot to Contexts section drm/i915/dp: Iterate DSC BPP from high to low on all platforms drm/i915: Drop 64bpp YUV formats from ICL+ SDR planes drm/amdgpu: add a BO metadata flag to disable write compression for Vulkan drm/amd/display: Fix seamless boot sequence Bluetooth: L2CAP: handle NULL sock pointer in l2cap_sock_alloc Bluetooth: L2CAP: accept zero as a special value for MTU auto-selection KEYS: trusted: dcp: fix improper sg use with CONFIG_VMAP_STACK=y clk: sunxi-ng: a100: enable MMC clock reparenting clk: mmp2: call pm_genpd_init() only after genpd.name is set media: i2c: ds90ub960: Fix UB9702 refclk register access clk: clk-loongson2: Fix the number count of clk provider clk: qcom: clk-alpha-pll: fix alpha mode configuration clk: qcom: gcc-sm8550: Do not turn off PCIe GDSCs during gdsc_disable() clk: qcom: gcc-sm8650: Do not turn off PCIe GDSCs during gdsc_disable() clk: qcom: gcc-sm6350: Add missing parent_map for two clocks clk: qcom: dispcc-sm6350: Add missing parent_map for a clock clk: qcom: gcc-mdm9607: Fix cmd_rcgr offset for blsp1_uart6 rcg clk: qcom: clk-rpmh: prevent integer overflow in recalc_rate clk: mediatek: mt2701-vdec: fix conversion to mtk_clk_simple_probe clk: mediatek: mt2701-aud: fix conversion to mtk_clk_simple_probe clk: mediatek: mt2701-bdp: add missing dummy clk clk: mediatek: mt2701-img: add missing dummy clk clk: mediatek: mt2701-mm: add missing dummy clk seccomp: passthrough uretprobe systemcall without filtering blk-cgroup: Fix class @block_class's subsystem refcount leakage efi: libstub: Use '-std=gnu11' to fix build with GCC 15 perf bench: Fix undefined behavior in cmpworker() scsi: ufs: core: Fix the HIGH/LOW_TEMP Bit Definitions of: Correct child specifier used as input of the 2nd nexus node of: address: Fix empty resource handling in __of_address_resource_bounds() of: Fix of_find_node_opts_by_path() handling of alias+path+options of: reserved-memory: Fix using wrong number of cells to get property 'alignment' Input: bbnsm_pwrkey - add remove hook HID: hid-sensor-hub: don't use stale platform-data on remove ring-buffer: Do not allow events in NMI with generic atomic64 cmpxchg() atomic64: Use arch_spin_locks instead of raw_spin_locks wifi: rtlwifi: rtl8821ae: Fix media status report wifi: brcmfmac: fix NULL pointer dereference in brcmf_txfinalize() wifi: mt76: mt7921u: Add VID/PID for TP-Link TXE50UH wifi: rtw88: sdio: Fix disconnection after beacon loss wifi: mt76: mt7915: add module param to select 5 GHz or 6 GHz on MT7916 wifi: rtw88: 8703b: Fix RX/TX issues usb: gadget: f_tcm: Translate error to sense usb: gadget: f_tcm: Decrement command ref count on cleanup usb: gadget: f_tcm: ep_autoconfig with fullspeed endpoint usb: gadget: f_tcm: Don't prepare BOT write request twice usbnet: ipheth: fix possible overflow in DPE length check usbnet: ipheth: use static NDP16 location in URB usbnet: ipheth: check that DPE points past NCM header usbnet: ipheth: refactor NCM datagram loop usbnet: ipheth: break up NCM header size computation usbnet: ipheth: fix DPE OoB read usbnet: ipheth: document scope of NCM implementation arm64: dts: qcom: x1e80100-asus-vivobook-s15: Fix USB QMP PHY supplies arm64: dts: qcom: x1e80100-qcp: Fix USB QMP PHY supplies arm64: dts: qcom: x1e78100-lenovo-thinkpad-t14s: Fix USB QMP PHY supplies arm64: dts: qcom: x1e80100-crd: Fix USB QMP PHY supplies arm64: dts: qcom: x1e80100-lenovo-yoga-slim7x: Fix USB QMP PHY supplies arm64: dts: qcom: x1e80100-microsoft-romulus: Fix USB QMP PHY supplies arm64: dts: qcom: x1e80100: Fix usb_2 controller interrupts ASoC: acp: Support microphone from Lenovo Go S soc: qcom: socinfo: Avoid out of bounds read of serial number serial: sh-sci: Drop __initdata macro for port_cfg serial: sh-sci: Do not probe the serial port if its slot in sci_ports[] is in use MIPS: Loongson64: remove ROM Size unit in boardinfo LoongArch: Extend the maximum number of watchpoints powerpc/pseries/eeh: Fix get PE state translation dm-crypt: don't update io->sector after kcryptd_crypt_write_io_submit() dm-crypt: track tag_offset in convert_context mips/math-emu: fix emulation of the prefx instruction MIPS: pci-legacy: Override pci_address_to_pio Revert "MIPS: csrc-r4k: Select HAVE_UNSTABLE_SCHED_CLOCK if SMP && 64BIT" block: don't revert iter for -EIOCBQUEUED Revert "media: uvcvideo: Require entities to have a non-zero unique ID" firmware: qcom: scm: Fix missing read barrier in qcom_scm_is_available() firmware: qcom: scm: Fix missing read barrier in qcom_scm_get_tzmem_pool() ALSA: hda/realtek: Enable headset mic on Positivo C6400 ALSA: hda/realtek: Fix quirk matching for Legion Pro 7 ALSA: hda: Fix headset detection failure due to unstable sort arm64: tegra: Fix Tegra234 PCIe interrupt-map s390/pci: Fix SR-IOV for PFs initially in standby PCI: Avoid putting some root ports into D3 on TUXEDO Sirius Gen1 PCI: endpoint: Finish virtual EP removal in pci_epf_remove_vepf() PCI: dwc: ep: Write BAR_MASK before iATU registers in pci_epc_set_bar() PCI: dwc: ep: Prevent changing BAR size/flags in pci_epc_set_bar() nvme-pci: Add TUXEDO InfinityFlex to Samsung sleep quirk nvme-pci: Add TUXEDO IBP Gen9 to Samsung sleep quirk KVM: x86/mmu: Ensure NX huge page recovery thread is alive before waking scsi: st: Don't set pos_unknown just after device recognition scsi: qla2xxx: Move FCE Trace buffer allocation to user control scsi: ufs: qcom: Fix crypto key eviction scsi: ufs: core: Fix use-after free in init error and remove paths scsi: storvsc: Set correct data length for sending SCSI command without payload scsi: core: Do not retry I/Os during depopulation kbuild: Move -Wenum-enum-conversion to W=2 rust: init: use explicit ABI to clean warning in future compilers x86: rust: set rustc-abi=x86-softfloat on rustc>=1.86.0 x86/acpi: Fix LAPIC/x2APIC parsing order x86/boot: Use '-std=gnu11' to fix build with GCC 15 ubi: Add a check for ubi_num ARM: dts: dra7: Add bus_dma_limit for l4 cfg bus ARM: dts: ti/omap: gta04: fix pm issues caused by spi module arm64: dts: mediatek: mt8183: Disable DPI display output by default arm64: dts: qcom: sdx75: Fix MPSS memory length arm64: dts: qcom: x1e80100: Fix ADSP memory base and length arm64: dts: qcom: x1e80100: Fix CDSP memory length arm64: dts: qcom: sm6115: Fix MPSS memory length arm64: dts: qcom: sm6115: Fix CDSP memory length arm64: dts: qcom: sm6115: Fix ADSP memory base and length arm64: dts: qcom: sm6350: Fix ADSP memory length arm64: dts: qcom: sm6350: Fix MPSS memory length arm64: dts: qcom: sm6350: Fix uart1 interconnect path arm64: dts: qcom: sm6375: Fix ADSP memory length arm64: dts: qcom: sm6375: Fix CDSP memory base and length arm64: dts: qcom: sm6375: Fix MPSS memory base and length arm64: dts: qcom: sm8350: Fix ADSP memory base and length arm64: dts: qcom: sm8350: Fix CDSP memory base and length arm64: dts: qcom: sm8350: Fix MPSS memory length arm64: dts: qcom: sm8450: Fix ADSP memory base and length arm64: dts: qcom: sm8450: Fix CDSP memory length arm64: dts: qcom: sm8450: Fix MPSS memory length arm64: dts: qcom: sm8550: Fix ADSP memory base and length arm64: dts: qcom: sm8550: Fix CDSP memory length arm64: dts: qcom: sm8550: Fix MPSS memory length arm64: dts: qcom: sm8650: Fix ADSP memory base and length arm64: dts: qcom: sm8650: Fix CDSP memory length arm64: dts: qcom: sm8650: Fix MPSS memory length arm64: dts: qcom: sm8550: correct MDSS interconnects arm64: dts: qcom: sm8650: correct MDSS interconnects crypto: qce - fix priority to be less than ARMv8 CE arm64: tegra: Fix typo in Tegra234 dce-fabric compatible arm64: tegra: Disable Tegra234 sce-fabric node parisc: Temporarily disable jump label support pwm: microchip-core: fix incorrect comparison with max period xfs: don't call remap_verify_area with sb write protection held xfs: Propagate errors from xfs_reflink_cancel_cow_range in xfs_dax_write_iomap_end xfs: Add error handling for xfs_reflink_cancel_cow_range accel/ivpu: Clear runtime_error after pm_runtime_resume_and_get() fails ACPI: PRM: Remove unnecessary strict handler address checks tpm: Change to kvalloc() in eventlog/acpi.c rv: Reset per-task monitors also for idle tasks hrtimers: Force migrate away hrtimers queued after CPUHP_AP_HRTIMERS_DYING iommufd: Fix struct iommu_hwpt_pgfault init and padding kfence: skip __GFP_THISNODE allocations on NUMA systems media: ccs: Clean up parsed CCS static data on parse failure mm/hugetlb: fix avoid_reserve to allow taking folio from subpool iio: light: as73211: fix channel handling in only-color triggered buffer iommu/tegra241-cmdqv: Read SMMU IDR1.CMDQS instead of hardcoding iommufd/fault: Destroy response and mutex in iommufd_fault_destroy() iommufd/fault: Use a separate spinlock to protect fault->deliver list soc: samsung: exynos-pmu: Fix uninitialized ret in tensor_set_bits_atomic() soc: mediatek: mtk-devapc: Fix leaking IO map on error paths soc: mediatek: mtk-devapc: Fix leaking IO map on driver remove soc: qcom: llcc: Enable LLCC_WRCACHE at boot on X1 soc: qcom: smem_state: fix missing of_node_put in error path media: mmp: Bring back registration of the device media: mc: fix endpoint iteration media: nuvoton: Fix an error check in npcm_video_ece_init() media: imx296: Add standby delay during probe media: intel/ipu6: remove cpu latency qos request on error media: ov5640: fix get_light_freq on auto media: stm32: dcmipp: correct dma_set_mask_and_coherent mask value media: ccs: Fix CCS static data parsing for large block sizes media: ccs: Fix cleanup order in ccs_probe() media: i2c: ds90ub9x3: Fix extra fwnode_handle_put() media: i2c: ds90ub960: Fix use of non-existing registers on UB9702 media: i2c: ds90ub960: Fix UB9702 VC map media: i2c: ds90ub960: Fix logging SP & EQ status only for UB9702 media: uvcvideo: Fix crash during unbind if gpio unit is in use media: uvcvideo: Fix event flags in uvc_ctrl_send_events media: uvcvideo: Support partial control reads media: uvcvideo: Only save async fh if success media: uvcvideo: Remove redundant NULL assignment media: uvcvideo: Remove dangling pointers mm: kmemleak: fix upper boundary check for physical address objects mm: gup: fix infinite loop within __get_longterm_locked mm/vmscan: accumulate nr_demoted for accurate demotion statistics mm/hugetlb: fix hugepage allocation for interleaved memory nodes mm/compaction: fix UBSAN shift-out-of-bounds warning ata: libata-sff: Ensure that we cannot write outside the allocated buffer irqchip/irq-mvebu-icu: Fix access to msi_data from irq_domain::host_data crypto: qce - fix goto jump in error path crypto: qce - unregister previously registered algos in error path ceph: fix memory leak in ceph_mds_auth_match() nvmem: qcom-spmi-sdam: Set size in struct nvmem_config nvmem: core: improve range check for nvmem_cell_write() nvmem: imx-ocotp-ele: simplify read beyond device check nvmem: imx-ocotp-ele: fix MAC address byte order nvmem: imx-ocotp-ele: fix reading from non zero offset nvmem: imx-ocotp-ele: set word length to 1 io_uring: fix multishots with selected buffers io_uring/net: don't retry connect operation on EPOLLERR vfio/platform: check the bounds of read/write syscalls selftests: mptcp: connect: -f: no reconnect pnfs/flexfiles: retry getting layout segment for reads ocfs2: fix incorrect CPU endianness conversion causing mount failure ocfs2: handle a symlink read error correctly nilfs2: fix possible int overflows in nilfs_fiemap() nfs: Make NFS_FSCACHE select NETFS_SUPPORT instead of depending on it NFSD: Encode COMPOUND operation status on page boundaries mailbox: tegra-hsp: Clear mailbox before using message mailbox: zynqmp: Remove invalid __percpu annotation in zynqmp_ipi_probe() NFC: nci: Add bounds checking in nci_hci_create_pipe() fgraph: Fix set_graph_notrace with setting TRACE_GRAPH_NOTRACE_BIT i3c: master: Fix missing 'ret' assignment in set_speed() irqchip/apple-aic: Only handle PMC interrupt as FIQ when configured so mtd: onenand: Fix uninitialized retlen in do_otp_read() misc: misc_minor_alloc to use ida for all dynamic/misc dynamic minors misc: fastrpc: Deregister device nodes properly in error scenarios misc: fastrpc: Fix registered buffer page address misc: fastrpc: Fix copy buffer page size net/ncsi: wait for the last response to Deselect Package before configuring channel net: phy: c45-tjaxx: add delay between MDIO write and read in soft_reset maple_tree: simplify split calculation scripts/gdb: fix aarch64 userspace detection in get_current_task tracing/osnoise: Fix resetting of tracepoints rtla/osnoise: Distinguish missing workload option rtla/timerlat_hist: Set OSNOISE_WORKLOAD for kernel threads rtla/timerlat_top: Set OSNOISE_WORKLOAD for kernel threads rtla: Add trace_instance_stop rtla/timerlat_hist: Stop timerlat tracer on signal rtla/timerlat_top: Stop timerlat tracer on signal pinctrl: samsung: fix fwnode refcount cleanup if platform_get_irq_optional() fails pinctrl: renesas: rzg2l: Fix PFC_MASK for RZ/V2H and RZ/G3E ptp: Ensure info->enable callback is always set RDMA/mlx5: Fix a race for an ODP MR which leads to CQE with error rtc: zynqmp: Fix optional clock name property timers/migration: Fix off-by-one root mis-connection s390/fpu: Add fpc exception handler / remove fixup section again MIPS: ftrace: Declare ftrace_get_parent_ra_addr() as static xfs: avoid nested calls to __xfs_trans_commit xfs: don't lose solo superblock counter update transactions xfs: separate dquot buffer reads from xfs_dqflush xfs: clean up log item accesses in xfs_qm_dqflush{,_done} xfs: attach dquot buffer to dquot log item buffer xfs: convert quotacheck to attach dquot buffers xfs: release the dquot buf outside of qli_lock xfs: lock dquot buffer before detaching dquot from b_li_list xfs: fix mount hang during primary superblock recovery failure spi: atmel-quadspi: Create `atmel_qspi_ops` to support newer SoC families spi: atmel-qspi: Memory barriers after memory-mapped I/O Revert "btrfs: avoid monopolizing a core when activating a swap file" btrfs: avoid monopolizing a core when activating a swap file mptcp: prevent excessive coalescing on receive x86/mm: Convert unreachable() to BUG() md/md-linear: Fix a NULL vs IS_ERR() bug in linear_add() md: Fix linear_set_limits() Revert "selftests/sched_ext: fix build after renames in sched_ext API" Revert "drm/amd/display: Fix green screen issue after suspend" drm/xe: Fix and re-enable xe_print_blob_ascii85() fs: prepend statmount.mnt_opts string with security_sb_mnt_opts() fs: fix adding security options to statmount.mnt_opt statmount: let unset strings be empty arm64: dts: rockchip: add reset-names for combphy on rk3568 ocfs2: check dir i_size in ocfs2_find_entry Linux 6.12.14 Change-Id: Id4141bfc8ee9a6320b056561aa528228e7a3f1df Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
754 lines
15 KiB
C
754 lines
15 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Module-based API test facility for ww_mutexes
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/completion.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/kthread.h>
|
|
#include <linux/module.h>
|
|
#include <linux/prandom.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/ww_mutex.h>
|
|
|
|
static DEFINE_WD_CLASS(ww_class);
|
|
struct workqueue_struct *wq;
|
|
|
|
#ifdef CONFIG_DEBUG_WW_MUTEX_SLOWPATH
|
|
#define ww_acquire_init_noinject(a, b) do { \
|
|
ww_acquire_init((a), (b)); \
|
|
(a)->deadlock_inject_countdown = ~0U; \
|
|
} while (0)
|
|
#else
|
|
#define ww_acquire_init_noinject(a, b) ww_acquire_init((a), (b))
|
|
#endif
|
|
|
|
struct test_mutex {
|
|
struct work_struct work;
|
|
struct ww_mutex mutex;
|
|
struct completion ready, go, done;
|
|
unsigned int flags;
|
|
};
|
|
|
|
#define TEST_MTX_SPIN BIT(0)
|
|
#define TEST_MTX_TRY BIT(1)
|
|
#define TEST_MTX_CTX BIT(2)
|
|
#define __TEST_MTX_LAST BIT(3)
|
|
|
|
static void test_mutex_work(struct work_struct *work)
|
|
{
|
|
struct test_mutex *mtx = container_of(work, typeof(*mtx), work);
|
|
|
|
complete(&mtx->ready);
|
|
wait_for_completion(&mtx->go);
|
|
|
|
if (mtx->flags & TEST_MTX_TRY) {
|
|
while (!ww_mutex_trylock(&mtx->mutex, NULL))
|
|
cond_resched();
|
|
} else {
|
|
ww_mutex_lock(&mtx->mutex, NULL);
|
|
}
|
|
complete(&mtx->done);
|
|
ww_mutex_unlock(&mtx->mutex);
|
|
}
|
|
|
|
static int __test_mutex(unsigned int flags)
|
|
{
|
|
#define TIMEOUT (HZ / 16)
|
|
struct test_mutex mtx;
|
|
struct ww_acquire_ctx ctx;
|
|
int ret;
|
|
|
|
ww_mutex_init(&mtx.mutex, &ww_class);
|
|
ww_acquire_init(&ctx, &ww_class);
|
|
|
|
INIT_WORK_ONSTACK(&mtx.work, test_mutex_work);
|
|
init_completion(&mtx.ready);
|
|
init_completion(&mtx.go);
|
|
init_completion(&mtx.done);
|
|
mtx.flags = flags;
|
|
|
|
schedule_work(&mtx.work);
|
|
|
|
wait_for_completion(&mtx.ready);
|
|
ww_mutex_lock(&mtx.mutex, (flags & TEST_MTX_CTX) ? &ctx : NULL);
|
|
complete(&mtx.go);
|
|
if (flags & TEST_MTX_SPIN) {
|
|
unsigned long timeout = jiffies + TIMEOUT;
|
|
|
|
ret = 0;
|
|
do {
|
|
if (completion_done(&mtx.done)) {
|
|
ret = -EINVAL;
|
|
break;
|
|
}
|
|
cond_resched();
|
|
} while (time_before(jiffies, timeout));
|
|
} else {
|
|
ret = wait_for_completion_timeout(&mtx.done, TIMEOUT);
|
|
}
|
|
ww_mutex_unlock(&mtx.mutex);
|
|
ww_acquire_fini(&ctx);
|
|
|
|
if (ret) {
|
|
pr_err("%s(flags=%x): mutual exclusion failure\n",
|
|
__func__, flags);
|
|
ret = -EINVAL;
|
|
}
|
|
|
|
flush_work(&mtx.work);
|
|
destroy_work_on_stack(&mtx.work);
|
|
return ret;
|
|
#undef TIMEOUT
|
|
}
|
|
|
|
static int test_mutex(void)
|
|
{
|
|
int ret;
|
|
int i;
|
|
|
|
for (i = 0; i < __TEST_MTX_LAST; i++) {
|
|
ret = __test_mutex(i);
|
|
if (ret)
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int test_aa(bool trylock)
|
|
{
|
|
struct ww_mutex mutex;
|
|
struct ww_acquire_ctx ctx;
|
|
int ret;
|
|
const char *from = trylock ? "trylock" : "lock";
|
|
|
|
ww_mutex_init(&mutex, &ww_class);
|
|
ww_acquire_init(&ctx, &ww_class);
|
|
|
|
if (!trylock) {
|
|
ret = ww_mutex_lock(&mutex, &ctx);
|
|
if (ret) {
|
|
pr_err("%s: initial lock failed!\n", __func__);
|
|
goto out;
|
|
}
|
|
} else {
|
|
ret = !ww_mutex_trylock(&mutex, &ctx);
|
|
if (ret) {
|
|
pr_err("%s: initial trylock failed!\n", __func__);
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
if (ww_mutex_trylock(&mutex, NULL)) {
|
|
pr_err("%s: trylocked itself without context from %s!\n", __func__, from);
|
|
ww_mutex_unlock(&mutex);
|
|
ret = -EINVAL;
|
|
goto out;
|
|
}
|
|
|
|
if (ww_mutex_trylock(&mutex, &ctx)) {
|
|
pr_err("%s: trylocked itself with context from %s!\n", __func__, from);
|
|
ww_mutex_unlock(&mutex);
|
|
ret = -EINVAL;
|
|
goto out;
|
|
}
|
|
|
|
ret = ww_mutex_lock(&mutex, &ctx);
|
|
if (ret != -EALREADY) {
|
|
pr_err("%s: missed deadlock for recursing, ret=%d from %s\n",
|
|
__func__, ret, from);
|
|
if (!ret)
|
|
ww_mutex_unlock(&mutex);
|
|
ret = -EINVAL;
|
|
goto out;
|
|
}
|
|
|
|
ww_mutex_unlock(&mutex);
|
|
ret = 0;
|
|
out:
|
|
ww_acquire_fini(&ctx);
|
|
return ret;
|
|
}
|
|
|
|
struct test_abba {
|
|
struct work_struct work;
|
|
struct ww_mutex a_mutex;
|
|
struct ww_mutex b_mutex;
|
|
struct completion a_ready;
|
|
struct completion b_ready;
|
|
bool resolve, trylock;
|
|
int result;
|
|
};
|
|
|
|
static void test_abba_work(struct work_struct *work)
|
|
{
|
|
struct test_abba *abba = container_of(work, typeof(*abba), work);
|
|
struct ww_acquire_ctx ctx;
|
|
int err;
|
|
|
|
ww_acquire_init_noinject(&ctx, &ww_class);
|
|
if (!abba->trylock)
|
|
ww_mutex_lock(&abba->b_mutex, &ctx);
|
|
else
|
|
WARN_ON(!ww_mutex_trylock(&abba->b_mutex, &ctx));
|
|
|
|
WARN_ON(READ_ONCE(abba->b_mutex.ctx) != &ctx);
|
|
|
|
complete(&abba->b_ready);
|
|
wait_for_completion(&abba->a_ready);
|
|
|
|
err = ww_mutex_lock(&abba->a_mutex, &ctx);
|
|
if (abba->resolve && err == -EDEADLK) {
|
|
ww_mutex_unlock(&abba->b_mutex);
|
|
ww_mutex_lock_slow(&abba->a_mutex, &ctx);
|
|
err = ww_mutex_lock(&abba->b_mutex, &ctx);
|
|
}
|
|
|
|
if (!err)
|
|
ww_mutex_unlock(&abba->a_mutex);
|
|
ww_mutex_unlock(&abba->b_mutex);
|
|
ww_acquire_fini(&ctx);
|
|
|
|
abba->result = err;
|
|
}
|
|
|
|
static int test_abba(bool trylock, bool resolve)
|
|
{
|
|
struct test_abba abba;
|
|
struct ww_acquire_ctx ctx;
|
|
int err, ret;
|
|
|
|
ww_mutex_init(&abba.a_mutex, &ww_class);
|
|
ww_mutex_init(&abba.b_mutex, &ww_class);
|
|
INIT_WORK_ONSTACK(&abba.work, test_abba_work);
|
|
init_completion(&abba.a_ready);
|
|
init_completion(&abba.b_ready);
|
|
abba.trylock = trylock;
|
|
abba.resolve = resolve;
|
|
|
|
schedule_work(&abba.work);
|
|
|
|
ww_acquire_init_noinject(&ctx, &ww_class);
|
|
if (!trylock)
|
|
ww_mutex_lock(&abba.a_mutex, &ctx);
|
|
else
|
|
WARN_ON(!ww_mutex_trylock(&abba.a_mutex, &ctx));
|
|
|
|
WARN_ON(READ_ONCE(abba.a_mutex.ctx) != &ctx);
|
|
|
|
complete(&abba.a_ready);
|
|
wait_for_completion(&abba.b_ready);
|
|
|
|
err = ww_mutex_lock(&abba.b_mutex, &ctx);
|
|
if (resolve && err == -EDEADLK) {
|
|
ww_mutex_unlock(&abba.a_mutex);
|
|
ww_mutex_lock_slow(&abba.b_mutex, &ctx);
|
|
err = ww_mutex_lock(&abba.a_mutex, &ctx);
|
|
}
|
|
|
|
if (!err)
|
|
ww_mutex_unlock(&abba.b_mutex);
|
|
ww_mutex_unlock(&abba.a_mutex);
|
|
ww_acquire_fini(&ctx);
|
|
|
|
flush_work(&abba.work);
|
|
destroy_work_on_stack(&abba.work);
|
|
|
|
ret = 0;
|
|
if (resolve) {
|
|
if (err || abba.result) {
|
|
pr_err("%s: failed to resolve ABBA deadlock, A err=%d, B err=%d\n",
|
|
__func__, err, abba.result);
|
|
ret = -EINVAL;
|
|
}
|
|
} else {
|
|
if (err != -EDEADLK && abba.result != -EDEADLK) {
|
|
pr_err("%s: missed ABBA deadlock, A err=%d, B err=%d\n",
|
|
__func__, err, abba.result);
|
|
ret = -EINVAL;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
struct test_cycle {
|
|
struct work_struct work;
|
|
struct ww_mutex a_mutex;
|
|
struct ww_mutex *b_mutex;
|
|
struct completion *a_signal;
|
|
struct completion b_signal;
|
|
int result;
|
|
};
|
|
|
|
static void test_cycle_work(struct work_struct *work)
|
|
{
|
|
struct test_cycle *cycle = container_of(work, typeof(*cycle), work);
|
|
struct ww_acquire_ctx ctx;
|
|
int err, erra = 0;
|
|
|
|
ww_acquire_init_noinject(&ctx, &ww_class);
|
|
ww_mutex_lock(&cycle->a_mutex, &ctx);
|
|
|
|
complete(cycle->a_signal);
|
|
wait_for_completion(&cycle->b_signal);
|
|
|
|
err = ww_mutex_lock(cycle->b_mutex, &ctx);
|
|
if (err == -EDEADLK) {
|
|
err = 0;
|
|
ww_mutex_unlock(&cycle->a_mutex);
|
|
ww_mutex_lock_slow(cycle->b_mutex, &ctx);
|
|
erra = ww_mutex_lock(&cycle->a_mutex, &ctx);
|
|
}
|
|
|
|
if (!err)
|
|
ww_mutex_unlock(cycle->b_mutex);
|
|
if (!erra)
|
|
ww_mutex_unlock(&cycle->a_mutex);
|
|
ww_acquire_fini(&ctx);
|
|
|
|
cycle->result = err ?: erra;
|
|
}
|
|
|
|
static int __test_cycle(unsigned int nthreads)
|
|
{
|
|
struct test_cycle *cycles;
|
|
unsigned int n, last = nthreads - 1;
|
|
int ret;
|
|
|
|
cycles = kmalloc_array(nthreads, sizeof(*cycles), GFP_KERNEL);
|
|
if (!cycles)
|
|
return -ENOMEM;
|
|
|
|
for (n = 0; n < nthreads; n++) {
|
|
struct test_cycle *cycle = &cycles[n];
|
|
|
|
ww_mutex_init(&cycle->a_mutex, &ww_class);
|
|
if (n == last)
|
|
cycle->b_mutex = &cycles[0].a_mutex;
|
|
else
|
|
cycle->b_mutex = &cycles[n + 1].a_mutex;
|
|
|
|
if (n == 0)
|
|
cycle->a_signal = &cycles[last].b_signal;
|
|
else
|
|
cycle->a_signal = &cycles[n - 1].b_signal;
|
|
init_completion(&cycle->b_signal);
|
|
|
|
INIT_WORK(&cycle->work, test_cycle_work);
|
|
cycle->result = 0;
|
|
}
|
|
|
|
for (n = 0; n < nthreads; n++)
|
|
queue_work(wq, &cycles[n].work);
|
|
|
|
flush_workqueue(wq);
|
|
|
|
ret = 0;
|
|
for (n = 0; n < nthreads; n++) {
|
|
struct test_cycle *cycle = &cycles[n];
|
|
|
|
if (!cycle->result)
|
|
continue;
|
|
|
|
pr_err("cyclic deadlock not resolved, ret[%d/%d] = %d\n",
|
|
n, nthreads, cycle->result);
|
|
ret = -EINVAL;
|
|
break;
|
|
}
|
|
|
|
for (n = 0; n < nthreads; n++)
|
|
ww_mutex_destroy(&cycles[n].a_mutex);
|
|
kfree(cycles);
|
|
return ret;
|
|
}
|
|
|
|
static int test_cycle(unsigned int ncpus)
|
|
{
|
|
unsigned int n;
|
|
int ret;
|
|
|
|
for (n = 2; n <= ncpus + 1; n++) {
|
|
ret = __test_cycle(n);
|
|
if (ret)
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct stress {
|
|
struct work_struct work;
|
|
struct ww_mutex *locks;
|
|
unsigned long timeout;
|
|
int nlocks;
|
|
};
|
|
|
|
struct rnd_state rng;
|
|
DEFINE_SPINLOCK(rng_lock);
|
|
|
|
static inline u32 prandom_u32_below(u32 ceil)
|
|
{
|
|
u32 ret;
|
|
|
|
spin_lock(&rng_lock);
|
|
ret = prandom_u32_state(&rng) % ceil;
|
|
spin_unlock(&rng_lock);
|
|
return ret;
|
|
}
|
|
|
|
static int *get_random_order(int count)
|
|
{
|
|
int *order;
|
|
int n, r;
|
|
|
|
order = kmalloc_array(count, sizeof(*order), GFP_KERNEL);
|
|
if (!order)
|
|
return order;
|
|
|
|
for (n = 0; n < count; n++)
|
|
order[n] = n;
|
|
|
|
for (n = count - 1; n > 1; n--) {
|
|
r = prandom_u32_below(n + 1);
|
|
if (r != n)
|
|
swap(order[n], order[r]);
|
|
}
|
|
|
|
return order;
|
|
}
|
|
|
|
static void dummy_load(struct stress *stress)
|
|
{
|
|
usleep_range(1000, 2000);
|
|
}
|
|
|
|
static void stress_inorder_work(struct work_struct *work)
|
|
{
|
|
struct stress *stress = container_of(work, typeof(*stress), work);
|
|
const int nlocks = stress->nlocks;
|
|
struct ww_mutex *locks = stress->locks;
|
|
struct ww_acquire_ctx ctx;
|
|
int *order;
|
|
|
|
order = get_random_order(nlocks);
|
|
if (!order)
|
|
return;
|
|
|
|
do {
|
|
int contended = -1;
|
|
int n, err;
|
|
|
|
ww_acquire_init(&ctx, &ww_class);
|
|
retry:
|
|
err = 0;
|
|
for (n = 0; n < nlocks; n++) {
|
|
if (n == contended)
|
|
continue;
|
|
|
|
err = ww_mutex_lock(&locks[order[n]], &ctx);
|
|
if (err < 0)
|
|
break;
|
|
}
|
|
if (!err)
|
|
dummy_load(stress);
|
|
|
|
if (contended > n)
|
|
ww_mutex_unlock(&locks[order[contended]]);
|
|
contended = n;
|
|
while (n--)
|
|
ww_mutex_unlock(&locks[order[n]]);
|
|
|
|
if (err == -EDEADLK) {
|
|
if (!time_after(jiffies, stress->timeout)) {
|
|
ww_mutex_lock_slow(&locks[order[contended]], &ctx);
|
|
goto retry;
|
|
}
|
|
}
|
|
|
|
ww_acquire_fini(&ctx);
|
|
if (err) {
|
|
pr_err_once("stress (%s) failed with %d\n",
|
|
__func__, err);
|
|
break;
|
|
}
|
|
} while (!time_after(jiffies, stress->timeout));
|
|
|
|
kfree(order);
|
|
}
|
|
|
|
struct reorder_lock {
|
|
struct list_head link;
|
|
struct ww_mutex *lock;
|
|
};
|
|
|
|
static void stress_reorder_work(struct work_struct *work)
|
|
{
|
|
struct stress *stress = container_of(work, typeof(*stress), work);
|
|
LIST_HEAD(locks);
|
|
struct ww_acquire_ctx ctx;
|
|
struct reorder_lock *ll, *ln;
|
|
int *order;
|
|
int n, err;
|
|
|
|
order = get_random_order(stress->nlocks);
|
|
if (!order)
|
|
return;
|
|
|
|
for (n = 0; n < stress->nlocks; n++) {
|
|
ll = kmalloc(sizeof(*ll), GFP_KERNEL);
|
|
if (!ll)
|
|
goto out;
|
|
|
|
ll->lock = &stress->locks[order[n]];
|
|
list_add(&ll->link, &locks);
|
|
}
|
|
kfree(order);
|
|
order = NULL;
|
|
|
|
do {
|
|
ww_acquire_init(&ctx, &ww_class);
|
|
|
|
list_for_each_entry(ll, &locks, link) {
|
|
err = ww_mutex_lock(ll->lock, &ctx);
|
|
if (!err)
|
|
continue;
|
|
|
|
ln = ll;
|
|
list_for_each_entry_continue_reverse(ln, &locks, link)
|
|
ww_mutex_unlock(ln->lock);
|
|
|
|
if (err != -EDEADLK) {
|
|
pr_err_once("stress (%s) failed with %d\n",
|
|
__func__, err);
|
|
break;
|
|
}
|
|
|
|
ww_mutex_lock_slow(ll->lock, &ctx);
|
|
list_move(&ll->link, &locks); /* restarts iteration */
|
|
}
|
|
|
|
dummy_load(stress);
|
|
list_for_each_entry(ll, &locks, link)
|
|
ww_mutex_unlock(ll->lock);
|
|
|
|
ww_acquire_fini(&ctx);
|
|
} while (!time_after(jiffies, stress->timeout));
|
|
|
|
out:
|
|
list_for_each_entry_safe(ll, ln, &locks, link)
|
|
kfree(ll);
|
|
kfree(order);
|
|
}
|
|
|
|
static void stress_one_work(struct work_struct *work)
|
|
{
|
|
struct stress *stress = container_of(work, typeof(*stress), work);
|
|
const int nlocks = stress->nlocks;
|
|
struct ww_mutex *lock = stress->locks + get_random_u32_below(nlocks);
|
|
int err;
|
|
|
|
do {
|
|
err = ww_mutex_lock(lock, NULL);
|
|
if (!err) {
|
|
dummy_load(stress);
|
|
ww_mutex_unlock(lock);
|
|
} else {
|
|
pr_err_once("stress (%s) failed with %d\n",
|
|
__func__, err);
|
|
break;
|
|
}
|
|
} while (!time_after(jiffies, stress->timeout));
|
|
}
|
|
|
|
#define STRESS_INORDER BIT(0)
|
|
#define STRESS_REORDER BIT(1)
|
|
#define STRESS_ONE BIT(2)
|
|
#define STRESS_ALL (STRESS_INORDER | STRESS_REORDER | STRESS_ONE)
|
|
|
|
static int stress(int nlocks, int nthreads, unsigned int flags)
|
|
{
|
|
struct ww_mutex *locks;
|
|
struct stress *stress_array;
|
|
int n, count;
|
|
|
|
locks = kmalloc_array(nlocks, sizeof(*locks), GFP_KERNEL);
|
|
if (!locks)
|
|
return -ENOMEM;
|
|
|
|
stress_array = kmalloc_array(nthreads, sizeof(*stress_array),
|
|
GFP_KERNEL);
|
|
if (!stress_array) {
|
|
kfree(locks);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
for (n = 0; n < nlocks; n++)
|
|
ww_mutex_init(&locks[n], &ww_class);
|
|
|
|
count = 0;
|
|
for (n = 0; nthreads; n++) {
|
|
struct stress *stress;
|
|
void (*fn)(struct work_struct *work);
|
|
|
|
fn = NULL;
|
|
switch (n & 3) {
|
|
case 0:
|
|
if (flags & STRESS_INORDER)
|
|
fn = stress_inorder_work;
|
|
break;
|
|
case 1:
|
|
if (flags & STRESS_REORDER)
|
|
fn = stress_reorder_work;
|
|
break;
|
|
case 2:
|
|
if (flags & STRESS_ONE)
|
|
fn = stress_one_work;
|
|
break;
|
|
}
|
|
|
|
if (!fn)
|
|
continue;
|
|
|
|
stress = &stress_array[count++];
|
|
|
|
INIT_WORK(&stress->work, fn);
|
|
stress->locks = locks;
|
|
stress->nlocks = nlocks;
|
|
stress->timeout = jiffies + 2*HZ;
|
|
|
|
queue_work(wq, &stress->work);
|
|
nthreads--;
|
|
}
|
|
|
|
flush_workqueue(wq);
|
|
|
|
for (n = 0; n < nlocks; n++)
|
|
ww_mutex_destroy(&locks[n]);
|
|
kfree(stress_array);
|
|
kfree(locks);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static DEFINE_MUTEX(run_lock);
|
|
|
|
static int run_tests(void)
|
|
{
|
|
int ncpus = num_online_cpus();
|
|
int ret, i;
|
|
|
|
printk(KERN_INFO "Beginning ww mutex selftests\n");
|
|
|
|
ret = test_mutex();
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = test_aa(false);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = test_aa(true);
|
|
if (ret)
|
|
return ret;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
ret = test_abba(i & 1, i & 2);
|
|
if (ret)
|
|
return ret;
|
|
}
|
|
|
|
ret = test_cycle(ncpus);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = stress(16, 2*ncpus, STRESS_INORDER);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = stress(16, 2*ncpus, STRESS_REORDER);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = stress(2047, hweight32(STRESS_ALL)*ncpus, STRESS_ALL);
|
|
if (ret)
|
|
return ret;
|
|
|
|
printk(KERN_INFO "All ww mutex selftests passed\n");
|
|
return 0;
|
|
}
|
|
|
|
static ssize_t run_tests_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
if (!mutex_trylock(&run_lock)) {
|
|
pr_err("Test already running\n");
|
|
return count;
|
|
}
|
|
|
|
run_tests();
|
|
mutex_unlock(&run_lock);
|
|
|
|
return count;
|
|
}
|
|
|
|
static struct kobj_attribute run_tests_attribute =
|
|
__ATTR(run_tests, 0664, NULL, run_tests_store);
|
|
|
|
static struct attribute *attrs[] = {
|
|
&run_tests_attribute.attr,
|
|
NULL, /* need to NULL terminate the list of attributes */
|
|
};
|
|
|
|
static struct attribute_group attr_group = {
|
|
.attrs = attrs,
|
|
};
|
|
|
|
static struct kobject *test_ww_mutex_kobj;
|
|
|
|
static int __init test_ww_mutex_init(void)
|
|
{
|
|
int ret;
|
|
|
|
prandom_seed_state(&rng, get_random_u64());
|
|
|
|
wq = alloc_workqueue("test-ww_mutex", WQ_UNBOUND, 0);
|
|
if (!wq)
|
|
return -ENOMEM;
|
|
|
|
test_ww_mutex_kobj = kobject_create_and_add("test_ww_mutex", kernel_kobj);
|
|
if (!test_ww_mutex_kobj) {
|
|
destroy_workqueue(wq);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
/* Create the files associated with this kobject */
|
|
ret = sysfs_create_group(test_ww_mutex_kobj, &attr_group);
|
|
if (ret) {
|
|
kobject_put(test_ww_mutex_kobj);
|
|
destroy_workqueue(wq);
|
|
return ret;
|
|
}
|
|
|
|
mutex_lock(&run_lock);
|
|
ret = run_tests();
|
|
mutex_unlock(&run_lock);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void __exit test_ww_mutex_exit(void)
|
|
{
|
|
kobject_put(test_ww_mutex_kobj);
|
|
destroy_workqueue(wq);
|
|
}
|
|
|
|
module_init(test_ww_mutex_init);
|
|
module_exit(test_ww_mutex_exit);
|
|
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_AUTHOR("Intel Corporation");
|
|
MODULE_DESCRIPTION("API test facility for ww_mutexes");
|