Skip to contentSkip to conversation

7.2.4-rc1 review

PATCH In review Greg Kroah-Hartman 15 participants 731 messages Sep 4 – Sep 18 Page 1 of 6

Subsystems (2)
lore
Share & tools
lore

Greg Kroah-Hartman

author maintainer
#0 lore raw

cover 7.2.4-rc1 review

This is the start of the stable review cycle for the 7.2.4 release. There are 713 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.

Responses should be made by Sun, 06 Sep 2026 04:56:59 +0000. Anything received after that time might be too late.

The whole patch series can be found in one patch at:

	https://www.kernel.org/pub/linux/kernel/v7.x/stable-review/patch-7.2.4-rc1.gz

or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-7.2.y
and the diffstat can be found below.

thanks,

greg k-h

-------------
Pseudo-Shortlog of commits:

Greg Kroah-Hartman <[email protected]>

    Linux 7.2.4-rc1

Tzung-Bi Shih <[email protected]>
platform/chrome: sensorhub: Fix dropped timestamp events and log spam

Rafael J. Wysocki <[email protected]>
ACPI: scan: Do not combine resources that overlap completely

Injae Ryou <[email protected]>
selftests/mm: fix on-fault-limit false failure under sudo-rs

Zhan Xusheng <[email protected]>
udf: Fix i_lenExtents truncation on 32-bit kernels

Thomas Gleixner <[email protected]>
timer: Keep debugobjects state consistent in migrate_timer_list()

Thomas Weißschuh (Schneider Electric) <[email protected]>
timekeeping: Check the return value of tk_get_aux_ts64 in __do_adjtimex()

Bradley Morgan <[email protected]>
taskstats: fix cpumask parsing cutting off the last character

Jann Horn <[email protected]>
smack: fix cred UAF in smack_file_send_sigiotask()

Bradley Morgan <[email protected]>
signal: avoid shared siginfo namespace rewrites

Helge Deller <[email protected]>
sticon/parisc: Detect default STI graphics card for console output

Oleg Nesterov <[email protected]>

    sysctl: move the "cad_pid" entry from pid_table[] to kern_reboot_table[]

Myeonghun Pak <[email protected]>
tpm: tpm_i2c_nuvoton: disable IRQ on wait timeout

Xu Rao <[email protected]>
zloop: truncate finished zones to zone capacity

Zi Yan <[email protected]>
xarray: honor XA_FLAGS_ACCOUNT in xas_split_alloc()

Maoyi Xie <[email protected]>
w1: ds28e17: reject an oversize length on an I2C block read

Chengfeng Ye <[email protected]>
vsock/virtio: flush works in dependency order

Laxman Acharya Padhya <[email protected]>
wifi: mt76: mt7996: validate default EEPROM firmware size

Felix Fietkau <[email protected]>
wifi: mt76: mt7996: fix TX DMA mapping leak for AddBA req frames

Bryam Vargas <[email protected]>
wifi: mt76: mt7996: bound the device EEPROM address before the EFUSE copy

Devin Wittmayer <[email protected]>
wifi: mt76: mt7925: cancel mlo_pm_work on stop

Bryam Vargas <[email protected]>
wifi: mt76: mt7915: bound the device EEPROM address before the EFUSE copy

Runyu Xiao <[email protected]>
wifi: mt76: mt7615: avoid waiting for mac work under the mt76 mutex

Yuhang.chen <[email protected]>
wifi: rtw89: pci: add .shutdown callback to stop rfkill polling on reboot

Dawei Feng <[email protected]>
wifi: rtw88: pci: fix resource leak on failed NAPI setup

Abdun Nihaal <[email protected]>
wifi: rtw88: Fix potential memory leak in rtw_txq_push_skb()

Abdun Nihaal <[email protected]>
wifi: rtlwifi: rtl8192du: Fix possible memory leak in rtl92du_init_sw_vars()

Runyu Xiao <[email protected]>
wifi: rtlwifi: rtl8192du: check QoS TID before indexing tids

Stanislaw Gruszka <[email protected]>
wifi: rtl818x: initialize eeprom_93cx6 struct to zero

Fabio Estevam <[email protected]>
wifi: mwifiex: Detach sync cmd buffer on interrupted wait

Breno Leitao <[email protected]>
mm/kmemleak: report RCU-tasks quiescent states during the scan

Breno Leitao <[email protected]>
mm/kmemleak: stop the task stack scan early when interrupted

Thorsten Blum <[email protected]>
crypto: atmel-ecc - avoid stale fallback key after set_secret failure

Thorsten Blum <[email protected]>
crypto: atmel-ecc - clean up and improve ECDH comments

Vinicius Costa Gomes <[email protected]>
crypto: iaa - unmap dst before software fallback on decompress

Xiang Mei <[email protected]>
fuse: copy request headers via a stack buffer for io-uring

Joanne Koong <[email protected]>
fuse: decouple fuse_ring creation from ent registration

Fan Wu <[email protected]>
wifi: rtl8xxxu: fix use-after-free from rx_urb_wq on stop

Dawei Feng <[email protected]>
wifi: iwlwifi: dvm: fix memory leak in iwl_op_mode_dvm_start()

Abdun Nihaal <[email protected]>
wifi: brcmfmac: Fix memory leak in brcmf_sdio_read_control()

Claudiu Beznea <[email protected]>
i3c: renesas: Perform Dynamic Address Assignment on resume

Claudiu Beznea <[email protected]>
i3c: renesas: Restore STDBR and EXTBR registers on resume

Claudiu Beznea <[email protected]>
i3c: renesas: Reset the controller on resume

Claudiu Beznea <[email protected]>
i3c: renesas: Reconfigure the DATBAS register on re-attach

Claudiu Beznea <[email protected]>
i3c: renesas: Follow the reset deassert order used in probe

Claudiu Beznea <[email protected]>
i3c: renesas: Clean DATBAS register on detach

Claudiu Beznea <[email protected]>
i3c: renesas: Check that the transfer is valid before accessing it

Adrian Hunter <[email protected]>
i3c: master: Fix potential UAF in i3c_device_uevent()

Maoyi Xie <[email protected]>
i3c: master: svc: bound IBI payload to the requested max_payload_len

Adrian Hunter <[email protected]>
i3c: master: Fix info leak and UAF in device unregister path

Runyu Xiao <[email protected]>
i3c: master: adi: initialize the lock before enabling interrupts

Adrian Hunter <[email protected]>

    i3c: Fix unlocked dereference of dev->desc in i3c_device_get_supported_xfer_mode()

Jianyun Gao <[email protected]>
dm-pcache: fix use-after-free and invalid seg operations in kset_replay()

Jianyun Gao <[email protected]>
dm-pcache: fix implicit u8 truncation of gc_percent in message handler

Bryam Vargas <[email protected]>
dm-pcache: only hand out initialized cache segments

Bryam Vargas <[email protected]>
dm-pcache: detect a cycle in the last-kset chain during replay

Bryam Vargas <[email protected]>
dm-pcache: clamp the tail kset read to the segment data region

Bryam Vargas <[email protected]>
dm-pcache: bound the persisted tail-position offset

Bryam Vargas <[email protected]>
dm-pcache: validate on-media seg_num against the cache device size

Bryam Vargas <[email protected]>
dm-pcache: validate kset key_num and intra-segment bounds

Bryam Vargas <[email protected]>
dm-pcache: validate geometry fields from on-disk cache_info

Haotian Zhang <[email protected]>
dm-switch: use WRITE_ONCE() in switch_region_table_write()

Mikulas Patocka <[email protected]>
dm-stats: fix a crash if allocation of per-cpu data fails

Nathan Chancellor <[email protected]>
arch_numa: avoid false positive fortify warning in setup_node_to_cpumask_map()

Eliot Courtney <[email protected]>
rust: num: reject Bounded::shr overshifts at build time

Zhang Heng <[email protected]>
ALSA: hda/realtek: Fix Lenovo Yoga Slim 7 14AKP10 quirk ordering

Denis Batishchev <[email protected]>
ALSA: hda/realtek: Enable micmute LED on HP EliteBook 6 G1a p/n: AD3Q9ET#UUG

Ajrat Makhmutov <[email protected]>
ALSA: hda/realtek: Enable headset mic on F+ FLAPTOP r

Eckhart Mohr <[email protected]>
ALSA: hda/realtek: Add quirk for TongFang XxAF5xxx

Takashi Iwai <[email protected]>
ALSA: virmidi: Check card index validity at probe

Takashi Iwai <[email protected]>
ALSA: serial-u16550: Check card index validity at probe

Takashi Iwai <[email protected]>
ALSA: portman2x4: Check card index validity at probe

Runyu Xiao <[email protected]>
ALSA: pcxhr: initialize mutexes before requesting threaded IRQ

Takashi Iwai <[email protected]>
ALSA: mts64: Check card index validity at probe

Takashi Iwai <[email protected]>
ALSA: mpu401: Check card index validity at probe

Xu Rao <[email protected]>
ALSA: hda/ext: preserve PPLCCTL bits when clearing reset

Baul Lee <[email protected]>
ALSA: FCP: do not copy out an uninitialised init response

Baul Lee <[email protected]>
ALSA: bcd2000: clear the URB pointers on disconnect

Takashi Iwai <[email protected]>
ALSA: aloop: Check card index validity at probe

Baul Lee <[email protected]>
ALSA: 6fire: bound the MIDI event length from the device

Abdun Nihaal <[email protected]>
mfd: sm501: Fix potential memory leaks during remove

Ali Ahmet Memis <[email protected]>
mfd: qnap-mcu: keep the reply buffer alive past a command timeout

Thomas Richard <[email protected]>
mfd: cgbc: Fix teardown ordering in cgbc_remove()

Can Peng <[email protected]>
hwrng: stm32 - Fix runtime PM cleanup on registration failure

Zhiling Zou <[email protected]>
seg6: reset IP6CB after IPv6 decapsulation

Norbert Szetei <[email protected]>
net: skbuff: don't touch shared zerocopy state in skb_tx_error()

Breno Leitao <[email protected]>
net: fix spurious TX timeout after dev_activate()

Zhiling Zou <[email protected]>
net: cap advertised IP tunnel headroom

Bryam Vargas <[email protected]>
net/smc: unregister the connection before draining the rx tasklet

Hidayath Khan <[email protected]>
net/smc: stop killed, freed and out_of_sync sharing a byte

Yehyeong Lee <[email protected]>
net/smc: fix use-after-free of the LLC qentry in smc_llc_srv_add_link()

Hidayath Khan <[email protected]>
net/smc: fix use-after-free in smc_rx_pipe_buf_release()

Hidayath Khan <[email protected]>
net/smc: fix socket refcount leak in smc_switch_conns()

Bryam Vargas <[email protected]>
net/smc: do not dereference an unset send buffer on the SMC-D teardown path

Yehyeong Lee <[email protected]>
net/smc: carry oversized SMC-Rv2 LLC messages in the queue entry

Yehyeong Lee <[email protected]>
net/smc: bound the peer rkey counts in SMC-Rv2 LLC messages

Glenn Judd <[email protected]>
net/mlx5e: do not HW-GRO coalesce small frames

Koichiro Den <[email protected]>
net: ntb_netdev: Count packets dropped on RX refill failure

Koichiro Den <[email protected]>
net: ntb_netdev: Avoid double-accounting netif_rx() drops

Koichiro Den <[email protected]>
net: ntb_netdev: Fix TX busy and drop handling

Koichiro Den <[email protected]>
NTB: ntb_transport: Reject oversized TX buffers

Koichiro Den <[email protected]>
NTB: ntb_transport: Fail TX enqueue when the QP link is down

Koichiro Den <[email protected]>
NTB: ntb_transport: Recycle TX entries before client callbacks

Fan Ye <[email protected]>
net: thunderbolt: Mark the connection down when bringing it up fails

Fan Ye <[email protected]>
net: thunderbolt: Release the Rx HopID that was handed out on mismatch

Xuanqiang Luo <[email protected]>
net: ravb: serialize PTP clock teardown

Xuanqiang Luo <[email protected]>
net: ravb: avoid dereferencing an invalid PTP clock

Christian Marangi <[email protected]>
net: phylink: correctly validate returned PCS in phylink_inband_caps

Ruoyu Wang <[email protected]>
net: openvswitch: fix nf_connlabels leak in ovs_ct_init

Ilya Maximets <[email protected]>
net: openvswitch: fix flow mask use-after-free on flow deletion

Aldo Ariel Panzardo <[email protected]>
net: mctp: hold a reference to the route device in mctp_route_lookup()

Zihan Xi <[email protected]>
net: l2tp: do not propagate multicast notification errors

Jorijn van der Graaf <[email protected]>
net: ipa: fix stalled modem TX queue after runtime resume

Runyu Xiao <[email protected]>
net: ibm: emac: mal: fix NAPI locking

Joe Damato <[email protected]>
net: bnxt: ring the doorbell when SW USO exits early

Ahmad Fatoum <[email protected]>
net: dsa: realtek: use gpiod_set_value_cansleep for reset GPIO

Asim Viladi Oglu Manizada <[email protected]>
net: tun: bound receive headroom

Fabio Porcedda <[email protected]>
net: usb: qmi_wwan: add Telit Cinterion FE990D50 composition

Aleksandr Khromov <[email protected]>
slip: fix use-after-free in sl_sync()

Weiming Shi <[email protected]>
xdp: fix zero-copy frame layout

Alexandra Winter <[email protected]>
net/iucv: filter frames in afiucv_hs_rcv() by ingress device

Corey Minyard <[email protected]>
ipmi:msghandler: Cancel work cleanly on an error

Seiji Nishikawa <[email protected]>
ipmi: si: Fix NULL pointer dereference after failed registration

Yuho Choi <[email protected]>
ipmi: Remove all sysfs files on registration failure

Yousef Alhouseen <[email protected]>
ipmi: ipmb: validate write message length

Kuan-Wei Chiu <[email protected]>
interconnect: Fix use after free in icc_get() and of_icc_get_by_index()

Laxman Acharya Padhya <[email protected]>
io_uring/query: cap user size passed to copy_struct_to_user

Hui Su <[email protected]>
io_uring/waitid: avoid siginfo copy during ring teardown

Hui Su <[email protected]>
io_uring/waitid: honor task_work cancellation

Muhammad Bilal <[email protected]>
platform/x86: hp-bioscfg: warn on element type mismatch instead of failing

Muhammad Bilal <[email protected]>
platform/x86: hp-bioscfg: pass validated element count to package parsers

Muhammad Bilal <[email protected]>
platform/x86: hp-bioscfg: fix ORD_LIST_ELEMENTS never being parsed

Muhammad Bilal <[email protected]>
platform/x86: hp-bioscfg: fix off-by-one write in hp_get_string_from_buffer()

Muhammad Bilal <[email protected]>
platform/x86: hp-bioscfg: fix new_password_store() overwriting current_password

Muhammad Bilal <[email protected]>
platform/x86: hp-bioscfg: fix heap OOB read on empty password write

Muhammad Bilal <[email protected]>
platform/x86: hp-bioscfg: fix heap OOB read in sk_store() and kek_store()

Muhammad Bilal <[email protected]>
platform/x86: hp-bioscfg: bound ordered-list parsing by the package count

Muhammad Bilal <[email protected]>
platform/x86: hp-bioscfg: advance elem past consumed array elements

Muhammad Bilal <[email protected]>
platform/x86: hp-bioscfg: accept reduced ACPI packages from older HP BIOS

Mario Limonciello <[email protected]>
platform/x86/amd/pmc: Fix msg_port restoration in amd_stb_debugfs_open_v2()

Mario Limonciello <[email protected]>
platform/x86/amd/pmc: Fix LPS0 and debugfs leaks when STB init fails

Mario Limonciello <[email protected]>
platform/x86/amd/pmc: Propagate SMU errors and validate S2D address

Mario Limonciello <[email protected]>
platform/x86/amd/pmc: Restore msg_port on amd_stb_s2d_init() error paths

Bryam Vargas <[email protected]>
platform/chrome: sensorhub: Bound the EC-reported sensor number

Thorsten Blum <[email protected]>
platform/x86: think-lmi: Fix current password length check

Thorsten Blum <[email protected]>
platform/x86: think-lmi: Free system certificate signatures

Thorsten Blum <[email protected]>
platform/x86: think-lmi: Fix certificate thumbprint sysfs output

Hilgad Montelo <[email protected]>

    platform/x86: panasonic-laptop: Fix sentinel write past pcc->sinf[]

Julian Haarmann <[email protected]>
platform/x86: lenovo/ymc: Only match lower byte in WMI lid switch query response

Ma Ke <[email protected]>
platform/x86: ishtp_eclite: Fix ACPI device reference leak in probe error path

Abdun Nihaal <[email protected]>
platform/x86: int1092: Fix potential memory leak in sar_probe()

Krishna Chomal <[email protected]>

    platform/x86: hp-wmi: Add support for OMEN MAX 16-ak0xxx (8DD6)

Srinivas Pandruvada <[email protected]>
platform/x86: ISST: Return error during profile addition

Srinivas Pandruvada <[email protected]>
platform/x86: ISST: Validate parameter for frequency and priority

Srinivas Pandruvada <[email protected]>
platform/x86: ISST: Validate parameter for core power state

Srinivas Pandruvada <[email protected]>
platform/x86: ISST: Validate max level for set feature

Srinivas Pandruvada <[email protected]>
platform/x86: ISST: Validate logical CPU id and clos id

Srinivas Pandruvada <[email protected]>
platform/x86: ISST: Use PP level enable mask

Srinivas Pandruvada <[email protected]>
platform/x86: ISST: Just allow 2 bits for SST feature enable

Srinivas Pandruvada <[email protected]>

    platform/x86: ISST: Add a NULL check for sst_inst[]

Fan Wu <[email protected]>
mmc: via-sdmmc: stop card-detect handling on probe failure

Fan Wu <[email protected]>
mmc: via-sdmmc: cancel card-detect work on remove

HyeongJun An <[email protected]>
platform/x86: ISST: Validate socket ID in clos_assoc ioctl

HyeongJun An <[email protected]>
platform/x86: ISST: Validate level in perf mask ioctls

HyeongJun An <[email protected]>
platform/x86: dell-wmi-sysman: Don't hex dump attribute security buffer

Peiyang He <[email protected]>
iommufd: Fix UAF in selftest IOPF reporting

Shuai Xue <[email protected]>
iommufd: Release current IOAS on xa_store() failure

Shuai Xue <[email protected]>
iommufd: Avoid locking internal accesses during unmap

Shuai Xue <[email protected]>
iommupt: Return zero for invalid iova_to_phys() ranges

Kevin Tian <[email protected]>
iommu/vt-d: Force requesting ACS when tboot is enabled

Kevin Tian <[email protected]>
iommu/vt-d: Fix no_iommu to disable platform opt-in

Peiyang He <[email protected]>
iommu: Fix dev_iommu memory leak when device_add fails in iommu_mock_device_add

Shameer Kolothum <[email protected]>
iommu/arm-smmu-v3: Manage teardown with devm

Robin Murphy <[email protected]>
iommu/arm-smmu-v3: Add HAFT support for SVA

Nicolin Chen <[email protected]>
iommu/tegra241-cmdqv: Reject a vSID wider than the SID_MATCH field

Shuai Xue <[email protected]>

    iommu/sva: Set handle->dev before the SVA handle is visible

Weimin Xiong <[email protected]>
iommu/msm: Unwind probe state on registration failure

Shuai Xue <[email protected]>
iommu/amd: Put PCI device after handling PPR faults

Krzysztof Wilczyński <[email protected]>
PCI/proc: Warn on writes to kernel-exclusive config space regions

Krzysztof Wilczyński <[email protected]>
PCI/proc: Use file_ns_capable() when checking config space read access

Krzysztof Wilczyński <[email protected]>
PCI/proc: Avoid spurious runtime PM wakeup on config space accesses

Farhan Ali <[email protected]>
PCI/MSI: Enable memory decoding before restoring MSI-X messages

Darshit Shah <[email protected]>
PCI/DPC: Allow DPC on all Downstream Ports when OS controls AER

Max Lee <[email protected]>
PCI/ASPM: Avoid L0s for Realtek RTS525A

Lukas Wunner <[email protected]>
PCI/AER: Fix mapping of errors to agent & layer

Lukas Wunner <[email protected]>
PCI/AER: Emit TLP Log only for unmasked errors

Krzysztof Wilczyński <[email protected]>
PCI/sysfs: Avoid spurious runtime PM wakeup on config space accesses

Krzysztof Wilczyński <[email protected]>
PCI/sysfs: Fix read byte order in pci_read_legacy_io()

Tim Harvey <[email protected]>

    PCI: Add ACS quirk for Pericom PI7C9X2G608 switches [12d8:2608]

Ali Tariq <[email protected]>
PCI: plda: Fix IRQ domain leaks in the error paths of plda_init_interrupts()

Ali Tariq <[email protected]>
PCI: plda: Fix use-after-free of event IRQs during teardown

Ali Tariq <[email protected]>
PCI: starfive: Fix resource leaks on error paths in host_init()

Ronald Claveau <[email protected]>
PCI: meson: Fix GPIO state while requesting PERST#

Mohamad Raizudeen <[email protected]>
PCI: Fix 32-bit config write in Intel PCH Root Port MPC ACS quirk

Naman Jain <[email protected]>
PCI: hv: Set irq_retrigger callback for the Hyper-V PCI MSI irqchip

Stefan Haberland <[email protected]>
s390/dasd: Propagate partial completion length across ERP recovery

Stefan Haberland <[email protected]>
s390/dasd: Guard sysfs discipline callbacks against unallocated private data

Stefan Haberland <[email protected]>
s390/dasd: Do not complete a failed ESE read as successful

Karl Mehltretter <[email protected]>
s390/percpu: Fix MVIY_PERCPU() with older binutils

Thomas Richter <[email protected]>
s390/cpum_cf: Handle CPU hotplug via prepare/dead callbacks

Jianing Li <[email protected]>
power: supply: max17040: synchronize work cancellation on suspend

Jianing Li <[email protected]>
power: supply: max17040: drop incorrect I2C functionality check

Jianing Li <[email protected]>
power: supply: max17040: propagate register read errors

Fan Wu <[email protected]>
power: supply: ucs1002: fix use-after-free on remove

Maoyi Xie <[email protected]>
power: supply: twl4030_charger: cancel workers via devm

Fan Wu <[email protected]>
power: supply: rt9455: quiesce delayed work before teardown

HyeongJun An <[email protected]>
power: supply: qcom_battmgr: terminate the strings from firmware

Fan Wu <[email protected]>
power: supply: qcom_battmgr: fix use-after-free

Xu Rao <[email protected]>
power: supply: pf1550: enable charging when battery profile exists

Fan Wu <[email protected]>
power: supply: lp8788-charger: fix use-after-free on remove

Fan Wu <[email protected]>

    power: supply: lp8727: fix use-after-free in lp8727_release_irq()

Jameson Thies <[email protected]>
power: supply: cros_usbpd: Limit port counts to EC_USB_PD_MAX_PORTS

Bryam Vargas <[email protected]>
power: supply: cros_usbpd-charger: bound the EC-reported port count

Fan Wu <[email protected]>
power: supply: charger-manager: register regulators before exposing sysfs

Ma Ke <[email protected]>
power: supply: bq25890: Fix power_supply reference leak

Fan Wu <[email protected]>
power: supply: bq256xx: drain usb_work before freeing the charger

Fan Wu <[email protected]>
power: supply: bq24257: fix use-after-free on remove

Jun Yang <[email protected]>

    sctp: fix stream->outcnt underflow on duplicate RECONF responses

Jun Yang <[email protected]>
sctp: distinguish sequence zero from wildcard in reconf lookup

Weiming Shi <[email protected]>
sctp: fix NULL deref on untransmitted RECONF completion

Hyunwoo Kim <[email protected]>
sctp: drop a chunk if its transport was removed

Hyunwoo Kim <[email protected]>
sctp: stop processing a packet once its association is deleted

Yehyeong Lee <[email protected]>
nvme-tcp: reject a read that transferred too few bytes

Yehyeong Lee <[email protected]>
nvme-tcp: fix host memory disclosure on R2T for a read command

Yehyeong Lee <[email protected]>
nvme-tcp: do not accept C2HData based on blk_rq_payload_bytes() alone

Myeonghun Pak <[email protected]>
nvme-pci: disable controller on admin queue IRQ setup failure

Yehyeong Lee <[email protected]>
nvme: zero the discard fallback page

Ewan D. Milne <[email protected]>
nvme: nvme-fc: Fix nvme_fc_create_hw_io_queues() queue deletion in error path

Oscar Ou <[email protected]>
lockd: fix swapped arguments in nlmsvc_match_ip()

Shuangpeng Bai <[email protected]>
lockd: fix NULL dereference on lockowner allocation failure

Olga Kornievskaia <[email protected]>
lockd: fix NLMv4 GRANTED_MSG handling

Michael Bommarito <[email protected]>
lockd: pin next file across nlm_inspect_file lock-drop

Yifei Gao <[email protected]>
ipmi: Fix use-after-free of cmd_rcvr in _ipmi_destroy_user()

Ruoyu Wang <[email protected]>
i2c: mxs: fix DMA channel leak on probe error

Cong Nguyen <[email protected]>
hwmon: (max6621) fix temperature clamp range

Cong Nguyen <[email protected]>
hwmon: (max6621) fix negative temperature offset and crit readings

Alexander Graf <[email protected]>
dma-contiguous: fix truncation of numa_cma / cma_pernuma sizes >= 2G

Jorijn van der Graaf <[email protected]>
ASoC: codecs: aw88261: only check PLL and clock state at power-up

Christopher Tolang <[email protected]>
ASoC: amd: yc: Add DMI entry for MSI Thin A15 B7UC

Karl Mehltretter <[email protected]>
arm64: proton-pack: Restore the nospectre_bhb command-line option

Karl Mehltretter <[email protected]>
arm64: compat: Fix decrementing LDM/STM alignment emulation

HyeongJun An <[email protected]>
ALSA: ump: Fix corrupted data bytes at MIDI 1.0 SysEx to UMP conversion

Norbert Szetei <[email protected]>
openvswitch: only skb_tx_error() a packet we are about to drop

Yuqi Xu <[email protected]>
openvswitch: Fix CT limit teardown use-after-free

Ali Ahmet Memis <[email protected]>
openrisc: fix arbitrary kernel memory access via or1k_atomic syscall

Zhan Xusheng <[email protected]>
ocfs2: fix readdir position truncation on 32-bit kernels

Matthias Goergens <[email protected]>
ocfs2: fix cached cluster count after suballocator reclaim

Joseph Qi <[email protected]>
ocfs2: cluster: fix o2hb_dependent_users leak on pin failure

Joseph Qi <[email protected]>
ocfs2: cluster: avoid lock order inversion in o2hb_region_pin() from drop_item

Joseph Qi <[email protected]>
ocfs2: cluster: don't sleep while holding o2hb_live_lock in o2hb_region_pin()

Doruk Tan Ozturk <[email protected]>
ocfs2: validate directory-index entry counts when reading metadata

Ibrahim Hashimov <[email protected]>
ocfs2: validate rl_used against rl_count in refcount block validator

Bryam Vargas <[email protected]>
ocfs2: validate lengths in dlm_mig_lockres_handler

Bryam Vargas <[email protected]>
ocfs2: bound namelen in dlm_migrate_request_handler

Dmitry Antipov <[email protected]>
ocfs2: always run deallocs on copy-on-write completion

Zhiling Zou <[email protected]>
orangefs: skip leading spaces before parsing client debug masks

Yifei Gao <[email protected]>
orangefs: fix double-free of trailer_buf on readdir copy failure

Shibo Zhu <[email protected]>
PM: sleep: Unblock runtime PM when device prepare fails

Ivan Immanuel Shaji <[email protected]>
ring-buffer: Stop remote reader update when page swap fails

Vincent Donnefort <[email protected]>
ring-buffer: Make cpu_buffer::free_page a buffer_data_read_page

Vincent Donnefort <[email protected]>
ring-buffer: Hold cpu_buffer::lock when resizing a subbuf

Vincent Donnefort <[email protected]>
ring-buffer: Free cpu_buffer::free_page with subbuf_order

Vincent Donnefort <[email protected]>
ring-buffer: Fix subbuf resize race with ring_buffer_alloc_read_page()

Kathiravan Thirumoorthy <[email protected]>
regulator: qcom-refgen: correct the regulator type to CURRENT

WenTao Liang <[email protected]>
regulator: max8998_pmic_dt_parse_pdata: of_node_put on reg_np after ownership transferred to rdata

WenTao Liang <[email protected]>
regulator: as3722_get_regulator_dt_data: fix premature of_node_put leaving dangling of_node pointer

Yuhang Pan <[email protected]>
RDMA/uverbs: Guard legacy bundles without method_elm

Jason Gunthorpe <[email protected]>
RDMA/uverbs: Add UVERBS_ATTR_UHW to UVERBS_METHOD_REG_MR

Norbert Szetei <[email protected]>
RDMA/ucma: Lock the handler in ucma_write_cm_event()

Norbert Szetei <[email protected]>
RDMA/ucma: Lock the handler in ucma_set_ib_path()

Abhijit Gangurde <[email protected]>
RDMA/ionic: Embed counter driver data in rdma_counter allocation

Brett Creeley <[email protected]>
RDMA/ionic: Cap eq_count to the eth driver's interrupt vector budget

Fan Wu <[email protected]>
RDMA/cxgb4: Cancel reg_work before freeing device on remove

Vaibhav Nagare <[email protected]>
qede: Fix NULL pointer dereference in TPA fragment processing

Abdifatah Suruur <[email protected]>
ptp: vmclock: prevent read-only mappings from becoming writable

Johan Hovold <[email protected]>
remoteproc: scp: Fix device reference leak on failed lookup

Nam Cao <[email protected]>
riscv: unaligned: stop using kthread for check_vector_unaligned_access()

Peixin Xie <[email protected]>
riscv: acpi: Handle LPI architectural context loss flags

Guidong Han <[email protected]>
RISC-V: KVM: Fix PMU event info array size overflow

Aurelien Jarno <[email protected]>
riscv: dts: spacemit: k1-orangepi-rv2: fix maximum CPU core voltage

Aurelien Jarno <[email protected]>
riscv: dts: spacemit: k1-orangepi-r2s: fix maximum CPU core voltage

Aurelien Jarno <[email protected]>
riscv: dts: spacemit: k1-musepi-pro: fix maximum CPU core voltage

Aurelien Jarno <[email protected]>
riscv: dts: spacemit: k1-milkv-jupiter: fix maximum CPU core voltage

Aurelien Jarno <[email protected]>
riscv: dts: spacemit: k1-bananapi-f3: fix maximum CPU core voltage

Fabio Estevam <[email protected]>
arm64: dts: rockchip: Fix rk3588s-roc-pc audio description

Fabio Estevam <[email protected]>
arm64: dts: rockchip: Fix rk3399-roc-pc-plus analog audio

Jakob Unterwurzacher <[email protected]>
arm64: dts: rockchip: fix emmc reset polarity on px30-cobra

Quentin Schulz <[email protected]>
arm64: dts: rockchip: fix eMMC reset polarity on PX30 Ringneck

Quentin Schulz <[email protected]>
arm64: dts: rockchip: fix eMMC reset polarity on PP-1516

Michael Scott <[email protected]>
arm64: dts: qcom: x1-dell-thena: mark l12b and l15b always-on

Krzysztof Kozlowski <[email protected]>
arm64: dts: qcom: sm6115-pro1x: Correct touchscreen GPIO flags

Jianping Li <[email protected]>
arm64: dts: qcom: kodiak: avoid EFI overlap for ADSP remote heap

Oren Klopfer <[email protected]>
Revert "arm64: dts: rockchip: Further describe the WiFi for the Pinephone Pro"

Chunkai Deng <[email protected]>
rpmsg: glink: smem: order FIFO read after availability check

Linkai Gong <[email protected]>
scsi: fnic: Use GFP_ATOMIC for VLAN alloc under spinlock

Petr Vaganov <[email protected]>
scsi: core: Fill in DMA padding bytes in scsi_alloc_sgtables()

Tejun Heo <[email protected]>
sched_ext: Keep kick_sync waiting on the rq's own CPU

Tejun Heo <[email protected]>
sched_ext: Fix scx_bpf_dsq_reenq___compat kfunc extern prototype

Tao Cui <[email protected]>
sched_ext: Don't BUG_ON a destroyed DSQ in process_deferred_reenq_users

Tejun Heo <[email protected]>
sched_ext: Fix inverted ops.core_sched_before() invocation

fangqiurong <[email protected]>
sched_ext: Fix exit_task leak on fork failure during enable

fangqiurong <[email protected]>
sched_ext: Fix scx_bpf_dsq_move_to_local___v2 compat detection

Tejun Heo <[email protected]>

    sched_ext: Count rq lock releases in rq->scx.lock_drop_seq

Tejun Heo <[email protected]>

    sched_ext: Fix rq->core_pick corruption under core scheduling

Tejun Heo <[email protected]>
sched_ext: Fix this_rq() assumptions in dispatch kfuncs

Tejun Heo <[email protected]>
sched_ext: Replace SCX_RQ_BAL_KEEP with a dispatch verdict return

Tejun Heo <[email protected]>
sched/core: Make core-sched flips wait for in-flight selections

Tejun Heo <[email protected]>
sched/core: Handle pick_task() releasing the rq lock

Cong Nguyen <[email protected]>
media: staging/ipu7: fix async notifier UAF on probe error path

Hao-Qun Huang <[email protected]>
staging: media: tegra-video: vi: fix probe failure on skipped last port

Hao-Qun Huang <[email protected]>
staging: media: tegra-video: fix of_node_put() on VIP parse errors

Wentao Guan <[email protected]>
wifi: mt76: mt7925: cancel pending mlo_pm_work

Doruk Tan Ozturk <[email protected]>
wifi: ath6kl: clamp assoc request/response lengths before subtracting IE offsets

David Lee <[email protected]>
udf: reject VAT indexes equal to the entry count

Chuck Lever <[email protected]>
svcrdma: Validate Read chunk positions before reconstruction

Chuck Lever <[email protected]>
svcrdma: Use svc_xprt_put to free listener on create failure

Chris Mason <[email protected]>
svcrdma: Reject Write/Reply chunks with segcount 0

Chuck Lever <[email protected]>
svcrdma: Reject Read lists that exceed the page budget

Chuck Lever <[email protected]>
svcrdma: Reject oversized Read segments at decode time

Chuck Lever <[email protected]>
svcrdma: Reject inline replies that overflow the pull-up buffer

Chuck Lever <[email protected]>
svcrdma: Reject connection when transport allocation fails

Chris Mason <[email protected]>
svcrdma: Fix unmatched rn_unregister on failed accept

Chris Mason <[email protected]>
svcrdma: Fix pcl_for_each_segment for empty chunks

Chris Mason <[email protected]>
svcrdma: Fix offset arithmetic in read_chunk_range

Chuck Lever <[email protected]>
svcrdma: Clear sc_cm_id when ADDR_CHANGE replacement fails

Chuck Lever <[email protected]>
svcrdma: Reorder rpcrdma_rn_unregister before rdma_destroy_id

Jérémy Jean <[email protected]>
SUNRPC: wait for in-flight client TLS handshake callback

Chuck Lever <[email protected]>
SUNRPC: Reject short RFC 4121 MIC tokens in gss_krb5_verify_mic_v2

Chuck Lever <[email protected]>
SUNRPC: Reject krb5 v2 wrap tokens with oversized ec field

Chris Mason <[email protected]>
SUNRPC: reject duplicate CREDS_VALUE options

Chris Mason <[email protected]>
sunrpc: init gssp_lock before publishing proc entry

Chris Mason <[email protected]>
SUNRPC: harden gss_unwrap_resp_priv length checks

Chris Mason <[email protected]>
SUNRPC: harden gss_krb5_unwrap_v2 against short tokens

Chris Mason <[email protected]>
SUNRPC: Guard svcauth_gss_release() dispatch on rq_auth_stat

Luxiao Xu <[email protected]>
sunrpc: fix use-after-free in __rpc_clnt_handle_event and __rpc_clnt_remove_pipedir

Chris Mason <[email protected]>
SUNRPC: fix gssx_dec_option_array error path bugs

Jeff Layton <[email protected]>
sunrpc: defer rq_argp and rq_resp free until after RCU grace period

Chuck Lever <[email protected]>
SUNRPC: close backchannel before destroying callback service

Chuck Lever <[email protected]>
SUNRPC: Check svc pool percpu counter allocation

Jeff Layton <[email protected]>
SUNRPC: always drain cache_cleaner before destroying a cache_detail

Ameer Hamza <[email protected]>
SUNRPC: Restore NUMA_NO_NODE for svc thread allocations in global mode

Jeff Layton <[email protected]>
sunrpc: route to a populated pool in svc_pool_for_cpu()

Chris Mason <[email protected]>
SUNRPC: svcauth_gss: enforce krb5 token minimum length

Chris Mason <[email protected]>
SUNRPC: Zero rpc_gss_wire_cred at svcauth_gss_decode_credbody() entry

Chris Mason <[email protected]>

    SUNRPC: xdr_buf_trim: clamp buf->len to avoid underflow

Felix Gu <[email protected]>
phy: fsl-imx8mq-usb: fix typec switch leak on probe error path

Jiacheng Yu <[email protected]>
params: fix charp corruption on allocation failure

Dave Airlie <[email protected]>
nouveau/gem: reserve the bo in the info ioctl around the vma lookup

Stanislaw Gruszka <[email protected]>
module/kallsyms: fix nextval for data symbol lookup

Harshit Varu <[email protected]>
mptcp: fix uninitialized local_id in syncookie MP_JOIN reconstruction

Qing Ming <[email protected]>
mpls: reload header after pskb_may_pull()

Thiébaud Weksteen <[email protected]>
module: validate string table section types

Coly Li <[email protected]>

    md: do overflow check for sb->bblog_shift in super_1_load()

Yunye Zhao <[email protected]>
md/raid10: fix still_degraded being inverted in raid10_sync_request()

Anup Vishwakarma <[email protected]>
mailbox: qcom-ipcc: fix duplicate channel allocation across holes

Bryam Vargas <[email protected]>
libnvdimm/labels: Prevent integer overflow in __nd_label_validate()

Günther Noack <[email protected]>
landlock: Require LANDLOCK_ACCESS_FS_MAKE_REG for whiteout creation

Yuyang Huang <[email protected]>
ipv6: use RCU iterator to dump route exceptions

Andrea Mayer <[email protected]>
ipv6: rpl: fix NULL dereference of idev in ipv6_rpl_srh_rcv()

Zhiling Zou <[email protected]>
ip6_gre: fix hardware header length for NBMA tunnels

Zhiling Zou <[email protected]>
ip6_tunnel: use skb_cow_head() in ip6_tnl_xmit()

Zhiling Zou <[email protected]>
ip: orphan prefetched skbs before multicast forwarding

Anton Danilov <[email protected]>
ipip: fix skb leak in collect_md mode when metadata_dst allocation fails

Max Kellermann <[email protected]>
jbd2: check need_resched() when skipping busy checkpoint buffers

Max Kellermann <[email protected]>
jbd2: bound shrinker scans by examined checkpoint buffers

Pratyush Yadav (Google) <[email protected]>
kho: fix size calculation in kho_preserved_memory_reserve()

Hui Su <[email protected]>
kasan: fix cache shrink race with CPU hotplug

Ibrahim Abdelkader <[email protected]>
Bluetooth: hci_sync: Clear HCI_CMD_PENDING when dropping the last request

Guangshuo Li <[email protected]>
Bluetooth: hci_intel: fix usage_count leak when autosuspend_delay is negative

Guangshuo Li <[email protected]>
Bluetooth: hci_h5: fix usage_count leak when autosuspend_delay is negative

Valentin Kindschi <[email protected]>
Bluetooth: hci_event: clear HCI_LE_ADV only on a created connection

Xin Chen <[email protected]>
Bluetooth: hci_core: use skb_get() instead of skb_clone() for req_skb

Valentin Kindschi <[email protected]>
Bluetooth: hci_conn: re-enable advertising only for peripheral role

Chengfeng Ye <[email protected]>
Bluetooth: RFCOMM: serialize security confirmation handling

Hang Nan <[email protected]>
Bluetooth: ISO: fix use-after-free of listener socket in iso_conn_ready

Gongwei Li <[email protected]>
Bluetooth: hci_uart: Fix false success return in hci_uart_setup()

Guangshuo Li <[email protected]>
Bluetooth: hci_bcm: fix usage_count leak when autosuspend_delay is negative

Lorenzo Stoakes (ARM) <[email protected]>
Bluetooth: hci_bcm4377: Ignore reserved PHY in ext adv reports on BCM4378

Terry Bowman <[email protected]>
cxl/ras: Fix cxl_rch_get_aer_severity() wrong severity register

Alison Schofield <[email protected]>
cxl/pmem: Format the nvdimm serial number as unsigned decimal

Dave Jiang <[email protected]>
cxl/mce: Make the MCE notifier per-region

Zhenhao Wan <[email protected]>
cxl/features: bound fwctl command payload to the input buffer

Hui Su <[email protected]>
cpufreq: schedutil: Fix rate limit overflow

Haoxiang Li <[email protected]>
cpufreq: apple-soc: Fix OPP table cleanup

Kuan-Wei Chiu <[email protected]>
coresight: etm3x: Fix cntr_val_show() to match cntr_val_store() behavior

Bryam Vargas <[email protected]>
dm array: reject an array block whose value size is not the caller's

Bryam Vargas <[email protected]>
dm array: validate array block headers on read

Ilya Krutskih <[email protected]>
dm raid1: reserve space for NUL-terminator in build_constructor_string()

liyouhong <[email protected]>
dm-era: fix shadowed superblock leak on take-snap failure

Mikulas Patocka <[email protected]>
dm-io: report non-retryable errors separatedly

Keith Busch <[email protected]>
dm-io: clone the source bio instead of copying its biovec

Jérémy Jean <[email protected]>
bpf: Harden bloom filter sizing and indexing on 32-bit kernels

Jia Zhu <[email protected]>
buffer: avoid tail commit walk for uptodate folios

Daniel Borkmann <[email protected]>
bpf: Disable preemption in __bpf_get_stack

Vineet Gupta <[email protected]>
bpf, x86: Fix per-CPU address resolution into an extended register

Joe Damato <[email protected]>
bnxt_en: Write doorbell when linearizing skb fails

Jiangshan Yi <[email protected]>
bnx2x: fix double free in bnx2x_init_firmware() error path

HyeongJun An <[email protected]>
Bluetooth: eir: Fix OOB read in eir_get_service_data()

Junjie Cao <[email protected]>
Bluetooth: btusb: limit RTL8761B BROKEN_EXT_SCAN quirk to 0bda:a728

Christoph Zwerschke <[email protected]>
Bluetooth: btusb: Add ASUS USB-BT600 for Realtek 8761CU

Christoph Zwerschke <[email protected]>
Bluetooth: btusb: Add ASUS USB-BT540 for Realtek 8761CU

胡连勤 <[email protected]>
block: set QUEUE_FLAG_DYING unconditionally in blk_mark_disk_dead()

Keith Busch <[email protected]>
block: validate user space vectors during extraction

Junjie Cao <[email protected]>
backlight: aw99706: Honor the core blank state in update_status()

Junjie Cao <[email protected]>
backlight: aw99706: Fix DT property names to match binding

Hongyan Xu <[email protected]>
auxdisplay: charlcd: cancel backlight work on registration failure

Niklas Cassel <[email protected]>
ata: libata-scsi: fix DSM TRIM for sector sizes larger than 2048 bytes

Ethan Nelson-Moore <[email protected]>
ARM: 9477/1: Disable broken eBPF JIT on the Risc PC

Matt Turner <[email protected]>
alpha: marvel: Fix lock ordering in init_io7_irqs()

Matt Turner <[email protected]>
alpha: marvel: Fix irq_set_status_flags to use correct IRQ number

Krzysztof Wilczyński <[email protected]>
alpha/PCI: Fix I/O port accessor argument order in pci_legacy_write()

Rafael J. Wysocki <[email protected]>
ACPI: TAD: Add locking around AML evaluations

Rafael J. Wysocki <[email protected]>
ACPI: scan: Avoid registering platform devices with resource overlaps

Anirudh Prasad <[email protected]>
ACPI: pfr_update: fix stack buffer overflow in query_capability()

Christian Loehle <[email protected]>
ACPI: CPPC: Skip desired_perf read in cppc_get_perf()

Christian Loehle <[email protected]>
ACPI: CPPC: Reject desired_perf reads on _CPC revision 4+

TanZheng <[email protected]>
ACPI: APEI: GHES: fix ARM section length accounting after header

Nirmoy Das <[email protected]>
ACPI: APEI: Fix ERST timeout unit conversion

Terry Bowman <[email protected]>
acpi/apei/ghes: Use raw_spinlock_t for CXL CPER work locks

ZhaoJinming <[email protected]>
accel/rocket: Fix error path handling in rocket_job_run()

Shuvam Pandey <[email protected]>
accel/rocket: initialize job domain before cleanup paths

Muhammad Bilal <[email protected]>
accel/rocket: fix NULL dereference and integer overflow in rocket_job_push()

Guillaume Morin <[email protected]>
hugetlb: only adjust reservation during unmapping if mapcount is 0

Ivaylo Dimitrov <[email protected]>
hsi: omap_ssi_core: fix missing DMA mask setup for SSI controller device

Youngjae Kwon <[email protected]>
fsnotify: Fix stale object mask after concurrent mark updates

Tien Sung Ang <[email protected]>
fpga: stratix10-soc: Fix SVC mailbox handling during reconfiguration

Marek Czernohous <[email protected]>
forcedeth: fix off-by-one when saving/restoring non-PCI config space

Randy Dunlap <[email protected]>
fonts: fixup font.h kernel-doc warnings

Myeonghun Pak <[email protected]>
fbdev: uvesafb: unregister connector callback on init failure

Hui Su <[email protected]>
fbdev: ssd1307fb: defer I2C transfers from damage callbacks

Florian Fuchs <[email protected]>
fbdev: pvr2fb: correct user pointer annotation and sentinel initializer

Runyu Xiao <[email protected]>
fbdev: omapfb: panel-dsi-cm: initialize lock before registering display

Yemu Lu <[email protected]>
fat: restore original value when fat_ent_write failed

Chengfeng Ye <[email protected]>
fanotify: fix use-after-free of file range info

Jan Kara <[email protected]>
ext2: Fix lost inode updates for IS_SYNC inodes

Nikhil Gurudasani <[email protected]>
erofs: skip sufficiently large global buffers when resizing

Jinjie Ruan <[email protected]>
entry: Fix seccomp bypass after ptrace with TSYNC

Ard Biesheuvel <[email protected]>
efivarfs: Rate limit statfs() handler

Yichong Chen <[email protected]>
ecryptfs: show filename encryption options

Yichong Chen <[email protected]>
ecryptfs: release message context on send failure

Yichong Chen <[email protected]>
ecryptfs: reject too-small tag 70 packets

HanQuan <[email protected]>
ecryptfs: reject oversized encrypted_key_size in parse_tag_3_packet

Yichong Chen <[email protected]>
ecryptfs: pass packet set buffer size to parser

Yichong Chen <[email protected]>
ecryptfs: hold msg ctx list lock when cleaning daemon queue

Yichong Chen <[email protected]>
ecryptfs: fix tag 11 packet exact-fit size check

Pengpeng Hou <[email protected]>
eCryptfs: bound the packet-length peek to the user buffer

Hongling Zeng <[email protected]>
ntfs: verify run length exceeding volume boundary

Hongling Zeng <[email protected]>
ntfs: validate non-resident attribute offsets

Hyunchul Lee <[email protected]>
ntfs: reject invalid MFT LCNs from boot sector

Hyunchul Lee <[email protected]>
ntfs: reject invalid empty mapping pairs

Bryam Vargas <[email protected]>
ntfs: bound the free-cluster bitmap scan to the volume

Konstantin Komarov <[email protected]>

    fs/ntfs3: bound page_lcns[] index by the log record

Samuel Page <[email protected]>
fs/ntfs3: fix info-leak on partial LZNT decompress in ni_read_frame()

Xiang Mei <[email protected]>
fs/ntfs3: validate dirty page table on log replay

Deepanshu Kartikey <[email protected]>

    eventfs: Initialize ei->children and ei->list in init_ei()

Guangshuo Li <[email protected]>
HID: intel-thc-hid: intel-quickspi: fix autosuspend cleanup during teardown

Guangshuo Li <[email protected]>
HID: intel-thc-hid: intel-quicki2c: fix autosuspend cleanup during teardown

HyeongJun An <[email protected]>
HID: intel-thc-hid: intel-quickspi: bound GET_REPORT response to the caller buffer

HyeongJun An <[email protected]>
HID: intel-thc-hid: intel-quickspi: validate report size before copy

Jiangshan Yi <[email protected]>
HID: mcp2221: validate report size in mcp2221_raw_event()

Jiangshan Yi <[email protected]>
HID: mcp2221: clear rxbuf after I2C/SMBus transfer completes

Jiangshan Yi <[email protected]>
HID: mcp2221: stop device IO before hid_hw_stop

Baul Lee <[email protected]>
HID: universal-pidff: stop the device when force-feedback init fails

Doruk Tan Ozturk <[email protected]>
HID: sony: fix UAF of ghl_poke_timer / ghl_urb at driver unbind

Haoxiang Li <[email protected]>
HID: sensor: custom: Fix field sysfs group cleanup on failure

Xu Rao <[email protected]>
HID: roccat: free buffered reports when destroying device

Ibrahim Hashimov <[email protected]>
HID: picolcd: clamp eeprom debugfs read to bytes actually received

Stuart Hayhurst <[email protected]>
HID: corsair-void: Check size of status and firmware events before reading them

Andre Eikmeyer <[email protected]>
HID: apple: preserve keyboard backlight across T2 resume

Bryam Vargas <[email protected]>
smb: client: restore the data_offset bound in is_valid_oplock_break()

Bryam Vargas <[email protected]>
smb: client: reject a tree connect response whose byte count is too small

Fredric Cover <[email protected]>
smb: client: harden DFS cache against invalid target hints

Frank Sorenson <[email protected]>
smb: client: fix use-before-check of ReparseDataLength in reparse_buf_ptr()

Frank Sorenson <[email protected]>
smb: client: fix OOB read/write from unvalidated DataOffset in coalesce_t2()

Frank Sorenson <[email protected]>
smb: client: fix copy-paste error in WSL EA length accounting for $LXDEV

Frank Sorenson <[email protected]>
smb: client: fix ALIGN() overflow in symlink_data() error context loop

Aldo Ariel Panzardo <[email protected]>
ksmbd: only rebind the reopened file's own oplock on durable reconnect

Fredric Cover <[email protected]>

    smb: client: clear ce->tgthint in free_tgts()

Frank Sorenson <[email protected]>
smb: client: fix UAF and buffer leak in cifs_check_trans2() for malformed secondary T2

Jiangshan Yi <[email protected]>
smb: client: clear setuid/setgid bit on write with cifsacl/modefromsid/posix extensions

Frank Sorenson <[email protected]>
cifs: use cifs_invalidate_cache() in cifs_do_truncate() for O_TRUNC

Frank Sorenson <[email protected]>

    cifs: fix loff_t underflow in cifs_remap_file_range() when len == 0

Frank Sorenson <[email protected]>
cifs: clear tcon after cifsFileInfo_put() in cifs_file_set_size()

Frank Sorenson <[email protected]>
cifs: call pagecache_isize_extended() in cifs_setsize() when extending

Frank Sorenson <[email protected]>
cifs: add cifs_resize_file_locked() to guard fscache_resize_cookie() under i_rwsem

Jérémy Jean <[email protected]>
audit: avoid dropping live tree ref on fsnotify rule autoremove

Qu Wenruo <[email protected]>
btrfs: do not overwrite NODATASUM flag when removing NODATACOW flag

Shuangpeng Bai <[email protected]>
btrfs: fix extent map leak in NOCOW direct I/O write

Guanghui Yang <[email protected]>
btrfs: drop recovered reloc root refs on recovery failure

Matthew Brown <[email protected]>
ceph: fix leaked inode reference on writeback abort at umount

Max Kellermann <[email protected]>
ceph: do not repeat ceph_trim_dentries() if no progress possible

Michael Bommarito <[email protected]>
ceph: cap delegated inode count in ceph_parse_deleg_inos()

Michael Bommarito <[email protected]>
ceph: bound xattr value length in __build_xattrs()

Michael Bommarito <[email protected]>
ceph: bound num_export_targets array for mds info v2/v3

Michael Bommarito <[email protected]>
ceph: bound MDSCapAuth path and fs_name decode in handle_session()

Michael Bommarito <[email protected]>
ceph: bound copied dentry name length in NFS export get_name

Jérémy Jean <[email protected]>
ceph: reject export_targets ranks >= CEPH_MAX_MDS in mdsmap decode

Max Kellermann <[email protected]>
ceph: force a cap message when a deferred revoke can't be acked immediately

Xiubo Li <[email protected]>
ceph: fix UAF in check_new_map() on session freed during unlock

Xiubo Li <[email protected]>
ceph: fix UAF in __kick_flushing_caps() on cf entry freed during unlock

Jérémy Jean <[email protected]>
libceph: reject buckets with mismatched CRUSH ids

Michael Bommarito <[email protected]>
libceph: validate OSD extent maps before cursor advance

Jeff Layton <[email protected]>
nfsd: use test_and_clear_bit for somebody_reclaimed to prevent lost update

Chuck Lever <[email protected]>
NFSD: Prevent client use-after-free during NFSv4.0 revoked-state cleanup

Chuck Lever <[email protected]>
NFSD: Prevent client use-after-free during delegation revoke

Chuck Lever <[email protected]>
NFSD: Prevent client use-after-free during admin state revocation

Chuck Lever <[email protected]>
NFSD: Prevent post-shutdown use-after-free in unlock_filesystem

Chuck Lever <[email protected]>
NFSD: Prevent lock owner use-after-free during client teardown

Jeff Layton <[email protected]>
nfsd: revoke copy-notify stateids before dropping their reference

Jeff Layton <[email protected]>
nfsd: release OPEN-decoded posix ACLs via op_release

Jeff Layton <[email protected]>
nfsd: reject reclaim LOCK after RECLAIM_COMPLETE

Robbie Ko <[email protected]>
nfsd: reject out-of-range useconds in NFSv2 SETATTR/CREATE

Robbie Ko <[email protected]>
nfsd: reject out-of-range nseconds in NFSv3 SETATTR and create ops

Jeff Layton <[email protected]>
nfsd: close shrinker/GC/fsnotify vs per-net shutdown race in filecache

Jeff Layton <[email protected]>
nfsd: move nfsd_debugfs_init() after nfsd4_init_slabs() in init_nfsd()

Jeff Layton <[email protected]>
nfsd: initialize DRC hash table before registering shrinker

Jeff Layton <[email protected]>
nfsd: initialize copy-notify stateid before publishing it

Chris Mason <[email protected]>
nfsd: hold rcu across localio cmpxchg retry

Chris Mason <[email protected]>

    nfsd: gate nfs3 setacl by argp->mask

Chuck Lever <[email protected]>

    nfsd: gate nfs2 setacl by argp->mask

Jeff Layton <[email protected]>
nfsd: fix XDR padding calculation in ff_encode_getdeviceinfo

Jeff Layton <[email protected]>
nfsd: fix XDR length calculation in nfsd4_ff_encode_layoutget

Jeff Layton <[email protected]>
nfsd: fix version mismatch loops in nfsd_acl_init_request()

Jeff Layton <[email protected]>
nfsd: fix UAF in async copy cancel and shutdown

Jeff Layton <[email protected]>
nfsd: fix stale s2s_cp_stateids IDR entry for async COPY

Jeff Layton <[email protected]>
nfsd: fix reply size estimate for GET_DIR_DELEGATION

Jeff Layton <[email protected]>
nfsd: fix refcount leak in nfsd_file_lru_add on insertion failure

NeilBrown <[email protected]>
nfsd: fix possible fh_compose of wrong dentry in nfsd4_create_file()

Chris Mason <[email protected]>
nfsd: fix partial-write detection in nfsd_direct_write

Nikol Kuklev <[email protected]>
nfsd: fix null dereference in nfsd4_setattr for deleg timestamp attrs

Jeff Layton <[email protected]>
nfsd: fix nfsd_file leak on inter-server COPY setup failure

Jeff Layton <[email protected]>
nfsd: fix netlink dumpit error handling for rpc_status_get

Jeff Layton <[email protected]>
nfsd: fix layout fence worker double-reference race

Jeff Layton <[email protected]>
nfsd: fix FL_SLEEP being set unconditionally for all LOCK types

Jeff Layton <[email protected]>
nfsd: fix fcache_disposal UAF by inlining dispose state into nfsd_net

Jeff Layton <[email protected]>
nfsd: fix dentry ref leak on V4ROOT export filehandle lookup

Chris Mason <[email protected]>
nfsd: fix cpntf publish race in nfs4_init_cp_state

Jeff Layton <[email protected]>
nfsd: fix clock domain mismatch in clients_still_reclaiming()

Jeff Layton <[email protected]>
nfsd: fix BUG_ON in nfsd4_alloc_layout_stateid on racing delegation revoke

NeilBrown <[email protected]>
nfsd: ensure nfsd_file_do_acquire() does not use a non-opened file

Jeff Layton <[email protected]>
nfsd: drop the stateid, not the stateowner, on seqid_op replay retry

Jeff Layton <[email protected]>
nfsd: don't free session slots that are still in use

Jeff Layton <[email protected]>
nfsd: defer vfree of compound ops to fix rpc_status UAF

Jeff Layton <[email protected]>
nfsd: defer setting NFSD4_CALLBACK_RUNNING in deleg_reaper

Jeff Layton <[email protected]>
nfsd: dedup nfs4_client_to_reclaim inserts

Chris Mason <[email protected]>
nfsd: convert nfsd_net boolean flags to unsigned long flags word

Jeff Layton <[email protected]>
nfsd: clear opcnt on compound arg release to prevent OOB read

Jeff Layton <[email protected]>
nfsd: clear CALLBACK_RUNNING on failed delegation recall queue

Jeff Layton <[email protected]>
nfsd: check nfsd4_acl_to_attr() return value in nfsd4_create()

Jeff Layton <[email protected]>
nfsd: check client ownership when cancelling a copy-notify stateid

Chris Mason <[email protected]>
nfsd: cap decoded POSIX ACL count to bound sort cost

Jeff Layton <[email protected]>
nfsd: block non-SAVEFH ops after FOREIGN PUTFH to prevent NULL deref

Jeff Layton <[email protected]>
nfsd: add missing read barrier to rpc_status_get dumpit seqcount retry

Jeff Layton <[email protected]>
nfsd: add filehandle match check to nfsd4_delegreturn()

Jeff Layton <[email protected]>
nfsd: add fh_want_write() for early-verified SETATTR in nfsd_proc_setattr()

Jeff Layton <[email protected]>
nfsd: widen nfsd_genl_rqstp address fields to sockaddr_storage

Jeff Layton <[email protected]>
nfsd: validate symlink target length in NFSv4 CREATE

Jeff Layton <[email protected]>
nfsd: validate sockaddr length per family in listener_set

Jeff Layton <[email protected]>
nfsd: validate nseconds in TIME_DELEG decode paths

Chris Mason <[email protected]>
nfsd: size fh_verify server sockaddr slot by xpt_locallen

Zhenghang Xiao <[email protected]>
nfsd: set SC_STATUS_FREED in nfsd4_drop_revoked_stid for delegations

Chuck Lever <[email protected]>
nfsd: sample writeback error cursor before async COPY loop

Jeff Layton <[email protected]>
nfsd: return NFS4ERR_NOTSUPP for unsupported netloc4 types

Jeff Layton <[email protected]>
nfsd: restore rq_status_counter to even on all nfsd_dispatch() exit paths

Chuck Lever <[email protected]>
nfsd: Reset write verifier when async COPY writeback fails

Chris Mason <[email protected]>
nfsd: release path refs on follow_down() error

Jeff Layton <[email protected]>
nfsd: RCU-protect cl_cb_session to fix use-after-free on session teardown

Jeff Layton <[email protected]>
lockd, nfsd: RCU-protect nlmsvc_ops dispatch

Tim Menninger <[email protected]>
pNFS: Fix EBUSY check in pnfs_layout_need_return

Junrui Luo <[email protected]>
NFSv4.1: fix layout segment leak on the pnfs_layout_process() forget path

Chris Mason <[email protected]>
nfsd: guard nfsd_serv deref in nfsd_file_net_dispose

Mike Snitzer <[email protected]>
NFSD: remove flawed WARN_ON_ONCE from nfsd_mode_check

Michael Bommarito <[email protected]>
NFSD: restart ssc_expire_umount walk after dropping nfsd_ssc_lock

Scott Mayhew <[email protected]>
NFSD: fix up error returned by write_threads()

Chuck Lever <[email protected]>
NFSD: Fix off-by-one in DRC bucket pruning limit

Chuck Lever <[email protected]>
NFSD: Encode only the status in NFS-ACL v2 GETACL error replies

Chuck Lever <[email protected]>
NFSD: check truncate permission under inode lock

Nate Prodromou <[email protected]>
NFS: fix delegation_hash_table leak when nfs4_server_common_setup() fails

Chris Mason <[email protected]>
NFS/localio: fix ref leak on nfs_uuid_add_file failure

Longlong Xia <[email protected]>
zsmalloc: account for handle size in class lookup

Sergey Senozhatsky <[email protected]>
zram: validate deflate params

Sergey Senozhatsky <[email protected]>
zram: set default primary compressor in zram_destroy_comps()

Longlong Xia <[email protected]>
zram: fix out-of-bounds access in writeback_store()

Longlong Xia <[email protected]>
zram: fix out-of-bounds access in read_block_state()

Ibrahim Hashimov <[email protected]>
ubifs: fix out-of-bounds read in signature length check

Jason Yang <[email protected]>
phy: rockchip-samsung-dcphy: fix out-of-range max_register

Krzysztof Wilczyński <[email protected]>
PCI/sysfs: Fix out-of-bounds read in pci_write_legacy_io()

Abdurrahman Hussain <[email protected]>
of: fix out-of-bounds read in of_alias_scan() stem parser

Ryusuke Konishi <[email protected]>
nilfs2: fix slab-out-of-bounds in nilfs_direct_propagate after truncation

Junrui Luo <[email protected]>
media: vicodec: fix out-of-bounds write in FWHT encoder

Weigang He <[email protected]>
media: cec: stm32: prevent out-of-bounds write on RX overflow

Vincent Mailhol <[email protected]>
lib/ucs2_string.c: fix out-of-bounds read in ucs2_strnlen()

Karl Mehltretter <[email protected]>
KVM: arm64: GICv2: Don't WARN on out-of-range GICV_DIR INTID

Claudiu Beznea <[email protected]>
i3c: renesas: Fix out-of-bounds access for newdevs mask

Xingrui Li <[email protected]>
HID: sensor-hub: Fix out-of-bounds write in sensor_hub_get_feature

Daisuke Matsuda <[email protected]>
fpga: altera-cvp: Avoid out-of-bounds read in trailing byte write

Terry Bowman <[email protected]>
cxl/ras: Fix cxl_rch_get_aer_info() out-of-bounds AER register read

Neill Kapron <[email protected]>
usb: gadget: f_fs: Prevent deadlock during ep0 read loop

Jeffin Philip <[email protected]>
usb: gadget: uvc: fix dangling pointers in uvc_function_bind() and uvc_function_unbind()

Jeffin Philip <[email protected]>
usb: gadget: uvc: Fix null pointer dereference in uvcg_video_init()

Yun Zhou <[email protected]>
usb: gadget: f_tcm: fix deadlock in usbg_make_tpg()

Joshua Crofts <[email protected]>
usb: gadget: midi2: remove default configfs groups on teardown

Myeonghun Pak <[email protected]>
usb: gadget: snps_udc_plat: clean up PHY on probe deferral

Sonali Pradhan <[email protected]>
usb: gadget: u_audio: Fix use-after-free on sound card disconnect

Huang Wei <[email protected]>
usb: typec: ucsi: use UCSI_TIMEOUT_MS for sync command completion

Fan Wu <[email protected]>
usb: typec: thunderbolt: Disable work before freeing tbt on remove

Xu Yang <[email protected]>
usb: typec: tcpci: pass correct rx_type to tcpm_pd_receive()

Xu Rao <[email protected]>
usb: typec: hd3ss3220: fix VBUS regulator error message

Johan Hovold <[email protected]>
USB: phy: fsl-usb: fix missing static keywords

Fan Wu <[email protected]>
usb: gadget: at91_udc: drain polled-VBUS timer/work before udc is freed

Pei Xiao <[email protected]>
usb: dwc3: gadget: Fix use-after-free in dwc3_gadget_free_endpoints due to race condition

Francesco Lavra <[email protected]>
usb: dwc2: gadget: Exit partial power down state when changing USB pull-up

Hao-Qun Huang <[email protected]>
staging: greybus: hid: fix SET_REPORT return value

Karl Mehltretter <[email protected]>

    serial: imx: serialize imx_uart_ports[] lifetime

Hans Verkuil <[email protected]>
Revert "media: v4l2-dev: fix error handling in __video_register_device()"

James Kim <[email protected]>
rapidio: mport_cdev: fix use-after-free in dma_req_free()

Bartosz Golaszewski <[email protected]>
powerpc/powermac: fix OF node refcount

Bryam Vargas <[email protected]>
misc: nsm: bound the device-reported response length

Xu Yang <[email protected]>
device property: fix infinite loop in fwnode_for_each_child_node()

Chun-Yi Lee <[email protected]>
debugfs: Fix lockdown check for mmap_prepare

Prasanna Kumar T S M <[email protected]>
cdx: Fix double free when sysfs file creation fails

Hui Su <[email protected]>
tracing: Fix use-after-free with same-name named triggers

Deepanshu Kartikey <[email protected]>
tracing: Fix use-after-free in trace_pipe read on sub-buffer order change

Ivan Immanuel Shaji <[email protected]>
tracing: Fix retry exhaustion in simple ring buffer reader swap

Vincent Donnefort <[email protected]>
tracing: Fix logged instance name on creation failure

Hui Su <[email protected]>
tracing: Fix crash passing ERR_PTR to kthread_stop()

Jérémy Jean <[email protected]>
tracing/user_events: Clear copied tracing state before fork duplication

Sanman Pradhan <[email protected]>
hwtracing: hisi_ptt: Propagate DMA reset timeout in trace_start()

Roger Pau Monne <[email protected]>
x86/xen: fix init of balloon stats again

Kiryl Shutsemau (Meta) <[email protected]>
x86/tdx: Fix zero-extension for 32-bit port I/O

Kiryl Shutsemau (Meta) <[email protected]>
x86/tdx: Fix off-by-one in port I/O handling

Kiryl Shutsemau (Meta) <[email protected]>
x86/insn-eval: Move assign_register() out of KVM as insn_assign_reg()

Yao Zi <[email protected]>
x86/locking: Use sfence for wmb() if SSE is available

Joy H.J. Lee <[email protected]>
tools/compiler: match glibc 2.42 definition of __attribute_const__

Ridong Chen <[email protected]>
mm: vmscan: fix node reclaim ignoring swappiness parameter

Johannes Weiner <[email protected]>
mm: page_alloc: fix non-movable reclaim storm in defrag_mode

Vlastimil Babka (SUSE) <[email protected]>
mm: page_alloc: move capture_control to the page allocator

Johannes Weiner <[email protected]>
mm: page_alloc: __GFP_FS lockdep annotation for direct compaction

Johannes Weiner <[email protected]>
mm: mempolicy: fix automatic numa balancing for shmem

Guopeng Zhang <[email protected]>
mm: memcontrol: update state_local when flushing NMI stats

Guopeng Zhang <[email protected]>
mm: memcg: stop reclaim when a limit update is superseded

Guopeng Zhang <[email protected]>
mm: memcg-v1: fix memsw and TCP failcnt accounting

Guopeng Zhang <[email protected]>
mm: memcg-v1: fix wrong linux-mm list address in deprecation warnings

Johannes Weiner <[email protected]>
mm: compaction: support non-movable compaction for pageblock requests

Hao Jia <[email protected]>
mm/zswap: fix global shrinker when memory cgroup is disabled

Breno Leitao <[email protected]>
mm/vmscan: report RCU-tasks quiescent states in shrink_lruvec()

Artem Lytkin <[email protected]>
mm/vmalloc: make vm_struct.nr_pages an unsigned long

Shengming Hu <[email protected]>
mm/slub: prevent pfmemalloc objects from entering the barn

Li Xiasong <[email protected]>
mm/slub: fix missing debugfs entries for caches created before sysfs init

Dev Jain <[email protected]>
mm/rmap: use huge_ptep_get() in try_to_migrate_one()

Dev Jain <[email protected]>
mm/rmap: use huge_ptep_get() in try_to_unmap_one()

Hyunwoo Kim <[email protected]>

    mm/pagewalk: fix stale walk->action escaping walk_pmd_range()

Dev Jain <[email protected]>
mm/page_vma_mapped: use huge_ptep_get() for hugetlb

Ye Liu <[email protected]>
mm/page_owner: use memcg_data snapshot to avoid TOCTOU in print_page_owner_memcg()

Alexander Graf <[email protected]>
mm/mm_init: deferred_grow_zone(): fix out-of-range first_deferred_pfn

Arvind Yadav <[email protected]>
mm/migrate_device: clear stale mapping after freeing swapcache

Dev Jain <[email protected]>
mm/migrate: use huge_ptep_get() in remove_migration_pte()

Breno Leitao <[email protected]>
mm/migrate: report RCU-tasks quiescent states in migrate_pages_batch()

Kairui Song <[email protected]>
mm/mglru: fix and remove redundant unevictable folio handling

Usama Arif <[email protected]>
mm/mempolicy: skip non-present PMDs when queueing folios

Usama Arif <[email protected]>
mm/madvise: skip device-private PMDs in cold and pageout walks

Breno Leitao <[email protected]>
mm/kmemleak: avoid soft lockup when scanning task stacks

Muchun Song <[email protected]>
mm/hugetlb_vmemmap: fix __hugetlb_vmemmap_optimize_folios()

Muchun Song <[email protected]>
mm/hugetlb: initialize gigantic bootmem hugepage struct pages earlier

Muchun Song <[email protected]>
mm/hugetlb: fix boot panic with CONFIG_DEBUG_VM and HVO bootmem pages

Zi Yan <[email protected]>
mm/huge_memory: use folio's memcg inside __folio_split()

Usama Arif <[email protected]>
mm/huge_memory: skip device-private PMDs in madvise_free_huge_pmd

David Hildenbrand (Arm) <[email protected]>
mm/gup: fix always draining LRU caches in collect_longterm_unpinnable_folios()

Breno Leitao <[email protected]>
mm, swap: ratelimit bad swap entry reports

Youngjun Park <[email protected]>
mm, swap: don't free a hibernation slot that is in the swap cache

Jordan R Abrahams-Whitehead <[email protected]>
include/linux/list.h: mark list_add and __list_add as __always_inline

Hyunwoo Kim <[email protected]>
apparmor: fix out-of-bounds write when null terminating a label vec

Jann Horn <[email protected]>
apparmor: fix cred UAF caused by begin_current_label_crit_section()

Chengfeng Ye <[email protected]>
KEYS: trusted: Fix TPM teardown ordering

Miguel Ojeda <[email protected]>
kbuild: rust: keep Rust objects out of Clang LTO with inline helpers

Miguel Ojeda <[email protected]>
kbuild: rust: preserve unreachable traps with inline helpers

Gary Guo <[email protected]>
rust: cfi: disable function merging if CFI is enabled

Younes Akhouayri <[email protected]>
rust: num: restrict bool conversion to unsigned Bounded

Miguel Ojeda <[email protected]>
objtool/rust: add one more noreturn Rust function

Nikolai Grlica <[email protected]>
rust: kernel: list: fix incorrect pop_back example comment

Miguel Ojeda <[email protected]>
rust: kbuild: disambiguate zerocopy_derive for rusttest

Danilo Krummrich <[email protected]>
rust: devres: ensure revocation is complete before device finishes unbinding

Danilo Krummrich <[email protected]>
rust: devres: fix race between concurrent revokers

Younes Akhouayri <[email protected]>
rust: dma: return zero for Coherent reads past EOF

Miguel Ojeda <[email protected]>

    rust: rust_is_available: warn for `bindgen` < 0.72.1 && libclang >= 22

FUJITA Tomonori <[email protected]>
rust: bug: prevent dead_code warning from warn_on!'s flags constant

FUJITA Tomonori <[email protected]>
rust: bug: fix warn_on macro build error on UML

FUJITA Tomonori <[email protected]>
rust: bug: skip arch-specific asm in testlib builds

Antoni Boucher <[email protected]>
rust: kbuild: disambiguate zerocopy for rusttest

Miguel Ojeda <[email protected]>
objtool/rust: add one more noreturn Rust function for Rust 1.99.0

Jérémy Jean <[email protected]>
timers/itimer: Zero-init old itimerval before copy to userspace

Ke Sun <[email protected]>
rust: fmt: fix {:p} printing stack addresses

Gaurav Batra <[email protected]>
powerpc/pseries/iommu: switch to Default DMA window during kdump

Chen Linxuan <[email protected]>
pidfd: hold exec_update_lock around namespace ioctl

Vivek Parikh <[email protected]>
ovl: fix double end_creating() on the casefold-mismatch path

Baokun Li <[email protected]>
fs: fix user path of nested backing files

Felix Yan <[email protected]>
clocksource/drivers/timer-sun4i: Advertise a real minimum delta

WenTao Liang <[email protected]>
clocksource/drivers/nxp-pit: Fix IRQ leak on cpuhp_setup_state error path

Matt Turner <[email protected]>
alpha: don't leak hardware-fabricated FP exception bits to user space

FUJITA Tomonori <[email protected]>
rust: time: fix as_micros_ceil() rounding near i64::MAX

Christoph Hellwig <[email protected]>
iomap: don't free integrity payload that doesn't exist

Matt Turner <[email protected]>
alpha: fix ieee_swcr_to_fpcr setting FPCR_DNOD unconditionally

Fangzhi Zuo <[email protected]>
drm/amd/display: Prune per-tile Timing from Apple Studio Display Primary Tile

Jerry Zuo <[email protected]>
drm/amd/display: hide Apple Studio Display secondary tile

Vincent Donnefort <[email protected]>
ring-buffer: Fix subbuf resize race with ring buffer readers

Boris Burkov <[email protected]>
btrfs: write-protect folios during data writeback

Jon Hunter <[email protected]>
ASoC: tegra: Sort MBDRC register defaults

Jon Hunter <[email protected]>
ASoC: tegra: Sort ADMAIF register defaults

Jon Hunter <[email protected]>
ASoC: tegra: Fix the MIXER enable default value

Jon Hunter <[email protected]>
ASoC: tegra: Fix the I2S enable default value

Peter Ujfalusi <[email protected]>
ASoC: tegra210_mixer: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: tegra210_i2s: sort the Tegra264 register default table

Peter Ujfalusi <[email protected]>
ASoC: tegra210_i2s: sort the register default table

Fangzhi Zuo <[email protected]>
drm/amd/display: Skip Update HDCP Config In Transition State

-------------

Diffstat:

 Documentation/ABI/testing/sysfs-bus-nvdimm         |   3 +-
 Documentation/admin-guide/blockdev/zoned_loop.rst  |   9 +-
 Makefile                                           |  17 +-
 arch/alpha/include/uapi/asm/fpu.h                  |   8 +-
 arch/alpha/kernel/pci-sysfs.c                      |   6 +-
 arch/alpha/kernel/sys_marvel.c                     |  25 +-
 arch/alpha/kernel/traps.c                          |   6 +-
 arch/alpha/math-emu/math.c                         |  88 ++++-
 arch/arm/Kconfig                                   |   2 +-
 arch/arm64/boot/dts/qcom/kodiak.dtsi               |   9 +-
 arch/arm64/boot/dts/qcom/sm6115-fxtec-pro1x.dts    |   2 +-
 arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi        |   2 +
 arch/arm64/boot/dts/rockchip/px30-cobra.dtsi       |   2 +-
 arch/arm64/boot/dts/rockchip/px30-pp1516.dtsi      |   2 +-
 arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi    |   2 +-
 .../boot/dts/rockchip/rk3399-pinephone-pro.dts     |  18 -
 .../arm64/boot/dts/rockchip/rk3399-roc-pc-plus.dts |  12 +
 arch/arm64/boot/dts/rockchip/rk3588s-roc-pc.dts    |  23 +-
 arch/arm64/kernel/compat_alignment.c               |   4 +-
 arch/arm64/kernel/proton-pack.c                    |   9 +-
 arch/arm64/kvm/vgic/vgic-v2.c                      |   3 +-
 arch/openrisc/kernel/entry.S                       |  43 ++-
 arch/powerpc/kernel/pci-common.c                   |   9 +-
 arch/powerpc/platforms/powermac/low_i2c.c          |   2 +-
 arch/powerpc/platforms/pseries/iommu.c             |  23 +-
 arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts    |   4 +-
 arch/riscv/boot/dts/spacemit/k1-milkv-jupiter.dts  |   4 +-
 arch/riscv/boot/dts/spacemit/k1-musepi-pro.dts     |   4 +-
 arch/riscv/boot/dts/spacemit/k1-orangepi-r2s.dts   |   4 +-
 arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts   |   4 +-
 arch/riscv/include/asm/acpi.h                      |  19 +
 arch/riscv/kernel/unaligned_access_speed.c         |  19 +-
 arch/riscv/kvm/vcpu_pmu.c                          |  14 +-
 arch/s390/include/asm/percpu.h                     |   4 +-
 arch/s390/kernel/perf_cpum_cf.c                    | 221 ++++++++----
 arch/x86/coco/tdx/tdx.c                            |  10 +-
 arch/x86/include/asm/barrier.h                     |   2 +-
 arch/x86/include/asm/insn-eval.h                   |  36 ++
 arch/x86/kvm/emulate.c                             |  26 +-
 arch/x86/net/bpf_jit_comp.c                        |   2 +-
 block/bio.c                                        |  56 ++-
 block/blk-map.c                                    |   2 +-
 block/fops.c                                       |   2 +-
 block/genhd.c                                      |   1 +
 drivers/accel/rocket/rocket_job.c                  |  32 +-
 drivers/acpi/acpi_platform.c                       |  45 ++-
 drivers/acpi/acpi_tad.c                            |  46 ++-
 drivers/acpi/apei/erst.c                           |   2 +-
 drivers/acpi/apei/ghes.c                           |  52 ++-
 drivers/acpi/cppc_acpi.c                           |  24 +-
 drivers/acpi/pfr_update.c                          |  45 +--
 drivers/ata/libata-scsi.c                          |  28 +-
 drivers/auxdisplay/charlcd.c                       |  21 +-
 drivers/base/arch_numa.c                           |  12 +
 drivers/base/power/main.c                          |   1 +
 drivers/base/property.c                            |  19 +-
 drivers/block/zloop.c                              |   3 +-
 drivers/block/zram/backend_deflate.c               |  10 +-
 drivers/block/zram/zram_drv.c                      |  14 +-
 drivers/bluetooth/btrtl.c                          |  13 -
 drivers/bluetooth/btusb.c                          |  14 +
 drivers/bluetooth/hci_bcm.c                        |   1 +
 drivers/bluetooth/hci_bcm4377.c                    |   1 +
 drivers/bluetooth/hci_h5.c                         |   4 +-
 drivers/bluetooth/hci_intel.c                      |   1 +
 drivers/bluetooth/hci_ldisc.c                      |   2 +-
 drivers/bluetooth/hci_serdev.c                     |   2 +-
 drivers/cdx/cdx.c                                  |   7 +-
 drivers/char/hw_random/stm32-rng.c                 |  10 +-
 drivers/char/ipmi/ipmb_dev_int.c                   |   5 +-
 drivers/char/ipmi/ipmi_msghandler.c                |   4 +
 drivers/char/tpm/tpm_i2c_nuvoton.c                 |   6 +-
 drivers/clocksource/timer-nxp-pit.c                |   4 +-
 drivers/clocksource/timer-sun4i.c                  |   2 +-
 drivers/cpufreq/apple-soc-cpufreq.c                |  36 +-
 drivers/cpufreq/cppc_cpufreq.c                     |   2 +-
 drivers/crypto/atmel-ecc.c                         |  46 +--
 drivers/crypto/intel/iaa/iaa_crypto_main.c         |  27 +-
 drivers/cxl/core/features.c                        |   8 +-
 drivers/cxl/core/mbox.c                            |   8 -
 drivers/cxl/core/mce.c                             |  27 +-
 drivers/cxl/core/pmem.c                            |  10 +-
 drivers/cxl/core/ras.c                             |   1 -
 drivers/cxl/core/ras_rch.c                         |  27 +-
 drivers/cxl/core/region.c                          |  43 +--
 drivers/cxl/cxl.h                                  |  11 +-
 drivers/cxl/cxlmem.h                               |   2 -
 drivers/cxl/pci.c                                  |   1 -
 drivers/cxl/pmem.c                                 |   2 +-
 drivers/fpga/altera-cvp.c                          |  10 +-
 drivers/fpga/stratix10-soc.c                       |  21 +-
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c  |  79 ++++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c |  28 +-
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c  |  11 +
 drivers/gpu/drm/amd/display/dc/dc_types.h          |   1 +
 drivers/gpu/drm/nouveau/nouveau_gem.c              |  11 +-
 drivers/hid/hid-apple.c                            |  18 +-
 drivers/hid/hid-corsair-void.c                     |  17 +
 drivers/hid/hid-mcp2221.c                          |  17 +-
 drivers/hid/hid-picolcd_debugfs.c                  |   9 +
 drivers/hid/hid-roccat.c                           |  13 +-
 drivers/hid/hid-sensor-custom.c                    |   9 +-
 drivers/hid/hid-sensor-hub.c                       |  46 ++-
 drivers/hid/hid-sony.c                             |   4 +-
 drivers/hid/hid-universal-pidff.c                  |   4 +-
 .../intel-thc-hid/intel-quicki2c/pci-quicki2c.c    |   1 +
 .../intel-thc-hid/intel-quickspi/pci-quickspi.c    |  10 +-
 .../intel-thc-hid/intel-quickspi/quickspi-dev.h    |   1 +
 .../intel-thc-hid/intel-quickspi/quickspi-hid.c    |   2 +-
 .../intel-quickspi/quickspi-protocol.c             |  19 +-
 .../intel-quickspi/quickspi-protocol.h             |   2 +-
 drivers/hsi/controllers/omap_ssi_core.c            |   6 +
 drivers/hwmon/max6621.c                            |   8 +-
 .../hwtracing/coresight/coresight-etm3x-sysfs.c    |  15 +-
 drivers/hwtracing/ptt/hisi_ptt.c                   |  20 +-
 drivers/i2c/busses/i2c-mxs.c                       |   5 +-
 drivers/i3c/device.c                               |   2 +-
 drivers/i3c/internals.h                            |   5 +
 drivers/i3c/master.c                               |  18 +-
 drivers/i3c/master/adi-i3c-master.c                |  15 +-
 drivers/i3c/master/renesas-i3c.c                   | 142 +++++---
 drivers/i3c/master/svc-i3c-master.c                |  10 +-
 drivers/infiniband/core/ib_core_uverbs.c           |   3 +
 drivers/infiniband/core/ucma.c                     |  14 +-
 drivers/infiniband/core/uverbs_main.c              |   1 +
 drivers/infiniband/core/uverbs_std_types_mr.c      |   6 +-
 drivers/infiniband/hw/cxgb4/device.c               |   6 +
 drivers/infiniband/hw/ionic/ionic_hw_stats.c       |  95 +++--
 drivers/infiniband/hw/ionic/ionic_ibdev.h          |  11 +-
 drivers/infiniband/hw/ionic/ionic_lif_cfg.c        |   2 +-
 drivers/interconnect/core.c                        |   7 +-
 drivers/iommu/amd/ppr.c                            |   3 +-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c    |  24 +-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c        |  65 +++-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h        |   3 +
 drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c     |   8 +-
 drivers/iommu/generic_pt/iommu_pt.h                |   2 +-
 drivers/iommu/intel/dmar.c                         |  15 +-
 drivers/iommu/intel/iommu.c                        |   8 +-
 drivers/iommu/intel/iommu.h                        |   2 +
 drivers/iommu/iommu-sva.c                          |   2 +-
 drivers/iommu/iommu.c                              |   2 +-
 drivers/iommu/iommufd/device.c                     |   4 +-
 drivers/iommu/iommufd/ioas.c                       |   2 +
 drivers/iommu/iommufd/selftest.c                   |  31 +-
 drivers/iommu/msm_iommu.c                          |  10 +-
 drivers/mailbox/qcom-ipcc.c                        |  17 +-
 drivers/md/dm-bufio.c                              |  10 +-
 drivers/md/dm-era-target.c                         |   5 +
 drivers/md/dm-integrity.c                          |  32 +-
 drivers/md/dm-io.c                                 |  96 +++--
 drivers/md/dm-kcopyd.c                             |  10 +-
 drivers/md/dm-log-userspace-base.c                 |   1 +
 drivers/md/dm-log.c                                |   4 +-
 drivers/md/dm-pcache/cache.c                       |  18 +
 drivers/md/dm-pcache/cache.h                       |  21 ++
 drivers/md/dm-pcache/cache_dev.c                   |  22 +-
 drivers/md/dm-pcache/cache_gc.c                    |  10 +-
 drivers/md/dm-pcache/cache_key.c                   |  32 +-
 drivers/md/dm-pcache/cache_segment.c               |  12 +-
 drivers/md/dm-pcache/cache_writeback.c             |  10 +-
 drivers/md/dm-pcache/dm_pcache.c                   |   4 +-
 drivers/md/dm-raid1.c                              |  26 +-
 drivers/md/dm-snap-persistent.c                    |   4 +-
 drivers/md/dm-stats.c                              |   6 +-
 drivers/md/dm-switch.c                             |   2 +-
 drivers/md/dm-verity-target.c                      |   2 +-
 drivers/md/dm-writecache.c                         |  14 +-
 drivers/md/md.c                                    |   7 +
 drivers/md/persistent-data/dm-array.c              |  53 ++-
 drivers/md/raid10.c                                |   2 +-
 drivers/media/cec/platform/stm32/stm32-cec.c       |   3 +-
 drivers/media/test-drivers/vicodec/vicodec-core.c  |   4 +-
 drivers/media/v4l2-core/v4l2-dev.c                 |  14 +-
 drivers/mfd/cgbc-core.c                            |   4 +-
 drivers/mfd/qnap-mcu.c                             |  13 +-
 drivers/mfd/sm501.c                                |   2 +
 drivers/misc/nsm.c                                 |   2 +-
 drivers/mmc/host/via-sdmmc.c                       |  12 +-
 drivers/net/dsa/realtek/rtl83xx.c                  |   4 +-
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c   |   3 +
 drivers/net/ethernet/broadcom/bnxt/bnxt.c          |  17 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_gso.c      |   4 +-
 drivers/net/ethernet/ibm/emac/mal.c                |  13 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_rx.c    |   5 +
 drivers/net/ethernet/nvidia/forcedeth.c            |   4 +-
 drivers/net/ethernet/qlogic/qede/qede.h            |   8 +-
 drivers/net/ethernet/qlogic/qede/qede_fp.c         |   1 +
 drivers/net/ethernet/renesas/ravb.h                |   3 +
 drivers/net/ethernet/renesas/ravb_main.c           |   9 +-
 drivers/net/ethernet/renesas/ravb_ptp.c            |  44 ++-
 drivers/net/ipa/ipa_modem.c                        |  18 +-
 drivers/net/ntb_netdev.c                           |  38 +-
 drivers/net/phy/phylink.c                          |   2 +-
 drivers/net/slip/slip.c                            |  11 +-
 drivers/net/thunderbolt/main.c                     |  12 +
 drivers/net/tun.c                                  |  21 +-
 drivers/net/usb/qmi_wwan.c                         |   1 +
 drivers/net/wireless/ath/ath6kl/cfg80211.c         |   5 +
 .../wireless/broadcom/brcm80211/brcmfmac/sdio.c    |   3 +-
 drivers/net/wireless/intel/iwlwifi/dvm/main.c      |   4 +-
 drivers/net/wireless/marvell/mwifiex/sta_ioctl.c   |  12 +
 drivers/net/wireless/mediatek/mt76/mt7615/main.c   |   5 +-
 drivers/net/wireless/mediatek/mt76/mt7915/mcu.c    |  11 +-
 drivers/net/wireless/mediatek/mt76/mt7925/mac.c    |   1 +
 drivers/net/wireless/mediatek/mt76/mt7925/main.c   |  12 +-
 drivers/net/wireless/mediatek/mt76/mt7925/pci.c    |   2 +
 drivers/net/wireless/mediatek/mt76/mt7925/usb.c    |   1 +
 drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c |   6 +
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c    |  26 +-
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    |   9 +-
 drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c |   2 +-
 drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c |   2 +-
 drivers/net/wireless/realtek/rtl8xxxu/core.c       |  19 +-
 .../net/wireless/realtek/rtlwifi/rtl8192du/sw.c    |  12 +-
 .../net/wireless/realtek/rtlwifi/rtl8192du/trx.c   |   3 +-
 drivers/net/wireless/realtek/rtw88/pci.c           |   4 +-
 drivers/net/wireless/realtek/rtw88/tx.c            |   1 +
 drivers/net/wireless/realtek/rtw89/core.h          |   1 +
 drivers/net/wireless/realtek/rtw89/mac80211.c      |   3 +-
 drivers/net/wireless/realtek/rtw89/pci.c           |  13 +
 drivers/net/wireless/realtek/rtw89/pci.h           |   1 +
 drivers/net/wireless/realtek/rtw89/rtw8851be.c     |   1 +
 drivers/net/wireless/realtek/rtw89/rtw8852ae.c     |   1 +
 drivers/net/wireless/realtek/rtw89/rtw8852be.c     |   1 +
 drivers/net/wireless/realtek/rtw89/rtw8852bte.c    |   1 +
 drivers/net/wireless/realtek/rtw89/rtw8852ce.c     |   1 +
 drivers/net/wireless/realtek/rtw89/rtw8922ae.c     |   1 +
 drivers/net/wireless/realtek/rtw89/rtw8922de.c     |   1 +
 drivers/ntb/ntb_transport.c                        |  38 +-
 drivers/nvdimm/label.c                             |   2 +-
 drivers/nvme/host/core.c                           |   2 +-
 drivers/nvme/host/fc.c                             |   2 +-
 drivers/nvme/host/pci.c                            |   1 +
 drivers/nvme/host/tcp.c                            |  45 ++-
 drivers/of/base.c                                  |   2 +-
 drivers/pci/controller/dwc/pci-meson.c             |   2 +-
 drivers/pci/controller/pci-hyperv.c                |   1 +
 drivers/pci/controller/plda/pcie-plda-host.c       |  52 ++-
 drivers/pci/controller/plda/pcie-starfive.c        |  13 +-
 drivers/pci/msi/msi.c                              |  10 +
 drivers/pci/pci-sysfs.c                            |  42 ++-
 drivers/pci/pcie/aer.c                             |  29 +-
 drivers/pci/pcie/portdrv.c                         |   2 +-
 drivers/pci/proc.c                                 |  16 +-
 drivers/pci/quirks.c                               |   9 +-
 drivers/phy/freescale/phy-fsl-imx8mq-usb.c         |  21 +-
 drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c  |   2 +-
 drivers/platform/chrome/cros_ec_sensorhub_ring.c   |  19 +-
 drivers/platform/x86/amd/pmc/mp1_stb.c             |  66 ++--
 drivers/platform/x86/amd/pmc/pmc.c                 |   6 +-
 .../x86/dell/dell-wmi-sysman/biosattr-interface.c  |   1 -
 drivers/platform/x86/hp/hp-bioscfg/bioscfg.c       |  18 +-
 drivers/platform/x86/hp/hp-bioscfg/bioscfg.h       |   8 +
 .../platform/x86/hp/hp-bioscfg/enum-attributes.c   |  15 +-
 .../platform/x86/hp/hp-bioscfg/int-attributes.c    |   6 +-
 .../x86/hp/hp-bioscfg/order-list-attributes.c      |  14 +-
 .../x86/hp/hp-bioscfg/passwdobj-attributes.c       |  14 +-
 .../platform/x86/hp/hp-bioscfg/spmobj-attributes.c |   4 +-
 .../platform/x86/hp/hp-bioscfg/string-attributes.c |   6 +-
 drivers/platform/x86/hp/hp-wmi.c                   |   4 +
 drivers/platform/x86/intel/int1092/intel_sar.c     |  32 +-
 drivers/platform/x86/intel/ishtp_eclite.c          |   5 +-
 .../x86/intel/speed_select_if/isst_tpmi_core.c     |  80 ++++-
 drivers/platform/x86/lenovo/think-lmi.c            |  19 +-
 drivers/platform/x86/lenovo/ymc.c                  |   8 +-
 drivers/platform/x86/panasonic-laptop.c            |  11 +-
 drivers/power/supply/bq24257_charger.c             |  16 +-
 drivers/power/supply/bq256xx_charger.c             |  29 +-
 drivers/power/supply/bq25890_charger.c             |  12 +
 drivers/power/supply/charger-manager.c             |  54 ++-
 drivers/power/supply/cros_usbpd-charger.c          |  17 +-
 drivers/power/supply/lp8727_charger.c              |   4 +-
 drivers/power/supply/lp8788-charger.c              |   2 +-
 drivers/power/supply/max17040_battery.c            |  32 +-
 drivers/power/supply/pf1550-charger.c              |   2 +-
 drivers/power/supply/qcom_battmgr.c                |   9 +-
 drivers/power/supply/rt9455_charger.c              |  21 +-
 drivers/power/supply/twl4030_charger.c             |  12 +-
 drivers/power/supply/ucs1002_power.c               |   6 +-
 drivers/ptp/ptp_vmclock.c                          |   6 +
 drivers/rapidio/devices/rio_mport_cdev.c           |  10 +-
 drivers/regulator/as3722-regulator.c               |   1 -
 drivers/regulator/max8998.c                        |   1 -
 drivers/regulator/qcom-refgen-regulator.c          |   4 +-
 drivers/remoteproc/mtk_scp.c                       |   9 +-
 drivers/rpmsg/qcom_glink_smem.c                    |   7 +
 drivers/s390/block/dasd.c                          |   6 +-
 drivers/s390/block/dasd_eckd.c                     |  40 ++-
 drivers/s390/block/dasd_erp.c                      |   3 +
 drivers/scsi/fnic/fip.c                            |   2 +-
 drivers/scsi/scsi_lib.c                            |   2 +
 drivers/staging/greybus/hid.c                      |   2 +-
 drivers/staging/media/ipu7/ipu7-isys.c             |   1 +
 drivers/staging/media/tegra-video/vi.c             |   9 +-
 drivers/staging/media/tegra-video/vip.c            |  10 +-
 drivers/tty/serial/imx.c                           |  20 +-
 drivers/usb/dwc2/gadget.c                          |  11 +-
 drivers/usb/dwc3/gadget.c                          |   1 +
 drivers/usb/gadget/function/f_fs.c                 |  14 +-
 drivers/usb/gadget/function/f_midi2.c              |   2 +
 drivers/usb/gadget/function/f_tcm.c                |  23 +-
 drivers/usb/gadget/function/f_uvc.c                |   7 +-
 drivers/usb/gadget/function/u_audio.c              |  24 +-
 drivers/usb/gadget/function/uvc_video.c            |   2 +-
 drivers/usb/gadget/udc/at91_udc.c                  |  20 +-
 drivers/usb/gadget/udc/snps_udc_plat.c             |   5 +-
 drivers/usb/phy/phy-fsl-usb.c                      |  52 +--
 drivers/usb/phy/phy-fsl-usb.h                      |   6 +-
 drivers/usb/typec/altmodes/thunderbolt.c           |   2 +
 drivers/usb/typec/hd3ss3220.c                      |   2 +-
 drivers/usb/typec/tcpm/tcpci.c                     |  12 +-
 drivers/usb/typec/ucsi/ucsi.c                      |   3 +-
 drivers/video/backlight/aw99706.c                  |  10 +-
 .../fbdev/omap2/omapfb/displays/panel-dsi-cm.c     |   4 +-
 drivers/video/fbdev/pvr2fb.c                       |   4 +-
 drivers/video/fbdev/ssd1307fb.c                    |  72 +++-
 drivers/video/fbdev/uvesafb.c                      |   2 +
 drivers/video/sticore.c                            |  22 +-
 drivers/w1/slaves/w1_ds28e17.c                     |   8 +
 drivers/xen/balloon.c                              |  29 +-
 fs/backing-file.c                                  |   2 +-
 fs/btrfs/direct-io.c                               |  19 +-
 fs/btrfs/extent_io.c                               |  31 ++
 fs/btrfs/extent_io.h                               |   5 +
 fs/btrfs/inode.c                                   |  23 +-
 fs/btrfs/ioctl.c                                   |  23 +-
 fs/btrfs/relocation.c                              |  31 +-
 fs/buffer.c                                        |   3 +
 fs/ceph/addr.c                                     |  11 +
 fs/ceph/caps.c                                     |  74 +++-
 fs/ceph/dir.c                                      |  10 +-
 fs/ceph/export.c                                   |  26 +-
 fs/ceph/mds_client.c                               |  73 +++-
 fs/ceph/mds_client.h                               |   1 +
 fs/ceph/mdsmap.c                                   |  11 +-
 fs/ceph/super.h                                    |  14 +
 fs/ceph/xattr.c                                    |   1 +
 fs/debugfs/file.c                                  |   3 +-
 fs/ecryptfs/crypto.c                               |   2 +-
 fs/ecryptfs/ecryptfs_kernel.h                      |   3 +-
 fs/ecryptfs/keystore.c                             |  45 ++-
 fs/ecryptfs/messaging.c                            |  11 +-
 fs/ecryptfs/miscdev.c                              |   5 +-
 fs/ecryptfs/super.c                                |   7 +
 fs/efivarfs/super.c                                |  30 +-
 fs/erofs/zutil.c                                   |   2 +
 fs/ext2/inode.c                                    |   7 +-
 fs/ext2/xattr.c                                    |   4 +-
 fs/fat/misc.c                                      |   4 +
 fs/fuse/dev.c                                      |   8 +-
 fs/fuse/dev.h                                      |   2 +-
 fs/fuse/dev_uring.c                                |  38 +-
 fs/fuse/dev_uring_i.h                              |   5 +
 fs/fuse/inode.c                                    |   4 +-
 fs/iomap/bio.c                                     |   2 +-
 fs/iomap/direct-io.c                               |   1 +
 fs/jbd2/checkpoint.c                               |  28 +-
 fs/lockd/clntproc.c                                |   3 +
 fs/lockd/lockd.h                                   |   2 +-
 fs/lockd/svc.c                                     |   4 +-
 fs/lockd/svc4proc.c                                |   7 +-
 fs/lockd/svcproc.c                                 |   4 +-
 fs/lockd/svcsubs.c                                 | 107 ++++--
 fs/nfs/callback.c                                  |   4 +-
 fs/nfs/nfs4client.c                                |  17 +-
 fs/nfs/pnfs.c                                      |   3 +-
 fs/nfs_common/nfslocalio.c                         |  16 +-
 fs/nfsd/filecache.c                                | 143 ++++----
 fs/nfsd/flexfilelayoutxdr.c                        |  20 +-
 fs/nfsd/localio.c                                  |   8 +-
 fs/nfsd/lockd.c                                    |   6 +-
 fs/nfsd/netns.h                                    |  35 +-
 fs/nfsd/nfs2acl.c                                  |  52 +--
 fs/nfsd/nfs3acl.c                                  |  17 +-
 fs/nfsd/nfs3proc.c                                 |  40 +++
 fs/nfsd/nfs4callback.c                             | 113 +++++-
 fs/nfsd/nfs4layouts.c                              |  39 +-
 fs/nfsd/nfs4proc.c                                 | 225 ++++++++----
 fs/nfsd/nfs4recover.c                              |  48 ++-
 fs/nfsd/nfs4state.c                                | 399 ++++++++++++++++-----
 fs/nfsd/nfs4xdr.c                                  |  40 ++-
 fs/nfsd/nfscache.c                                 |   6 +-
 fs/nfsd/nfsctl.c                                   | 156 ++++++--
 fs/nfsd/nfsfh.c                                    |  12 +-
 fs/nfsd/nfsproc.c                                  |   7 +
 fs/nfsd/nfssvc.c                                   |  49 ++-
 fs/nfsd/nfsxdr.c                                   |  32 +-
 fs/nfsd/state.h                                    |   4 +-
 fs/nfsd/trace.h                                    |  18 +-
 fs/nfsd/vfs.c                                      |  39 +-
 fs/nilfs2/bmap.c                                   |   2 +-
 fs/nilfs2/bmap.h                                   |   2 +-
 fs/nilfs2/btree.c                                  |  39 +-
 fs/nilfs2/direct.c                                 |   4 +-
 fs/notify/fanotify/fanotify.c                      |   3 +-
 fs/notify/fanotify/fanotify.h                      |   6 +-
 fs/notify/fanotify/fanotify_user.c                 |  17 +-
 fs/notify/inotify/inotify_user.c                   |  15 +-
 fs/ntfs/attrib.c                                   |  24 +-
 fs/ntfs/lcnalloc.c                                 |   7 +-
 fs/ntfs/runlist.c                                  |  48 +++
 fs/ntfs/super.c                                    |  12 +-
 fs/ntfs3/frecord.c                                 |   9 +
 fs/ntfs3/fslog.c                                   |  34 ++
 fs/ocfs2/cluster/heartbeat.c                       | 150 ++++++--
 fs/ocfs2/cluster/nodemanager.c                     |   6 +
 fs/ocfs2/cluster/nodemanager.h                     |   1 +
 fs/ocfs2/dir.c                                     |  47 ++-
 fs/ocfs2/dlm/dlmmaster.c                           |   6 +
 fs/ocfs2/dlm/dlmrecovery.c                         |   9 +
 fs/ocfs2/refcounttree.c                            |  47 ++-
 fs/ocfs2/suballoc.c                                |   2 +-
 fs/ocfs2/xattr.c                                   |   5 +-
 fs/orangefs/devorangefs-req.c                      |   1 +
 fs/orangefs/orangefs-debugfs.c                     |   1 +
 fs/overlayfs/dir.c                                 |   1 -
 fs/pidfs.c                                         |  43 ++-
 fs/smb/client/cifsfs.c                             |  15 +-
 fs/smb/client/cifsfs.h                             |   1 +
 fs/smb/client/cifssmb.c                            |   6 +
 fs/smb/client/dfs_cache.c                          |  33 +-
 fs/smb/client/file.c                               |   1 +
 fs/smb/client/inode.c                              |  56 ++-
 fs/smb/client/smb1misc.c                           |   3 +-
 fs/smb/client/smb1ops.c                            |   2 +-
 fs/smb/client/smb1transport.c                      |  35 +-
 fs/smb/client/smb2file.c                           |   5 +-
 fs/smb/client/smb2inode.c                          |   6 +-
 fs/smb/client/smb2ops.c                            |   9 +-
 fs/smb/client/trace.h                              |   3 +-
 fs/smb/server/vfs_cache.c                          |   2 +-
 fs/tracefs/event_inode.c                           |   7 +-
 fs/ubifs/auth.c                                    |   2 +-
 fs/udf/inode.c                                     |   2 +-
 fs/udf/partition.c                                 |   2 +-
 include/linux/bio.h                                |   2 +-
 include/linux/compaction.h                         |   3 +-
 include/linux/dm-io.h                              |   6 +-
 include/linux/entry-common.h                       |   3 +
 include/linux/font.h                               |   4 +-
 include/linux/hugetlb.h                            |   7 +
 include/linux/list.h                               |  15 +-
 include/linux/lockd/bind.h                         |  12 +-
 include/linux/sunrpc/bc_xprt.h                     |   5 +
 include/linux/sunrpc/svc_rdma_pcl.h                |   2 +-
 include/linux/uio.h                                |  10 +-
 include/linux/usb/tcpci.h                          |   1 +
 include/linux/vmalloc.h                            |   2 +-
 include/net/ip_tunnels.h                           |  11 +-
 include/net/sctp/structs.h                         |   2 +-
 include/uapi/linux/landlock.h                      |   1 +
 io_uring/query.c                                   |   3 +
 io_uring/waitid.c                                  |  33 +-
 kernel/auditfilter.c                               |   6 +-
 kernel/bpf/bloom_filter.c                          |  19 +-
 kernel/bpf/stackmap.c                              |   3 +
 kernel/dma/contiguous.c                            |  16 +-
 kernel/liveupdate/kexec_handover.c                 |   2 +-
 kernel/module/kallsyms.c                           |  24 +-
 kernel/module/main.c                               |  14 +-
 kernel/params.c                                    |  14 +-
 kernel/pid.c                                       |  31 --
 kernel/reboot.c                                    |  29 ++
 kernel/sched/core.c                                |  49 ++-
 kernel/sched/cpufreq_schedutil.c                   |  15 +-
 kernel/sched/ext/ext.c                             | 342 +++++++++++++-----
 kernel/sched/sched.h                               |   5 +-
 kernel/signal.c                                    |   4 +
 kernel/taskstats.c                                 |   3 +-
 kernel/time/itimer.c                               |   2 +-
 kernel/time/timekeeping.c                          |   8 +-
 kernel/time/timer.c                                |   1 +
 kernel/trace/ring_buffer.c                         | 202 +++++++----
 kernel/trace/simple_ring_buffer.c                  |   4 +-
 kernel/trace/trace.c                               |   6 +-
 kernel/trace/trace_events.c                        |   2 +
 kernel/trace/trace_events_hist.c                   |   4 +-
 kernel/trace/trace_events_user.c                   |   3 +
 lib/iov_iter.c                                     |   9 +-
 lib/ucs2_string.c                                  |   2 +-
 lib/xarray.c                                       |   3 +
 mm/compaction.c                                    |  98 ++---
 mm/gup.c                                           |  10 +-
 mm/huge_memory.c                                   |  24 +-
 mm/hugetlb.c                                       |  38 +-
 mm/hugetlb_vmemmap.c                               |  23 +-
 mm/internal.h                                      |  10 +-
 mm/kasan/quarantine.c                              |   7 +-
 mm/kmemleak.c                                      |  77 ++--
 mm/madvise.c                                       |   4 +-
 mm/memcontrol-v1.c                                 |   6 +-
 mm/memcontrol.c                                    |  13 +
 mm/mempolicy.c                                     |  29 +-
 mm/migrate.c                                       |   8 +-
 mm/migrate_device.c                                |  13 +
 mm/mm_init.c                                       |  10 +-
 mm/page_alloc.c                                    |  76 +++-
 mm/page_owner.c                                    |  10 +-
 mm/page_vma_mapped.c                               |   8 +-
 mm/pagewalk.c                                      |   6 +-
 mm/rmap.c                                          |  31 +-
 mm/slub.c                                          |  80 +++--
 mm/sparse-vmemmap.c                                |   4 +-
 mm/swapfile.c                                      |  15 +-
 mm/vmalloc.c                                       |  58 ++-
 mm/vmscan.c                                        |  40 +--
 mm/zsmalloc.c                                      |  11 +-
 mm/zswap.c                                         |  13 +-
 net/bluetooth/eir.c                                |   3 +-
 net/bluetooth/hci_conn.c                           |   3 +-
 net/bluetooth/hci_core.c                           |   2 +-
 net/bluetooth/hci_event.c                          |   7 +-
 net/bluetooth/hci_sync.c                           |   2 +
 net/bluetooth/iso.c                                |   8 +
 net/bluetooth/rfcomm/core.c                        |   8 +-
 net/ceph/osd_client.c                              |  30 ++
 net/ceph/osdmap.c                                  |   2 +
 net/core/skbuff.c                                  |   5 +-
 net/core/xdp.c                                     |   4 +-
 net/ipv4/ip_tunnel.c                               |   2 +-
 net/ipv4/ipip.c                                    |   2 +-
 net/ipv4/ipmr.c                                    |   3 +
 net/ipv6/exthdrs.c                                 |  26 +-
 net/ipv6/ip6_gre.c                                 |  14 +-
 net/ipv6/ip6_input.c                               |   1 +
 net/ipv6/ip6_tunnel.c                              |  22 +-
 net/ipv6/route.c                                   |   2 +-
 net/ipv6/seg6_local.c                              |   9 +
 net/ipv6/sit.c                                     |   2 +-
 net/iucv/af_iucv.c                                 |   2 +
 net/l2tp/l2tp_netlink.c                            |  16 +-
 net/mctp/route.c                                   |  19 +-
 net/mpls/af_mpls.c                                 |   2 +
 net/mptcp/syncookies.c                             |   1 +
 net/openvswitch/conntrack.c                        | 128 ++++---
 net/openvswitch/conntrack.h                        |   6 +-
 net/openvswitch/datapath.c                         |  60 ++--
 net/openvswitch/datapath.h                         |   8 +-
 net/sched/sch_generic.c                            |   2 +-
 net/sctp/inqueue.c                                 |   7 +-
 net/sctp/sm_sideeffect.c                           |   4 +
 net/sctp/stream.c                                  |  48 ++-
 net/smc/af_smc.c                                   |   3 +-
 net/smc/smc.h                                      |   6 +-
 net/smc/smc_core.c                                 |  27 +-
 net/smc/smc_llc.c                                  | 122 +++++--
 net/smc/smc_rx.c                                   |  11 +-
 net/smc/smc_tx.h                                   |   6 +-
 net/smc/smc_wr.c                                   |   6 +-
 net/sunrpc/auth_gss/auth_gss.c                     |   6 +-
 net/sunrpc/auth_gss/gss_krb5_unseal.c              |   3 +
 net/sunrpc/auth_gss/gss_krb5_wrap.c                |  13 +-
 net/sunrpc/auth_gss/gss_rpc_upcall.c               |   6 -
 net/sunrpc/auth_gss/gss_rpc_upcall.h               |   1 -
 net/sunrpc/auth_gss/gss_rpc_xdr.c                  |  15 +-
 net/sunrpc/auth_gss/svcauth_gss.c                  |   8 +-
 net/sunrpc/backchannel_rqst.c                      |  38 +-
 net/sunrpc/cache.c                                 |   7 +-
 net/sunrpc/clnt.c                                  |  22 +-
 net/sunrpc/sunrpc_syms.c                           |   1 +
 net/sunrpc/svc.c                                   |  93 ++++-
 net/sunrpc/xdr.c                                   |   2 +-
 net/sunrpc/xprtrdma/ib_client.c                    |  24 +-
 net/sunrpc/xprtrdma/svc_rdma_pcl.c                 |   2 +-
 net/sunrpc/xprtrdma/svc_rdma_recvfrom.c            |  21 +-
 net/sunrpc/xprtrdma/svc_rdma_rw.c                  |  52 ++-
 net/sunrpc/xprtrdma/svc_rdma_sendto.c              |  47 ++-
 net/sunrpc/xprtrdma/svc_rdma_transport.c           |  69 +++-
 net/sunrpc/xprtsock.c                              |  12 +-
 net/vmw_vsock/virtio_transport.c                   |   2 +-
 rust/Makefile                                      |   6 +-
 rust/kernel/bug.rs                                 |  34 +-
 rust/kernel/devres.rs                              |  25 +-
 rust/kernel/dma.rs                                 |   6 +-
 rust/kernel/fmt.rs                                 |   9 +-
 rust/kernel/list.rs                                |   2 +-
 rust/kernel/num/bounded.rs                         |  31 +-
 rust/kernel/time.rs                                |  17 +-
 scripts/Makefile.build                             |   3 +-
 scripts/rust_is_available.sh                       |  14 +
 scripts/rust_is_available_bindgen_libclang_22.h    |   5 +
 scripts/rust_is_available_test.py                  |  30 +-
 security/apparmor/include/cred.h                   |   6 +-
 security/apparmor/include/label.h                  |   6 +-
 security/apparmor/include/task.h                   |  15 +-
 security/apparmor/task.c                           |  27 ++
 security/keys/trusted-keys/trusted_tpm1.c          |   2 +-
 security/landlock/errata/abi-1.h                   |  23 ++
 security/landlock/fs.c                             |  41 ++-
 security/smack/smack_lsm.c                         |   2 +-
 sound/core/ump_convert.c                           |   1 +
 sound/drivers/aloop.c                              |   6 +
 sound/drivers/mpu401/mpu401.c                      |   6 +
 sound/drivers/mts64.c                              |   6 +
 sound/drivers/portman2x4.c                         |   6 +
 sound/drivers/serial-u16550.c                      |   6 +
 sound/drivers/virmidi.c                            |   6 +
 sound/hda/codecs/realtek/alc269.c                  |   7 +-
 sound/hda/codecs/realtek/alc662.c                  |   1 +
 sound/hda/core/ext/stream.c                        |   4 +-
 sound/pci/pcxhr/pcxhr.c                            |  14 +-
 sound/soc/amd/yc/acp6x-mach.c                      |   7 +
 sound/soc/codecs/aw88261.c                         |   6 +-
 sound/soc/codecs/aw88261.h                         |   6 -
 sound/soc/tegra/tegra210_admaif.c                  | 210 +++++++----
 sound/soc/tegra/tegra210_i2s.c                     |  24 +-
 sound/soc/tegra/tegra210_i2s.h                     |   1 +
 sound/soc/tegra/tegra210_mbdrc.c                   |  42 +--
 sound/soc/tegra/tegra210_mixer.c                   |  10 +-
 sound/usb/6fire/comm.c                             |   9 +-
 sound/usb/bcd2000/bcd2000.c                        |  11 +-
 sound/usb/fcp.c                                    |   4 +-
 tools/include/linux/compiler.h                     |   2 +-
 tools/objtool/check.c                              |   2 +
 tools/sched_ext/include/scx/compat.bpf.h           |  12 +-
 tools/sched_ext/include/scx/enum_defs.autogen.h    |   1 -
 tools/sched_ext/include/scx/enums.autogen.bpf.h    |   3 -
 tools/sched_ext/include/scx/enums.autogen.h        |   1 -
 tools/sched_ext/scx_qmap.bpf.c                     |   2 +-
 tools/testing/selftests/mm/run_vmtests.sh          |   2 +-
 621 files changed, 7838 insertions(+), 3129 deletions(-)
author maintainer
#1 lore raw

PATCH 1/713 drm/amd/display: Skip Update HDCP Config In Transition State

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Fangzhi Zuo <[email protected]>

[ Upstream commit d5164580a99477dcfe15cea101b153b1e63f1535 ]

Transition state does not have a valid dm_stream_ctx that should skip configuring HDCP routine. The routine is valid to go through only when a valid stream is created.

---
 .../amd/display/amdgpu_dm/amdgpu_dm_hdcp.c    | 28 +++++++++++++------
 1 file changed, 20 insertions(+), 8 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +20 -8
index 4c164ae4a4f9c..8304e8897a3ed 100644
@@ -535,15 +535,27 @@ static bool enable_assr(void *handle, struct dc_link *link)
 static void update_config(void *handle, struct cp_psp_stream_config *config)
 {
 	struct hdcp_workqueue *hdcp_work = handle;
-	struct amdgpu_dm_connector *aconnector = config->dm_stream_ctx;
-	int link_index = aconnector->dc_link->link_index;
-	unsigned int conn_index = aconnector->base.index;
-	struct mod_hdcp_display *display = &hdcp_work[link_index].display;
-	struct mod_hdcp_link *link = &hdcp_work[link_index].link;
-	struct hdcp_workqueue *hdcp_w = &hdcp_work[link_index];
+	struct amdgpu_dm_connector *aconnector;
+	const struct dc *dc;
+	int link_index;
+	unsigned int conn_index;
+	struct mod_hdcp_display *display;
+	struct mod_hdcp_link *link;
+	struct hdcp_workqueue *hdcp_w;
 	struct dc_sink *sink = NULL;
 	bool link_is_hdcp14 = false;
-	const struct dc *dc = aconnector->dc_link->dc;
+
+	aconnector = config->dm_stream_ctx;
+	if (!aconnector || !aconnector->dc_link)
+		return;
+
+	link_index = aconnector->dc_link->link_index;
+	display = &hdcp_work[link_index].display;
+	link = &hdcp_work[link_index].link;
+	hdcp_w = &hdcp_work[link_index];
+
+	conn_index = aconnector->base.index;
+	dc = aconnector->dc_link->dc;
 
 	if (config->dpms_off) {
 		hdcp_remove_display(hdcp_work, link_index, aconnector);
@@ -581,7 +593,7 @@ static void update_config(void *handle, struct cp_psp_stream_config *config)
 	link->dp.mst_enabled = config->mst_enabled;
 	link->dp.dp2_enabled = config->dp2_enabled;
 	link->dp.usb4_enabled = config->usb4_enabled;
-	if (aconnector->dc_sink->sink_signal == SIGNAL_TYPE_HDMI_FRL)
+	if (sink && sink->sink_signal == SIGNAL_TYPE_HDMI_FRL)
 		link->hdmi.frl_enabled = config->frl_enabled;
 	display->adjust.disable = MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION;
 	link->adjust.auth_delay = 2;
Signature · 1 line
2.53.0
author maintainer
#2 lore raw

PATCH 2/713 ASoC: tegra210_i2s: sort the register default table

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Peter Ujfalusi <[email protected]>

[ Upstream commit 597273563d90d03fda852a29c3a76c41a22bf6ac ]

reg_defaults must be sorted by ascending register address, as regcache_lookup_reg() locates entries in it with bsearch(). See commit fd80df352ba1 ("regcache: Add support for sorting defaults arrays").

TEGRA210_I2S_ENABLE (0x80) is listed after TEGRA210_I2S_CG (0x88) and TEGRA210_I2S_TIMING (0xa4), so both it and TEGRA210_I2S_TIMING are unreachable. regcache_reg_needs_sync() then cannot compare them against their default and reports that a sync is needed, so they are written to the device on every regcache_sync() even when they were never touched.

Sort the table by register address.

Fixes c0bfa98349d1 ("ASoC: tegra: Add Tegra210 based I2S driver")
---
 sound/soc/tegra/tegra210_i2s.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/tegra/tegra210_i2s.c +1 -1
index ff8c72fc38c5c..fd49d2d6ee498 100644
@@ -23,9 +23,9 @@ static const struct reg_default tegra210_i2s_reg_defaults[] = {
 	{ TEGRA210_I2S_RX_CIF_CTRL, 0x00007700 },
 	{ TEGRA210_I2S_TX_INT_MASK, 0x00000003 },
 	{ TEGRA210_I2S_TX_CIF_CTRL, 0x00007700 },
+	{ TEGRA210_I2S_ENABLE, 0x1 },
 	{ TEGRA210_I2S_CG, 0x1 },
 	{ TEGRA210_I2S_TIMING, 0x0000001f },
-	{ TEGRA210_I2S_ENABLE, 0x1 },
 	/*
 	 * Below update does not have any effect on Tegra186 and Tegra194.
 	 * On Tegra210, I2S4 has "i2s4a" and "i2s4b" pins and below update
Signature · 1 line
2.53.0
author maintainer
#3 lore raw

PATCH 3/713 ASoC: tegra210_i2s: sort the Tegra264 register default table

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Peter Ujfalusi <[email protected]>

[ Upstream commit 82da8df388004af4540e930ab3de2ce5787207e7 ]

reg_defaults must be sorted by ascending register address, as regcache_lookup_reg() locates entries in it with bsearch(). See commit fd80df352ba1 ("regcache: Add support for sorting defaults arrays").

TEGRA264_I2S_ENABLE (0x100), TEGRA264_I2S_RX_FIFO_WR_ACCESS_MODE (0x30) and TEGRA264_I2S_TX_FIFO_RD_ACCESS_MODE (0xb0) are listed at the end of the table, after TEGRA264_I2S_TIMING (0x130), which leaves 4 of the 9 entries unreachable. regcache_reg_needs_sync() then cannot compare them against their default and reports that a sync is needed, so they are written to the device on every regcache_sync() even when they were never touched.

Sort the table by register address.

Fixes b3354438d898 ("ASoC: tegra: I2S: Add Tegra264 support")
---
 sound/soc/tegra/tegra210_i2s.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
sound/soc/tegra/tegra210_i2s.c +3 -3
index fd49d2d6ee498..e4d11518ff019 100644
@@ -38,13 +38,13 @@ static const struct reg_default tegra210_i2s_reg_defaults[] = {
 static const struct reg_default tegra264_i2s_reg_defaults[] = {
 	{ TEGRA210_I2S_RX_INT_MASK, 0x00000003 },
 	{ TEGRA210_I2S_RX_CIF_CTRL, 0x00003f00 },
+	{ TEGRA264_I2S_RX_FIFO_WR_ACCESS_MODE, 0x1 },
 	{ TEGRA264_I2S_TX_INT_MASK, 0x00000003 },
 	{ TEGRA264_I2S_TX_CIF_CTRL, 0x00003f00 },
+	{ TEGRA264_I2S_TX_FIFO_RD_ACCESS_MODE, 0x1 },
+	{ TEGRA264_I2S_ENABLE, 0x1 },
 	{ TEGRA264_I2S_CG, 0x1 },
 	{ TEGRA264_I2S_TIMING, 0x0000001f },
-	{ TEGRA264_I2S_ENABLE, 0x1 },
-	{ TEGRA264_I2S_RX_FIFO_WR_ACCESS_MODE, 0x1 },
-	{ TEGRA264_I2S_TX_FIFO_RD_ACCESS_MODE, 0x1 },
 };
 
 static void tegra210_i2s_set_slot_ctrl(struct tegra210_i2s *i2s,
Signature · 1 line
2.53.0
author maintainer
#4 lore raw

PATCH 4/713 ASoC: tegra210_mixer: sort the register default table

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Peter Ujfalusi <[email protected]>

[ Upstream commit f70bc276fc7f712ff5c8e995d5050558a3198df2 ]

reg_defaults must be sorted by ascending register address, as regcache_lookup_reg() locates entries in it with bsearch(). See commit fd80df352ba1 ("regcache: Add support for sorting defaults arrays").

TEGRA210_MIXER_ENABLE (0x400) is the last entry of the table, after TEGRA210_MIXER_PEAKM_RAM_CTRL (0x434), which makes it unreachable. regcache_reg_needs_sync() then cannot compare it against its default and reports that a sync is needed, so it is written to the device on every regcache_sync() even when it was never touched.

Sort the table by register address.

Fixes 05bb3d5ec64a ("ASoC: tegra: Add Tegra210 based Mixer driver")
---
 sound/soc/tegra/tegra210_mixer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/tegra/tegra210_mixer.c +1 -1
index a69774578d69f..8eb4e54b954b1 100644
@@ -57,10 +57,10 @@ static const struct reg_default tegra210_mixer_reg_defaults[] = {
 	MIXER_TX_REG_DEFAULTS(3),
 	MIXER_TX_REG_DEFAULTS(4),
 
+	{ TEGRA210_MIXER_ENABLE, 0x1 },
 	{ TEGRA210_MIXER_CG, 0x00000001},
 	{ TEGRA210_MIXER_GAIN_CFG_RAM_CTRL, 0x00004000},
 	{ TEGRA210_MIXER_PEAKM_RAM_CTRL, 0x00004000},
-	{ TEGRA210_MIXER_ENABLE, 0x1 },
 };
 
 /* Default gain parameters */
Signature · 1 line
2.53.0
author maintainer
#5 lore raw

PATCH 5/713 ASoC: tegra: Fix the I2S enable default value

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jon Hunter <[email protected]>

[ Upstream commit 53dd1c1de851280c71385f49a24715e5615c926c ]

Commit 4b05ccb17f92 ("regcache: Sort the local copy of an unsorted reg_defaults array") exposed an issue in the Tegra I2S driver where the register default for the TEGRA210_I2S_ENABLE is specified as 1, but the hardware default is actually 0. After this commit was added the I2S driver is no longer working and so fix this by correcting the default value for this register and explicitly configuring the I2S_ENABLE register when runtime resuming the I2S device.

The I2S_ENABLE register offset is different on Tegra264 devices than other Tegra devices and so add a 'enable_reg' variable to the SoC data structure to specify the offset for different SoC devices.

Fixes c0bfa98349d1 ("ASoC: tegra: Add Tegra210 based I2S driver")
---
 sound/soc/tegra/tegra210_i2s.c | 20 +++++++++++++++++---
 sound/soc/tegra/tegra210_i2s.h |  1 +
 2 files changed, 18 insertions(+), 3 deletions(-)
sound/soc/tegra/tegra210_i2s.c +17 -3
index e4d11518ff019..fdcc5d62b720c 100644
@@ -23,7 +23,7 @@ static const struct reg_default tegra210_i2s_reg_defaults[] = {
 	{ TEGRA210_I2S_RX_CIF_CTRL, 0x00007700 },
 	{ TEGRA210_I2S_TX_INT_MASK, 0x00000003 },
 	{ TEGRA210_I2S_TX_CIF_CTRL, 0x00007700 },
-	{ TEGRA210_I2S_ENABLE, 0x1 },
+	{ TEGRA210_I2S_ENABLE, 0x0 },
 	{ TEGRA210_I2S_CG, 0x1 },
 	{ TEGRA210_I2S_TIMING, 0x0000001f },
 	/*
@@ -42,7 +42,7 @@ static const struct reg_default tegra264_i2s_reg_defaults[] = {
 	{ TEGRA264_I2S_TX_INT_MASK, 0x00000003 },
 	{ TEGRA264_I2S_TX_CIF_CTRL, 0x00003f00 },
 	{ TEGRA264_I2S_TX_FIFO_RD_ACCESS_MODE, 0x1 },
-	{ TEGRA264_I2S_ENABLE, 0x1 },
+	{ TEGRA264_I2S_ENABLE, 0x0 },
 	{ TEGRA264_I2S_CG, 0x1 },
 	{ TEGRA264_I2S_TIMING, 0x0000001f },
 };
@@ -201,9 +201,21 @@ static int tegra210_i2s_runtime_resume(struct device *dev)
 	}
 
 	regcache_cache_only(i2s->regmap, false);
-	regcache_sync(i2s->regmap);
+	err = regcache_sync(i2s->regmap);
+	if (err)
+		goto err;
+
+	err = regmap_write(i2s->regmap, i2s->soc_data->enable_reg, I2S_EN);
+	if (err)
+		goto err;
 
 	return 0;
+
+err:
+	regcache_cache_only(i2s->regmap, true);
+	clk_disable_unprepare(i2s->clk_i2s);
+
+	return err;
 }
 
 static void tegra210_i2s_set_data_offset(struct tegra210_i2s *i2s,
@@ -1133,6 +1145,7 @@ static const struct tegra_i2s_soc_data soc_data_tegra210 = {
 	.regmap_conf		= &tegra210_regmap_conf,
 	.i2s_cmpnt		= &tegra210_i2s_cmpnt,
 	.max_ch			= TEGRA210_I2S_MAX_CHANNEL,
+	.enable_reg		= TEGRA210_I2S_ENABLE,
 	.tx_offset		= TEGRA210_I2S_TX_OFFSET,
 	.i2s_ctrl_offset	= TEGRA210_I2S_CTRL_OFFSET,
 	.fsync_width_mask	= I2S_CTRL_FSYNC_WIDTH_MASK,
@@ -1144,6 +1157,7 @@ static const struct tegra_i2s_soc_data soc_data_tegra264 = {
 	.regmap_conf		= &tegra264_regmap_conf,
 	.i2s_cmpnt		= &tegra264_i2s_cmpnt,
 	.max_ch			= TEGRA264_I2S_MAX_CHANNEL,
+	.enable_reg		= TEGRA264_I2S_ENABLE,
 	.tx_offset		= TEGRA264_I2S_TX_OFFSET,
 	.i2s_ctrl_offset	= TEGRA264_I2S_CTRL_OFFSET,
 	.fsync_width_mask	= TEGRA264_I2S_CTRL_FSYNC_WIDTH_MASK,
sound/soc/tegra/tegra210_i2s.h +1 -0
index 42be2137342c4..82292f96ab367 100644
@@ -150,6 +150,7 @@ struct tegra_i2s_soc_data {
 	const struct regmap_config *regmap_conf;
 	const struct snd_soc_component_driver *i2s_cmpnt;
 	unsigned int max_ch;
+	unsigned int enable_reg;
 	unsigned int tx_offset;
 	unsigned int i2s_ctrl_offset;
 	unsigned int fsync_width_mask;
Signature · 1 line
2.53.0
author maintainer
#6 lore raw

PATCH 6/713 ASoC: tegra: Fix the MIXER enable default value

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jon Hunter <[email protected]>

[ Upstream commit 5442b8093a2f94ecd4696b3875194be09e2676c5 ]

Commit 4b05ccb17f92 ("regcache: Sort the local copy of an unsorted reg_defaults array") exposed an issue in the Tegra MIXER driver where the register default for the TEGRA210_MIXER_ENABLE is specified as 1, but the hardware default is actually 0. After this commit was added the MIXER driver is no longer working and so fix this by correcting the default value for this register and explicitly configuring the MIXER_ENABLE register when runtime resuming the MIXER device.

Fixes 05bb3d5ec64a ("ASoC: tegra: Add Tegra210 based Mixer driver")
---
 sound/soc/tegra/tegra210_mixer.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
sound/soc/tegra/tegra210_mixer.c +7 -3
index 8eb4e54b954b1..96259a6cbc59b 100644
@@ -57,7 +57,7 @@ static const struct reg_default tegra210_mixer_reg_defaults[] = {
 	MIXER_TX_REG_DEFAULTS(3),
 	MIXER_TX_REG_DEFAULTS(4),
 
-	{ TEGRA210_MIXER_ENABLE, 0x1 },
+	{ TEGRA210_MIXER_ENABLE, 0x0 },
 	{ TEGRA210_MIXER_CG, 0x00000001},
 	{ TEGRA210_MIXER_GAIN_CFG_RAM_CTRL, 0x00004000},
 	{ TEGRA210_MIXER_PEAKM_RAM_CTRL, 0x00004000},
@@ -86,11 +86,15 @@ static int tegra210_mixer_runtime_suspend(struct device *dev)
 static int tegra210_mixer_runtime_resume(struct device *dev)
 {
 	struct tegra210_mixer *mixer = dev_get_drvdata(dev);
+	int err;
 
 	regcache_cache_only(mixer->regmap, false);
-	regcache_sync(mixer->regmap);
+	err = regcache_sync(mixer->regmap);
+	if (err)
+		return err;
 
-	return 0;
+	return regmap_write(mixer->regmap, TEGRA210_MIXER_ENABLE,
+			    TEGRA210_MIXER_EN);
 }
 
 static int tegra210_mixer_write_ram(struct tegra210_mixer *mixer,
Signature · 1 line
2.53.0
author maintainer
#7 lore raw

PATCH 7/713 ASoC: tegra: Sort ADMAIF register defaults

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jon Hunter <[email protected]>

[ Upstream commit 18d48bfd1bc178da7cfc7a1be3eaa1c8cb10f05c ]

Commit 4b05ccb17f92 ("regcache: Sort the local copy of an unsorted reg_defaults array") exposed an issue in the Tegra ADMAIF driver and now the following warning is observed:

tegra210-admaif 290f000.admaif: Driver needs fixing: Unsorted
reg_defaults, sorting the copy

This warning occurs because register defaults in the structures tegra186_admaif_reg_defaults and tegra264_admaif_reg_defaults are not specified in ascending order which is required by regmap. Fix this by sorting the register defaults according to their address. Note that in order to do this it is necessary to split the macro ADMAIF_REG_DEFAULTS into separate RX and TX macros to the RX and TX registers.

Fixes f74028e159bb ("ASoC: tegra: Add Tegra210 based ADMAIF driver")
---
 sound/soc/tegra/tegra210_admaif.c | 208 ++++++++++++++++++++----------
 1 file changed, 138 insertions(+), 70 deletions(-)
sound/soc/tegra/tegra210_admaif.c +138 -70
index 7299c6bfcf158..87e898cc35e42 100644
@@ -26,94 +26,162 @@
 
 #define CH_RX_REG(reg, id) CH_REG(admaif->soc_data->rx_base, reg, id)
 
-#define REG_DEFAULTS(id, rx_ctrl, tx_ctrl, tx_base, rx_base, cif_ctrl)	       \
+#define RX_REG_DEFAULTS(id, rx_ctrl, rx_base, cif_ctrl)			       \
 	{ CH_REG(rx_base, TEGRA_ADMAIF_RX_INT_MASK, id), 0x00000001 },	       \
 	{ CH_REG(rx_base, TEGRA_ADMAIF_CH_ACIF_RX_CTRL, id), cif_ctrl },     \
-	{ CH_REG(rx_base, TEGRA_ADMAIF_RX_FIFO_CTRL, id), rx_ctrl },	       \
+	{ CH_REG(rx_base, TEGRA_ADMAIF_RX_FIFO_CTRL, id), rx_ctrl }
+
+#define TX_REG_DEFAULTS(id, tx_ctrl, tx_base, cif_ctrl)			       \
 	{ CH_REG(tx_base, TEGRA_ADMAIF_TX_INT_MASK, id), 0x00000001 },	       \
 	{ CH_REG(tx_base, TEGRA_ADMAIF_CH_ACIF_TX_CTRL, id), cif_ctrl },     \
 	{ CH_REG(tx_base, TEGRA_ADMAIF_TX_FIFO_CTRL, id), tx_ctrl }
 
-#define ADMAIF_REG_DEFAULTS(id, chip)					       \
-	REG_DEFAULTS((id) - 1,						       \
+#define ADMAIF_RX_REG_DEFAULTS(id, chip)				       \
+	RX_REG_DEFAULTS((id) - 1,					       \
 		chip ## _ADMAIF_RX ## id ## _FIFO_CTRL_REG_DEFAULT,	       \
+		chip ## _ADMAIF_RX_BASE,				       \
+		chip ## _ADMAIF_CIF_REG_DEFAULT)
+
+#define ADMAIF_TX_REG_DEFAULTS(id, chip)				       \
+	TX_REG_DEFAULTS((id) - 1,					       \
 		chip ## _ADMAIF_TX ## id ## _FIFO_CTRL_REG_DEFAULT,	       \
 		chip ## _ADMAIF_TX_BASE,				       \
-		chip ## _ADMAIF_RX_BASE,				       \
 		chip ## _ADMAIF_CIF_REG_DEFAULT)
 
 static const struct reg_default tegra186_admaif_reg_defaults[] = {
-	{(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA186_ADMAIF_GLOBAL_BASE), 0x00000003},
-	ADMAIF_REG_DEFAULTS(1, TEGRA186),
-	ADMAIF_REG_DEFAULTS(2, TEGRA186),
-	ADMAIF_REG_DEFAULTS(3, TEGRA186),
-	ADMAIF_REG_DEFAULTS(4, TEGRA186),
-	ADMAIF_REG_DEFAULTS(5, TEGRA186),
-	ADMAIF_REG_DEFAULTS(6, TEGRA186),
-	ADMAIF_REG_DEFAULTS(7, TEGRA186),
-	ADMAIF_REG_DEFAULTS(8, TEGRA186),
-	ADMAIF_REG_DEFAULTS(9, TEGRA186),
-	ADMAIF_REG_DEFAULTS(10, TEGRA186),
-	ADMAIF_REG_DEFAULTS(11, TEGRA186),
-	ADMAIF_REG_DEFAULTS(12, TEGRA186),
-	ADMAIF_REG_DEFAULTS(13, TEGRA186),
-	ADMAIF_REG_DEFAULTS(14, TEGRA186),
-	ADMAIF_REG_DEFAULTS(15, TEGRA186),
-	ADMAIF_REG_DEFAULTS(16, TEGRA186),
-	ADMAIF_REG_DEFAULTS(17, TEGRA186),
-	ADMAIF_REG_DEFAULTS(18, TEGRA186),
-	ADMAIF_REG_DEFAULTS(19, TEGRA186),
-	ADMAIF_REG_DEFAULTS(20, TEGRA186)
+	ADMAIF_RX_REG_DEFAULTS(1, TEGRA186),
+	ADMAIF_RX_REG_DEFAULTS(2, TEGRA186),
+	ADMAIF_RX_REG_DEFAULTS(3, TEGRA186),
+	ADMAIF_RX_REG_DEFAULTS(4, TEGRA186),
+	ADMAIF_RX_REG_DEFAULTS(5, TEGRA186),
+	ADMAIF_RX_REG_DEFAULTS(6, TEGRA186),
+	ADMAIF_RX_REG_DEFAULTS(7, TEGRA186),
+	ADMAIF_RX_REG_DEFAULTS(8, TEGRA186),
+	ADMAIF_RX_REG_DEFAULTS(9, TEGRA186),
+	ADMAIF_RX_REG_DEFAULTS(10, TEGRA186),
+	ADMAIF_RX_REG_DEFAULTS(11, TEGRA186),
+	ADMAIF_RX_REG_DEFAULTS(12, TEGRA186),
+	ADMAIF_RX_REG_DEFAULTS(13, TEGRA186),
+	ADMAIF_RX_REG_DEFAULTS(14, TEGRA186),
+	ADMAIF_RX_REG_DEFAULTS(15, TEGRA186),
+	ADMAIF_RX_REG_DEFAULTS(16, TEGRA186),
+	ADMAIF_RX_REG_DEFAULTS(17, TEGRA186),
+	ADMAIF_RX_REG_DEFAULTS(18, TEGRA186),
+	ADMAIF_RX_REG_DEFAULTS(19, TEGRA186),
+	ADMAIF_RX_REG_DEFAULTS(20, TEGRA186),
+	ADMAIF_TX_REG_DEFAULTS(1, TEGRA186),
+	ADMAIF_TX_REG_DEFAULTS(2, TEGRA186),
+	ADMAIF_TX_REG_DEFAULTS(3, TEGRA186),
+	ADMAIF_TX_REG_DEFAULTS(4, TEGRA186),
+	ADMAIF_TX_REG_DEFAULTS(5, TEGRA186),
+	ADMAIF_TX_REG_DEFAULTS(6, TEGRA186),
+	ADMAIF_TX_REG_DEFAULTS(7, TEGRA186),
+	ADMAIF_TX_REG_DEFAULTS(8, TEGRA186),
+	ADMAIF_TX_REG_DEFAULTS(9, TEGRA186),
+	ADMAIF_TX_REG_DEFAULTS(10, TEGRA186),
+	ADMAIF_TX_REG_DEFAULTS(11, TEGRA186),
+	ADMAIF_TX_REG_DEFAULTS(12, TEGRA186),
+	ADMAIF_TX_REG_DEFAULTS(13, TEGRA186),
+	ADMAIF_TX_REG_DEFAULTS(14, TEGRA186),
+	ADMAIF_TX_REG_DEFAULTS(15, TEGRA186),
+	ADMAIF_TX_REG_DEFAULTS(16, TEGRA186),
+	ADMAIF_TX_REG_DEFAULTS(17, TEGRA186),
+	ADMAIF_TX_REG_DEFAULTS(18, TEGRA186),
+	ADMAIF_TX_REG_DEFAULTS(19, TEGRA186),
+	ADMAIF_TX_REG_DEFAULTS(20, TEGRA186),
+	{(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA186_ADMAIF_GLOBAL_BASE), 0x00000003}
 };
 
 static const struct reg_default tegra210_admaif_reg_defaults[] = {
-	{(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA210_ADMAIF_GLOBAL_BASE), 0x00000003},
-	ADMAIF_REG_DEFAULTS(1, TEGRA210),
-	ADMAIF_REG_DEFAULTS(2, TEGRA210),
-	ADMAIF_REG_DEFAULTS(3, TEGRA210),
-	ADMAIF_REG_DEFAULTS(4, TEGRA210),
-	ADMAIF_REG_DEFAULTS(5, TEGRA210),
-	ADMAIF_REG_DEFAULTS(6, TEGRA210),
-	ADMAIF_REG_DEFAULTS(7, TEGRA210),
-	ADMAIF_REG_DEFAULTS(8, TEGRA210),
-	ADMAIF_REG_DEFAULTS(9, TEGRA210),
-	ADMAIF_REG_DEFAULTS(10, TEGRA210)
+	ADMAIF_RX_REG_DEFAULTS(1, TEGRA210),
+	ADMAIF_RX_REG_DEFAULTS(2, TEGRA210),
+	ADMAIF_RX_REG_DEFAULTS(3, TEGRA210),
+	ADMAIF_RX_REG_DEFAULTS(4, TEGRA210),
+	ADMAIF_RX_REG_DEFAULTS(5, TEGRA210),
+	ADMAIF_RX_REG_DEFAULTS(6, TEGRA210),
+	ADMAIF_RX_REG_DEFAULTS(7, TEGRA210),
+	ADMAIF_RX_REG_DEFAULTS(8, TEGRA210),
+	ADMAIF_RX_REG_DEFAULTS(9, TEGRA210),
+	ADMAIF_RX_REG_DEFAULTS(10, TEGRA210),
+	ADMAIF_TX_REG_DEFAULTS(1, TEGRA210),
+	ADMAIF_TX_REG_DEFAULTS(2, TEGRA210),
+	ADMAIF_TX_REG_DEFAULTS(3, TEGRA210),
+	ADMAIF_TX_REG_DEFAULTS(4, TEGRA210),
+	ADMAIF_TX_REG_DEFAULTS(5, TEGRA210),
+	ADMAIF_TX_REG_DEFAULTS(6, TEGRA210),
+	ADMAIF_TX_REG_DEFAULTS(7, TEGRA210),
+	ADMAIF_TX_REG_DEFAULTS(8, TEGRA210),
+	ADMAIF_TX_REG_DEFAULTS(9, TEGRA210),
+	ADMAIF_TX_REG_DEFAULTS(10, TEGRA210),
+	{(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA210_ADMAIF_GLOBAL_BASE), 0x00000003}
 };
 
 static const struct reg_default tegra264_admaif_reg_defaults[] = {
-	{(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA264_ADMAIF_GLOBAL_BASE), 0x00000003},
-	ADMAIF_REG_DEFAULTS(1, TEGRA264),
-	ADMAIF_REG_DEFAULTS(2, TEGRA264),
-	ADMAIF_REG_DEFAULTS(3, TEGRA264),
-	ADMAIF_REG_DEFAULTS(4, TEGRA264),
-	ADMAIF_REG_DEFAULTS(5, TEGRA264),
-	ADMAIF_REG_DEFAULTS(6, TEGRA264),
-	ADMAIF_REG_DEFAULTS(7, TEGRA264),
-	ADMAIF_REG_DEFAULTS(8, TEGRA264),
-	ADMAIF_REG_DEFAULTS(9, TEGRA264),
-	ADMAIF_REG_DEFAULTS(10, TEGRA264),
-	ADMAIF_REG_DEFAULTS(11, TEGRA264),
-	ADMAIF_REG_DEFAULTS(12, TEGRA264),
-	ADMAIF_REG_DEFAULTS(13, TEGRA264),
-	ADMAIF_REG_DEFAULTS(14, TEGRA264),
-	ADMAIF_REG_DEFAULTS(15, TEGRA264),
-	ADMAIF_REG_DEFAULTS(16, TEGRA264),
-	ADMAIF_REG_DEFAULTS(17, TEGRA264),
-	ADMAIF_REG_DEFAULTS(18, TEGRA264),
-	ADMAIF_REG_DEFAULTS(19, TEGRA264),
-	ADMAIF_REG_DEFAULTS(20, TEGRA264),
-	ADMAIF_REG_DEFAULTS(21, TEGRA264),
-	ADMAIF_REG_DEFAULTS(22, TEGRA264),
-	ADMAIF_REG_DEFAULTS(23, TEGRA264),
-	ADMAIF_REG_DEFAULTS(24, TEGRA264),
-	ADMAIF_REG_DEFAULTS(25, TEGRA264),
-	ADMAIF_REG_DEFAULTS(26, TEGRA264),
-	ADMAIF_REG_DEFAULTS(27, TEGRA264),
-	ADMAIF_REG_DEFAULTS(28, TEGRA264),
-	ADMAIF_REG_DEFAULTS(29, TEGRA264),
-	ADMAIF_REG_DEFAULTS(30, TEGRA264),
-	ADMAIF_REG_DEFAULTS(31, TEGRA264),
-	ADMAIF_REG_DEFAULTS(32, TEGRA264)
+	ADMAIF_RX_REG_DEFAULTS(1, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(2, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(3, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(4, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(5, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(6, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(7, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(8, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(9, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(10, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(11, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(12, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(13, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(14, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(15, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(16, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(17, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(18, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(19, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(20, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(21, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(22, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(23, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(24, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(25, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(26, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(27, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(28, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(29, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(30, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(31, TEGRA264),
+	ADMAIF_RX_REG_DEFAULTS(32, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(1, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(2, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(3, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(4, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(5, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(6, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(7, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(8, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(9, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(10, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(11, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(12, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(13, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(14, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(15, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(16, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(17, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(18, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(19, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(20, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(21, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(22, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(23, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(24, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(25, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(26, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(27, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(28, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(29, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(30, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(31, TEGRA264),
+	ADMAIF_TX_REG_DEFAULTS(32, TEGRA264),
+	{(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA264_ADMAIF_GLOBAL_BASE), 0x00000003}
 };
 
 static bool tegra_admaif_wr_reg(struct device *dev, unsigned int reg)
Signature · 1 line
2.53.0
author maintainer
#8 lore raw

PATCH 8/713 ASoC: tegra: Sort MBDRC register defaults

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jon Hunter <[email protected]>

[ Upstream commit abb5bed6f48d54d3b82724a430fd462579ecd876 ]

Commit 4b05ccb17f92 ("regcache: Sort the local copy of an unsorted reg_defaults array") exposed an issue with the Tegra MBDRC driver and now the following warning is observed:

tegra210-ope 2908000.processing-engine: Driver needs fixing: Unsorted
reg_defaults, sorting the copy

This warning occurs because register defaults in the structure tegra210_mbdrc_reg_defaults are not specified in ascending order which is required by regmap. Fix this by sorting the register defaults according to their address. Note that in order to do this it is necessary to replace the macro MBDRC_FILTER_REG_DEFAULTS with a per register macro MBDRC_FILTER_PARAM_REG_DEFAULTS.

Fixes 7358a803c778 ("ASoC: tegra: Add Tegra210 based OPE driver")
---
 sound/soc/tegra/tegra210_mbdrc.c | 42 ++++++++++++++++----------------
 1 file changed, 21 insertions(+), 21 deletions(-)
sound/soc/tegra/tegra210_mbdrc.c +21 -21
index f5d4a93dd6f16..1d78b4c1cc885 100644
@@ -20,33 +20,33 @@
 #define MBDRC_FILTER_REG(reg, id)					    \
 	((reg) + ((id) * TEGRA210_MBDRC_FILTER_PARAM_STRIDE))
 
-#define MBDRC_FILTER_REG_DEFAULTS(id)					    \
-	{ MBDRC_FILTER_REG(TEGRA210_MBDRC_IIR_CFG, id), 0x00000005},	    \
-	{ MBDRC_FILTER_REG(TEGRA210_MBDRC_IN_ATTACK, id), 0x3e48590c},	    \
-	{ MBDRC_FILTER_REG(TEGRA210_MBDRC_IN_RELEASE, id), 0x08414e9f},	    \
-	{ MBDRC_FILTER_REG(TEGRA210_MBDRC_FAST_ATTACK, id), 0x7fffffff},    \
-	{ MBDRC_FILTER_REG(TEGRA210_MBDRC_IN_THRESHOLD, id), 0x06145082},   \
-	{ MBDRC_FILTER_REG(TEGRA210_MBDRC_OUT_THRESHOLD, id), 0x060d379b},  \
-	{ MBDRC_FILTER_REG(TEGRA210_MBDRC_RATIO_1ST, id), 0x0000a000},	    \
-	{ MBDRC_FILTER_REG(TEGRA210_MBDRC_RATIO_2ND, id), 0x00002000},	    \
-	{ MBDRC_FILTER_REG(TEGRA210_MBDRC_RATIO_3RD, id), 0x00000b33},	    \
-	{ MBDRC_FILTER_REG(TEGRA210_MBDRC_RATIO_4TH, id), 0x00000800},	    \
-	{ MBDRC_FILTER_REG(TEGRA210_MBDRC_RATIO_5TH, id), 0x0000019a},	    \
-	{ MBDRC_FILTER_REG(TEGRA210_MBDRC_MAKEUP_GAIN, id), 0x00000002},    \
-	{ MBDRC_FILTER_REG(TEGRA210_MBDRC_INIT_GAIN, id), 0x00066666},	    \
-	{ MBDRC_FILTER_REG(TEGRA210_MBDRC_GAIN_ATTACK, id), 0x00d9ba0e},    \
-	{ MBDRC_FILTER_REG(TEGRA210_MBDRC_GAIN_RELEASE, id), 0x3e48590c},   \
-	{ MBDRC_FILTER_REG(TEGRA210_MBDRC_FAST_RELEASE, id), 0x7ffff26a},   \
-	{ MBDRC_FILTER_REG(TEGRA210_MBDRC_CFG_RAM_CTRL, id), 0x4000}
+#define MBDRC_FILTER_PARAM_REG_DEFAULTS(reg, val)			    \
+	{ MBDRC_FILTER_REG(reg, 0), val},				    \
+	{ MBDRC_FILTER_REG(reg, 1), val},				    \
+	{ MBDRC_FILTER_REG(reg, 2), val}
 
 static const struct reg_default tegra210_mbdrc_reg_defaults[] = {
 	{ TEGRA210_MBDRC_CFG, 0x0030de51},
 	{ TEGRA210_MBDRC_CHANNEL_MASK, 0x00000003},
 	{ TEGRA210_MBDRC_FAST_FACTOR, 0x30000800},
 
-	MBDRC_FILTER_REG_DEFAULTS(0),
-	MBDRC_FILTER_REG_DEFAULTS(1),
-	MBDRC_FILTER_REG_DEFAULTS(2),
+	MBDRC_FILTER_PARAM_REG_DEFAULTS(TEGRA210_MBDRC_IIR_CFG, 0x00000005),
+	MBDRC_FILTER_PARAM_REG_DEFAULTS(TEGRA210_MBDRC_IN_ATTACK, 0x3e48590c),
+	MBDRC_FILTER_PARAM_REG_DEFAULTS(TEGRA210_MBDRC_IN_RELEASE, 0x08414e9f),
+	MBDRC_FILTER_PARAM_REG_DEFAULTS(TEGRA210_MBDRC_FAST_ATTACK, 0x7fffffff),
+	MBDRC_FILTER_PARAM_REG_DEFAULTS(TEGRA210_MBDRC_IN_THRESHOLD, 0x06145082),
+	MBDRC_FILTER_PARAM_REG_DEFAULTS(TEGRA210_MBDRC_OUT_THRESHOLD, 0x060d379b),
+	MBDRC_FILTER_PARAM_REG_DEFAULTS(TEGRA210_MBDRC_RATIO_1ST, 0x0000a000),
+	MBDRC_FILTER_PARAM_REG_DEFAULTS(TEGRA210_MBDRC_RATIO_2ND, 0x00002000),
+	MBDRC_FILTER_PARAM_REG_DEFAULTS(TEGRA210_MBDRC_RATIO_3RD, 0x00000b33),
+	MBDRC_FILTER_PARAM_REG_DEFAULTS(TEGRA210_MBDRC_RATIO_4TH, 0x00000800),
+	MBDRC_FILTER_PARAM_REG_DEFAULTS(TEGRA210_MBDRC_RATIO_5TH, 0x0000019a),
+	MBDRC_FILTER_PARAM_REG_DEFAULTS(TEGRA210_MBDRC_MAKEUP_GAIN, 0x00000002),
+	MBDRC_FILTER_PARAM_REG_DEFAULTS(TEGRA210_MBDRC_INIT_GAIN, 0x00066666),
+	MBDRC_FILTER_PARAM_REG_DEFAULTS(TEGRA210_MBDRC_GAIN_ATTACK, 0x00d9ba0e),
+	MBDRC_FILTER_PARAM_REG_DEFAULTS(TEGRA210_MBDRC_GAIN_RELEASE, 0x3e48590c),
+	MBDRC_FILTER_PARAM_REG_DEFAULTS(TEGRA210_MBDRC_FAST_RELEASE, 0x7ffff26a),
+	MBDRC_FILTER_PARAM_REG_DEFAULTS(TEGRA210_MBDRC_CFG_RAM_CTRL, 0x4000),
 };
 
 /* Default MBDRC parameters */
Signature · 1 line
2.53.0
author maintainer
#9 lore raw

PATCH 9/713 btrfs: write-protect folios during data writeback

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Boris Burkov <[email protected]>

commit 5376c9db45368eb210b4d71104ac00a59dc8b6e0 upstream.

commit 095be159f3eb ("btrfs: unify folio dirty flag clearing") replaced the folio_clear_dirty_for_io() call in extent_write_cache_pages() with a plain folio_test_dirty() check. Besides clearing the dirty flag, folio_clear_dirty_for_io() also calls folio_mkclean(), which write-protects the shared mmap PTEs mapping the folio. Note that we still do call folio_clear_dirty_for_io() later in submit_one_sector() when we clear dirty on the last sector of the folio (the only sector for non-subpage cases). But we lost this early call in extent_write_cache_pages().

Without the extra write-protection, a process with the file mmap-ed can modify a sector while it is being used by writeback in a way that expects a stable folio (checksumming, compressing, copying, etc...) without faulting, which manifests as a handful of concrete bugs.

1. For large folios or subpage sectorsize, it is possible to submit a bio which does not cover the whole folio. When this happens, we will have a bio in flight for a folio that we have *not* called folio_clear_dirty_for_io() on. If a task with an existing mmap-ed PTE writes (without faulting..) in this window, it can result in corruptions. If the write arrives while the checksumming or writing itself is underway, this can result in an invalid checksum and later corruption reports on read. If the write arrives after checksumming/writing is done but before the last sector dirty is cleared, then the write is present in page cache but doesn't affect the dirty tracking and will be lost when the folio is fully finished being submitted and the dirty bit is cleared. This results in losing the write even if fsync() is called.

2. For zoned submissions which are done in batch separate from the main extent_writepage() loop, we also risk csum violations for those submissions. Zoned writes are clamped to max_zone_append_size and are not aligned with folios, so a submission can span two folios. The first folio being processed in extent_write_cache_pages() will call extent_write_locked_range() which will submit the partial range of the next folio, while the rest of that folio could still be dirty. So clearing dirty on the submitted sectors doesn't call folio_clear_dirty_for_io() and we have the same issue. Since extent_write_cache_pages() skips these batch submitted folios (they are already marked for writeback from submission by the preceding folio), we must add the extra write protection in lock_delalloc_folios().

3. For inline extents this will subtly risk losing writes that happen after/while we copy the inline extent but before we clear dirty on the folio.

4. For folios spanning EOF, mmap could tamper with the zeroed bytes past EOF and cause them to be persisted where future faults would improperly see them instead of zeros.

5. Finally, for compressed extents, we risk modifying the folios while we
work on compressing them which will result in corrupted compressed data.
Specifically, in run_delalloc_compressed() we queue up work to do
compress_file_range() in BTRFS_COMPRESSION_CHUNK_SIZE (512K) chunks which
will call btrfs_folio_clamp_clear_dirty() on the range. For non-subpage,
this will always clear the whole folio, safely. For subpage, we risk a
partial clear here as well. In particular, imagine a 2M folio broken up
into 512K chunks of work which might start compression work on one chunk
before all the chunks compress_file_range() workers have gotten far
enough to finish clearing all the dirty bitmaps of the folio and getting
to folio_clear_dirty_for_io(). Large folios on the edges of submission
ranges are similarly at risk to be only partly cleared.
This particular gap was introduced by a second patch in the same series:
commit a4ef54dbb576 ("btrfs: make extent_range_clear_dirty_for_io() to handle sector size < page size cases")

We cannot simply restore the call to folio_clear_dirty_for_io() because
that also drops the dirty flag off the folio which violates invariants
introduced for large folios by
commit 334509ce9d07 ("btrfs: use dirty flag to check if an ordered extent needs to be truncated") and results in failing to invalidate clean folios past i_size, resulting
in deadlocks.

Therefore, to fix it, leave the existing semantics w.r.t. the folio's dirty flag (to preserve the correct invalidate behavior) but ensure that the other aspect of folio_clear_dirty_for_io(), folio_mkclean(), is run on the folio when we lock it for writeback.

Finally, to help prevent similar regressions in the future, add a debug warning that triggers at the known corruption sites if we have failed to write protect the folio.

Assisted-by LLM (debug, reproduce, research fix, review patch)
Fixes 095be159f3eb ("btrfs: unify folio dirty flag clearing")
Fixes a4ef54dbb576 ("btrfs: make extent_range_clear_dirty_for_io() to handle sector size < page size cases")
---
 fs/btrfs/extent_io.c | 31 +++++++++++++++++++++++++++++++
 fs/btrfs/extent_io.h |  5 +++++
 fs/btrfs/inode.c     | 23 +++++++++++++++++------
 3 files changed, 53 insertions(+), 6 deletions(-)
fs/btrfs/extent_io.c +31 -0
index f032f0858f40f..45c4d4a3b29b1 100644
@@ -6,6 +6,7 @@
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/page-flags.h>
+#include <linux/rmap.h>
 #include <linux/sched/mm.h>
 #include <linux/spinlock.h>
 #include <linux/blkdev.h>
@@ -299,6 +300,25 @@ static noinline void unlock_delalloc_folio(const struct inode *inode,
 				PAGE_UNLOCK);
 }
 
+#ifdef CONFIG_BTRFS_DEBUG
+/*
+ * Writeback must write-protect a folio when locking it for IO, before
+ * anything consumes its data (zeroing, inline copy, compression,
+ * checksumming). If this fails, then an mmap writer would be able to
+ * modify the data concurrently while we need it to be stable.
+ */
+void btrfs_check_folio_write_protected(struct folio *folio)
+{
+	if (folio_mkclean(folio)) {
+		const struct btrfs_inode *inode = BTRFS_I(folio->mapping->host);
+
+		DEBUG_WARN("writable mmap PTEs, root %llu ino %llu pos %llu order %u",
+			   btrfs_root_id(inode->root), btrfs_ino(inode), folio_pos(folio),
+			   folio_order(folio));
+	}
+}
+#endif
+
 static noinline int lock_delalloc_folios(struct inode *inode,
 					 struct folio *locked_folio,
 					 u64 start, u64 end)
@@ -332,6 +352,8 @@ static noinline int lock_delalloc_folios(struct inode *inode,
 				folio_unlock(folio);
 				goto out;
 			}
+			/* Locked for writeback; revoke writable mmap PTEs before using the data. */
+			folio_mkclean(folio);
 			range_start = max_t(u64, folio_pos(folio), start);
 			range_len = min_t(u64, folio_next_pos(folio), end + 1) - range_start;
 			btrfs_folio_set_lock(fs_info, folio, range_start, range_len);
@@ -1893,6 +1915,13 @@ static noinline_for_stack int extent_writepage_io(struct btrfs_inode *inode,
 	ASSERT(end <= folio_end, "start=%llu len=%u folio_start=%llu folio_size=%zu",
 	       start, len, folio_start, folio_size(folio));
 
+	/*
+	 * We are about to checksum and write out the data, so it must not be
+	 * mmap writeable, or we could corrupt the data and end up with invalid
+	 * checksums.
+	 */
+	btrfs_check_folio_write_protected(folio);
+
 	/* Truncate the submit bitmap to the current range. */
 	if (start > folio_start)
 		bitmap_clear(bio_ctrl->submit_bitmap, 0,
@@ -2703,6 +2732,8 @@ static int extent_write_cache_pages(struct address_space *mapping,
 				continue;
 			}
 
+			/* Locked for writeback; revoke writable mmap PTEs before using the data. */
+			folio_mkclean(folio);
 			ret = extent_writepage(folio, bio_ctrl);
 			if (ret < 0) {
 				done = true;
fs/btrfs/extent_io.h +5 -0
index 9896e15ddc406..8699253376993 100644
@@ -255,6 +255,11 @@ bool try_release_extent_mapping(struct folio *folio, gfp_t mask);
 int try_release_extent_buffer(struct folio *folio);
 
 int btrfs_read_folio(struct file *file, struct folio *folio);
+#ifdef CONFIG_BTRFS_DEBUG
+void btrfs_check_folio_write_protected(struct folio *folio);
+#else
+static inline void btrfs_check_folio_write_protected(struct folio *folio) { }
+#endif
 void extent_write_locked_range(struct inode *inode, const struct folio *locked_folio,
 			       u64 start, u64 end, struct writeback_control *wbc,
 			       bool pages_dirty);
fs/btrfs/inode.c +17 -6
index 2534cd9284d54..39a01f9cf6b51 100644
@@ -775,19 +775,28 @@ static inline void inode_should_defrag(struct btrfs_inode *inode,
 
 static int extent_range_clear_dirty_for_io(struct btrfs_inode *inode, u64 start, u64 end)
 {
+	pgoff_t index = start >> PAGE_SHIFT;
 	const pgoff_t end_index = end >> PAGE_SHIFT;
 	struct folio *folio;
 	int ret = 0;
 
-	for (pgoff_t index = start >> PAGE_SHIFT; index <= end_index; index++) {
+	while (index <= end_index) {
 		folio = filemap_get_folio(inode->vfs_inode.i_mapping, index);
 		if (IS_ERR(folio)) {
 			if (!ret)
 				ret = PTR_ERR(folio);
+			index++;
 			continue;
 		}
+		/*
+		 * We are about to compress the folio, so it must not be mmap
+		 * writeable or we could corrupt the data as we attempt to
+		 * compress it.
+		 */
+		btrfs_check_folio_write_protected(folio);
 		btrfs_folio_clamp_clear_dirty(inode->root->fs_info, folio, start,
 					      end + 1 - start);
+		index = folio_next_index(folio);
 		folio_put(folio);
 	}
 	return ret;
@@ -877,11 +886,6 @@ static void compress_file_range(struct btrfs_work *work)
 
 	inode_should_defrag(inode, start, end, end - start + 1, SZ_16K);
 
-	/*
-	 * We need to call clear_page_dirty_for_io on each page in the range.
-	 * Otherwise applications with the file mmap'd can wander in and change
-	 * the page contents while we are compressing them.
-	 */
 	ret = extent_range_clear_dirty_for_io(inode, start, end);
 
 	/*
@@ -2317,6 +2321,13 @@ static int run_delalloc_inline(struct btrfs_inode *inode, struct folio *locked_f
 	int ret;
 
 	ASSERT(folio_pos(locked_folio) == 0);
+	/*
+	 * If an mmap writer could modify the folio while we copy it into an
+	 * inline extent we might see only part of their modification then
+	 * wrongly mark it clean again after copying, losing that write. So the
+	 * folio must be write protected here.
+	 */
+	btrfs_check_folio_write_protected(locked_folio);
 
 	if (btrfs_inode_can_compress(inode) &&
 	    inode_need_compress(inode, 0, blocksize, true)) {
Signature · 1 line
2.53.0
author maintainer
#10 lore raw

PATCH 10/713 ring-buffer: Fix subbuf resize race with ring buffer readers

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Vincent Donnefort <[email protected]>

[ Upstream commit 8a5f63637890f03177146efddaba5ec7a1b4d61f ]

trace_buffer subbuf_size is read lockless in ring_buffer_read_page() and ring_buffer_read_start(), while it can simultaneously be resized with ring_buffer_subbuf_order_set().

Instead of trace_buffer::subbuf_size, use bpage::order in ring_buffer_read_start() and ring_buffer_read_page().

In ring_buffer_read_start(), even with resize_disabled, there is still a possibility of a race with a buffer modification. Hold the trace_buffer mutex to synchronise with any pending ring buffer order modification.

trace_buffer::subbuf_size is now actually useless, remove it. Also, create accessors rb_subbuf_capacity() and rb_page_capacity() which return the actual size available for storing events, while rb_subbuf_size() returns the actual subbuf page-size.

---
 kernel/trace/ring_buffer.c | 167 +++++++++++++++++++++++--------------
 1 file changed, 106 insertions(+), 61 deletions(-)
kernel/trace/ring_buffer.c +106 -61
index 2667992f0aa29..0e92ee401813d 100644
@@ -391,6 +391,17 @@ static __always_inline unsigned int rb_page_size(struct buffer_page *bpage)
 	return rb_data_page_size(bpage->page);
 }
 
+/**
+ * rb_page_capacity - Get the capacity of a buffer page
+ * @bpage:	The buffer page
+ *
+ * Return: The maximum size available for events in the given buffer page.
+ */
+static __always_inline unsigned int rb_page_capacity(struct buffer_page *bpage)
+{
+	return (PAGE_SIZE << bpage->order) - BUF_PAGE_HDR_SIZE;
+}
+
 static void free_buffer_page(struct buffer_page *bpage)
 {
 	/* Range pages are not to be freed */
@@ -586,11 +597,42 @@ struct trace_buffer {
 
 	struct ring_buffer_meta		*meta;
 
-	unsigned int			subbuf_size;
 	unsigned int			subbuf_order;
 	unsigned int			max_data_size;
 };
 
+static __always_inline unsigned int rb_subbuf_size(struct trace_buffer *buffer)
+{
+	return PAGE_SIZE << buffer->subbuf_order;
+}
+
+/**
+ * rb_subbuf_capacity - Get the capacity of a subbuffer
+ * @buffer:	A trace buffer
+ *
+ * Unsafe to use without holding trace_buffer::mutex or with resizing enabled.
+ * Consider rb_page_capacity() instead.
+ *
+ * Return: The maximum size available for events in a trace buffer subbuffer.
+ */
+static __always_inline unsigned int rb_subbuf_capacity(struct trace_buffer *buffer)
+{
+	return rb_subbuf_size(buffer) - BUF_PAGE_HDR_SIZE;
+}
+
+/**
+ * rb_subbuf_start - Get the start address of a subbuffer
+ * @buffer:	A trace buffer
+ * @addr:	An address of an event on a subbuffer
+ *
+ * Return: The start of the subbuffer for where @addr sits
+ */
+static __always_inline
+unsigned long rb_subbuf_start(struct trace_buffer *buffer, unsigned long addr)
+{
+	return addr & ~((unsigned long)(rb_subbuf_size(buffer) - 1));
+}
+
 struct ring_buffer_iter {
 	struct ring_buffer_per_cpu	*cpu_buffer;
 	unsigned long			head;
@@ -630,7 +672,7 @@ int ring_buffer_print_page_header(struct trace_buffer *buffer, struct trace_seq
 	trace_seq_printf(s, "\tfield: char data;\t"
 			 "offset:%u;\tsize:%u;\tsigned:%u;\n",
 			 (unsigned int)offsetof(typeof(field), data),
-			 (unsigned int)(buffer ? buffer->subbuf_size :
+			 (unsigned int)(buffer ? rb_subbuf_capacity(buffer) :
 						 PAGE_SIZE - BUF_PAGE_HDR_SIZE),
 			 (unsigned int)is_signed_type(char));
 
@@ -1620,7 +1662,7 @@ rb_range_align_subbuf(unsigned long addr, int subbuf_size, int nr_subbufs)
  */
 static void *rb_range_meta(struct trace_buffer *buffer, int nr_pages, int cpu)
 {
-	int subbuf_size = buffer->subbuf_size + BUF_PAGE_HDR_SIZE;
+	int subbuf_size = rb_subbuf_size(buffer);
 	struct ring_buffer_cpu_meta *meta;
 	struct ring_buffer_meta *bmeta;
 	unsigned long ptr;
@@ -2432,8 +2474,8 @@ static int __rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer,
 			bpage->id = i + 1;
 			cpu_buffer->subbuf_ids[i + 1] = bpage;
 		} else {
-			int order = cpu_buffer->buffer->subbuf_order;
-			bpage->page = alloc_cpu_data(cpu_buffer->cpu, order);
+			bpage->page = alloc_cpu_data(cpu_buffer->cpu,
+						     cpu_buffer->buffer->subbuf_order);
 			if (!bpage->page)
 				goto free_pages;
 		}
@@ -2556,8 +2598,7 @@ rb_allocate_cpu_buffer(struct trace_buffer *buffer, long nr_pages, int cpu)
 		bpage->range = 1;
 		cpu_buffer->subbuf_ids[0] = bpage;
 	} else {
-		int order = cpu_buffer->buffer->subbuf_order;
-		bpage->page = alloc_cpu_data(cpu, order);
+		bpage->page = alloc_cpu_data(cpu, bpage->order);
 		if (!bpage->page)
 			goto fail_free_reader;
 	}
@@ -2731,10 +2772,9 @@ static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags,
 
 	buffer->subbuf_order = order;
 	subbuf_size = (PAGE_SIZE << order);
-	buffer->subbuf_size = subbuf_size - BUF_PAGE_HDR_SIZE;
 
 	/* Max payload is buffer page size - header (8bytes) */
-	buffer->max_data_size = buffer->subbuf_size - (sizeof(u32) * 2);
+	buffer->max_data_size = rb_subbuf_capacity(buffer) - (sizeof(u32) * 2);
 
 	buffer->flags = flags;
 	buffer->clock = trace_clock_local;
@@ -2818,9 +2858,8 @@ static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags,
 		if (nr_pages < 2)
 			goto fail_free_buffers;
 	} else {
-
 		/* need at least two pages */
-		nr_pages = DIV_ROUND_UP(size, buffer->subbuf_size);
+		nr_pages = DIV_ROUND_UP(size, rb_subbuf_capacity(buffer));
 		if (nr_pages < 2)
 			nr_pages = 2;
 	}
@@ -3203,7 +3242,7 @@ static void update_pages_handler(struct work_struct *work)
  * @size: the new size.
  * @cpu_id: the cpu buffer to resize
  *
- * Minimum size is 2 * buffer->subbuf_size.
+ * Minimum size is 2 * rb_subbuf_capacity(buffer).
  *
  * Returns 0 on success and < 0 on failure.
  */
@@ -3225,12 +3264,6 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size,
 	    !cpumask_test_cpu(cpu_id, buffer->cpumask))
 		return 0;
 
-	nr_pages = DIV_ROUND_UP(size, buffer->subbuf_size);
-
-	/* we need a minimum of two pages */
-	if (nr_pages < 2)
-		nr_pages = 2;
-
 	/*
 	 * Keep CPUs from coming online while resizing to synchronize
 	 * with new per CPU buffers being created.
@@ -3241,6 +3274,12 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size,
 	mutex_lock(&buffer->mutex);
 	atomic_inc(&buffer->resizing);
 
+	nr_pages = DIV_ROUND_UP(size, rb_subbuf_capacity(buffer));
+
+	/* we need a minimum of two pages */
+	if (nr_pages < 2)
+		nr_pages = 2;
+
 	if (cpu_id == RING_BUFFER_ALL_CPUS) {
 		/*
 		 * Don't succeed if resizing is disabled, as a reader might be
@@ -3513,7 +3552,7 @@ rb_event_index(struct ring_buffer_per_cpu *cpu_buffer, struct ring_buffer_event
 {
 	unsigned long addr = (unsigned long)event;
 
-	addr &= (PAGE_SIZE << cpu_buffer->buffer->subbuf_order) - 1;
+	addr &= (unsigned long)rb_subbuf_size(cpu_buffer->buffer) - 1;
 
 	return addr - BUF_PAGE_HDR_SIZE;
 }
@@ -3755,8 +3794,8 @@ static inline void
 rb_reset_tail(struct ring_buffer_per_cpu *cpu_buffer,
 	      unsigned long tail, struct rb_event_info *info)
 {
-	unsigned long bsize = READ_ONCE(cpu_buffer->buffer->subbuf_size);
 	struct buffer_page *tail_page = info->tail_page;
+	unsigned long bsize = rb_page_capacity(tail_page);
 	struct ring_buffer_event *event;
 	unsigned long length = info->length;
 
@@ -4101,8 +4140,7 @@ rb_try_to_discard(struct ring_buffer_per_cpu *cpu_buffer,
 
 	new_index = rb_event_index(cpu_buffer, event);
 	old_index = new_index + rb_event_ts_length(event);
-	addr = (unsigned long)event;
-	addr &= ~((PAGE_SIZE << cpu_buffer->buffer->subbuf_order) - 1);
+	addr = rb_subbuf_start(cpu_buffer->buffer, (unsigned long)event);
 
 	bpage = READ_ONCE(cpu_buffer->tail_page);
 
@@ -4767,7 +4805,7 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,
 	tail = write - info->length;
 
 	/* See if we shot pass the end of this buffer page */
-	if (unlikely(write > cpu_buffer->buffer->subbuf_size)) {
+	if (unlikely(write > rb_page_capacity(tail_page))) {
 		check_buffer(cpu_buffer, info, CHECK_FULL_PAGE);
 		return rb_move_tail(cpu_buffer, tail, info);
 	}
@@ -5012,7 +5050,7 @@ rb_decrement_entry(struct ring_buffer_per_cpu *cpu_buffer,
 	struct buffer_page *bpage = cpu_buffer->commit_page;
 	struct buffer_page *start;
 
-	addr &= ~((PAGE_SIZE << cpu_buffer->buffer->subbuf_order) - 1);
+	addr = rb_subbuf_start(cpu_buffer->buffer, addr);
 
 	/* Do the likely case first */
 	if (likely(bpage->page == (void *)addr)) {
@@ -5799,7 +5837,6 @@ static struct buffer_page *
 __rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer)
 {
 	int max_loops = cpu_buffer->ring_meta ? cpu_buffer->nr_pages : 3;
-	unsigned long bsize = READ_ONCE(cpu_buffer->buffer->subbuf_size);
 	struct buffer_page *reader = NULL;
 	unsigned long overwrite;
 	unsigned long flags;
@@ -5947,7 +5984,7 @@ __rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer)
 #define USECS_WAIT	1000000
         for (nr_loops = 0; nr_loops < USECS_WAIT; nr_loops++) {
 		/* If the write is past the end of page, a writer is still updating it */
-		if (likely(!reader || rb_page_write(reader) <= bsize))
+		if (likely(!reader || rb_page_write(reader) <= rb_page_capacity(reader)))
 			break;
 
 		udelay(1);
@@ -6380,36 +6417,44 @@ EXPORT_SYMBOL_GPL(ring_buffer_consume);
 struct ring_buffer_iter *
 ring_buffer_read_start(struct trace_buffer *buffer, int cpu, gfp_t flags)
 {
+	struct ring_buffer_iter *iter __free(kfree) = kzalloc_obj(*iter, flags);
 	struct ring_buffer_per_cpu *cpu_buffer;
-	struct ring_buffer_iter *iter;
-
-	if (!cpumask_test_cpu(cpu, buffer->cpumask))
-		return NULL;
 
-	iter = kzalloc_obj(*iter, flags);
 	if (!iter)
 		return NULL;
 
-	/* Holds the entire event: data and meta data */
-	iter->event_size = buffer->subbuf_size;
-	iter->event = kmalloc(iter->event_size, flags);
-	if (!iter->event) {
-		kfree(iter);
+	if (!cpumask_test_cpu(cpu, buffer->cpumask))
 		return NULL;
-	}
 
 	cpu_buffer = buffer->buffers[cpu];
 
-	iter->cpu_buffer = cpu_buffer;
+	/*
+	 * Only KDB is using GFP_ATOMIC, for the others, lock the buffer to
+	 * prevent concurrent resizing.
+	 */
+	if (gfpflags_allow_blocking(flags))
+		mutex_lock(&buffer->mutex);
 
 	atomic_inc(&cpu_buffer->resize_disabled);
 
+	if (gfpflags_allow_blocking(flags))
+		mutex_unlock(&buffer->mutex);
+
+	/* Holds the entire event: data and meta data. */
+	iter->event_size = rb_page_capacity(READ_ONCE(cpu_buffer->reader_page));
+	iter->event = kmalloc(iter->event_size, flags);
+	if (!iter->event) {
+		atomic_dec(&cpu_buffer->resize_disabled);
+		return NULL;
+	}
+	iter->cpu_buffer = cpu_buffer;
+
 	guard(raw_spinlock_irqsave)(&cpu_buffer->reader_lock);
 	arch_spin_lock(&cpu_buffer->lock);
 	rb_iter_reset(iter);
 	arch_spin_unlock(&cpu_buffer->lock);
 
-	return iter;
+	return_ptr(iter);
 }
 EXPORT_SYMBOL_GPL(ring_buffer_read_start);
 
@@ -6463,7 +6508,7 @@ unsigned long ring_buffer_size(struct trace_buffer *buffer, int cpu)
 	if (!cpumask_test_cpu(cpu, buffer->cpumask))
 		return 0;
 
-	return buffer->subbuf_size * buffer->buffers[cpu]->nr_pages;
+	return rb_subbuf_capacity(buffer) * buffer->buffers[cpu]->nr_pages;
 }
 EXPORT_SYMBOL_GPL(ring_buffer_size);
 
@@ -7094,15 +7139,15 @@ int ring_buffer_read_page(struct trace_buffer *buffer,
 	if (!data_page || !data_page->data)
 		return -1;
 
-	if (data_page->order != buffer->subbuf_order)
-		return -1;
-
 	dpage = data_page->data;
 	if (!dpage)
 		return -1;
 
 	guard(raw_spinlock_irqsave)(&cpu_buffer->reader_lock);
 
+	if (data_page->order != cpu_buffer->reader_page->order)
+		return -1;
+
 	reader = rb_get_reader_page(cpu_buffer);
 	if (!reader)
 		return -1;
@@ -7228,7 +7273,7 @@ int ring_buffer_read_page(struct trace_buffer *buffer,
 		 * missed events, then record it there.
 		 */
 		if (missed_events > 0 &&
-		    buffer->subbuf_size - size >= sizeof(missed_events)) {
+		    rb_page_capacity(reader) - size >= sizeof(missed_events)) {
 			memcpy(&dpage->data[size], &missed_events,
 			       sizeof(missed_events));
 			local_add(RB_MISSED_STORED, &dpage->commit);
@@ -7248,8 +7293,8 @@ int ring_buffer_read_page(struct trace_buffer *buffer,
 	/*
 	 * This page may be off to user land. Zero it out here.
 	 */
-	if (size < buffer->subbuf_size)
-		memset(&dpage->data[size], 0, buffer->subbuf_size - size);
+	if (size < rb_page_capacity(reader))
+		memset(&dpage->data[size], 0, rb_page_capacity(reader) - size);
 
 	return read;
 }
@@ -7275,7 +7320,7 @@ EXPORT_SYMBOL_GPL(ring_buffer_read_page_data);
  */
 int ring_buffer_subbuf_size_get(struct trace_buffer *buffer)
 {
-	return buffer->subbuf_size + BUF_PAGE_HDR_SIZE;
+	return rb_subbuf_size(buffer);
 }
 EXPORT_SYMBOL_GPL(ring_buffer_subbuf_size_get);
 
@@ -7320,7 +7365,8 @@ int ring_buffer_subbuf_order_set(struct trace_buffer *buffer, int order)
 {
 	struct ring_buffer_per_cpu *cpu_buffer;
 	struct buffer_page *bpage, *tmp;
-	int old_order, old_size;
+	unsigned int old_capacity;
+	int old_order;
 	int nr_pages;
 	int psize;
 	int err;
@@ -7329,9 +7375,6 @@ int ring_buffer_subbuf_order_set(struct trace_buffer *buffer, int order)
 	if (!buffer || order < 0)
 		return -EINVAL;
 
-	if (buffer->subbuf_order == order)
-		return 0;
-
 	psize = (1 << order) * PAGE_SIZE;
 	if (psize <= BUF_PAGE_HDR_SIZE)
 		return -EINVAL;
@@ -7340,18 +7383,21 @@ int ring_buffer_subbuf_order_set(struct trace_buffer *buffer, int order)
 	if (psize > RB_WRITE_MASK + 1)
 		return -EINVAL;
 
-	old_order = buffer->subbuf_order;
-	old_size = buffer->subbuf_size;
-
 	/* prevent another thread from changing buffer sizes */
 	guard(mutex)(&buffer->mutex);
+
+	old_order = buffer->subbuf_order;
+	if (old_order == order)
+		return 0;
+
+	old_capacity = rb_subbuf_capacity(buffer);
+
 	atomic_inc(&buffer->record_disabled);
 
 	/* Make sure all commits have finished */
 	synchronize_rcu();
 
 	buffer->subbuf_order = order;
-	buffer->subbuf_size = psize - BUF_PAGE_HDR_SIZE;
 
 	/* Make sure all new buffers are allocated, before deleting the old ones */
 	for_each_buffer_cpu(buffer, cpu) {
@@ -7367,8 +7413,8 @@ int ring_buffer_subbuf_order_set(struct trace_buffer *buffer, int order)
 		}
 
 		/* Update the number of pages to match the new size */
-		nr_pages = old_size * buffer->buffers[cpu]->nr_pages;
-		nr_pages = DIV_ROUND_UP(nr_pages, buffer->subbuf_size);
+		nr_pages = old_capacity * buffer->buffers[cpu]->nr_pages;
+		nr_pages = DIV_ROUND_UP(nr_pages, rb_subbuf_capacity(buffer));
 
 		/* we need a minimum of two pages */
 		if (nr_pages < 2)
@@ -7454,7 +7500,6 @@ int ring_buffer_subbuf_order_set(struct trace_buffer *buffer, int order)
 
 error:
 	buffer->subbuf_order = old_order;
-	buffer->subbuf_size = old_size;
 
 	atomic_dec(&buffer->record_disabled);
 
@@ -7532,7 +7577,7 @@ static void rb_setup_ids_meta_page(struct ring_buffer_per_cpu *cpu_buffer,
 
 	meta->meta_struct_len = sizeof(*meta);
 	meta->nr_subbufs = nr_subbufs;
-	meta->subbuf_size = cpu_buffer->buffer->subbuf_size + BUF_PAGE_HDR_SIZE;
+	meta->subbuf_size = rb_subbuf_size(cpu_buffer->buffer);
 	meta->meta_page_size = meta->subbuf_size;
 
 	rb_update_meta_page(cpu_buffer);
@@ -7894,7 +7939,7 @@ int ring_buffer_map_get_reader(struct trace_buffer *buffer, int cpu)
 			 * missed events, then record it there.
 			 */
 			commit = rb_page_size(reader);
-			if (buffer->subbuf_size - commit >= sizeof(missed_events)) {
+			if (rb_subbuf_capacity(buffer) - commit >= sizeof(missed_events)) {
 				memcpy(&dpage->data[commit], &missed_events,
 				       sizeof(missed_events));
 				local_add(RB_MISSED_STORED, &dpage->commit);
@@ -7926,7 +7971,7 @@ int ring_buffer_map_get_reader(struct trace_buffer *buffer, int cpu)
 out:
 	/* Some archs do not have data cache coherency between kernel and user-space */
 	flush_kernel_vmap_range(cpu_buffer->reader_page->page,
-				buffer->subbuf_size + BUF_PAGE_HDR_SIZE);
+				rb_subbuf_size(buffer));
 
 	rb_update_meta_page(cpu_buffer);
 
Signature · 1 line
2.53.0
author maintainer
#11 lore raw

PATCH 11/713 drm/amd/display: hide Apple Studio Display secondary tile

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jerry Zuo <[email protected]>

[ Upstream commit 49521be4809d63fe3efb6bc68ee11cb1e1ef3d63 ]

The Apple Studio Display exposes a 2x1 tiled panel over two SST DP links. The primary tile advertises the full 5120x2880 mode (with DSC on the bandwidth-sufficient link) while the secondary carries a per-tile 2560x2880 timing on a link without sufficient bandwidth. Report the non-primary tile connector as disconnected during detect so compositors only see the primary DP link and configure a single 5K mode instead of driving both tiled streams independently.

Drive the behaviour from an EDID quirk: add a disable_second_tile panel patch that apply_edid_quirks() sets for the affected Apple Studio Display panel IDs (0xAE3A, 0xAE42, 0xAE46), and have detect() hide the secondary tile when the sink carries that quirk.

Adjust for lack of movement from amdgpu_dm.c to amdgpu_dm_connector.c

---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 36 +++++++++++++++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 11 ++++++
 drivers/gpu/drm/amd/display/dc/dc_types.h     |  1 +
 3 files changed, 48 insertions(+)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +36 -0
index 941c1a3128249..6604ce25255d8 100644
@@ -7846,6 +7846,39 @@ amdgpu_dm_connector_poll(struct amdgpu_dm_connector *aconnector, bool force)
 	return status;
 }
 
+/*
+ * Apple Studio Display exposes two SST DP links for a 2x1 tiled panel.
+ * The primary tile advertises the full 5120x2880 mode (with DSC on the
+ * bandwidth-sufficient link) while the secondary carries a per-tile
+ * 2560x2880 timing on a insufficient bandwidth link. Hide the secondary
+ * connector from userspace so compositors configure a single 5K stream
+ * on the primary link only.
+ */
+static bool amdgpu_dm_hide_secondary_tile_from_userspace(struct drm_connector *connector)
+{
+	struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
+
+	if (!aconnector->dc_sink)
+		return false;
+
+	if (!aconnector->dc_sink->edid_caps.panel_patch.disable_second_tile)
+		return false;
+
+	drm_edid_connector_update(connector, aconnector->drm_edid);
+
+	if (!connector->has_tile)
+		return false;
+
+	if (!connector->tile_h_loc && !connector->tile_v_loc)
+		return false;
+
+	drm_dbg_kms(connector->dev,
+		    "[CONNECTOR:%d:%s] hiding secondary Apple Studio Display tile from userspace\n",
+		    connector->base.id, connector->name);
+
+	return true;
+}
+
 /**
  * amdgpu_dm_connector_detect() - Detect whether a DRM connector is connected to a display
  *
@@ -7889,6 +7922,9 @@ amdgpu_dm_connector_detect(struct drm_connector *connector, bool force)
 		(!aconnector->dc_sink || aconnector->dc_sink->edid_caps.analog))
 		return amdgpu_dm_connector_poll(aconnector, force);
 
+	if (amdgpu_dm_hide_secondary_tile_from_userspace(connector))
+		return connector_status_disconnected;
+
 	return (aconnector->dc_sink ? connector_status_connected :
 			connector_status_disconnected);
 }
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +11 -0
index 6be7f6edd0b29..41aa8f9bb152b 100644
@@ -134,6 +134,17 @@ static void apply_edid_quirks(struct dc_link *link, struct edid *edid,
 		drm_dbg_driver(dev, "Skip PHY SSC reduction on panel id %X\n", panel_id);
 		link->wa_flags.skip_phy_ssc_reduction = true;
 		break;
+	/*
+	 * Workaround for Apple Studio Display which exposes a 2x1 tiled panel
+	 * over two SST DP links. Hide the secondary tile from userspace so
+	 * compositors drive a single 5K stream on the primary link only.
+	 */
+	case drm_edid_encode_panel_id('A', 'P', 'P', 0xAE3A):
+	case drm_edid_encode_panel_id('A', 'P', 'P', 0xAE42):
+	case drm_edid_encode_panel_id('A', 'P', 'P', 0xAE46):
+		drm_dbg_driver(dev, "Hiding secondary tile on panel id %X\n", panel_id);
+		edid_caps->panel_patch.disable_second_tile = true;
+		break;
 	default:
 		return;
 	}
drivers/gpu/drm/amd/display/dc/dc_types.h +1 -0
index 4ed1efa172709..6482e275e63bf 100644
@@ -187,6 +187,7 @@ struct dc_panel_patch {
 	unsigned int skip_audio_sab_check;
 	unsigned int mst_start_top_delay;
 	unsigned int remove_sink_ext_caps;
+	bool disable_second_tile;
 	unsigned int disable_colorimetry;
 	uint8_t blankstream_before_otg_off;
 	bool oled_optimize_display_on;
Signature · 1 line
2.53.0
author maintainer
#12 lore raw

PATCH 12/713 drm/amd/display: Prune per-tile Timing from Apple Studio Display Primary Tile

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Fangzhi Zuo <[email protected]>

[ Upstream commit 7a4dd08c3f921576c6a7524f60e4f0e4601835d2 ]

[why]
The Apple Studio Display primary tile advertises both the full 5120x2880 mode and the per-tile 2560x2880 timing. With the secondary tile already hidden from userspace, the stray 2560x2880 mode on the primary connector can still be picked by compositors, defeating the single 5K stream goal.

[how]
Prune the per-tile timing from the primary connector during get_modes:
when the sink carries the disable_second_tile quirk and the connector is the primary tile (tile_h_loc == 0 && tile_v_loc == 0), drop any probed mode matching the advertised tile size (tile_h_size x tile_v_size) so userspace only sees the full 5120x2880 mode.

Fixes 49521be4809d ("drm/amd/display: hide Apple Studio Display secondary tile")

Adjust for lack of movement from amdgpu_dm.c to amdgpu_dm_connector.c

---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 43 +++++++++++++++++++
 1 file changed, 43 insertions(+)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +43 -0
index 6604ce25255d8..9320e49e44289 100644
@@ -9116,6 +9116,47 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder,
 	}
 }
 
+/*
+ * The Apple Studio Display primary tile advertises both the full 5120x2880
+ * mode and the per-tile 2560x2880 timing. As the secondary tile is hidden from
+ * userspace (see amdgpu_dm_hide_secondary_tile_from_userspace()), drop the
+ * per-tile timing from the primary connector so compositors only pick the full
+ * 5K mode.
+ */
+static void amdgpu_dm_prune_primary_tile_modes(struct drm_connector *connector)
+{
+	struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
+	struct drm_display_mode *mode, *t;
+
+	if (!aconnector->dc_sink)
+		return;
+
+	if (!aconnector->dc_sink->edid_caps.panel_patch.disable_second_tile)
+		return;
+
+	if (!connector->has_tile)
+		return;
+
+	/* Only prune the per-tile timing from the primary tile. */
+	if (connector->tile_h_loc || connector->tile_v_loc)
+		return;
+
+	list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
+		if (mode->hdisplay != connector->tile_h_size ||
+		    mode->vdisplay != connector->tile_v_size)
+			continue;
+
+		drm_dbg_kms(connector->dev,
+			    "[CONNECTOR:%d:%s] pruning per-tile %dx%d timing from primary Apple Studio Display tile\n",
+			    connector->base.id, connector->name,
+			    mode->hdisplay, mode->vdisplay);
+
+		list_del(&mode->head);
+		drm_mode_destroy(connector->dev, mode);
+		aconnector->num_modes--;
+	}
+}
+
 static void amdgpu_set_panel_orientation(struct drm_connector *connector)
 {
 	struct drm_encoder *encoder;
@@ -9158,6 +9199,8 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector,
 		amdgpu_dm_connector->num_modes =
 				drm_edid_connector_add_modes(connector);
 
+		amdgpu_dm_prune_primary_tile_modes(connector);
+
 		/* sorting the probed modes before calling function
 		 * amdgpu_dm_get_native_mode() since EDID can have
 		 * more than one preferred mode. The modes that are
Signature · 1 line
2.53.0
author maintainer
#13 lore raw

PATCH 13/713 alpha: fix ieee_swcr_to_fpcr setting FPCR_DNOD unconditionally

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matt Turner <[email protected]>

commit 49672d026cc4773608e1222b69b29fd70f41336b upstream.

ieee_swcr_to_fpcr() converts the software IEEE trap-enable and status bits kept in thread_info.ieee_state into the hardware FPCR format. It contained:

	fp |= (~sw & IEEE_TRAP_ENABLE_DNO) << 41;

FPCR_DNOD (bit 47) disables denormal operand traps: with it set the hardware handles a denormal operand itself, treating it as zero, instead of trapping for software completion. The intent was to set DNOD when the user has not asked for SIGFPE on denormal operands, but IEEE_TRAP_ENABLE_DNO is clear by default, so ieee_swcr_to_fpcr(0) always set DNOD.

Instructions built with the software completion suffix therefore never trapped on a denormal operand. The hardware silently substituted zero and produced wrong results, affecting every program compiled with -mieee and default FPU settings, glibc included.

Set FPCR_DNOD only when IEEE_MAP_DMZ is requested, which is exactly the case where flushing denormal inputs to zero is what the user asked for. DNOD then encodes MAP_DMZ, which ieee_fpcr_to_swcr() already recovers from FPCR_DNZ, so drop its attempt to recover IEEE_TRAP_ENABLE_DNO from DNOD; the DNO trap enable lives solely in ieee_state.

Both functions are in a uapi header, so the encoding change is visible to userspace, but nothing outside the kernel is known to depend on DNOD carrying the DNO trap enable, and the kernel is the only writer of the FPCR.

This must not be backported on its own. Re-enabling denormal operand traps exposes a second bug, fixed in the following patch: those traps usually find an exact result, and for an exact result the emulator did not write the FPCR back, leaving hardware-fabricated exception bits visible to user space. Taken alone this change would make spurious exception flags more common.

The bug predates the git history, so there is no commit to reference in a Fixes tag.

---
 arch/alpha/include/uapi/asm/fpu.h |    8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
arch/alpha/include/uapi/asm/fpu.h +6 -2
@@ -101,7 +101,12 @@ ieee_swcr_to_fpcr(unsigned long sw)
 		      | IEEE_TRAP_ENABLE_OVF)) << 48;
 	fp |= (~sw & (IEEE_TRAP_ENABLE_UNF | IEEE_TRAP_ENABLE_INE)) << 57;
 	fp |= (sw & IEEE_MAP_UMZ ? FPCR_UNDZ | FPCR_UNFD : 0);
-	fp |= (~sw & IEEE_TRAP_ENABLE_DNO) << 41;
+	/*
+	 * Disable denormal operand traps only when denormal inputs are to be
+	 * flushed to zero.  Otherwise they must keep trapping, so that /S
+	 * instructions reach the kernel emulation handler.
+	 */
+	fp |= (sw & IEEE_MAP_DMZ ? FPCR_DNOD : 0);
 	return fp;
 }
 
@@ -116,7 +121,6 @@ ieee_fpcr_to_swcr(unsigned long fp)
 			     | IEEE_TRAP_ENABLE_OVF);
 	sw |= (~fp >> 57) & (IEEE_TRAP_ENABLE_UNF | IEEE_TRAP_ENABLE_INE);
 	sw |= (fp >> 47) & IEEE_MAP_UMZ;
-	sw |= (~fp >> 41) & IEEE_TRAP_ENABLE_DNO;
 	return sw;
 }
 
author maintainer
#14 lore raw

PATCH 14/713 iomap: dont free integrity payload that doesnt exist

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Christoph Hellwig <[email protected]>

commit 8a8685b32c0718cc7b2cb4d6202e5a5b8e0a8e2d upstream.

fs_bio_integrity_alloc might not allocate a bio integrity payload if PI verification is disabled on the block device. Check for that case before calling fs_bio_integrity_free in iomap_bio_read_folio_range_sync to avoid a NULL pointer dereferences.

Make the branch cover the PI verification as well - while fs_bio_integrity_verify works without an integrity payload, it requires one to actually do useful work.

---
 fs/iomap/bio.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/iomap/bio.c +1 -1
@@ -179,7 +179,7 @@ int iomap_bio_read_folio_range_sync(cons
 	if (srcmap->flags & IOMAP_F_INTEGRITY)
 		fs_bio_integrity_alloc(&bio);
 	error = submit_bio_wait(&bio);
-	if (srcmap->flags & IOMAP_F_INTEGRITY) {
+	if (bio_integrity(&bio)) {
 		if (!error)
 			error = fs_bio_integrity_verify(&bio, sector, len);
 		fs_bio_integrity_free(&bio);
author maintainer
#15 lore raw

PATCH 15/713 rust: time: fix as_micros_ceil() rounding near i64::MAX

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: FUJITA Tomonori <[email protected]>

commit ec90dfcf05f02206c280bb59af660bbb3ae177d0 upstream.

The ceiling adjustment used saturating_add(NSEC_PER_USEC - 1) before dividing. Once the nanosecond value gets within NSEC_PER_USEC - 1 of i64::MAX the addition saturates to i64::MAX, which drops the ceiling bias and can yield a result one microsecond too small.

---
 rust/kernel/time.rs |   17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)
rust/kernel/time.rs +10 -7
@@ -441,22 +441,25 @@ impl Delta {
     /// to the value in the [`Delta`].
     #[inline]
     pub fn as_micros_ceil(self) -> i64 {
+        // Only positive values need to be rounded up: truncating division already
+        // rounds towards zero, i.e. up, for negative values.
+        //
+        // The usual `(nanos + d - 1) / d` is not used because the addition overflows
+        // once `nanos` exceeds `i64::MAX - (d - 1)`; saturating the addition instead
+        // would drop the rounding bias and return a result one unit too small.
         let n = self.as_nanos();
-        let n = if n >= 0 {
-            n.saturating_add(NSEC_PER_USEC - 1)
-        } else {
-            n
-        };
+
+        let (n, add) = if n > 0 { (n - 1, 1) } else { (n, 0) };
 
         #[cfg(CONFIG_64BIT)]
         {
-            n / NSEC_PER_USEC
+            n / NSEC_PER_USEC + add
         }
 
         #[cfg(not(CONFIG_64BIT))]
         // SAFETY: It is always safe to call `ktime_to_us()` with any value.
         unsafe {
-            bindings::ktime_to_us(n)
+            bindings::ktime_to_us(n) + add
         }
     }
 
author maintainer
#16 lore raw

PATCH 16/713 alpha: dont leak hardware-fabricated FP exception bits to user space

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matt Turner <[email protected]>

commit bcfe3187412e342b4619efb92c945f073855ebc0 upstream.

On EV6 and later the hardware records exception status bits in the FPCR before delivering a software completion trap, and those bits can be wrong for the instruction that trapped. Converting a double that is exactly representable as a subnormal float sets FPCR_UNF even though the result is exact, and an underflow trap additionally sets FPCR_INE even when the emulated operation turns out to be exact.

alpha_fp_emul() only wrote the FPCR when soft-fp raised an exception, so whenever it determined that the instruction was exact the fabricated bits stayed in the FPCR and were reported to user space by fetestexcept().

Pass the exception summary register down from do_entArith() so the handler can tell which exceptions the hardware attributed to the trapping instruction, and always write the FPCR. Clear the exceptions that the trap reported but that soft-fp did not raise. EXC_SUM reports only the underflow or overflow when the hardware also set INE, so treat INE as a candidate in that case, and treat a trap with no reported exception as a denormal operand trap, for which the hardware can fabricate INE and UNF as well. Bits that software has already confirmed in ieee_state belong to this or an earlier instruction and are never cleared.

The imprecise path passes no summary. There the trap was taken somewhere in the trap shadow, so EXC_SUM is not attribution for the instruction being re-executed -- and only EV6, which traps precisely and so never takes that path, has fabricated bits to clear. For the same reason the clearing is guarded by implver(), matching swcr_update_status().

On an UP1500 (EV68) this takes the glibc math testsuite from 831 failures to 28, the remainder being unrelated to exception status.

This belongs with the preceding fix to ieee_swcr_to_fpcr(), and should not be backported without it -- nor it without this. That fix stops FPCR_DNOD being set unconditionally, so denormal operand traps start firing again. Those traps very often find an exact result, which is precisely the case where the old code left the FPCR unwritten and the fabricated bits visible. Applied alone it would make spurious exception flags more common, not less.

One case cannot be resolved here: an inexact instruction without the software completion suffix never traps, so its INE reaches the FPCR without being recorded anywhere else. Such a bit is indistinguishable from an INE the hardware fabricated for a trapping instruction, and is lost if an underflow or overflow trap with an exact result follows it. The FPCR is the only record of those instructions and it carries no attribution.

The bug predates the git history, so there is no commit to reference in a Fixes tag.

---
 arch/alpha/kernel/traps.c  |    6 +--
 arch/alpha/math-emu/math.c |   88 +++++++++++++++++++++++++++++++++++++++------
 2 files changed, 80 insertions(+), 14 deletions(-)
arch/alpha/kernel/traps.c +3 -3
@@ -166,12 +166,12 @@ static long dummy_emul(void) { return 0;
 long (*alpha_fp_emul_imprecise)(struct pt_regs *regs, unsigned long writemask)
   = (void *)dummy_emul;
 EXPORT_SYMBOL_GPL(alpha_fp_emul_imprecise);
-long (*alpha_fp_emul) (unsigned long pc)
+long (*alpha_fp_emul) (unsigned long pc, unsigned long summary)
   = (void *)dummy_emul;
 EXPORT_SYMBOL_GPL(alpha_fp_emul);
 #else
 long alpha_fp_emul_imprecise(struct pt_regs *regs, unsigned long writemask);
-long alpha_fp_emul (unsigned long pc);
+long alpha_fp_emul (unsigned long pc, unsigned long summary);
 #endif
 
 asmlinkage void
@@ -185,7 +185,7 @@ do_entArith(unsigned long summary, unsig
 		   emulate the instruction.  If the processor supports
 		   precise exceptions, we don't have to search.  */
 		if (!amask(AMASK_PRECISE_TRAP))
-			si_code = alpha_fp_emul(regs->pc - 4);
+			si_code = alpha_fp_emul(regs->pc - 4, summary);
 		else
 			si_code = alpha_fp_emul_imprecise(regs, write_mask);
 		if (si_code == 0)
arch/alpha/math-emu/math.c +77 -11

125 lines not on this page · raw message

author maintainer
#17 lore raw

PATCH 17/713 clocksource/drivers/nxp-pit: Fix IRQ leak on cpuhp_setup_state error path

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: WenTao Liang <[email protected]>

commit 05520e035f8332c8e33f3011b5ca016fde61793d upstream.

When cpuhp_setup_state fails after pit_clockevent_per_cpu_init has successfully called request_irq, the error handling jumps directly to out_pit_clocksource_unregister without freeing the registered IRQ.

This leaks the IRQ line and, since kfree(pit) follows, leaves a dangling pointer registered as the interrupt handler's dev_id, potentially leading to a use-after-free if the IRQ fires afterwards.

Fix it by calling pit_clockevent_per_cpu_exit to properly release the IRQ before falling through to the existing cleanup chain.

Fixes bee33f22d7c3 ("clocksource/drivers/nxp-pit: Add NXP Automotive s32g2 / s32g3 support")
---
 drivers/clocksource/timer-nxp-pit.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/clocksource/timer-nxp-pit.c +3 -1
@@ -328,8 +328,10 @@ static int pit_timer_init(struct device_
 	if (pit_instances == max_pit_instances) {
 		ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "PIT timer:starting",
 					pit_clockevent_starting_cpu, NULL);
-		if (ret < 0)
+		if (ret < 0) {
+			pit_clockevent_per_cpu_exit(pit, pit_instances);
 			goto out_pit_clocksource_unregister;
+		}
 	}
 
 	return 0;
author maintainer
#18 lore raw

PATCH 18/713 clocksource/drivers/timer-sun4i: Advertise a real minimum delta

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Felix Yan <[email protected]>

commit d21808328225ab8cee46885bf9a0dffcefbe630e upstream.

sun4i_clkevt_next_event() compensates for the timer stop/start synchronization delay by programming evt - TIMER_SYNC_TICKS into the hardware interval register. The clockevent device currently advertises TIMER_SYNC_TICKS as min_delta_ticks, so the clockevents core is allowed to call set_next_event() with evt == TIMER_SYNC_TICKS.

That programs a zero-tick interval. With oneshot/highres/nohz timer operation this can leave the next event stuck, which was observed as a boot hang on Allwinner D1 after the clockevents core started reusing forced minimum-delta events.

Advertise one extra tick instead, so the smallest event accepted by the core still programs at least one hardware tick after the synchronization compensation.

---
 drivers/clocksource/timer-sun4i.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/clocksource/timer-sun4i.c +1 -1
@@ -208,7 +208,7 @@ static int __init sun4i_timer_init(struc
 	sun4i_timer_clear_interrupt(timer_of_base(&to));
 
 	clockevents_config_and_register(&to.clkevt, timer_of_rate(&to),
-					TIMER_SYNC_TICKS, 0xffffffff);
+					TIMER_SYNC_TICKS + 1, 0xffffffff);
 
 	/* Enable timer0 interrupt */
 	val = readl(timer_of_base(&to) + TIMER_IRQ_EN_REG);
author maintainer
#19 lore raw

PATCH 19/713 fs: fix user path of nested backing files

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Baokun Li <[email protected]>

commit f2381b546e7e6a35c9fcee0d0ccb6c042a9aeb5d upstream.

backing_file_open() derives the path to be stored in the new backing file from user_file->f_path. This is incorrect when user_file itself is a backing file, which is the case for nested stacking filesystems, e.g. overlayfs mounts where the lowerdir of one overlayfs is the merged directory of another. Since commit def3ae83da02 ("fs: store real path instead of fake path in backing file f_path") the f_path of a backing file holds the real path of the intermediate layer, not the path that the user opened.

Commit 924577e4f6ca ("ovl: Fix nested backing file paths") fixed this for such configurations by passing file_user_path() from ovl_open_realfile(). However, commit 6af36aeb147a ("lsm: add backing_file LSM hooks") changed the first argument of backing_file_open() from the user path back to the user file and derived the path from user_file->f_path again, silently re-introducing the problem.

As a result, files mapped through a nested overlayfs show the wrong path in /proc/<pid>/maps and in perf/ftrace mmap records. For example, with two nested overlayfs mounts:

mkdir -p /ovl/{lower,upper,work,merged} /ovl/nested echo hello > /ovl/lower/foo

  mount -t overlay overlay \
	-o lowerdir=/ovl/lower,upperdir=/ovl/upper,workdir=/ovl/work \
	/ovl/merged
  # at least two lowerdirs are needed when upperdir is nonexistent
  mount -t overlay overlay \
	-o lowerdir=/ovl/merged:/ovl/lower /ovl/nested

mapping /ovl/nested/foo shows a disconnected path instead of the user path:

  # readlink /proc/self/fd/3
  /ovl/nested/foo
  # grep foo /proc/self/maps
  7f6e2c100000-7f6e2c101000 r--s 00000000 00:24 15813027 /foo

The bogus path is derived from the f_path of the intermediate backing file, whose mount is a private clone that d_path() cannot resolve.

Fix this by using file_user_path(), which returns the outermost user-visible path for backing files and falls back to &user_file->f_path for regular files. This restores the behavior of commit 924577e4f6ca ("ovl: Fix nested backing file paths") for overlayfs and also fixes the same problem for the other backing_file_open() callers, fuse passthrough and erofs ishare, when their user file is itself a backing file.

backing_tmpfile_open() has the same pattern but is not affected: it is only called by ovl_create_tmpfile() for the upper layer, and another overlayfs is rejected as upperdir by the DCACHE_OP_REAL check in ovl_mount_dir_check(), so its user_file can never be a backing file.

---
 fs/backing-file.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/backing-file.c +1 -1
@@ -35,7 +35,7 @@ struct file *backing_file_open(const str
 			       const struct path *real_path,
 			       const struct cred *cred)
 {
-	const struct path *user_path = &user_file->f_path;
+	const struct path *user_path = file_user_path(user_file);
 	struct file *f;
 	int error;
 
author maintainer
#20 lore raw

PATCH 20/713 ovl: fix double end_creating() on the casefold-mismatch path

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Vivek Parikh <[email protected]>

commit 077ab8985ee278c3d8618182d335b0f0cd919e16 upstream.

ovl_create_real() releases the new dentry twice when the casefold consistency check fails. The S_IFDIR branch calls end_creating() and sets err, then falls through to the common out: label which calls end_creating() on the same dentry again:

	case S_IFDIR:
		newdentry = ovl_do_mkdir(ofs, dir, newdentry, attr->mode);
		err = PTR_ERR_OR_ZERO(newdentry);
		if (!err && ofs->casefold != ovl_dentry_casefolded(newdentry)) {
			pr_warn_ratelimited(...);
			end_creating(newdentry);	/* first */
			err = -EINVAL;
		}
		break;
	...
	if (err)
		goto out;
	...
 out:
	if (err) {
		end_creating(newdentry);	/* second, same dentry */
		return ERR_PTR(err);
	}

end_creating() is end_dirop(), which does inode_unlock() on the parent and dput() on the dentry, so the parent directory's i_rwsem is unlocked twice and the dentry is put twice. The second unlock releases a lock that is not held, which is what wedges every later creation under that parent, and the second dput() drops a reference that was never taken.

The branch was added by commit dfc7da402ccc ("ovl: Check for casefold consistency when creating new dentries") as a bare dput(), which already released the reference twice; commit fe497f0759e0 ("VFS: change vfs_mkdir() to unlock on failure.") converted both sites to end_creating(), adding the double unlock.

This is reachable by an unprivileged user. The casefold consistency of the layers is validated at mount time in ovl_parse_layer(), and again on every lookup in ovl_lookup_single(), but ofs->workdir is the internal "work" subdirectory created inside the user-supplied workdir, and that subdirectory is not re-checked. Marking it casefolded after the mount therefore makes every ovl_create_temp() inherit the wrong state - and that path reaches ovl_create_real() through ovl_start_creating_temp(), which uses start_creating() with a generated name and so never runs the lookup-time check.

  unshare -Urm
  mount -t tmpfs -o casefold=utf8-12.1.0 tmpfs mnt
  mkdir -p mnt/lower/d mnt/upper mnt/work mnt/merged
  mount -t overlay ovl -o lowerdir=mnt/lower,\
        upperdir=mnt/upper,workdir=mnt/work mnt/merged
  chattr +F mnt/work/work
  mkdir mnt/merged/d/sub		# directory copy-up

overlayfs: wrong inherited casefold (work/#5)

and the next copy-up blocks forever on the parent's i_rwsem:

mkdir D start_creating+0x65/0xb0

                     ovl_start_creating_temp+0xb0/0xe0 [overlay]
                     ovl_create_temp+0xa3/0x1d0 [overlay]
                     ovl_copy_up_one+0x1f1c/0x21c0 [overlay]
                     ovl_copy_up_flags+0xf5/0x140 [overlay]
                     ovl_create_object+0xb7/0x220 [overlay]
                     ovl_mkdir+0x23/0x40 [overlay]

Drop the end_creating() from the branch and let out: own the cleanup, which is what every other error path in this function already does.

Fixes dfc7da402ccc ("ovl: Check for casefold consistency when creating new dentries")
---
 fs/overlayfs/dir.c |    1 -
 1 file changed, 1 deletion(-)
fs/overlayfs/dir.c +0 -1
@@ -188,7 +188,6 @@ struct dentry *ovl_create_real(struct ov
 			if (!err && ofs->casefold != ovl_dentry_casefolded(newdentry)) {
 				pr_warn_ratelimited("wrong inherited casefold (%pd2)\n",
 						    newdentry);
-				end_creating(newdentry);
 				err = -EINVAL;
 			}
 			break;
author maintainer
#21 lore raw

PATCH 21/713 pidfd: hold exec_update_lock around namespace ioctl

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Chen Linxuan <[email protected]>

commit 9688a46802939da28f00cb40e8129615d5d4af39 upstream.

The PIDFD_GET_*_NAMESPACE ioctls in pidfd_ioctl() perform a filesystem credentials ptrace access check before handing out a namespace file descriptor. The accompanying comment states that the code "mirrors nsfs behavior", but, unlike the corresponding procfs paths, it does so without holding the target task's exec_update_lock.

proc_ns_get_link() and proc_ns_readlink() both take exec_update_lock for reading around the ptrace check and the namespace lookup, so that the credentials used for the access decision match those of the task when its namespace is read. Without it, a caller can pass the check against the target's old credentials and then read the namespace after the target has execve()'d a setuid binary and committed new credentials -- accessing namespace information it should have been denied.

Hold exec_update_lock for reading around the ptrace check and the namespace lookup so that pidfd truly mirrors nsfs behavior, as the comment already claims. open_namespace() itself runs outside the lock: once a namespace reference is obtained it carries its own refcount and is opened with the caller's own credentials, so a concurrent execve() on the target can no longer affect the outcome.

---
 fs/pidfs.c |   43 +++++++++++++++++++++++++++++++------------
 1 file changed, 31 insertions(+), 12 deletions(-)
fs/pidfs.c +31 -12
@@ -532,6 +532,7 @@ static long pidfd_ioctl(struct file *fil
 	struct task_struct *task __free(put_task) = NULL;
 	struct nsproxy *nsp __free(put_nsproxy) = NULL;
 	struct ns_common *ns_common = NULL;
+	int error;
 
 	if (!pidfs_ioctl_valid(cmd))
 		return -ENOIOCTLCMD;
@@ -555,20 +556,33 @@ static long pidfd_ioctl(struct file *fil
 	if (arg)
 		return -EINVAL;
 
+	/*
+	 * We're trying to open a file descriptor to the namespace so perform a
+	 * filesystem cred ptrace check. Hold @task's exec_update_lock for the
+	 * duration of the ptrace check and the namespace lookup so that the
+	 * credentials used for the access decision match those of @task at the
+	 * time its namespace is read, preventing a concurrent execve() from
+	 * swapping the task's credentials in between the check and the use. We
+	 * mirror nsfs behavior.
+	 */
+	error = down_read_killable(&task->signal->exec_update_lock);
+	if (error)
+		return error;
+
+	if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) {
+		error = -EACCES;
+		goto out_unlock;
+	}
+
 	scoped_guard(task_lock, task) {
 		nsp = task->nsproxy;
 		if (nsp)
 			get_nsproxy(nsp);
 	}
-	if (!nsp)
-		return -ESRCH; /* just pretend it didn't exist */
-
-	/*
-	 * We're trying to open a file descriptor to the namespace so perform a
-	 * filesystem cred ptrace check. Also, we mirror nsfs behavior.
-	 */
-	if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
-		return -EACCES;
+	if (!nsp) {
+		error = -ESRCH; /* just pretend it didn't exist */
+		goto out_unlock;
+	}
 
 	switch (cmd) {
 	/* Namespaces that hang of nsproxy. */
@@ -650,11 +664,16 @@ static long pidfd_ioctl(struct file *fil
 #endif
 		break;
 	default:
-		return -ENOIOCTLCMD;
+		error = -ENOIOCTLCMD;
 	}
 
-	if (!ns_common)
-		return -EOPNOTSUPP;
+	if (!error && !ns_common)
+		error = -EOPNOTSUPP;
+
+out_unlock:
+	up_read(&task->signal->exec_update_lock);
+	if (error)
+		return error;
 
 	/* open_namespace() unconditionally consumes the reference */
 	return open_namespace(ns_common);
author maintainer
#22 lore raw

PATCH 22/713 powerpc/pseries/iommu: switch to Default DMA window during kdump

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Gaurav Batra <[email protected]>

commit 1304643a1c20badbb91b86a5084dd76cb7620c05 upstream.

In PowerPC (pseries) a non-virtualized adapter will have 2 DMA windows - 2GB default and a larger Dynamic DMA Window (DDW). DDW is large enough to map total RAM to a device.

During normal functioning of OS, since RAM is pre-mapped, 2GB default window is not used. The only scenario it might get used is when buffers in pmemory are mapped to the device for DMA.

As of today, during kdump, during early device discovery, pci_dma_find() finds that the device has 2 DMA windows. It selects to use DDW. This is a kdump path and DMA window is needed for IO to the device.

Although commit 09a3c1e46142 ("powerpc/pseries/iommu: IOMMU table is not initialized for kdump over SR-IOV") fixed an issue during kdump with SR-IOV case, but this also made the kdump prefer DDW over the default DMA window when both are present (dedicated adapter case). Since the DDW is fully mapped by the previous kernel, iommu_table_clear() can free only KDUMP_MIN_TCE_ENTRIES (2048) TCEs for use by kdump kernel.

This is not enough when the dump device is NVMe over Fibre Channel. Because nvme-fc driver DMA-maps the cmds and resp IUs of every pre-allocated request and each such mapping consumes roughly:

32 (IO queues, one per cpus = nr_cpus) *
64 (queue_depth, blk-mq kdump limit) *
2 (cmd+resp) = 4096

This is already double of what we have without counting admin queues and lpfc driver's own allocations / mapping requirement. Hence this results into iommu_alloc failures like -

lpfc 0153:70:00.0: iommu_alloc failed,
tbl 0000000034ebcf5e vaddr 00000000d814df0b npages 1 lpfc 0153:70:00.0: FCP Op failed - cmdiu dma mapping failed. lpfc 0153:70:00.0: iommu_alloc failed,
tbl 0000000034ebcf5e vaddr 000000009779e4d2 npages 1 lpfc 0153:70:00.0: FCP Op failed - cmdiu dma mapping failed.

iommu_map_phys+0x1c4/0x1f0 (unreliable)
dma_iommu_map_phys+0x54/0xa0
dma_map_phys+0x3f8/0x590
__nvme_fc_init_request+0x110/0x300 [nvme_fc]
nvme_fc_init_request+0x60/0xb8 [nvme_fc]
blk_mq_alloc_map_and_rqs+0x388/0x510
blk_mq_alloc_tag_set+0x2a4/0x5f0
nvme_alloc_io_tag_set+0xe0/0x1e0 [nvme_core]
nvme_fc_connect_ctrl_work+0x85c/0xdac [nvme_fc]
process_one_work+0x1e4/0x5a0
worker_thread+0x1ec/0x3e0

Increasing the number of free TCE entries in iommu_table_clear() will increase the probability of hitting EEH since there could still be some active IOs from the previous life of the kernel.

Hence this patch partially reverts the previous fixes commit and switches the kdump's default back to 2GB default DMA window instead of DDW window. This window will mostly be empty. Or, could be slightly used if buffers in pmemory were mapped for IO.

Fixes 09a3c1e46142 ("powerpc/pseries/iommu: IOMMU table is not initialized for kdump over SR-IOV")
---
 arch/powerpc/platforms/pseries/iommu.c |   23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)
arch/powerpc/platforms/pseries/iommu.c +12 -11
@@ -812,18 +812,11 @@ static struct device_node *pci_dma_find(
 
 	/* parse DMA window property. During normal system boot, only default
 	 * DMA window is passed in OF. But, for kdump, a dedicated adapter might
-	 * have both default and DDW in FDT. In this scenario, DDW takes precedence
-	 * over default window.
+	 * have both default and DDW in FDT. In this scenario, default window
+	 * takes precedence over DDW. For a dedicated adapter, default window will
+	 * potentially have more unused TCEs.
 	 */
-	if (ddw_win) {
-		struct dynamic_dma_window_prop *p;
-
-		p = (struct dynamic_dma_window_prop *)ddw_prop;
-		prop->liobn = p->liobn;
-		prop->dma_base = p->dma_base;
-		prop->tce_shift = p->tce_shift;
-		prop->window_shift = p->window_shift;
-	} else if (default_win) {
+	if (default_win) {
 		unsigned long offset, size, liobn;
 
 		of_parse_dma_window(rdn, default_prop, &liobn, &offset, &size);
@@ -832,6 +825,14 @@ static struct device_node *pci_dma_find(
 		prop->dma_base = cpu_to_be64(offset);
 		prop->tce_shift = cpu_to_be32(IOMMU_PAGE_SHIFT_4K);
 		prop->window_shift = cpu_to_be32(order_base_2(size));
+	} else {
+		struct dynamic_dma_window_prop *p;
+
+		p = (struct dynamic_dma_window_prop *)ddw_prop;
+		prop->liobn = p->liobn;
+		prop->dma_base = p->dma_base;
+		prop->tce_shift = p->tce_shift;
+		prop->window_shift = p->window_shift;
 	}
 
 	return rdn;
author maintainer
#23 lore raw

PATCH 23/713 rust: fmt: fix {:p} printing stack addresses

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ke Sun <[email protected]>

commit fb7d645176189d2b068d69861e230fa5aceb4922 upstream.

The impl_fmt_adapter_forward! macro forwards Pointer for Adapter<T> by destructuring self into a local t, causing {:p} to print the address of that temporary stack variable rather than the actual pointer.

Remove Pointer from the macro and provide a manual impl for Adapter<&T> that passes self.0 directly.

---
 rust/kernel/fmt.rs |    9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
rust/kernel/fmt.rs +8 -1
@@ -43,7 +43,14 @@ use core::fmt::{
     UpperExp,
     UpperHex, //
 };
-impl_fmt_adapter_forward!(Debug, LowerHex, UpperHex, Octal, Binary, Pointer, LowerExp, UpperExp);
+impl_fmt_adapter_forward!(Debug, LowerHex, UpperHex, Octal, Binary, LowerExp, UpperExp);
+
+impl<T: ?Sized + Pointer> Pointer for Adapter<&T> {
+    #[inline]
+    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+        Pointer::fmt(self.0, f)
+    }
+}
 
 /// A copy of [`core::fmt::Display`] that allows us to implement it for foreign types.
 ///
author maintainer
#24 lore raw

PATCH 24/713 timers/itimer: Zero-init old itimerval before copy to userspace

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jérémy Jean <[email protected]>

commit 18c7d85864e554adc8fad1e8d2e9d2cb6c3911c8 upstream.

On native sparc64, struct __kernel_old_timeval contains a four-byte hole after tv_usec because tv_sec is 64-bit while __kernel_suseconds_t is 32-bit. put_itimerval() fills only the named fields in a stack-allocated __kernel_old_itimerval and copies the entire object to userspace, so getitimer() can expose the two padding holes.

Zero-initialize the aggregate before assigning the fields so implicit padding is deterministic before it crosses the user/kernel boundary.

---
 kernel/time/itimer.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/time/itimer.c +1 -1
@@ -100,7 +100,7 @@ static int do_getitimer(int which, struc
 static int put_itimerval(struct __kernel_old_itimerval __user *o,
 			 const struct itimerspec64 *i)
 {
-	struct __kernel_old_itimerval v;
+	struct __kernel_old_itimerval v = {};
 
 	v.it_interval.tv_sec = i->it_interval.tv_sec;
 	v.it_interval.tv_usec = i->it_interval.tv_nsec / NSEC_PER_USEC;
author maintainer
#25 lore raw

PATCH 25/713 objtool/rust: add one more `noreturn` Rust function for Rust 1.99.0

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Miguel Ojeda <[email protected]>

commit 16861ca3508e0deac70d3bcacb6dcf435b49d9ef upstream.

Starting with Rust 1.99.0 (expected 2026-10-01), objtool may report:

rust/kernel.o: warning: objtool: _R..._6kernel3str9parse_intaNtNtB2_7private12FromStrRadix14from_str_radix() falls through to next function _R..._6kernel3str9parse_intaNtNtB2_7private12FromStrRadix16from_u64_negated()

due to calls to the noreturn symbol:

core::num::from_ascii_bytes_radix_panic

The function was renamed from from_ascii_radix_panic [1], which is already in the list.

Thus add the new one to the list so that objtool knows it is actually noreturn.

See commit 56d680dd23c3 ("objtool/rust: list noreturn Rust functions") for more details.

---
 tools/objtool/check.c |    1 +
 1 file changed, 1 insertion(+)
tools/objtool/check.c +1 -0
@@ -194,6 +194,7 @@ static bool is_rust_noreturn(const struc
 	 */
 	return str_ends_with(func->name, "_4core3num20from_str_radix_panic")				||
 	       str_ends_with(func->name, "_4core3num22from_ascii_radix_panic")				||
+	       str_ends_with(func->name, "_4core3num28from_ascii_bytes_radix_panic")			||
 	       str_ends_with(func->name, "_4core5sliceSp15copy_from_slice17len_mismatch_fail")		||
 	       str_ends_with(func->name, "_4core6option13expect_failed")				||
 	       str_ends_with(func->name, "_4core6option13unwrap_failed")				||
author maintainer
#26 lore raw

PATCH 26/713 rust: kbuild: disambiguate `zerocopy` for `rusttest`

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Antoni Boucher <[email protected]>

commit fe39a233ea52601d416a1d02e7f70049aae47016 upstream.

Starting with Rust 1.76.0, zerocopy was added as an (indirect) compiler dependency [1]. In turn, this meant that the rustc-dev component started including a precompiled zerocopy crate in the sysroot.

This makes rusttest fail because the compiler finds several candidates:

    error[E0464]: multiple candidates for `rmeta` dependency `zerocopy` found
      --> rust/kernel/prelude.rs:64:9
       |
    64 | pub use zerocopy::{
       |         ^^^^^^^^
       |
       = note: candidate #1: .../lib/rustlib/x86_64-unknown-linux-gnu/lib/libzerocopy-dfef4cb07ca752aa.rmeta
       = note: candidate #2: ./rust/test/libzerocopy.rlib

We cannot use --sysroot=/dev/null for these, thus point to the dependency explicitly.

Assisted-by Claude:claude-opus-4-8
Fixes 567621523ab7 ("rust: zerocopy: enable support in kbuild")

[ Investigated when it started happening, reworded to add that and to
follow our usual style and sent on behalf of Antoni, who found this during his work to support Rust for Linux with the GCC backend, i.e. with rustc_codegen_gcc. - Miguel ]

---
 rust/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
rust/Makefile +1 -1
index 627ed79dc6f5..fbe0accc51a3 100644
@@ -350,7 +350,7 @@ rusttestlib-pin_init: $(src)/pin-init/src/lib.rs rusttestlib-macros \
 rusttestlib-kernel: private rustc_target_flags = --extern ffi \
     --extern build_error --extern macros --extern pin_init \
     --extern bindings --extern uapi \
-    --extern zerocopy --extern zerocopy_derive
+    --extern zerocopy=$(objtree)/$(obj)/test/libzerocopy.rlib --extern zerocopy_derive
 rusttestlib-kernel: $(src)/kernel/lib.rs rusttestlib-bindings rusttestlib-uapi \
     rusttestlib-build_error rusttestlib-pin_init $(obj)/$(libmacros_name) \
     $(obj)/bindings.o rusttestlib-zerocopy rusttestlib-zerocopy_derive FORCE
Signature · 1 line
2.55.0
author maintainer
#27 lore raw

PATCH 27/713 rust: bug: skip arch-specific asm in `testlib` builds

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: FUJITA Tomonori <[email protected]>

commit 5d9668f3930609ead91f39b059ef4fe53db04942 upstream.

Running make rusttest with ARCH= set to an architecture other than the host's fails, e.g. ARCH=arm64 on an x86_64 host:

error: invalid instruction mnemonic 'brk'
--> rust/kernel/bug.rs:63:17

   |
63 | /                 concat!(
64 | |                     "/* {size} */",
65 | |                     include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_warn_asm.rs")),
66 | |                     include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_reachable_asm.rs")));
   | |_______________________________________________________________________________________________________^
   |
note: instantiated into assembly here
  --> <inline asm>:1:115
   |
 1 |     /* 8 */.pushsection __bug_table,"aw"; .align 2; 14470: .long 14471f - .;.short 2305;.align 2; .popsection; 14471:brk 0x800
   |                                                                                                                      ^^^

The reason is that rusttest builds the kernel crate as a host
library: it passes the CONFIG_* cfgs of the configured architecture, but not --target, so code generation happens for the host. warn_flags! then selects the arch-specific inline asm arm based on CONFIG_*, and the host assembler rejects it.

This does not happen with the current master because warn_on! has no user inside the kernel crate itself yet, but it will as soon as one is added.

---
 rust/kernel/bug.rs |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
rust/kernel/bug.rs +5 -1
@@ -8,6 +8,7 @@
 
 #[macro_export]
 #[doc(hidden)]
+#[cfg(not(testlib))]
 #[cfg(all(CONFIG_BUG, not(CONFIG_UML), not(CONFIG_LOONGARCH), not(CONFIG_ARM)))]
 #[cfg(CONFIG_DEBUG_BUGVERBOSE)]
 macro_rules! warn_flags {
@@ -47,6 +48,7 @@ macro_rules! warn_flags {
 
 #[macro_export]
 #[doc(hidden)]
+#[cfg(not(testlib))]
 #[cfg(all(CONFIG_BUG, not(CONFIG_UML), not(CONFIG_LOONGARCH), not(CONFIG_ARM)))]
 #[cfg(not(CONFIG_DEBUG_BUGVERBOSE))]
 macro_rules! warn_flags {
@@ -73,6 +75,7 @@ macro_rules! warn_flags {
 
 #[macro_export]
 #[doc(hidden)]
+#[cfg(not(testlib))]
 #[cfg(all(CONFIG_BUG, CONFIG_UML))]
 macro_rules! warn_flags {
     ($file:expr, $flags:expr) => {
@@ -91,6 +94,7 @@ macro_rules! warn_flags {
 
 #[macro_export]
 #[doc(hidden)]
+#[cfg(not(testlib))]
 #[cfg(all(CONFIG_BUG, any(CONFIG_LOONGARCH, CONFIG_ARM)))]
 macro_rules! warn_flags {
     ($file:expr, $flags:expr) => {
@@ -101,7 +105,7 @@ macro_rules! warn_flags {
 
 #[macro_export]
 #[doc(hidden)]
-#[cfg(not(CONFIG_BUG))]
+#[cfg(any(testlib, not(CONFIG_BUG)))]
 macro_rules! warn_flags {
     ($file:expr, $flags:expr) => {};
 }
author maintainer
#28 lore raw

PATCH 28/713 rust: bug: fix warn_on macro build error on UML

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: FUJITA Tomonori <[email protected]>

commit 30a449e04a32033d8e4844fdb4938a0ebccfa37b upstream.

Callers that go through kernel::prelude have CStrExt in scope, but code inside the kernel crate imports explicitly and may not. Using warn_on! from such a module fails to build on UML, which is the only configuration where warn_flags! needs a C string pointer rather than an inline asm bug entry:

error[E0599]: no method named as_char_ptr found for reference &ffi::CStr in the current scope
--> linux/rust/kernel/bug.rs:83:49

    |
 83 |                 $crate::c_str!(::core::file!()).as_char_ptr(),
    |                                                 ^^^^^^^^^^^
    |
   ::: linux/rust/kernel/time.rs:427:9
    |
427 |         warn_on!(self.nanos < 0);
    |         ------------------------ in this macro invocation
    |

= help: items from traits can only be used if the trait is in scope
= note: this error originates in the macro $crate::warn_flags which comes from the expansion of the macro warn_on (in Nightly builds, run with -Z mac)
help: trait CStrExt which provides as_char_ptr is implemented but not in scope; perhaps you want to import it
--> linux/rust/kernel/time.rs:27:1

    |

27 + use crate::str::CStrExt;

Call the method through its fully qualified path, which resolves without any import at the expansion site.

---
 rust/kernel/bug.rs |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
rust/kernel/bug.rs +1 -1
@@ -83,7 +83,7 @@ macro_rules! warn_flags {
         // with a valid null-terminated string.
         unsafe {
             $crate::bindings::warn_slowpath_fmt(
-                $crate::c_str!(::core::file!()).as_char_ptr(),
+                $crate::str::CStrExt::as_char_ptr($crate::c_str!(::core::file!())),
                 line!() as $crate::ffi::c_int,
                 $flags as $crate::ffi::c_uint,
                 ::core::ptr::null(),
author maintainer
#29 lore raw

PATCH 29/713 rust: bug: prevent dead_code warning from warn_on!s flags constant

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: FUJITA Tomonori <[email protected]>

commit e66cfc29e0d06fec34c06bb40d4d281f595677b1 upstream.

Fix the following dead_code warning on some configurations in an atomic development branch:

warning: constant WARN_ON_FLAGS is never used
--> linux/rust/kernel/bug.rs:126:19

    |
126 |               const WARN_ON_FLAGS: u32 = $crate::bug::bugflag_taint($crate::bindings::TAINT_WARN);
    |                     ^^^^^^^^^^^^^
    |
   ::: linux/rust/kernel/sync/srcu.rs:106:12
    |
106 |           if crate::warn_on!(
    |  ____________-
107 | |             // SAFETY: By the type invariants, `self` contains a valid and pinned `struct srcu_struct`
108 | |             // and `srcu_readers_active()` only checks the active reader count.
109 | |             unsafe { bindings::srcu_readers_active(ptr) }
110 | |         ) {
    | |_________- in this macro invocation
    |

= note: #[warn(dead_code)] (part of #[warn(unused)]) on by default
= note: this warning originates in the macro crate::warn_on (in Nightly builds, run with -Z macro-backtrace for more info)

The warn_on! macro always defines a WARN_ON_FLAGS constant and hands it to warn_flags!. On configurations where warn_flags! does not reference its flags argument (the LOONGARCH/ARM variant, which only calls WARN_ON(), and the !CONFIG_BUG no-op variant), the constant is left unused and triggers a dead_code warning.

warn_flags! is the macro that accepts (and here discards) the flags argument, so make it responsible for the argument it drops.

Also rename _COND_STR to COND_STR and consume $file for consistency.

Fixes dff64b072708 ("rust: Add warn_on macro")
[ Added newlines. - Miguel ]
---
 rust/kernel/bug.rs |   26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)
rust/kernel/bug.rs +22 -4
@@ -55,6 +55,10 @@ macro_rules! warn_flags {
     ($file:expr, $flags:expr) => {
         const FLAGS: u32 = $crate::bindings::BUGFLAG_WARNING | $flags;
 
+        if false {
+            _ = $file;
+        }
+
         // SAFETY:
         // - `flags` and `size` are all compile-time constants, preventing
         // any invalid memory access.
@@ -79,6 +83,10 @@ macro_rules! warn_flags {
 #[cfg(all(CONFIG_BUG, CONFIG_UML))]
 macro_rules! warn_flags {
     ($file:expr, $flags:expr) => {
+        if false {
+            _ = $file;
+        }
+
         // SAFETY: It is always safe to call `warn_slowpath_fmt()`
         // with a valid null-terminated string.
         unsafe {
@@ -98,6 +106,11 @@ macro_rules! warn_flags {
 #[cfg(all(CONFIG_BUG, any(CONFIG_LOONGARCH, CONFIG_ARM)))]
 macro_rules! warn_flags {
     ($file:expr, $flags:expr) => {
+        if false {
+            _ = $file;
+            _ = $flags;
+        }
+
         // SAFETY: It is always safe to call `WARN_ON()`.
         unsafe { $crate::bindings::WARN_ON(true) }
     };
@@ -107,7 +120,12 @@ macro_rules! warn_flags {
 #[doc(hidden)]
 #[cfg(any(testlib, not(CONFIG_BUG)))]
 macro_rules! warn_flags {
-    ($file:expr, $flags:expr) => {};
+    ($file:expr, $flags:expr) => {
+        if false {
+            _ = $file;
+            _ = $flags;
+        }
+    };
 }
 
 #[doc(hidden)]
@@ -122,14 +140,14 @@ macro_rules! warn_on {
         let cond = $cond;
 
         #[cfg(CONFIG_DEBUG_BUGVERBOSE_DETAILED)]
-        const _COND_STR: &str = concat!("[", stringify!($cond), "] ", file!());
+        const COND_STR: &str = concat!("[", stringify!($cond), "] ", file!());
         #[cfg(not(CONFIG_DEBUG_BUGVERBOSE_DETAILED))]
-        const _COND_STR: &str = file!();
+        const COND_STR: &str = file!();
 
         if cond {
             const WARN_ON_FLAGS: u32 = $crate::bug::bugflag_taint($crate::bindings::TAINT_WARN);
 
-            $crate::warn_flags!(_COND_STR, WARN_ON_FLAGS);
+            $crate::warn_flags!(COND_STR, WARN_ON_FLAGS);
         }
         cond
     }};
author maintainer
#30 lore raw

PATCH 30/713 rust: rust_is_available: warn for `bindgen` < 0.72.1 && libclang >= 22

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Miguel Ojeda <[email protected]>

commit dc01dfb37b34beeefcfe1c3055364d41a4070c7e upstream.

Starting with LLVM 22, clang_getTypeDeclaration() may return a forward declaration instead of the type definition. This made bindgen generate opaque types [1][2], which in turn made us fail with e.g.

    error[E0609]: no field `__bindgen_anon_1` on type `bindings::kernel_param`
      --> rust/kernel/module_param.rs:78:46
       |
    78 |         let container = unsafe { &*((*param).__bindgen_anon_1.arg.cast::<SetOnce<T>>()) };
       |                                              ^^^^^^^^^^^^^^^^ unknown field
       |
       = note: available field is: `_address`

This was fixed in bindgen 0.72.1 [3].

In order to clarify what is going on and avoid confusion [4][5], add a warning to rust_is_available.sh about it when the versions match, similar to past warnings like the one removed in:

  commit ae64324ad5c1 ("rust: rust_is_available: remove warning for `bindgen` < 0.69.5 && libclang >= 19.1")

In addition, even if the versions match, check if the issue appears to not reproduce with the given binaries, to avoid a warning in such a case.

Finally, include tests.

[ Nathan, in parallel, updated the instructions of the LLVM+Rust
kernel.org toolchains [6] so that --version is not passed to cargo for bindgen, and thus the latest bindgen is installed by default, which should help to avoid some of these situations.

Thanks!

- Miguel ]

---
 scripts/rust_is_available.sh                    |   14 +++++++++++
 scripts/rust_is_available_bindgen_libclang_22.h |    5 ++++
 scripts/rust_is_available_test.py               |   30 +++++++++++++++++++++++-
 3 files changed, 48 insertions(+), 1 deletion(-)
 create mode 100644 scripts/rust_is_available_bindgen_libclang_22.h
scripts/rust_is_available.sh +14 -0
@@ -208,6 +208,20 @@ if [ "$bindgen_libclang_cversion" -lt "$
 	exit 1
 fi
 
+if [ "$bindgen_libclang_cversion" -ge 2200000 ] &&
+	[ "$rust_bindings_generator_cversion" -lt 7201 ]; then
+	# Distributions may have patched the issue.
+	if ! "$BINDGEN" $(dirname $0)/rust_is_available_bindgen_libclang_22.h | grep -q 'pub foo'; then
+		echo >&2 "***"
+		echo >&2 "*** Rust bindings generator '$BINDGEN' < 0.72.1 together with libclang >= 22"
+		echo >&2 "*** may not work due to a bug (https://github.com/rust-lang/rust-bindgen/pull/3278)."
+		echo >&2 "***   Your bindgen version:  $rust_bindings_generator_version"
+		echo >&2 "***   Your libclang version: $bindgen_libclang_version"
+		echo >&2 "***"
+		warning=1
+	fi
+fi
+
 # If the C compiler is Clang, then we can also check whether its version
 # matches the `libclang` version used by the Rust bindings generator.
 #
scripts/rust_is_available_bindgen_libclang_22.h new file +5 -0
@@ -0,0 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+struct S;
+struct S {
+	int foo;
+};
scripts/rust_is_available_test.py +29 -1
@@ -54,16 +54,23 @@ else:
 """)
 
     @classmethod
-    def generate_bindgen(cls, version_stdout, libclang_stderr):
+    def generate_bindgen(cls, version_stdout, libclang_stderr, libclang_22_patched=False):
         if libclang_stderr is None:
             libclang_case = f"raise SystemExit({cls.bindgen_default_bindgen_libclang_failure_exit_code})"
         else:
             libclang_case = f"print({repr(libclang_stderr)}, file=sys.stderr)"
 
+        if libclang_22_patched:
+            libclang_22_case = "print('pub foo: ::std::os::raw::c_int,')"
+        else:
+            libclang_22_case = "pass"
+
         return cls.generate_executable(f"""#!/usr/bin/env python3
 import sys
 if "rust_is_available_bindgen_libclang.h" in " ".join(sys.argv):
     {libclang_case}
+elif "rust_is_available_bindgen_libclang_22.h" in " ".join(sys.argv):
+    {libclang_22_case}
 else:
     print({repr(version_stdout)})
 """)
@@ -248,6 +255,27 @@ else:
         result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen })
         self.assertIn(f"libclang (used by the Rust bindings generator '{bindgen}') is too old.", result.stderr)
 
+    def test_bindgen_bad_libclang_22(self):
+        for (bindgen_version, libclang_version, expected_not_patched) in (
+            ("0.71.1", "21.1.0", self.Expected.SUCCESS),
+            ("0.71.1", "22.0.0", self.Expected.SUCCESS_WITH_WARNINGS),
+            ("0.71.1", "22.1.0", self.Expected.SUCCESS_WITH_WARNINGS),
+
+            ("0.72.0", "22.0.0", self.Expected.SUCCESS_WITH_WARNINGS),
+
+            ("0.72.1", "22.0.0", self.Expected.SUCCESS),
+        ):
+            with self.subTest(bindgen_version=bindgen_version, libclang_version=libclang_version):
+                cc = self.generate_clang(f"clang version {libclang_version}")
+                libclang_stderr = f"scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {libclang_version} [-W#pragma-messages], err: false"
+                bindgen = self.generate_bindgen(f"bindgen {bindgen_version}", libclang_stderr)
+                result = self.run_script(expected_not_patched, { "BINDGEN": bindgen, "CC": cc })
+                if expected_not_patched == self.Expected.SUCCESS_WITH_WARNINGS:
+                    self.assertIn(f"Rust bindings generator '{bindgen}' < 0.72.1 together with libclang >= 22", result.stderr)
+
+                bindgen = self.generate_bindgen(f"bindgen {bindgen_version}", libclang_stderr, libclang_22_patched=True)
+                result = self.run_script(self.Expected.SUCCESS, { "BINDGEN": bindgen, "CC": cc })
+
     def test_clang_matches_bindgen_libclang_different_bindgen(self):
         bindgen = self.generate_bindgen_libclang("scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version 999.0.0 [-W#pragma-messages], err: false")
         result = self.run_script(self.Expected.SUCCESS_WITH_WARNINGS, { "BINDGEN": bindgen })
author maintainer
#31 lore raw

PATCH 31/713 rust: dma: return zero for Coherent reads past EOF

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Younes Akhouayri <[email protected]>

commit 5391b147d9fd8d4736e28c629cda00fd37c2304a upstream.

Coherent<T>::write_to_slice() calculates a zero-byte copy when the file offset is beyond the allocation, but still calls UserSliceWriter::write_dma(). The latter rejects offsets beyond the allocation even when the copy length is zero, so a debugfs read past EOF returns -ERANGE.

Return before calling write_dma() when the offset is at or beyond the allocation, matching simple_read_from_buffer() EOF semantics.

---
 rust/kernel/dma.rs |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
rust/kernel/dma.rs +5 -1
@@ -1005,7 +1005,11 @@ impl<T: KnownSize + AsBytes + ?Sized> de
             return Ok(0);
         };
 
-        let count = self.size().saturating_sub(offset_val).min(writer.len());
+        if offset_val >= self.size() {
+            return Ok(0);
+        }
+
+        let count = (self.size() - offset_val).min(writer.len());
 
         writer.write_dma(self, offset_val, count)?;
 
author maintainer
#32 lore raw

PATCH 32/713 rust: devres: fix race between concurrent revokers

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Danilo Krummrich <[email protected]>

commit acc516dfa1972d31836b50abc0115216cd0fccc5 upstream.

There is a potential race condition when two paths try to revoke a Devres concurrently.

The driver core's devres_release_all() calls Revocable::revoke() via the release callback, while Devres::drop() calls revoke_nosync() on another CPU.

The revoker that does not claim the is_available swap returns immediately, but the revoker that did may still be executing drop_in_place() on the inner data. This can cause a use-after-free when the other revoker's caller proceeds to drop adjacent resources that drop_in_place() still references (e.g., Devres<DmaMappedSgt> racing with SGTable freeing the backing sg_table and pages).

Fix this by adding a Completion. The release callback signals the Completion after revoke() finishes, and Devres::drop() waits for it when it loses the is_available swap. This ensures the wrapped object is fully torn down before Devres::drop() returns.

---
 rust/kernel/devres.rs |   18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)
rust/kernel/devres.rs +16 -2
@@ -21,7 +21,8 @@ use crate::{
     sync::{
         aref::ARef,
         rcu,
-        Arc, //
+        Arc,
+        Completion, //
     },
     types::{
         ForeignOwnable,
@@ -37,6 +38,8 @@ struct Inner<T> {
     node: Opaque<bindings::devres_node>,
     #[pin]
     data: Revocable<T>,
+    #[pin]
+    revocation: Completion,
 }
 
 /// This abstraction is meant to be used by subsystems to containerize [`Device`] bound resources to
@@ -53,6 +56,10 @@ struct Inner<T> {
 /// After the [`Devres`] has been unbound it is not possible to access the encapsulated resource
 /// anymore.
 ///
+/// When a [`Devres`] is dropped, it is guaranteed that `T` has been fully dropped by the time
+/// [`Devres::drop`] returns, even if a concurrent revocation through the release callback is in
+/// progress.
+///
 /// [`Devres`] users should make sure to simply free the corresponding backing resource in `T`'s
 /// [`Drop`] implementation.
 ///
@@ -218,6 +225,7 @@ impl<T: Send + 'static> Devres<T> {
                     };
                 }),
                 data <- Revocable::new(data),
+                revocation <- Completion::new(),
             }),
             GFP_KERNEL,
         )?;
@@ -255,7 +263,9 @@ impl<T: Send + 'static> Devres<T> {
         // SAFETY: `inner` is a valid `Inner<T>` pointer.
         let inner = unsafe { &*inner };
 
-        inner.data.revoke();
+        if inner.data.revoke() {
+            inner.revocation.complete_all();
+        }
     }
 
     #[allow(clippy::missing_safety_doc)]
@@ -362,6 +372,10 @@ impl<T: Send + 'static> Drop for Devres<
                 // this additional reference count.
                 drop(unsafe { Arc::from_raw(Arc::as_ptr(&self.inner)) });
             }
+        } else {
+            // The release callback is concurrently revoking; wait for it to finish
+            // `drop_in_place()` of the wrapped object before returning.
+            self.inner.revocation.wait_for_completion();
         }
     }
 }
author maintainer
#33 lore raw

PATCH 33/713 rust: devres: ensure revocation is complete before device finishes unbinding

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Danilo Krummrich <[email protected]>

commit a10639966fd72fff8f7fbf3c8e733307daabd38f upstream.

Now that the revocation Completion is in place, also address the symmetric case. When Devres::drop() wins the is_available swap and the devres callback loses, the callback returns to devres_release_all() without waiting. This means device unbinding can complete while Devres::drop() is still executing drop_in_place() on another CPU, which is a problem if T's destructor accesses device state.

Make the synchronization bidirectional. Whichever side performs drop_in_place() signals the Completion, and the other side waits.

This does not reintroduce the nested Devres deadlock fixed by commit ba268514ea14 ("rust: devres: fix race condition due to nesting"), because that deadlock was caused by drop waiting for the release callback to return (the old 'devm' Completion). Here, both sides only wait for drop_in_place() to finish, which completes within the current call chain. The Arc<Inner<T>> keeps the Inner allocation alive independently.

---
 rust/kernel/devres.rs |    7 +++++++
 1 file changed, 7 insertions(+)
rust/kernel/devres.rs +7 -0
@@ -265,6 +265,11 @@ impl<T: Send + 'static> Devres<T> {
 
         if inner.data.revoke() {
             inner.revocation.complete_all();
+        } else {
+            // Devres::drop() is concurrently revoking; wait for it to finish `drop_in_place()`
+            // before returning to `devres_release_all()`, ensuring `T` is fully torn down before
+            // the device finishes unbinding.
+            inner.revocation.wait_for_completion();
         }
     }
 
@@ -365,6 +370,8 @@ impl<T: Send + 'static> Drop for Devres<
         // SAFETY: When `drop` runs, it is guaranteed that nobody is accessing the revocable data
         // anymore, hence it is safe not to wait for the grace period to finish.
         if unsafe { self.data().revoke_nosync() } {
+            self.inner.revocation.complete_all();
+
             // We revoked `self.data` before devres did, hence try to remove it.
             if self.remove_node() {
                 // SAFETY: In `Self::new` we have taken an additional reference count of `self.data`
author maintainer
#34 lore raw

PATCH 34/713 rust: kbuild: disambiguate `zerocopy_derive` for `rusttest`

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Miguel Ojeda <[email protected]>

commit 1b0bab4a873f1034c27573cfc613394cff7e0a5b upstream.

The rustc-dev components for Rust 1.82.0 through 1.87.0 include a precompiled zerocopy_derive procedural macro in the sysroot. This range includes Rust 1.85.0, our minimum supported version.

This makes rusttest fail because the compiler finds both the sysroot copy and the copy built in rust/test:

    error[E0464]: multiple candidates for `dylib` dependency `zerocopy_derive` found
      --> rust/kernel/prelude.rs:70:9
       |
    70 | pub use zerocopy_derive::{
       |         ^^^^^^^^^^^^^^^
       |
       = note: candidate #1: .../lib/rustlib/x86_64-unknown-linux-gnu/lib/libzerocopy_derive-54d2b38896fa6bc5.so
       = note: candidate #2: .../rust/test/libzerocopy_derive.so

Commit fe39a233ea52 ("rust: kbuild: disambiguate zerocopy for rusttest") fixed the equivalent ambiguity for zerocopy.

Thus point to the dependency explicitly in this case too.

Cc Antoni Boucher <[email protected]>
Fixes 506054980429 ("rust: zerocopy-derive: enable support in kbuild")
---
 rust/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
rust/Makefile +2 -1
index 3afaad4a4a3a..9211d82ac96d 100644
@@ -350,7 +350,8 @@ rusttestlib-pin_init: $(src)/pin-init/src/lib.rs rusttestlib-macros \
 rusttestlib-kernel: private rustc_target_flags = --extern ffi \
     --extern build_error --extern macros --extern pin_init \
     --extern bindings --extern uapi \
-    --extern zerocopy=$(objtree)/$(obj)/test/libzerocopy.rlib --extern zerocopy_derive
+    --extern zerocopy=$(objtree)/$(obj)/test/libzerocopy.rlib \
+    --extern zerocopy_derive=$(objtree)/$(obj)/test/$(libzerocopy_derive_name)
 rusttestlib-kernel: $(src)/kernel/lib.rs rusttestlib-bindings rusttestlib-uapi \
     rusttestlib-build_error rusttestlib-pin_init $(obj)/$(libmacros_name) \
     $(obj)/bindings.o rusttestlib-zerocopy rusttestlib-zerocopy_derive FORCE
Signature · 1 line
2.55.0
author maintainer
#35 lore raw

PATCH 35/713 rust: kernel: list: fix incorrect pop_back example comment

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Nikolai Grlica <[email protected]>

commit a5c7d35e2fd3e24c411816c91f8f6cc78e652e0c upstream.

The example uses pop_back(), but the accompanying comment says pop_front(). Update the comment to match the example.

Fixes bf87a41b85d6 ("rust: list: Add an example for `ListLinksSelfPtr` usage")
---
 rust/kernel/list.rs |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
rust/kernel/list.rs +1 -1
@@ -249,7 +249,7 @@ pub use self::arc_field::{
 ///     assert_eq!(list.iter().count(), 3);
 /// }
 ///
-/// // Pop the items from the list using `pop_front()` and verify the content.
+/// // Pop the items from the list using `pop_back()` and verify the content.
 /// {
 ///     assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("a", 15));
 ///     assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("a", 32));
author maintainer
#36 lore raw

PATCH 36/713 objtool/rust: add one more `noreturn` Rust function

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Miguel Ojeda <[email protected]>

commit 993f235c4af49d0e912cc28abe6d733531600237 upstream.

When the pointer formatting series [1] is applied and KUnit tests are enabled, objtool would report an error with any of our supported Rust versions. For instance, with Rust 1.97.1:

rust/kernel.o: error: objtool: _R..._4core3fmt7Pointer3fmtB7_() falls through to next function _R..._4core7convert5AsRefNtB5_4BStrE6as_ref()

Or, with Rust 1.85.0:

rust/kernel.o: error: objtool: _R..._4core3fmt7Pointer3fmtB7_()
falls through to next function _R..._4core3ffi5c_str4CStrENtNtBS_3fmt7Display3fmtB7_()

This happens due to calls to the noreturn symbol:

core::str::slice_error_fail

Thus add the mangled one to the list so that objtool knows it is actually noreturn.

See commit 56d680dd23c3 ("objtool/rust: list noreturn Rust functions") for more details.

[ While the series [1] mentioned above was not applied in a way
that triggered this, Gary found another case [2]:

I am seeing this function causing issue on my 1.85.1 -Os build, although the error message is different this time:

rust/kernel.o: warning: objtool: _R..._5range9RangeFromjEE5indexCsldbe0TGTmNx_6kernel+0x1d:
stack state mismatch: cfa1=4+8 cfa2=4+16

Disassembly shows that the function call before the warning location is a call to _4core3str16slice_error_fail, and objtool thought it can return (which will end up with a unbalanced stack if it does return).

Thus apply it. - Miguel ]

---
 tools/objtool/check.c |    1 +
 1 file changed, 1 insertion(+)
tools/objtool/check.c +1 -0
@@ -195,6 +195,7 @@ static bool is_rust_noreturn(const struc
 	return str_ends_with(func->name, "_4core3num20from_str_radix_panic")				||
 	       str_ends_with(func->name, "_4core3num22from_ascii_radix_panic")				||
 	       str_ends_with(func->name, "_4core3num28from_ascii_bytes_radix_panic")			||
+	       str_ends_with(func->name, "_4core3str16slice_error_fail")				||
 	       str_ends_with(func->name, "_4core5sliceSp15copy_from_slice17len_mismatch_fail")		||
 	       str_ends_with(func->name, "_4core6option13expect_failed")				||
 	       str_ends_with(func->name, "_4core6option13unwrap_failed")				||
author maintainer
#37 lore raw

PATCH 37/713 rust: num: restrict bool conversion to unsigned Bounded

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Younes Akhouayri <[email protected]>

commit 7dd6343fc127935425a81a8f1989907996c2868d upstream.

From<bool> turns true into 1. A signed Bounded with N = 1 can hold only -1 and 0. The current implementation can therefore create a value that breaks Bounded's invariant. Deref relies on that invariant and calls unreachable_unchecked() when it is broken, so safe Rust can reach undefined behavior.

The other primitive conversions require the source and destination to have the same signedness. Treat bool as an unsigned one-bit value and allow conversions between bool and Bounded only when the backing integer type is unsigned.

---
 rust/kernel/num/bounded.rs |   30 +++++++++++++++++++++---------
 1 file changed, 21 insertions(+), 9 deletions(-)
rust/kernel/num/bounded.rs +21 -9
@@ -13,7 +13,10 @@ use core::{
 };
 
 use kernel::{
-    num::Integer,
+    num::{
+        Integer,
+        Unsigned, //
+    },
     prelude::*, //
 };
 
@@ -174,13 +177,16 @@ fn fits_within<T: Integer>(value: T, num
 /// // `u8` (regardless of the passed value).
 /// // let _ = Bounded::<u32, 6>::from(10u8);
 ///
-/// // Booleans can be converted into single-bit `Bounded`s.
+/// // Booleans can be converted into unsigned `Bounded`s.
 ///
 /// let v = Bounded::<u64, 1>::from(false);
 /// assert_eq!(v.get(), 0);
 ///
 /// let v = Bounded::<u64, 1>::from(true);
 /// assert_eq!(v.get(), 1);
+///
+/// // This does not build because `i8` is signed.
+/// // let _ = Bounded::<i8, 2>::from(true);
 /// ```
 ///
 /// Infallible conversions from a [`Bounded`] to a primitive integer are also supported, and
@@ -203,12 +209,16 @@ fn fits_within<T: Integer>(value: T, num
 /// let _v = Bounded::<u32, 10>::new::<10>();
 /// // assert_eq!(u8::from(_v), 10);
 ///
-/// // Single-bit `Bounded`s can be converted into a boolean.
+/// // Unsigned single-bit `Bounded`s can be converted into a boolean.
 /// let v = Bounded::<u8, 1>::new::<1>();
 /// assert_eq!(bool::from(v), true);
 ///
 /// let v = Bounded::<u8, 1>::new::<0>();
 /// assert_eq!(bool::from(v), false);
+///
+/// // This does not build because `i8` is signed.
+/// // let v = Bounded::<i8, 1>::new::<-1>();
+/// // let _ = bool::from(v);
 /// ```
 ///
 /// Fallible conversions from any primitive integer to any [`Bounded`] are also supported using the
@@ -1077,31 +1087,33 @@ impl_into_primitive!(
     i8 i16 i32 i64 isize
 );
 
-// Single-bit `Bounded`s can be converted from/to a boolean.
+// Unsigned single-bit `Bounded`s can be converted to a boolean.
 
 impl<T> From<Bounded<T, 1>> for bool
 where
-    T: Integer + Zeroable,
+    T: Integer<Signedness = Unsigned> + Zeroable,
 {
     fn from(value: Bounded<T, 1>) -> Self {
         value.get() != Zeroable::zeroed()
     }
 }
 
+// Booleans can be converted to unsigned `Bounded`s.
+
 impl<T, const N: u32> From<bool> for Bounded<T, N>
 where
-    T: Integer + From<bool>,
+    T: Integer<Signedness = Unsigned> + From<bool>,
 {
     fn from(value: bool) -> Self {
-        // SAFETY: A boolean can be represented using a single bit, and thus fits within any
-        // integer type for any `N` > 0.
+        // SAFETY: A boolean is represented by `0` or `1`, so it fits within any valid unsigned
+        // `Bounded` width.
         unsafe { Self::__new(T::from(value)) }
     }
 }
 
 impl<T> Bounded<T, 1>
 where
-    T: Integer + Zeroable,
+    T: Integer<Signedness = Unsigned> + Zeroable,
 {
     /// Converts this [`Bounded`] into a [`bool`].
     ///
author maintainer
#38 lore raw

PATCH 38/713 rust: cfi: disable function merging if CFI is enabled

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Gary Guo <[email protected]>

commit 29b03d1de967a177176d12811d970cac7882afcf upstream.

In Rust doc tests, there is a dummy __module_firmware_test_init function generated by the example in module_firmware!'s documentation, which just returns zero. Many other documentation examples generate functions that produce zero. LKP test robot reports [1] a Flags::zeroed instance; my local reproduction has a Bounded::new::<0>.

LLVM's MergeFunctionsPass incorrectly merges functions with different KCFI types, causing __module_firmware_test_init to be merged into one of the zero-returning functions. As module init is invoked via an indirect function call, KCFI is checked and this produces a KCFI failure.

I've reported this bug to upstream LLVM [2]; in the meantime, disable function merging if CFI is enabled. No separate treatment is needed for CONFIG_RUST_INLINE_HELPERS, as Clang does not enable function merging by default.

[ LLVM already has a pending PR:

    https://github.com/llvm/llvm-project/pull/217665

which solves the issue. In addition, I asked upstream Rust if the unstable -Zmerge-functions=disabled flag will remain around:

    https://rust-lang.zulipchat.com/#narrow/channel/425075-rust-for-linux/topic/.60-Zmerge-functions.3Ddisabled.60/

and it does indeed look like that will be the case. - Miguel ]

Fixes ca627e636551 ("rust: cfi: add support for CFI_CLANG with Rust")
[ Fixed typos as discussed. Reworded slightly for other typos. - Miguel ]
---
 Makefile |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
Makefile +2 -1
@@ -1118,7 +1118,8 @@ endif
 ifdef CONFIG_RUST
 	# Always pass -Zsanitizer-cfi-normalize-integers as CONFIG_RUST selects
 	# CONFIG_CFI_ICALL_NORMALIZE_INTEGERS.
-	RUSTC_FLAGS_CFI   := -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers
+	# Disable function merging as LLVM incorrectly merges functions with different KCFI types.
+	RUSTC_FLAGS_CFI   := -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers -Zmerge-functions=disabled
 	KBUILD_RUSTFLAGS += $(RUSTC_FLAGS_CFI)
 	export RUSTC_FLAGS_CFI
 endif
author maintainer
#39 lore raw

PATCH 39/713 kbuild: rust: preserve unreachable traps with inline helpers

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Miguel Ojeda <[email protected]>

commit 0bff7711c19ba05ff3b686554c5a2d503c3e9797 upstream.

When CONFIG_RUST_INLINE_HELPERS is enabled, it is possible to hit objtool warnings like:

vmlinux.o: warning: objtool: _R..._4cmdq12CommandToGsp4init() falls through to next function _R..._4core5array4iter8IntoIterRShKj3_EEEBa_()

rustc normally emits traps for unreachable paths. However, under CONFIG_RUST_INLINE_HELPERS=y, rustc emits LLVM bitcode and Clang performs final code generation after the helper bitcode is linked, but Clang does not trap unreachable IR by default.

In turn, this means objtool follows compiler-generated impossible Rust enum paths through alignment padding into the next function, resulting in fallthrough warnings.

Thus pass the LLVM trap-unreachable option to the final Clang invocation and suppress traps immediately after noreturn calls, which objtool already recognizes as dead ends. The combination of both flags makes it match rustc's behavior.

Rust 1.85.0 (the minimum supported one) supports LLVM >= 18, and both flags are available in LLVM 18.

Assisted-by LLM
Cc Gary Guo <[email protected]>
Cc Boqun Feng <[email protected]>
Cc Alice Ryhl <[email protected]>
Cc Matthew Maurer <[email protected]>
Cc Josh Poimboeuf <[email protected]>
Cc Peter Zijlstra <[email protected]>
Fixes 3a2486cc1da5 ("kbuild: rust: provide an option to inline C helpers into Rust")
---
 Makefile               |   10 ++++++++++
 rust/Makefile          |    3 ++-
 scripts/Makefile.build |    3 ++-
 3 files changed, 14 insertions(+), 2 deletions(-)
Makefile +10 -0
@@ -1083,6 +1083,16 @@ endif
 export CC_FLAGS_SCS
 endif
 
+ifdef CONFIG_RUST_INLINE_HELPERS
+# `rustc` normally emits traps for unreachable paths during code generation.
+# With inline helpers, Clang performs code generation from the linked bitcode
+# instead, so request the same behavior explicitly. Otherwise `objtool` may
+# follow an impossible Rust path into the next function.
+CC_FLAGS_RUST_INLINE_HELPERS := -mllvm -trap-unreachable \
+				-mllvm -no-trap-after-noreturn
+export CC_FLAGS_RUST_INLINE_HELPERS
+endif
+
 ifdef CONFIG_LTO_CLANG
 ifdef CONFIG_LTO_CLANG_FULL
 CC_FLAGS_LTO	:= -flto
rust/Makefile +2 -1
@@ -645,7 +645,8 @@ quiet_cmd_rustc_library = $(if $(skip_cl
 		-Zunstable-options \
 	$(if $(link_helper),;$(LLVM_LINK) --internalize --suppress-warnings $(patsubst %.o,%.bc,$@) \
 		$(obj)/helpers/helpers$(if $(part-of-module),_module).bc -o $(patsubst %.o,%.m.bc,$@); \
-		$(CC) $(CLANG_FLAGS) $(KBUILD_CFLAGS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@ \
+		$(CC) $(CLANG_FLAGS) $(KBUILD_CFLAGS) \
+		$(CC_FLAGS_RUST_INLINE_HELPERS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@ \
 		$(cmd_ld_single)) \
 	$(if $(rustc_objcopy),;$(OBJCOPY) $(rustc_objcopy) $@) \
 	$(cmd_objtool)
scripts/Makefile.build +2 -1
@@ -346,7 +346,8 @@ quiet_cmd_rustc_o_rs = $(RUSTC_OR_CLIPPY
       cmd_rustc_o_rs = $(rust_common_cmd) --emit=$(if $(CONFIG_RUST_INLINE_HELPERS),llvm-bc=$(patsubst %.o,%.bc,$@),obj=$@) $< \
 	$(if $(CONFIG_RUST_INLINE_HELPERS),;$(LLVM_LINK) --internalize --suppress-warnings $(patsubst %.o,%.bc,$@) \
 		$(objtree)/rust/helpers/helpers$(if $(part-of-module),_module).bc -o $(patsubst %.o,%.m.bc,$@); \
-		$(CC) $(CLANG_FLAGS) $(KBUILD_CFLAGS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@ \
+		$(CC) $(CLANG_FLAGS) $(KBUILD_CFLAGS) \
+		$(CC_FLAGS_RUST_INLINE_HELPERS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@ \
 		$(cmd_ld_single)) \
 	$(cmd_objtool)
 
author maintainer
#40 lore raw

PATCH 40/713 kbuild: rust: keep Rust objects out of Clang LTO with inline helpers

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Miguel Ojeda <[email protected]>

commit 5febf432df1cfa5b25d99b54c32103fafbdd0eb9 upstream.

Under CONFIG_LTO_CLANG + CONFIG_RUST_INLINE_HELPERS, one may hit objtool errors such as:

    vmlinux.o: error: objtool: _R..._3Gsp4boot+0xd6a:
    can't find jump dest instruction at .text._R..._3Gsp4boot+0x1dfd

The reason is that in such builds, the Clang invocation that compiles the combined Rust plus helpers bitcode emits LLVM bitcode (again) -- the final code generation happens in the linker's LTO step, which the -mllvm trap options passed to Clang do not reach.

This, in turn, means that unreachable traps are missing, and the impossible paths do not merely fallthrough to the next symbol, but past the end of their own section, since LTO builds place each function in its own section.

Thus filter CC_FLAGS_LTO out of the Clang invocation, so that it always emits machine code directly, with the traps in place.

Assisted-by LLM
Cc Gary Guo <[email protected]>
Cc Boqun Feng <[email protected]>
Cc Alice Ryhl <[email protected]>
Cc Matthew Maurer <[email protected]>
Cc Josh Poimboeuf <[email protected]>
Cc Peter Zijlstra <[email protected]>
Fixes 3a2486cc1da5 ("kbuild: rust: provide an option to inline C helpers into Rust")
---
 rust/Makefile          |    2 +-
 scripts/Makefile.build |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
rust/Makefile +1 -1
@@ -645,7 +645,7 @@ quiet_cmd_rustc_library = $(if $(skip_cl
 		-Zunstable-options \
 	$(if $(link_helper),;$(LLVM_LINK) --internalize --suppress-warnings $(patsubst %.o,%.bc,$@) \
 		$(obj)/helpers/helpers$(if $(part-of-module),_module).bc -o $(patsubst %.o,%.m.bc,$@); \
-		$(CC) $(CLANG_FLAGS) $(KBUILD_CFLAGS) \
+		$(CC) $(CLANG_FLAGS) $(filter-out $(CC_FLAGS_LTO),$(KBUILD_CFLAGS)) \
 		$(CC_FLAGS_RUST_INLINE_HELPERS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@ \
 		$(cmd_ld_single)) \
 	$(if $(rustc_objcopy),;$(OBJCOPY) $(rustc_objcopy) $@) \
scripts/Makefile.build +1 -1
@@ -346,7 +346,7 @@ quiet_cmd_rustc_o_rs = $(RUSTC_OR_CLIPPY
       cmd_rustc_o_rs = $(rust_common_cmd) --emit=$(if $(CONFIG_RUST_INLINE_HELPERS),llvm-bc=$(patsubst %.o,%.bc,$@),obj=$@) $< \
 	$(if $(CONFIG_RUST_INLINE_HELPERS),;$(LLVM_LINK) --internalize --suppress-warnings $(patsubst %.o,%.bc,$@) \
 		$(objtree)/rust/helpers/helpers$(if $(part-of-module),_module).bc -o $(patsubst %.o,%.m.bc,$@); \
-		$(CC) $(CLANG_FLAGS) $(KBUILD_CFLAGS) \
+		$(CC) $(CLANG_FLAGS) $(filter-out $(CC_FLAGS_LTO),$(KBUILD_CFLAGS)) \
 		$(CC_FLAGS_RUST_INLINE_HELPERS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@ \
 		$(cmd_ld_single)) \
 	$(cmd_objtool)
author maintainer
#41 lore raw

PATCH 41/713 KEYS: trusted: Fix TPM teardown ordering

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Chengfeng Ye <[email protected]>

commit 5e2d672280d97d83de43031d93761b12dadd7b8a upstream.

trusted_tpm_exit() drops the TPM chip reference and frees the digest array before unregistering the trusted key type. key_type_lookup() holds key_types_sem for reading until the key operation finishes, while unregister_key_type() takes it for writing. It therefore provides the synchronization point that must precede backend teardown.

The current order permits this interleaving:

CPU 0 CPU 1
trusted_tpm_exit() key_type_lookup("trusted")
put_device(&chip->dev) trusted_tpm_seal()
kfree(digests) pcrlock()
unregister_key_type() tpm_pcr_extend(..., digests)

CPU 1 can consequently dereference the freed digest array. The chip can also be released before callbacks stop using it.

KASAN reported:

  BUG: KASAN: slab-use-after-free in tpm_pcr_extend+0x1f0/0x200
  Read of size 2 at addr ffff88810872d000 by task poc/89
  Call Trace:
    tpm_pcr_extend+0x1f0/0x200
    pcrlock+0x42/0x70 [trusted]
    trusted_tpm_seal+0x1b6/0x570 [trusted]
    trusted_instantiate+0x293/0x340 [trusted]
    __key_instantiate_and_link+0xb2/0x2b0
    __key_create_or_update+0x61e/0xb50
    __do_sys_add_key+0x1b8/0x310
  Allocated by task 88:
    __kmalloc_noprof+0x1a7/0x490
    do_one_initcall+0xa1/0x390
    do_init_module+0x2df/0x840
  Freed by task 90:
    kfree+0x131/0x3c0
    trusted_tpm_exit+0x59/0xa0 [trusted]
    __do_sys_delete_module+0x346/0x510

Move unregister_key_type() before releasing either resource. This stops new lookups and waits for in-flight key operations to finish before the backend state is destroyed.

---
 security/keys/trusted-keys/trusted_tpm1.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
security/keys/trusted-keys/trusted_tpm1.c +1 -1
@@ -987,9 +987,9 @@ err_put:
 static void trusted_tpm_exit(void)
 {
 	if (chip) {
+		unregister_key_type(&key_type_trusted);
 		put_device(&chip->dev);
 		kfree(digests);
-		unregister_key_type(&key_type_trusted);
 	}
 }
 
author maintainer
#42 lore raw

PATCH 42/713 apparmor: fix cred UAF caused by begin_current_label_crit_section()

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jann Horn <[email protected]>

commit 3f4ae5fab613dca01d6a2a8210dd832e009fcf47 upstream.

AppArmor's begin_current_label_crit_section() is a scary function called from lots of LSM hooks (in particular VFS/socket-related ones) that checks if the label referenced by the current creds is marked FLAG_STALE, and if so, attempts to use aa_replace_current_label() to replace the creds with an updated version that uses a new label.

The first problem with this is that it would directly lead to UAF of struct cred if anything in the kernel takes a pointer to the current creds and accesses these past a security hook invocation that replaces creds, like so:

```
const struct cred *cred = current_cred();
alloc_file_pseudo(...);
uid_t uid = cred->euid;
```

I don't know if anything in the kernel actually does this, but I think it is very surprising that this pattern could lead to UAF.

The second problem is that things go wrong when aa_replace_current_label() runs with overridden credentials. aa_replace_current_label() bails out if current_cred() != current_real_cred() (mirroring the check in proc_pid_attr_write()), but this check can't actually reliably detect overridden credentials because the overridden creds can be the same as the objective creds.

So in approximately the following scenario, things go wrong:

1. task begins with <creds A> (as both objective and subjective creds), with refcount=2
2. task grabs an extra reference on <creds A> for overriding
3. task calls override_creds(<creds A>), which returns a pointer to the old subjective creds (<creds A>)
4. task enters AppArmor LSM hook
5. AppArmor checks that objective/subjective creds are equal
6. AppArmor replaces both cred pointers with <creds B> and drops 2 refs on <creds A>
7. task leaves AppArmor LSM hook
8. task calls revert_creds(<creds A>)
9. now task->cred is <creds A> while task->real_cred is <creds B>, but the task_struct logically holds two references to <creds B>
10. another task drops the extra reference on <creds A> that was used for overriding, refcount drops to 0
11. now task->real_cred points to freed creds

At this point, any access to current_cred() will be UAF.

I have a test case where I run aa-disable on a profile while a process using that profile is blocked on splice() from a FUSE passthrough file into a full pipe; after the profile update, the pipe becomes empty, splice() resumes, the credentials go out of sync, and a subsequent getuid() syscall results in a KASAN UAF splat.

To fix this, instead of directly replacing creds, do it via task_work that will run at the end of the current syscall. (The point in time at which the cred replacement happens should have no correctness impact; it is just a performance optimization to avoid unnecessarily touching the refcount of the new label.)

Note that AppArmor still performs direct cred replacements in the sb_pivotroot LSM hook after this change, and that direct cred replacements can still happen in VFS ->write() callbacks via proc_pid_attr_write().

There are two options for what to do with aa_dup_task_ctx(): Either explicitly reset new->label_replacement_pending after the entire aa_task_ctx has been copied, or switch to manually copying members over. I am switching to manually copying members over because that should make bugs more obvious.

Fixes c75afcd153f6 ("AppArmor: contexts used in attaching policy to system objects")
---
 security/apparmor/include/cred.h |    6 +-----
 security/apparmor/include/task.h |   15 +++++++++++----
 security/apparmor/task.c         |   27 +++++++++++++++++++++++++++
 3 files changed, 39 insertions(+), 9 deletions(-)
security/apparmor/include/cred.h +1 -5
@@ -222,13 +222,9 @@ static inline struct aa_label *begin_cur
 {
 	struct aa_label *label = aa_current_raw_label();
 
-	might_sleep();
-
 	if (label_is_stale(label)) {
 		label = aa_get_newest_label(label);
-		if (aa_replace_current_label(label) == 0)
-			/* task cred will keep the reference */
-			aa_put_label(label);
+		aa_schedule_stale_label_replacement();
 	}
 
 	return label;
security/apparmor/include/task.h +11 -4
@@ -21,15 +21,22 @@ static inline struct aa_task_ctx *task_c
  * @onexec: profile to transition to on next exec  (MAY BE NULL)
  * @previous: profile the task may return to     (MAY BE NULL)
  * @token: magic value the task must know for returning to @previous_profile
+ * @label_replacement_tw: for aa_schedule_stale_label_replacement()
+ * @label_replacement_pending: is @label_replacement_tw pending?
+ *
+ * When changing this, check if aa_dup_task_ctx() needs to be updated.
  */
 struct aa_task_ctx {
 	struct aa_label *nnp;
 	struct aa_label *onexec;
 	struct aa_label *previous;
 	u64 token;
+	struct callback_head label_replacement_tw;
+	bool label_replacement_pending;
 };
 
 int aa_replace_current_label(struct aa_label *label);
+void aa_schedule_stale_label_replacement(void);
 void aa_set_current_onexec(struct aa_label *label, bool stack);
 int aa_set_current_hat(struct aa_label *label, u64 token);
 int aa_restore_previous_label(u64 cookie);
@@ -56,10 +63,10 @@ static inline void aa_free_task_ctx(stru
 static inline void aa_dup_task_ctx(struct aa_task_ctx *new,
 				   const struct aa_task_ctx *old)
 {
-	*new = *old;
-	aa_get_label(new->nnp);
-	aa_get_label(new->previous);
-	aa_get_label(new->onexec);
+	new->nnp = aa_get_label(old->nnp);
+	new->onexec = aa_get_label(old->onexec);
+	new->previous = aa_get_label(old->previous);
+	new->token = old->token;
 }
 
 /**
security/apparmor/task.c +27 -0
@@ -14,6 +14,7 @@
 
 #include <linux/gfp.h>
 #include <linux/ptrace.h>
+#include <linux/task_work.h>
 
 #include "include/path.h"
 #include "include/audit.h"
@@ -89,6 +90,32 @@ int aa_replace_current_label(struct aa_l
 	return 0;
 }
 
+static void aa_replace_stale_label_tw_func(struct callback_head *tw)
+{
+	struct aa_task_ctx *ctx = task_ctx(current);
+	struct aa_label *label;
+
+	ctx->label_replacement_pending = false;
+	label = aa_current_raw_label();
+	if (!label_is_stale(label))
+		return;
+	label = aa_get_newest_label(label);
+	aa_replace_current_label(label);
+	aa_put_label(label);
+}
+
+/* replace the current task's stale label on syscall return */
+void aa_schedule_stale_label_replacement(void)
+{
+	struct aa_task_ctx *ctx = task_ctx(current);
+
+	if (ctx->label_replacement_pending)
+		return;
+	init_task_work(&ctx->label_replacement_tw, aa_replace_stale_label_tw_func);
+	if (task_work_add(current, &ctx->label_replacement_tw, TWA_RESUME) == 0)
+		ctx->label_replacement_pending = true;
+}
+
 
 /**
  * aa_set_current_onexec - set the tasks change_profile to happen onexec
author maintainer
#43 lore raw

PATCH 43/713 apparmor: fix out-of-bounds write when null terminating a label vec

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Hyunwoo Kim <[email protected]>

commit 9f1e40193eef7f047e6b77cfb4b4cafdecd7a123 upstream.

aa_vec_unique() null terminates at vec[n - dups] when VEC_FLAG_TERMINATE is passed. If the components are all distinct no duplicates are dropped, dups is 0 and the terminator goes to vec[n], so the caller has to provide room for n + 1 entries.

aa_label_strn_parse() sets up its vector with vec_setup(profile, vec, len, gfp) and then calls aa_vec_unique(vec, len, VEC_FLAG_TERMINATE), but vec_setup() does not reserve the terminator entry. Up to LOCAL_VEC_ENTRIES it uses the local array of LOCAL_VEC_ENTRIES pointers, above that it allocates exactly len pointers. The terminator therefore lands one entry past the end of the local array when len is LOCAL_VEC_ENTRIES, and one entry past the end of the allocation when len is larger.

len comes from the number of "//&" separated components in the label name and label_count_strn_entries() does not bound it. An unprivileged task reaches the parse by writing to /proc/self/attr/apparmor/current or through lsm_set_self_attr(2), both of which go through do_setattr(), and the name is parsed before the change_profile permission is checked.
The query_label() path behind the securityfs .access file, which is mode 0666, performs no permission check at all. Every component has to resolve to a loaded profile, so a system with policy loaded is required.

The other two VEC_FLAG_TERMINATE users work on a label vec that aa_label_alloc() has already sized with "+ 1 for null terminator entry on vec". Reserve the same entry in vec_setup() and DEFINE_VEC(). Passing len + 1 from the caller instead would move len == LOCAL_VEC_ENTRIES out of the local array and into kzalloc().

Fixes f1bd904175e8 ("apparmor: add the base fns() for domain labels")
---
 security/apparmor/include/label.h |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
security/apparmor/include/label.h +3 -3
@@ -23,7 +23,7 @@ struct aa_ruleset;
 
 #define LOCAL_VEC_ENTRIES 8
 #define DEFINE_VEC(T, V)						\
-	struct aa_ ## T *(_ ## V ## _localtmp)[LOCAL_VEC_ENTRIES];	\
+	struct aa_ ## T *(_ ## V ## _localtmp)[LOCAL_VEC_ENTRIES + 1];	\
 	struct aa_ ## T **(V)
 
 #define vec_setup(T, V, N, GFP)						\
@@ -31,10 +31,10 @@ struct aa_ruleset;
 	if ((N) <= LOCAL_VEC_ENTRIES) {					\
 		typeof(N) i;						\
 		(V) = (_ ## V ## _localtmp);				\
-		for (i = 0; i < (N); i++)				\
+		for (i = 0; i <= (N); i++)				\
 			(V)[i] = NULL;					\
 	} else								\
-		(V) = kzalloc(sizeof(struct aa_ ## T *) * (N), (GFP));	\
+		(V) = kzalloc_objs(struct aa_ ## T *, (N) + 1, (GFP));	\
 	(V) ? 0 : -ENOMEM;						\
 })
 
author maintainer
#44 lore raw

PATCH 44/713 include/linux/list.h: mark list_add and __list_add as __always_inline

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jordan R Abrahams-Whitehead <[email protected]>

commit 2780860eddecba9ffe210bb9436eee3cf22bfcdd upstream.

This commit resolves an issue where modpost section verification fails due to section mismatches between list_add and its callers.

At present, list_add (and its internal __list_add) are called from both .text and .init code sections. Since inlining can vary per call site, list_add can be 4 different states:

list_add in text with arguments to non-.init.data values list_add in init with arguments to static .init.data values list_add in init with arguments to non-.init.data values list_add in text with arguments to static .init.data values

It is last instance that ends up causing the section mismatch caused by constant propagation of the address of static libs inside the dir_add as seen below (with the dir_list being defined statically in initramfs.c, resting in .init.data).

WARNING: modpost: vmlinux.o: section mismatch in reference: __list_add (section: .text.unlikely.) -> dir_list (section: .init.data)

Because of these section matching requirements, semantically, __list_add and list_add MUST be inlined. This will then ensure callers inside .init will receive a list_add that exists and refers to only .init data, and list_add code in .text sections will only refer to non-init data.

This issue manifests predominently in AutoFDO with clang, which is very hesitant to inline cold functions such as list_add even when marked inline. Marking them as __always_inline therefore matches the existing semantic constraints imposed by modpost's section mismatch checks.

---
 include/linux/list.h |   15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)
include/linux/list.h +11 -4
@@ -150,10 +150,13 @@ static inline bool __list_del_entry_vali
  *
  * This is only for internal list manipulation where we know
  * the prev/next entries already!
+ *
+ * Must be inlined to ensure it can be safely called
+ * with initdata arguments.
  */
-static inline void __list_add(struct list_head *new,
-			      struct list_head *prev,
-			      struct list_head *next)
+static __always_inline void __list_add(struct list_head *new,
+				       struct list_head *prev,
+				       struct list_head *next)
 {
 	if (!__list_add_valid(new, prev, next))
 		return;
@@ -171,8 +174,12 @@ static inline void __list_add(struct lis
  *
  * Insert a new entry after the specified head.
  * This is good for implementing stacks.
+ *
+ * Must be inlined to ensure it can be safely called
+ * with initdata arguments.
  */
-static inline void list_add(struct list_head *new, struct list_head *head)
+static __always_inline void list_add(struct list_head *new,
+				     struct list_head *head)
 {
 	__list_add(new, head, head->next);
 }
author maintainer
#45 lore raw

PATCH 45/713 mm, swap: dont free a hibernation slot that is in the swap cache

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Youngjun Park <[email protected]>

commit 10d9012e83efedde8718ceaa5053f836e0c8596c upstream.

A slot with a folio in the swap cache is freed when the folio leaves the cache, not when its count drops. swap_put_entries_cluster() follows that rule. swap_free_hibernation_slot() does not, it calls __swap_cluster_free_entries() whether or not a folio sits on the slot.

Cluster readahead can put one there. It walks a raw page_cluster sized window of offsets around the faulting entry, and a hibernation slot passes __swap_cache_add_check() because it is not a folio and its count is not zero. Freeing the slot then clears the entry under that folio.

The folio is now unreachable from the swap table, and the offset goes back to the allocator. The folio is still on the LRU though, so reclaim can pick it up later. It then takes the old offset out of folio->swap and overwrites the table entry there, which by then may belong to someone else.

This bug can trigger silent memory corruption, process crashes, or data instability across completely unrelated userspace applications - typically occurring when uswsusp is preparing the hibernation image.

I found this while working on giving hibernation slots their own marker in the swap table, which I had discussed with Kairui.
(https://lore.kernel.org/linux-mm/abp7aDgYLrxF3Me8@KASONG-MC4/) As far as I know there are no reports, so there is no Reported-by/Closes to add.

Check for a cached folio before freeing. The slot is then left in the ordinary state where only the swap cache holds it, and it is freed when the folio leaves the cache, either through the reclaim below or through normal reclaim later.

Fixes 0d6af9bcf383 ("mm, swap: use the swap table to track the swap count")
Cc Baoquan He <[email protected]>
Cc Barry Song <[email protected]>
Cc Chris Li <[email protected]>
Cc Kemeng Shi <[email protected]>
Cc Nhat Pham <[email protected]>
---
 mm/swapfile.c |    9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
mm/swapfile.c +8 -1
@@ -2196,7 +2196,14 @@ void swap_free_hibernation_slot(swp_entr
 
 	ci = swap_cluster_lock(si, offset);
 	__swap_cluster_put_entry(ci, offset % SWAPFILE_CLUSTER);
-	__swap_cluster_free_entries(si, ci, offset % SWAPFILE_CLUSTER, 1);
+	/*
+	 * A slot with a folio in the swap cache is freed when the folio
+	 * leaves the cache, the same rule swap_put_entries_cluster() follows.
+	 * Readahead can put a folio here, and freeing the slot now would
+	 * leave that folio with no entry behind it.
+	 */
+	if (!swp_tb_is_folio(__swap_table_get(ci, offset % SWAPFILE_CLUSTER)))
+		__swap_cluster_free_entries(si, ci, offset % SWAPFILE_CLUSTER, 1);
 	swap_cluster_unlock(ci);
 
 	/* In theory readahead might add it to the swap cache by accident */
author maintainer
#46 lore raw

PATCH 46/713 mm, swap: ratelimit bad swap entry reports

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Breno Leitao <[email protected]>

commit f9dc428249ed962a70acf301f01eae8578449161 upstream.

A corrupt page table hands the same bogus entry to get_swap_device() on every access to the mapping, and every rejection is logged. One machine logged 6185620 copies of the same line in a few hours.

swap_dup_entry_direct() prints the same message from the fork path, once per call: the WARN_ON_ONCE() guarding it warns once, the pr_err() inside does not.

Rate limit all three prints.

---
 mm/swapfile.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
mm/swapfile.c +3 -3
@@ -1893,11 +1893,11 @@ struct swap_info_struct *get_swap_device
 
 	return si;
 bad_nofile:
-	pr_err("%s: %s%08lx\n", __func__, Bad_file, entry.val);
+	pr_err_ratelimited("%s: %s%08lx\n", __func__, Bad_file, entry.val);
 out:
 	return NULL;
 put_out:
-	pr_err("%s: %s%08lx\n", __func__, Bad_offset, entry.val);
+	pr_err_ratelimited("%s: %s%08lx\n", __func__, Bad_offset, entry.val);
 	percpu_ref_put(&si->users);
 	return NULL;
 }
@@ -3871,7 +3871,7 @@ int swap_dup_entry_direct(swp_entry_t en
 
 	si = swap_entry_to_info(entry);
 	if (WARN_ON_ONCE(!si)) {
-		pr_err("%s%08lx\n", Bad_file, entry.val);
+		pr_err_ratelimited("%s%08lx\n", Bad_file, entry.val);
 		return -EINVAL;
 	}
 
author maintainer
#47 lore raw

PATCH 47/713 mm/gup: fix always draining LRU caches in collect_longterm_unpinnable_folios()

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: David Hildenbrand (Arm) <[email protected]>

commit 078e1a0fc41a42baaf113383b52dab8874c0b967 upstream.

folio_may_be_lru_cached() is currently only true for small folios, and for small folios FOLL_PIN adds GUP_PIN_COUNTING_BIAS references instead of 1 in try_grab_folio()/try_grab_folio_fast().

Consequently, our

	folio_ref_count(folio) != folio_expected_ref_count(folio) + 1

check in collect_longterm_unpinnable_folios() will currently always identify "reference mismatch" and first drain the local LRU cache to then drain the LRU cache on all CPUs, as collect_longterm_unpinnable_folios() is really called after pinning the folios with FOLL_PIN.

Add a comment because the current code is not quite intuitive: we used to drain only to make sure the folio_isolate_lru() would succeed. But then we also started draining to make later migration more reliable.

We'll refactor that code soon a bit, to also make it usable in other context where we really want to remove any references from LRU caches.

Let's add CC stable, because having an easy way for excessive LRU cache draining on all CPUs does not sound right. In common scenarios we don't expect to ever have to drain.

Fixes 98c6d259319e ("mm/gup: check ref_count instead of lru before migration")
Fixes a09a8a1fbb37 ("mm/gup: local lru_add_drain() to avoid lru_add_drain_all()")
Cc Ackerley Tng <[email protected]>
Cc Jason Gunthorpe <[email protected]>
Cc John Hubbard <[email protected]>
Cc Kiryl Shutsemau <[email protected]>
Cc Peter Xu <[email protected]>
---
 mm/gup.c |   10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
mm/gup.c +8 -2
@@ -2273,6 +2273,7 @@ static unsigned long collect_longterm_un
 
 	for (folio = pofs_get_folio(pofs, i); folio;
 	     folio = pofs_next_folio(folio, pofs, &i)) {
+		const int pin_refs = folio_has_pincount(folio) ? 1 : GUP_PIN_COUNTING_BIAS;
 
 		if (folio_is_longterm_pinnable(folio))
 			continue;
@@ -2287,15 +2288,20 @@ static unsigned long collect_longterm_un
 			continue;
 		}
 
+		/*
+		 * We drain not only to make the folio_isolate_lru() succeed,
+		 * but also to remove any other folio references from LRU
+		 * caches.
+		 */
 		if (drained == 0 && folio_may_be_lru_cached(folio) &&
 				folio_ref_count(folio) !=
-				folio_expected_ref_count(folio) + 1) {
+				folio_expected_ref_count(folio) + pin_refs) {
 			lru_add_drain();
 			drained = 1;
 		}
 		if (drained == 1 && folio_may_be_lru_cached(folio) &&
 				folio_ref_count(folio) !=
-				folio_expected_ref_count(folio) + 1) {
+				folio_expected_ref_count(folio) + pin_refs) {
 			lru_add_drain_all();
 			drained = 2;
 		}
author maintainer
#48 lore raw

PATCH 48/713 mm/huge_memory: skip device-private PMDs in madvise_free_huge_pmd

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Usama Arif <[email protected]>

commit ce579dcf730ce5ed8043a5eeea18a3e6706a97e5 upstream.

madvise_free_pte_range() checks pmd_trans_huge(*pmd) unlocked, then madvise_free_huge_pmd() takes pmd_trans_huge_lock(). pmd_is_huge() returns true for a device-private PMD, so orig_pmd can be device-private and enter the !pmd_present() branch.

Skip device-private PMDs in that non-present branch and continue to out before calling pmd_folio(). Downgrade the check to VM_WARN_ON_ONCE() so an unexpected PMD softleaf logs a warning rather than panicking. Drop the thp_migration_supported() guard: it expands to IS_ENABLED(CONFIG_ARCH_SUPPORTS_PMD_SOFTLEAF), and both pmd_is_migration_entry() and pmd_is_device_private_entry() already return false when that config is not selected, so the guard suppresses only the case where the warning would already be silent.

Potential trigger: an HMM-based GPU driver races with madvise(MADV_FREE):
migrate_vma_pages() flips the PMD to a device-private entry between the caller's pmd_trans_huge() check and the callee's pmd_trans_huge_lock().

Fixes 368076f52ebe ("mm/huge_memory: add device-private THP support to PMD operations")
Cc Alistair Popple <[email protected]>
Cc Baolin Wang <[email protected]>
Cc Barry Song <[email protected]>
Cc Byungchul Park <[email protected]>
Cc Dev Jain <[email protected]>
Cc "Huang, Ying" <[email protected]>
Cc Jann Horn <[email protected]>
Cc Johannes Weiner <[email protected]>
Cc Lance Yang <[email protected]>
Cc Liam R. Howlett <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Matthew Brost <[email protected]>
Cc Nico Pache <[email protected]>
Cc Rakie Kim <[email protected]>
Cc Ryan Roberts <[email protected]>
Cc sashiko-bot <[email protected]>
Cc Shakeel Butt <[email protected]>
Cc Vlastimil Babka <[email protected]>
---
 mm/huge_memory.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
mm/huge_memory.c +2 -2
@@ -2340,8 +2340,8 @@ bool madvise_free_huge_pmd(struct mmu_ga
 		goto out;
 
 	if (unlikely(!pmd_present(orig_pmd))) {
-		VM_BUG_ON(thp_migration_supported() &&
-				  !pmd_is_migration_entry(orig_pmd));
+		VM_WARN_ON_ONCE(!pmd_is_migration_entry(orig_pmd) &&
+				!pmd_is_device_private_entry(orig_pmd));
 		goto out;
 	}
 
author maintainer
#49 lore raw

PATCH 49/713 mm/huge_memory: use folios memcg inside __folio_split()

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Zi Yan <[email protected]>

commit c299a2285d9d8bda4da024455de65e3d00de6f17 upstream.

Patch series "Honor XA_FLAGS_ACCOUNT in xas_split_alloc() and charge to folio's memcg", v3.

__GFP_ACCOUNT is needed for xarray node allocation accounting when XA_FLAGS_ACCOUNT is set. Commit 7b785645e8f13 ("mm: fix page cache convergence regression") fixed a workingset regression with it. xas_split_alloc() does not have it and needs to be fixed.

In addition, based on Sashiko's review[1] and Johannes' confirmation[2], to charge the right memcg, folio's memcg needs to be active during folio split. Add that before adding __GFP_ACCOUNT.

There is no workingset convergence regression related to missing __GFP_ACCOUNT in xas_split_alloc() and the impact to userspace should be minor.

This patch (of 2):

During a pagecache folio split, an xarray node allocation can happen and needs to charge at folio's memcg instead of folio split invoker's memcg, because for example folio split can happen during reclaim and reclaim's active memcg might not be folio's memcg. Switch to folio's memcg at the beginning and switch back afterwards.

---
 mm/huge_memory.c |   20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)
mm/huge_memory.c +16 -4
@@ -4027,34 +4027,42 @@ static int __folio_split(struct folio *f
 	XA_STATE(xas, &folio->mapping->i_pages, folio->index);
 	struct folio *end_folio = folio_next(folio);
 	bool is_anon = folio_test_anon(folio);
+	struct mem_cgroup *memcg, *old_memcg;
 	struct address_space *mapping = NULL;
 	struct anon_vma *anon_vma = NULL;
 	int old_order = folio_order(folio);
 	struct folio *new_folio, *next;
 	int nr_shmem_dropped = 0;
 	enum ttu_flags ttu_flags = 0;
-	int ret;
 	pgoff_t end = 0;
+	int ret;
 
 	VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio);
 	VM_WARN_ON_ONCE_FOLIO(!folio_test_large(folio), folio);
 
 	if (folio != page_folio(split_at) || folio != page_folio(lock_at)) {
 		ret = -EINVAL;
-		goto out;
+		goto out_no_memcg;
 	}
 
 	if (new_order >= old_order) {
 		ret = -EINVAL;
-		goto out;
+		goto out_no_memcg;
 	}
 
 	ret = folio_check_splittable(folio, new_order, split_type);
 	if (ret) {
 		VM_WARN_ONCE(ret == -EINVAL, "Tried to split an unsplittable folio");
-		goto out;
+		goto out_no_memcg;
 	}
 
+	/*
+	 * switch to folio's memcg as xarray node allocation can happen and
+	 * needs to charge to it.
+	 */
+	memcg = get_mem_cgroup_from_folio(folio);
+	old_memcg = set_active_memcg(memcg);
+
 	if (is_anon) {
 		/*
 		 * The caller does not necessarily hold an mmap_lock that would
@@ -4197,6 +4205,10 @@ out_unlock:
 	if (mapping)
 		i_mmap_unlock_read(mapping);
 out:
+	/* restore to caller's old_memcg */
+	set_active_memcg(old_memcg);
+	mem_cgroup_put(memcg);
+out_no_memcg:
 	xas_destroy(&xas);
 	if (is_pmd_order(old_order))
 		count_vm_event(!ret ? THP_SPLIT_PAGE : THP_SPLIT_PAGE_FAILED);
author maintainer
#50 lore raw

PATCH 50/713 mm/hugetlb: fix boot panic with CONFIG_DEBUG_VM and HVO bootmem pages

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Muchun Song <[email protected]>

commit c0caeceb0c3899dc42844d3979093b27d1434108 upstream.

Patch series "mm: Refactor bootmem gigantic hugepage allocation", v4.

This series is split out from the earlier larger series "mm: Generalize HVO for HugeTLB and device DAX" [1]. It collects the first 19 patches of that series as a standalone set of fixes and preparatory cleanups around bootmem HugeTLB handling, sparse initialization ordering, and related vmemmap setup.

The first patches fix a few bugs found while reviewing the existing code, including incorrect bootmem HVO handling, wrong vmemmap registration arguments, a powerpc compound-vmemmap tracking bug, and too-late initialization of gigantic bootmem HugeTLB struct pages.

The rest of the series reorders early memory initialization so the relevant zone state is available before sparse and HugeTLB boot-time setup runs, then simplifies the remaining bootmem gigantic hugepage allocation path and removes code made obsolete by that rework.

At a high level:
- patches [1-4] fix boot-time and arch-specific bugs
- patches [5-12] reorder and simplify sparse/mm/hugetlb early init
- patches [13-19] refactor bootmem gigantic hugepage allocation and remove obsolete helpers and state

This patch (of 19):

Commit 622026e87c40 ("mm/hugetlb: remove fake head pages") switched HVO to reuse per-zone shared tail pages from zone->vmemmap_tails[].

Those shared tail pages were initialized in hugetlb_vmemmap_init(), but bootmem HugeTLB folios are prepared earlier from gather_bootmem_prealloc(). With hugetlb_free_vmemmap=on, prep_and_add_bootmem_folios() can access pageblock flags on bootmem HugeTLB pages whose mirrored tail struct pages already point to the shared tail page. On CONFIG_DEBUG_VM kernels, get_pfnblock_bitmap_bitidx() then dereferences the still-uninitialized shared tail page and can panic during boot.

Initialize zone->vmemmap_tails[] from gather_bootmem_prealloc(), before bootmem HugeTLB folios are processed, and drop the later initialization from hugetlb_vmemmap_init().

This bug only affects CONFIG_DEBUG_VM kernels, where the relevant assertion is evaluated.

Fixes 622026e87c40 ("mm/hugetlb: remove fake head pages")
Cc "Aneesh Kumar K.V" <[email protected]>
Cc David Hildenbrand <[email protected]>
Cc Liam R. Howlett <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Madhavan Srinivasan <[email protected]>
Cc Michael Ellerman <[email protected]>
Cc Mike Rapoport <[email protected]>
Cc Nicholas Piggin <[email protected]>
Cc "Ritesh Harjani (IBM)" <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Frank van der Linden <[email protected]>
Cc Oscar Salvador (SUSE) <[email protected]>
Cc Usama Arif <[email protected]>
---
 mm/hugetlb.c         | 25 +++++++++++++++++++++++++
 mm/hugetlb_vmemmap.c | 17 -----------------
 mm/sparse-vmemmap.c  |  2 +-
 3 files changed, 26 insertions(+), 18 deletions(-)
mm/hugetlb.c +25 -0
index b75774455d65..4c234611e7a0 100644
@@ -3365,6 +3365,31 @@ static void __init gather_bootmem_prealloc(void)
 		.max_threads	= num_node_state(N_MEMORY),
 		.numa_aware	= true,
 	};
+#ifdef CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP
+	struct zone *zone;
+
+	for_each_zone(zone) {
+		for (int i = 0; i < NR_VMEMMAP_TAILS; i++) {
+			struct page *tail, *p;
+			unsigned int order;
+
+			tail = zone->vmemmap_tails[i];
+			if (!tail)
+				continue;
+
+			order = i + VMEMMAP_TAIL_MIN_ORDER;
+			p = page_to_virt(tail);
+			/*
+			 * prep_and_add_bootmem_folios() can access pageblock
+			 * flags on bootmem HugeTLB pages, so initialize the
+			 * shared tail struct pages here before bootmem folios
+			 * start using them.
+			 */
+			for (int j = 0; j < PAGE_SIZE / sizeof(struct page); j++)
+				init_compound_tail(p + j, NULL, order, zone);
+		}
+	}
+#endif
 
 	padata_do_multithreaded(&job);
 }
mm/hugetlb_vmemmap.c +0 -17
index 133b46dfb09f..c713c0d2593a 100644
@@ -870,27 +870,10 @@ static const struct ctl_table hugetlb_vmemmap_sysctls[] = {
 static int __init hugetlb_vmemmap_init(void)
 {
 	const struct hstate *h;
-	struct zone *zone;
 
 	/* HUGETLB_VMEMMAP_RESERVE_SIZE should cover all used struct pages */
 	BUILD_BUG_ON(__NR_USED_SUBPAGE > HUGETLB_VMEMMAP_RESERVE_PAGES);
 
-	for_each_zone(zone) {
-		for (int i = 0; i < NR_VMEMMAP_TAILS; i++) {
-			struct page *tail, *p;
-			unsigned int order;
-
-			tail = zone->vmemmap_tails[i];
-			if (!tail)
-				continue;
-
-			order = i + VMEMMAP_TAIL_MIN_ORDER;
-			p = page_to_virt(tail);
-			for (int j = 0; j < PAGE_SIZE / sizeof(struct page); j++)
-				init_compound_tail(p + j, NULL, order, zone);
-		}
-	}
-
 	for_each_hstate(h) {
 		if (hugetlb_vmemmap_optimizable(h)) {
 			register_sysctl_init("vm", hugetlb_vmemmap_sysctls);
mm/sparse-vmemmap.c +1 -1
index ebd3ac997f64..dff8da23eabb 100644
@@ -342,7 +342,7 @@ static __meminit struct page *vmemmap_get_tail(unsigned int order, struct zone *
 	 *
 	 * Any initialization done here will be overwritten by memmap_init().
 	 *
-	 * hugetlb_vmemmap_init() will take care of initialization after
+	 * gather_bootmem_prealloc() will take care of initialization after
 	 * memmap_init().
 	 */
 
Signature · 1 line
2.55.0
author maintainer
#51 lore raw

PATCH 51/713 mm/hugetlb: initialize gigantic bootmem hugepage struct pages earlier

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Muchun Song <[email protected]>

commit b1b7c045e808c761b1cc8c19b3040fadedda3fef upstream.

Gigantic bootmem HugeTLB pages are currently initialized from hugetlb_init(), but page_alloc_init_late() runs earlier and walks pageblocks to determine zone contiguity.

If a bootmem HugeTLB region is marked noinit, set_zone_contiguous() can observe still-uninitialized struct pages through __pageblock_pfn_to_page(). This may not trigger an immediate failure, but it can make set_zone_contiguous() compute the wrong zone contiguity state. If extra poisoned-page checks are added in this path, such as PF_POISONED_CHECK() in page_zone_id(), it can also trigger an early boot panic.

Initialize gigantic bootmem HugeTLB struct pages from page_alloc_init_late(), before zone contiguity is evaluated, so later page allocator setup only sees valid struct page state. This also makes the initialization order more natural, as struct pages should be initialized before later code inspects them.

Fixes fde1c4ecf916 ("mm: hugetlb: skip initialization of gigantic tail struct pages if freed by HVO")
Cc "Aneesh Kumar K.V" <[email protected]>
Cc David Hildenbrand <[email protected]>
Cc Frank van der Linden <[email protected]>
Cc Liam R. Howlett <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Madhavan Srinivasan <[email protected]>
Cc Michael Ellerman <[email protected]>
Cc Nicholas Piggin <[email protected]>
Cc Oscar Salvador (SUSE) <[email protected]>
Cc "Ritesh Harjani (IBM)" <[email protected]>
Cc Usama Arif <[email protected]>
Cc Vlastimil Babka <[email protected]>
---
 include/linux/hugetlb.h |    5 +++++
 mm/hugetlb.c            |    5 ++---
 mm/mm_init.c            |    1 +
 mm/sparse-vmemmap.c     |    4 ++--
 4 files changed, 10 insertions(+), 5 deletions(-)
include/linux/hugetlb.h +5 -0
@@ -171,6 +171,7 @@ extern int movable_gigantic_pages __read
 extern int sysctl_hugetlb_shm_group __read_mostly;
 extern struct list_head huge_boot_pages[MAX_NUMNODES];
 
+void hugetlb_bootmem_struct_page_init(void);
 void hugetlb_bootmem_alloc(void);
 extern nodemask_t hugetlb_bootmem_nodes;
 void hugetlb_bootmem_set_nodes(void);
@@ -1293,6 +1294,10 @@ static inline bool hugetlbfs_pagecache_p
 static inline void hugetlb_bootmem_alloc(void)
 {
 }
+
+static inline void hugetlb_bootmem_struct_page_init(void)
+{
+}
 #endif	/* CONFIG_HUGETLB_PAGE */
 
 static inline spinlock_t *huge_pte_lock(struct hstate *h,
mm/hugetlb.c +2 -3
@@ -3353,7 +3353,7 @@ static void __init gather_bootmem_preall
 		gather_bootmem_prealloc_node(nid);
 }
 
-static void __init gather_bootmem_prealloc(void)
+void __init hugetlb_bootmem_struct_page_init(void)
 {
 	struct padata_mt_job job = {
 		.thread_fn	= gather_bootmem_prealloc_parallel,
@@ -3582,7 +3582,7 @@ static unsigned long __init hugetlb_page
  * - For gigantic pages, this is called early in the boot process and
  *   pages are allocated from memblock allocated or something similar.
  *   Gigantic pages are actually added to pools later with the routine
- *   gather_bootmem_prealloc.
+ *   hugetlb_bootmem_struct_page_init.
  * - For non-gigantic pages, this is called later in the boot process after
  *   all of mm is up and functional.  Pages are allocated from buddy and
  *   then added to hugetlb pools.
@@ -4152,7 +4152,6 @@ static int __init hugetlb_init(void)
 	}
 
 	hugetlb_init_hstates();
-	gather_bootmem_prealloc();
 	report_hugepages();
 
 	hugetlb_sysfs_init();
mm/mm_init.c +1 -0
@@ -2330,6 +2330,7 @@ void __init page_alloc_init_late(void)
 	/* Reinit limits that are based on free pages after the kernel is up */
 	files_maxfiles_init();
 #endif
+	hugetlb_bootmem_struct_page_init();
 
 	/* Accounting of total+free memory is stable at this point. */
 	mem_init_print_info();
mm/sparse-vmemmap.c +2 -2
@@ -342,8 +342,8 @@ static __meminit struct page *vmemmap_ge
 	 *
 	 * Any initialization done here will be overwritten by memmap_init().
 	 *
-	 * gather_bootmem_prealloc() will take care of initialization after
-	 * memmap_init().
+	 * hugetlb_bootmem_struct_page_init() will take care of initialization
+	 * after memmap_init().
 	 */
 
 	p = vmemmap_alloc_block_zero(PAGE_SIZE, node);
author maintainer
#52 lore raw

PATCH 52/713 mm/hugetlb_vmemmap: fix __hugetlb_vmemmap_optimize_folios()

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Muchun Song <[email protected]>

commit 6e25c6a9c7eff141ecfc966ecdb7801db2a8810e upstream.

__hugetlb_vmemmap_optimize_folios() uses incorrect arguments when handling bootmem HugeTLB folios.

The section number passed to register_page_bootmem_memmap() is derived from the vmemmap virtual address of folio->page instead of the folio PFN, so the bootmem memmap metadata can be registered against the wrong section. The helper is also given HUGETLB_VMEMMAP_RESERVE_SIZE even though it expects a page count, not a size in bytes. In addition, the write-protect range is based on pages_per_huge_page(h), which does not cover the full HugeTLB vmemmap area and can leave part of the shared tail vmemmap mapping writable.

Fix the section lookup to use folio_pfn(folio), use HUGETLB_VMEMMAP_RESERVE_PAGES when registering the reserved memmap pages, and use hugetlb_vmemmap_size(h) for the write-protect range.

Fixes 752fe17af693 ("mm/hugetlb: add pre-HVO framework")
Cc "Aneesh Kumar K.V" <[email protected]>
Cc David Hildenbrand <[email protected]>
Cc Liam R. Howlett <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Madhavan Srinivasan <[email protected]>
Cc Michael Ellerman <[email protected]>
Cc Mike Rapoport (Microsoft) <[email protected]>
Cc Nicholas Piggin <[email protected]>
Cc Oscar Salvador (SUSE) <[email protected]>
Cc "Ritesh Harjani (IBM)" <[email protected]>
Cc Usama Arif <[email protected]>
Cc Vlastimil Babka <[email protected]>
---
 mm/hugetlb_vmemmap.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
mm/hugetlb_vmemmap.c +3 -3
@@ -635,12 +635,12 @@ static void __hugetlb_vmemmap_optimize_f
 			 * mirrored tail page structs RO.
 			 */
 			spfn = (unsigned long)&folio->page;
-			epfn = spfn + pages_per_huge_page(h);
+			epfn = spfn + hugetlb_vmemmap_size(h);
 			vmemmap_wrprotect_hvo(spfn, epfn, folio_nid(folio),
 					HUGETLB_VMEMMAP_RESERVE_SIZE);
-			register_page_bootmem_memmap(pfn_to_section_nr(spfn),
+			register_page_bootmem_memmap(pfn_to_section_nr(folio_pfn(folio)),
 					&folio->page,
-					HUGETLB_VMEMMAP_RESERVE_SIZE);
+					HUGETLB_VMEMMAP_RESERVE_PAGES);
 			continue;
 		}
 
author maintainer
#53 lore raw

PATCH 53/713 mm/kmemleak: avoid soft lockup when scanning task stacks

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Breno Leitao <[email protected]>

commit 5d10d4e19e6daa487f0cd0ea6cba472325de92f9 upstream.

Patch series "mm/kmemleak: avoid soft lockup when scanning task", v3.

kmemleak_scan() scans every task stack under one rcu_read_lock() with no reschedule point, which can trip the soft lockup watchdog on hosts with very many threads.

That prints the following message, depending on the workload+host configuration:

      watchdog: BUG: soft lockup - CPU#35 stuck for 22s! [kmemleak:537]
       scan_block
       kmemleak_scan
       kmemleak_scan_thread
       kthread

Patch 1 walks the tasks with find_ge_pid() so the scan reschedules between tasks

Patches 2-3 let the scan loops stop early once a scan is interrupted.

This patch (of 3):

kmemleak_scan() walks every thread and scans its kernel stack under a single rcu_read_lock() with no reschedule point. On a host with very many threads -- amplified by KASAN/lockdep in debug builds -- this loop can hog a CPU long enough to trip the soft lockup watchdog:

  watchdog: BUG: soft lockup - CPU#35 stuck for 22s! [kmemleak:537]
   scan_block
   kmemleak_scan
   kmemleak_scan_thread
   kthread

A cond_resched() cannot be added directly: the loop runs inside an RCU read-side critical section.

Walk the tasks one PID at a time with find_ge_pid(), taking the RCU read lock only to look up and pin each task. The stack is then scanned with no lock held, so cond_resched() runs between tasks and the scan stops early on scan_should_stop(). This follows the next_tgid()/task_seq_get_next() iteration pattern and keeps each RCU critical section short.

---
 mm/kmemleak.c |   51 ++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 38 insertions(+), 13 deletions(-)
mm/kmemleak.c +38 -13
@@ -1697,6 +1697,42 @@ unlock_put:
 }
 
 /*
+ * Scan all task kernel stacks, rescheduling between tasks. Each task is looked
+ * up and pinned within its own RCU read-side section, so no lock is held across
+ * the scan and the walk cannot trip the soft lockup watchdog.
+ */
+static void kmemleak_scan_task_stacks(void)
+{
+	struct pid *pid;
+	int nr = 1;
+
+	do {
+		struct task_struct *p = NULL;
+
+		rcu_read_lock();
+		pid = find_ge_pid(nr, &init_pid_ns);
+		if (pid) {
+			nr = pid_nr(pid) + 1;
+			p = pid_task(pid, PIDTYPE_PID);
+			if (p)
+				get_task_struct(p);
+		}
+		rcu_read_unlock();
+
+		if (p) {
+			void *stack = try_get_task_stack(p);
+
+			if (stack) {
+				scan_block(stack, stack + THREAD_SIZE, NULL);
+				put_task_stack(p);
+			}
+			put_task_struct(p);
+		}
+		cond_resched();
+	} while (pid && !scan_should_stop());
+}
+
+/*
  * Print one leak inline. The hex dump is gated on OBJECT_ALLOCATED so it
  * does not touch user memory that was freed concurrently; the rest of the
  * report (backtrace, comm, pid) is always emitted since the kmemleak_object
@@ -1885,19 +1921,8 @@ static void kmemleak_scan(void)
 	/*
 	 * Scanning the task stacks (may introduce false negatives).
 	 */
-	if (kmemleak_stack_scan) {
-		struct task_struct *p, *g;
-
-		rcu_read_lock();
-		for_each_process_thread(g, p) {
-			void *stack = try_get_task_stack(p);
-			if (stack) {
-				scan_block(stack, stack + THREAD_SIZE, NULL);
-				put_task_stack(p);
-			}
-		}
-		rcu_read_unlock();
-	}
+	if (kmemleak_stack_scan)
+		kmemleak_scan_task_stacks();
 
 	/*
 	 * Scan the objects already referenced from the sections scanned
author maintainer
#54 lore raw

PATCH 54/713 mm/madvise: skip device-private PMDs in cold and pageout walks

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Usama Arif <[email protected]>

commit d4b76d0b03cb49611312ecc4bcfb55ccdf0843e2 upstream.

madvise_cold_or_pageout_pte_range() takes pmd_trans_huge_lock(), whose pmd_is_huge() check returns true for a device-private PMD. The subsequent !pmd_present() branch has a VM_BUG_ON() asserting migration is the only allowed non-present case; a device-private PMD trips it.

Skip device-private PMDs in that non-present branch and continue to huge_unlock before calling pmd_folio(). Downgrade the check to VM_WARN_ON_ONCE() so an unexpected PMD softleaf logs a warning rather than panicking. Drop the thp_migration_supported() guard: it expands to IS_ENABLED(CONFIG_ARCH_SUPPORTS_PMD_SOFTLEAF), and both pmd_is_migration_entry() and pmd_is_device_private_entry() already return false when that config is not selected, so the guard suppresses only the case where the warning would already be silent.

Potential trigger: an HMM-based GPU driver races with madvise(MADV_COLD)/MADV_PAGEOUT: pmd_trans_huge(*pmd) reads true, then migrate_vma_pages() flips the PMD to a device-private entry before the PMD lock is acquired.

Fixes 368076f52ebe ("mm/huge_memory: add device-private THP support to PMD operations")
Cc Alistair Popple <[email protected]>
Cc Baolin Wang <[email protected]>
Cc Barry Song <[email protected]>
Cc Byungchul Park <[email protected]>
Cc David Hildenbrand (Arm) <[email protected]>
Cc Dev Jain <[email protected]>
Cc "Huang, Ying" <[email protected]>
Cc Jann Horn <[email protected]>
Cc Johannes Weiner <[email protected]>
Cc Lance Yang <[email protected]>
Cc Liam R. Howlett <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Matthew Brost <[email protected]>
Cc Nico Pache <[email protected]>
Cc Rakie Kim <[email protected]>
Cc Ryan Roberts <[email protected]>
Cc Shakeel Butt <[email protected]>
Cc Vlastimil Babka <[email protected]>
---
 mm/madvise.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
mm/madvise.c +2 -2
index 917f764fef80..bf9ce199935a 100644
@@ -388,8 +388,8 @@ static int madvise_cold_or_pageout_pte_range(pmd_t *pmd,
 			goto huge_unlock;
 
 		if (unlikely(!pmd_present(orig_pmd))) {
-			VM_BUG_ON(thp_migration_supported() &&
-					!pmd_is_migration_entry(orig_pmd));
+			VM_WARN_ON_ONCE(!pmd_is_migration_entry(orig_pmd) &&
+					!pmd_is_device_private_entry(orig_pmd));
 			goto huge_unlock;
 		}
 
Signature · 1 line
2.55.0
author maintainer
#55 lore raw

PATCH 55/713 mm/mempolicy: skip non-present PMDs when queueing folios

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Usama Arif <[email protected]>

commit 2858b4027f491e6fdb8ee2d8923798b619bf2791 upstream.

Patch series "mm: handle device-private PMDs in walk callbacks", v3.

Since commit 368076f52ebe ("mm/huge_memory: add device-private THP support to PMD operations") a PMD may hold a device-private swap entry whenever an HMM-based GPU driver migrates an anonymous THP folio to device memory via migrate_vma_pages().

pmd_trans_huge_lock() succeeds for such PMDs (pmd_is_huge() returns true for any non-present, non-none huge PMD), so several MM walk callbacks that used to assume present THP or migration entry are now reachable with a device-private PMD. The results range from a VM_BUG_ON() firing on debug kernels, to an oops on a bogus vmemmap dereference, to silently isolating an unrelated live folio from LRU in the aliasing case.

This patch (of 3):

queue_folios_pmd() is called under pmd_trans_huge_lock(), whose pmd_is_huge() check returns true for any non-present, non-none PMD softleaf. Passing such a PMD to pmd_folio() treats the softleaf encoding as a hardware PFN and can return a bogus folio pointer.

Mirror queue_folios_pte_range(): handle non-present entries before looking up a folio. Keep migration entries counted as failures, but skip other non-present PMDs such as device-private entries.

Potential trigger: an HMM-based GPU driver migrates an anonymous THP folio to device memory via migrate_vma_pages(), leaving a device-private PMD. Userspace then calls mbind(), migrate_pages() or set_mempolicy_home_node() on that range.

---
 mm/mempolicy.c |    8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
mm/mempolicy.c +5 -3
@@ -653,12 +653,14 @@ static void queue_folios_pmd(pmd_t *pmd,
 {
 	struct folio *folio;
 	struct queue_pages *qp = walk->private;
+	pmd_t pmdval = pmdp_get(pmd);
 
-	if (unlikely(pmd_is_migration_entry(*pmd))) {
-		qp->nr_failed++;
+	if (unlikely(!pmd_present(pmdval))) {
+		if (pmd_is_migration_entry(pmdval))
+			qp->nr_failed++;
 		return;
 	}
-	folio = pmd_folio(*pmd);
+	folio = pmd_folio(pmdval);
 	if (is_huge_zero_folio(folio)) {
 		walk->action = ACTION_CONTINUE;
 		return;
author maintainer
#56 lore raw

PATCH 56/713 mm/mglru: fix and remove redundant unevictable folio handling

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Kairui Song <[email protected]>

commit f7e698e326b239a91ea15844817551921209e826 upstream.

sort_folio() has a shortcut for moving folios that are no longer evictable but are still sitting on a generation list. However, this shortcut is buggy. It does not follow the PG_lru usage convention, and it has a more serious issue.

Unevictable folios are not threaded on lists[LRU_UNEVICTABLE], so that folio->lru can be reused to hold folio->mlock_count (see the comment in lruvec_init()). Hence lruvec_add_folio() skips the list_add() for them, and every other place that turns a folio unevictable initialises mlock_count explicitly: lru_add() sets it to 0, __mlock_folio() and __mlock_new_folio() set it to !!folio_test_mlocked(folio). sort_folio() sets nothing, and the lru_gen_del_folio() right above it may have already poisoned folio->lru via list_del(), so mlock_count ends up aliasing LIST_POISON2, which reads as 0x122, i.e. 290. The result is user visible. On munlock, __munlock_folio() decrements that bogus count, finds it still non-zero and bails out before clearing PG_mlocked, so the folio remains unevictable and the Mlocked accounting stays inflated until the folio is freed.

The shortcut also touches the LRU flags in the wrong order. It calls lru_gen_del_folio() while PG_lru is still set, so a concurrent folio_test_clear_lru() (e.g. compaction, folio_isolate_lru()) can succeed on a folio that has already been taken off the generation list, which may lead to unexpected behavior.

So fix it by isolating them as common folios and letting the generic shrink path cull them. This matches the classical LRU behavior, and there should be no visible effect on the generic eviction or isolation behavior.

There is no performance concern either, such a folio goes through this once, and then it is off the generation lists for good.

Fixes ac35a4902374 ("mm: multi-gen LRU: minimal implementation")
Cc Axel Rasmussen <[email protected]>
Cc Brian Geffon <[email protected]>
Cc David Hildenbrand <[email protected]>
Cc Jan Alexander Steffens (heftig) <[email protected]>
Cc Johannes Weiner <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Oleksandr Natalenko <[email protected]>
Cc Shakeel Butt <[email protected]>
Cc Steven Barrett <[email protected]>
Cc Suleiman Souhlal <[email protected]>
Cc Wei Xu <[email protected]>
Cc Yuanchu Xie <[email protected]>
Cc Yu Zhao <[email protected]>
---
 mm/vmscan.c |   19 +++++--------------
 1 file changed, 5 insertions(+), 14 deletions(-)
mm/vmscan.c +5 -14
@@ -4573,7 +4573,6 @@ void lru_gen_reparent_memcg(struct mem_c
 static bool sort_folio(struct lruvec *lruvec, struct folio *folio, struct scan_control *sc,
 		       int tier_idx)
 {
-	bool success;
 	int gen = folio_lru_gen(folio);
 	int type = folio_is_file_lru(folio);
 	int zone = folio_zonenum(folio);
@@ -4585,15 +4584,9 @@ static bool sort_folio(struct lruvec *lr
 
 	VM_WARN_ON_ONCE_FOLIO(gen >= MAX_NR_GENS, folio);
 
-	/* unevictable */
-	if (!folio_evictable(folio)) {
-		success = lru_gen_del_folio(lruvec, folio, true);
-		VM_WARN_ON_ONCE_FOLIO(!success, folio);
-		folio_set_unevictable(folio);
-		lruvec_add_folio(lruvec, folio);
-		__count_vm_events(UNEVICTABLE_PGCULLED, delta);
-		return true;
-	}
+	/* unevictable: let it through and the generic path will cull it */
+	if (!folio_evictable(folio))
+		return false;
 
 	/* promoted */
 	if (gen != lru_gen_from_seq(lrugen->min_seq[type])) {
@@ -4843,11 +4836,9 @@ retry:
 	list_for_each_entry_safe_reverse(folio, next, &list, lru) {
 		DEFINE_MIN_SEQ(lruvec);
 
-		if (!folio_evictable(folio)) {
-			list_del(&folio->lru);
-			folio_putback_lru(folio);
+		/* move_folios_to_lru() culls unevictable folios via folio_putback_lru() */
+		if (!folio_evictable(folio))
 			continue;
-		}
 
 		/* retry folios that may have missed folio_rotate_reclaimable() */
 		if (!skip_retry && !folio_test_active(folio) && !folio_mapped(folio) &&
author maintainer
#57 lore raw

PATCH 57/713 mm/migrate: report RCU-tasks quiescent states in migrate_pages_batch()

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Breno Leitao <[email protected]>

commit efe8f86c0916f0f74eea74ae21a3b37f728c6bad upstream.

migrate_pages_batch() unmaps each folio before moving it, and every unmap runs the mmu_notifier invalidate callbacks. On KVM hosts try_to_migrate() ends up in kvm_mmu_notifier_invalidate_range_start() -> tdp_mmu_zap_leafs(), which is expensive, so unmapping a large batch keeps the CPU busy for a long time.

The loop already calls cond_resched(), but on PREEMPTION kernels that is a no-op, and involuntary preemption is not a Tasks-RCU quiescent state.

A long batch therefore never reports a quiescent state, and the migrating task (e.g. kcompactd) becomes a Tasks-RCU holdout, stalling the Tasks-RCU grace period for minutes, which is common at Meta fleet:

  INFO: rcu_tasks detected stalls on tasks:
  0000000055349ecc: .. nvcsw: 1157401/1157401 holdout: 1 idle_cpu: -1/56 task:kcompactd0      state:R  running task
  Call Trace:
   tdp_mmu_zap_leafs
   tdp_mmu_next_root
   gfn_to_pfn_cache_invalidate_start
   kvm_mmu_notifier_invalidate_range_start
   __mmu_notifier_invalidate_range_start
   try_to_migrate_one
   try_to_migrate
   migrate_pages_batch
   migrate_pages
   compact_zone
   compact_node
   kcompactd
   kthread

Use cond_resched_tasks_rcu_qs() so a quiescent state is reported even when cond_resched() does nothing.

This has also been discussed at [1]

---
 mm/migrate.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
mm/migrate.c +1 -1
@@ -1830,7 +1830,7 @@ static int migrate_pages_batch(struct li
 			is_thp = folio_test_pmd_mappable(folio);
 			nr_pages = folio_nr_pages(folio);
 
-			cond_resched();
+			cond_resched_tasks_rcu_qs();
 
 			/*
 			 * The rare folio on the deferred split list should
author maintainer
#58 lore raw

PATCH 58/713 mm/migrate: use huge_ptep_get() in remove_migration_pte()

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Dev Jain <[email protected]>

commit ac1ec50d71b953524100ddc09057ee61a3dfaff3 upstream.

remove_migration_pte() converts migration entries back to present PTEs after folio migration completes. For hugetlb folios, page_vma_mapped_walk() returns the pte pointer to the hugetlb folio in pvmw.pte, but the code reads it with ptep_get().

On arches which provide their own huge_ptep_get() to dereference a huge pte pointer, accessing via ptep_get() would cause pte_pfn(), pte_present() etc to misbehave.

It is not clear whether this has a trivially visible effect to userspace.

Use huge_ptep_get() to dereference a huge pte pointer.

Fixes 290408d4a250 ("hugetlb: hugepage migration core")
Cc Alistair Popple <[email protected]>
Cc Andi Kleen <[email protected]>
Cc Anshuman Khandual <[email protected]>
Cc Byungchul Park <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Gregory Price <[email protected]>
Cc Harry Yoo <[email protected]>
Cc "Huang, Ying" <[email protected]>
Cc Jann Horn <[email protected]>
Cc Josh Poimboeuf <[email protected]>
Cc Joshua Hahn <[email protected]>
Cc Jun'ichi "Nick" Nomura <[email protected]>
Cc Kiryl Shutsemau <[email protected]>
Cc Lance Yang <[email protected]>
Cc Liam R. Howlett <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Matthew Brost <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Naoya Horiguchi <[email protected]>
Cc Oscar Salvador <[email protected]>
Cc Pedro Falcato <[email protected]>
Cc Rakie Kim <[email protected]>
Cc Ralph Campbell <[email protected]>
Cc Rik van Riel <[email protected]>
Cc Ryan Roberts <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Will Deacon <[email protected]>
Cc Zi Yan <[email protected]>
---
 mm/migrate.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
mm/migrate.c +5 -1
@@ -371,7 +371,11 @@ static bool remove_migration_pte(struct
 			continue;
 		}
 #endif
-		old_pte = ptep_get(pvmw.pte);
+		if (folio_test_hugetlb(folio))
+			old_pte = huge_ptep_get(vma->vm_mm, pvmw.address,
+						pvmw.pte);
+		else
+			old_pte = ptep_get(pvmw.pte);
 		if (rmap_walk_arg->map_unused_to_zeropage &&
 		    try_to_map_unused_to_zeropage(&pvmw, folio, old_pte, idx))
 			continue;
author maintainer
#59 lore raw

PATCH 59/713 mm/migrate_device: clear stale mapping after freeing swapcache

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Arvind Yadav <[email protected]>

commit 34a00895d032a414830d41106a09329ae6c251b6 upstream.

__migrate_device_pages() reads the folio mapping before calling folio_free_swap(). When folio_free_swap() succeeds, the folio is removed from the swap cache, but the saved mapping still points to swap_space.

Passing the stale mapping to folio_migrate_mapping() makes it use the mapped-folio path for a folio that is no longer in swapcache. It can then operate on swap_space.i_pages with invalid reference accounting, eventually triggering a folio reference count BUG.

After a successful split, nr still contains the number of pages in the original large folio, although each resulting page is now a separate order-0 folio. Reset nr to 1 so each split folio is processed separately, including its own swapcache removal and mapping lookup.

Refresh the saved mapping after folio_free_swap() so the current folio state is used during migration.

Fixes df263d9a7dff ("mm/migrate_device: try to handle swapcache pages")
Cc David Hildenbrand <[email protected]>
Cc Matthew Brost <[email protected]>
Cc Joshua Hahn <[email protected]>
Cc Rakie Kim <[email protected]>
Cc Byungchul Park <[email protected]>
Cc Gregory Price <[email protected]>
Cc Ying Huang <[email protected]>
Cc Alistair Popple <[email protected]>
---
 mm/migrate_device.c |   13 +++++++++++++
 1 file changed, 13 insertions(+)
mm/migrate_device.c +13 -0
@@ -1183,6 +1183,13 @@ static void __migrate_device_pages(unsig
 							 MIGRATE_PFN_COMPOUND);
 					goto next;
 				}
+
+				/*
+				 * reset nr so that only first after-split folio
+				 * is processed below
+				 */
+				VM_WARN_ON_ONCE(folio_test_large(folio));
+				nr = 1;
 			} else if ((src_pfns[i] & MIGRATE_PFN_MIGRATE) &&
 				(dst_pfns[i] & MIGRATE_PFN_COMPOUND) &&
 				!(src_pfns[i] & MIGRATE_PFN_COMPOUND)) {
@@ -1222,6 +1229,12 @@ static void __migrate_device_pages(unsig
 			folio = page_folio(migrate_pfn_to_page(src_pfns[i+j]));
 			newfolio = page_folio(migrate_pfn_to_page(dst_pfns[i+j]));
 
+			/*
+			 * folio_free_swap() removed the folio from the swap
+			 * cache. Refresh the saved mapping before migration.
+			 */
+			mapping = folio_mapping(folio);
+
 			r = folio_migrate_mapping(mapping, newfolio, folio, extra_cnt);
 			if (r)
 				src_pfns[i+j] &= ~MIGRATE_PFN_MIGRATE;
author maintainer
#60 lore raw

PATCH 60/713 mm/mm_init: deferred_grow_zone(): fix out-of-range first_deferred_pfn

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alexander Graf <[email protected]>

commit 97090500d776c3f6d08e857e3a0a7cf092999094 upstream.

With CONFIG_DEFERRED_STRUCT_PAGE_INIT enabled, deferred_grow_zone() initializes struct pages early in boot to satisfy an allocation.

With a large CMA reservation in place, the ranges deferred_init_memmap() finds may not add up to the allocation it was asked for, and the function ends up initializing the memory map of the entire zone and still falls short.

That is fine in itself: the function accounts for it and leaves the caller to decide whether it now has enough memory.

However, the update of pgdat->first_deferred_pfn that tracks where uninitialized memory map starts could overflow.

If the node's RAM end is not aligned on PAGES_PER_SECTION boundaries and some deferred struct pages were initialized, pgdat->first_deferred_pfn would point past the end of the node's memory.

deferred_init_memmap() later picks up from pgdat->first_deferred_pfn and hits a BUG_ON(), because it expects a pfn within its node.

For example, when running a kernel with CONFIG_DEFERRED_STRUCT_PAGE_INIT=y and CONFIG_CMA=y using the following qemu command line

  qemu-system-x86_64 -enable-kvm -m 8032M -kernel bzImage \
      -append "nokaslr cma=4768M@0x100000000"

the kernel panics:

kernel BUG at mm/mm_init.c:2131!

  CPU: 3 UID: 0 PID: 36 Comm: pgdatinit0 Not tainted 7.2.0-rc6 #1
  RIP: 0010:deferred_init_memmap+0x1b8/0x1c0
  RAX: 0000000000236000 R13: 0000000000238000
  Call Trace:
   kthread+0xdf/0x120
   ret_from_fork+0x187/0x250

Make sure that the update of pgdta->first_deferred_pfn does not overflow when the entire zone's (and therefore node's) memory map is initialized.

Fixes 3acb913c9d5b ("mm/mm_init: use deferred_init_memmap_chunk() in deferred_grow_zone()")
Assisted-by Kiro:claude-opus-5
[rppt: massaged the changelog]
---
 mm/mm_init.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
mm/mm_init.c +6 -3
@@ -2214,10 +2214,13 @@ bool __init deferred_grow_zone(struct zo
 	}
 
 	/*
-	 * There were no pages to initialize and free which means the zone's
-	 * memory map is completely initialized.
+	 * The loop only tests spfn before entering an iteration, so on exit it
+	 * may point up to a section past the end of the zone.  When it does,
+	 * the rest of the zone has already been handed to
+	 * deferred_init_memmap_chunk() and nothing is left to initialize.
 	 */
-	pgdat->first_deferred_pfn = nr_pages ? spfn : ULONG_MAX;
+	pgdat->first_deferred_pfn =
+		spfn < zone_end_pfn(zone) ? spfn : ULONG_MAX;
 
 	pgdat_resize_unlock(pgdat, &flags);
 
author maintainer
#61 lore raw

PATCH 61/713 mm/page_owner: use memcg_data snapshot to avoid TOCTOU in print_page_owner_memcg()

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ye Liu <[email protected]>

commit 90f095b816e25c6a9e4446d299bac5007fdcb3df upstream.

print_page_owner_memcg() reads page->memcg_data via READ_ONCE() at the start to guard against tail pages and NULL data. However, it later re-reads page->memcg_data locklessly in two places:

1: page_memcg_check(page)

2: PageMemcgKmem(page) (via folio_memcg_kmem(), which includes
VM_BUG_ON assertions for tail pages and MEMCG_DATA_OBJEXTS)

If the page is concurrently freed and reallocated as a THP tail page or slab page between these calls, the VM_BUG_ON assertions can trigger on CONFIG_DEBUG_VM=y builds, crashing the kernel.

Fix both TOCTOU issues by using the memcg_data snapshot throughout.

Fixes fcf8935832b8 ("mm/page_owner: print memcg information")
Cc Brendan Jackman <[email protected]>
Cc Johannes Weiner <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Suren Baghdasaryan <[email protected]>
Cc David Hildenbrand (Arm) <[email protected]>
---
 mm/page_owner.c |   10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
mm/page_owner.c +7 -3
@@ -513,6 +513,7 @@ static inline int print_page_owner_memcg
 {
 #ifdef CONFIG_MEMCG
 	unsigned long memcg_data;
+	struct obj_cgroup *objcg;
 	struct mem_cgroup *memcg;
 	bool online;
 	char name[80];
@@ -522,11 +523,14 @@ static inline int print_page_owner_memcg
 	if (!memcg_data || PageTail(page))
 		goto out_unlock;
 
-	if (memcg_data & MEMCG_DATA_OBJEXTS)
+	if (memcg_data & MEMCG_DATA_OBJEXTS) {
 		ret += scnprintf(kbuf + ret, count - ret,
 				"Slab cache page\n");
+		goto out_unlock;
+	}
 
-	memcg = page_memcg_check(page);
+	objcg = (void *)(memcg_data & ~OBJEXTS_FLAGS_MASK);
+	memcg = objcg ? obj_cgroup_memcg(objcg) : NULL;
 	if (!memcg)
 		goto out_unlock;
 
@@ -534,7 +538,7 @@ static inline int print_page_owner_memcg
 	cgroup_name(memcg->css.cgroup, name, sizeof(name));
 	ret += scnprintf(kbuf + ret, count - ret,
 			"Charged %sto %smemcg %s\n",
-			PageMemcgKmem(page) ? "(via objcg) " : "",
+			(memcg_data & MEMCG_DATA_KMEM) ? "(via objcg) " : "",
 			online ? "" : "offline ",
 			name);
 out_unlock:
author maintainer
#62 lore raw

PATCH 62/713 mm/page_vma_mapped: use huge_ptep_get() for hugetlb

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Dev Jain <[email protected]>

commit e87df0d5d6962bde50f55f6d02b779daa394f894 upstream.

check_pte() is the final validation step in page_vma_mapped_walk(). It reads pvmw->pte with ptep_get() to decide whether the entry maps the PFN range being walked. For hugetlb VMAs, that pointer refers to a hugetlb entry.

On arches which provide their own huge_ptep_get() to dereference a huge pte pointer, accessing via ptep_get() would cause pte_pfn(), pte_present() etc to misbehave.

It is not clear whether this has a trivially visible effect to userspace.

Use huge_ptep_get() to dereference a huge pte pointer.

Fixes ace71a19cec5 ("mm: introduce page_vma_mapped_walk()")
Cc Alistair Popple <[email protected]>
Cc Andi Kleen <[email protected]>
Cc Anshuman Khandual <[email protected]>
Cc Byungchul Park <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Gregory Price <[email protected]>
Cc Harry Yoo <[email protected]>
Cc "Huang, Ying" <[email protected]>
Cc Jann Horn <[email protected]>
Cc Josh Poimboeuf <[email protected]>
Cc Joshua Hahn <[email protected]>
Cc Jun'ichi "Nick" Nomura <[email protected]>
Cc Kiryl Shutsemau <[email protected]>
Cc Lance Yang <[email protected]>
Cc Liam R. Howlett <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Matthew Brost <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Naoya Horiguchi <[email protected]>
Cc Oscar Salvador <[email protected]>
Cc Pedro Falcato <[email protected]>
Cc Rakie Kim <[email protected]>
Cc Ralph Campbell <[email protected]>
Cc Rik van Riel <[email protected]>
Cc Ryan Roberts <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Will Deacon <[email protected]>
Cc Zi Yan <[email protected]>
---
 mm/page_vma_mapped.c |    8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
mm/page_vma_mapped.c +7 -1
@@ -107,7 +107,13 @@ again:
 static bool check_pte(struct page_vma_mapped_walk *pvmw, unsigned long pte_nr)
 {
 	unsigned long pfn;
-	pte_t ptent = ptep_get(pvmw->pte);
+	pte_t ptent;
+
+	if (is_vm_hugetlb_page(pvmw->vma))
+		ptent = huge_ptep_get(pvmw->vma->vm_mm, pvmw->address,
+				      pvmw->pte);
+	else
+		ptent = ptep_get(pvmw->pte);
 
 	if (pvmw->flags & PVMW_MIGRATION) {
 		const softleaf_t entry = softleaf_from_pte(ptent);
author maintainer
#63 lore raw

PATCH 63/713 mm/pagewalk: fix stale walk->action escaping walk_pmd_range()

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Hyunwoo Kim <[email protected]>

commit aedf2efd18977e0cef7eb963166e2b1fcc0aa321 upstream.

If ->pmd_entry() sets walk->action = ACTION_AGAIN, the pmd_none() check is retried. The PMD entry may be cleared at the point of retry.

In this case, if walk->ops->install_pte is not specified, the code continues to the next PMD entry in the range without resetting walk->action to ACTION_SUBTREE.

This leaves walk->action erroneously set to ACTION_AGAIN, which is incorrect.

This was incorrect but not problematic up until commit 3b89863c3fa4 ("mm/pagewalk: fix race between concurrent split and refault") which updated walk_pud_range() to check for walk->action == ACTION_AGAIN upon walk_pmd_range()'s return, causing the PUD walk to be retried.

In this case this results in duplicate walk callbacks being invoked, which is erroneous and will break any caller that is not idempotent with respect to this (and waste time for those which are). The result is an out-of-bounds write, triggered by a local fuzzer:

[    2.272695] ==================================================================
[    2.273471] BUG: KASAN: slab-out-of-bounds in __mincore_unmapped_range+0x14f/0x190
[    2.274302] Write of size 1 at addr ffff888008d9b000 by task poc/106
[    2.274966]
[    2.275154] CPU: 0 UID: 1000 PID: 106 Comm: poc Not tainted 7.2.0-rc6-00429-ga7c7074b58d2 #55 PREEMPT(lazy)
[    2.275159] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[    2.275164] Call Trace:
[    2.275170]  <TASK>
[    2.275172]  dump_stack_lvl+0x53/0x70
[    2.275200]  print_report+0xd0/0x630
[    2.275210]  ? __pfx__raw_spin_lock_irqsave+0x10/0x10
[    2.275219]  ? irqentry_exit+0xd2/0x670
[    2.275224]  ? irqentry_exit+0xd2/0x670
[    2.275226]  ? __virt_addr_valid+0xef/0x1a0
[    2.275239]  ? __mincore_unmapped_range+0x14f/0x190
[    2.275242]  kasan_report+0xce/0x100
[    2.275245]  ? __mincore_unmapped_range+0x14f/0x190
[    2.275248]  __mincore_unmapped_range+0x14f/0x190
[    2.275252]  mincore_unmapped_range+0x45/0x70
[    2.275254]  walk_pgd_range+0xafc/0xfc0
[    2.275261]  ? __pfx_walk_pgd_range+0x10/0x10
[    2.275264]  ? __update_load_avg_se+0x3d1/0x670
[    2.275275]  __walk_page_range+0xc0/0x310
[    2.275278]  ? __pfx_find_vma+0x10/0x10
[    2.275281]  ? finish_task_switch.isra.0+0x16d/0x4f0
[    2.275290]  walk_page_range_mm_unsafe+0x26f/0x3a0
[    2.275293]  ? __pfx_mtree_load+0x10/0x10
[    2.275298]  ? __pfx_walk_page_range_mm_unsafe+0x10/0x10
[    2.275302]  ? __free_frozen_pages+0x54d/0x7e0
[    2.275308]  __do_sys_mincore+0x132/0x380
[    2.275311]  do_syscall_64+0xf9/0x540
[    2.275316]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
[    2.275322] RIP: 0033:0x422ccd
[    2.275326] Code: b3 66 2e 0f 1f 84 00 00 00 00 00 66 90 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b8 ff ff ff f7 d8 64 89 01 48
[    2.275329] RSP: 002b:00007fffffffec18 EFLAGS: 00000287 ORIG_RAX: 000000000000001b
[    2.275337] RAX: ffffffffffffffda RBX: 0000000000000066 RCX: 0000000000422ccd
[    2.275339] RDX: 00000000004d0940 RSI: 0000000001000000 RDI: 00007ffff4000000
[    2.275340] RBP: 00000000004d0940 R08: 0000000000000100 R09: 0000000000000100
[    2.275342] R10: 0000000000000100 R11: 0000000000000287 R12: 20c49ba5e353f7cf
[    2.275343] R13: 00000000004990d3 R14: 0000000000000000 R15: 0000000000000001
[    2.275346]  </TASK>
[    2.275347]
[    2.296904] The buggy address belongs to the object at ffff888008d9b000
[    2.296904]  which belongs to the cache sigqueue of size 80
[    2.298151] The buggy address is located 0 bytes inside of
[    2.298151]  allocated 80-byte region [ffff888008d9b000, ffff888008d9b050)
[    2.299408]
[    2.299601] The buggy address belongs to the physical page:
[    2.300191] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x8d9b
[    2.301001] flags: 0x100000000000000(node=0|zone=1)
[    2.301535] page_type: f5(slab)
[    2.301884] raw: 0100000000000000 ffff888107e46780 dead000000000122 0000000000000000
[    2.302687] raw: 0000000000000000 0000000800240024 00000000f5000000 0000000000000000
[    2.303489] page dumped because: kasan: bad access detected
[    2.304092]
[    2.304276] Memory state around the buggy address:
[    2.304801]  ffff888008d9af00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[    2.305567]  ffff888008d9af80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[    2.306340] >ffff888008d9b000: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[    2.307115]                    ^
[    2.307474]  ffff888008d9b080: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[    2.308237]  ffff888008d9b100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[    2.308997] ==================================================================

A specific example of this breaking things is mincore which walks an internal cursor data structure a byte at a time on assumption that page table entry callbacks are called only once for each entry.

Fix the problem by resetting walk->action to ACTION_SUBTREE prior to the none check.

The pattern also exists in walk_pud_range() so fix it there too.

This issue was found through AI-based fuzzing.

Fixes 3b89863c3fa4 ("mm/pagewalk: fix race between concurrent split and refault")
Assisted-by Claude:claude-opus-5
Cc Max Boone <[email protected]>
Cc Liam R. Howlett <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Mike Rapoport <[email protected]>
Cc Suren Baghdasaryan <[email protected]>
Cc Vlastimil Babka <[email protected]>
---
 mm/pagewalk.c |    6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
mm/pagewalk.c +2 -4
@@ -126,6 +126,7 @@ static int walk_pmd_range(pud_t *pud, un
 	pmd = pmd_offset(pud, addr);
 	do {
 again:
+		walk->action = ACTION_SUBTREE;
 		next = pmd_addr_end(addr, end);
 		if (pmd_none(*pmd)) {
 			if (has_install)
@@ -138,8 +139,6 @@ again:
 				continue;
 		}
 
-		walk->action = ACTION_SUBTREE;
-
 		/*
 		 * This implies that each ->pmd_entry() handler
 		 * needs to know about pmd_trans_huge() pmds
@@ -196,6 +195,7 @@ static int walk_pud_range(p4d_t *p4d, un
 	pud = pud_offset(p4d, addr);
 	do {
  again:
+		walk->action = ACTION_SUBTREE;
 		next = pud_addr_end(addr, end);
 		if (pud_none(*pud)) {
 			if (has_install)
@@ -208,8 +208,6 @@ static int walk_pud_range(p4d_t *p4d, un
 				continue;
 		}
 
-		walk->action = ACTION_SUBTREE;
-
 		if (ops->pud_entry)
 			err = ops->pud_entry(pud, addr, next, walk);
 		if (err)
author maintainer
#64 lore raw

PATCH 64/713 mm/rmap: use huge_ptep_get() in try_to_unmap_one()

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Dev Jain <[email protected]>

commit f5407e9b697c940e78b27ff63c6e14d8d171adc3 upstream.

Patch series "Fix incorrect access of hugetlb pte entries", v3.

There are various places which use ptep_get() to get the pte entry corresponding to a hugetlb folio. Some arches (like s390) have special handling to compute the pteval, so they provide huge_ptep_get(). Use this helper consistently.

Additionally, some code paths may provide huge_ptep_get with an unaligned address. This is a problem on arm64 (I checked other arches and it looks fine for them), which is fixed in patch 1. The fix is made to be
backport-friendly: the cleaner fix would be to perhaps pass the hstate to huge_ptep_get() - that is wider churn and we can do that later.

This patch (of 5):

try_to_unmap_one() handles hugetlb folios when memory failure needs to replace a poisoned hugetlb mapping with a hwpoison entry. In that case page_vma_mapped_walk() returns the pte pointer to the hugetlb folio in pvmw.pte, but the code reads it with ptep_get().

On arches which provide their own huge_ptep_get() to dereference a huge pte pointer, accessing via ptep_get() would cause pte_pfn(), pte_present() etc to misbehave.

It is not clear whether this has a trivially visible effect to userspace.

Just use huge_ptep_get() for dereferencing a huge pte pointer.

Fixes c7ab0d2fdc84 ("mm: convert try_to_unmap_one() to use page_vma_mapped_walk()")
Cc Alistair Popple <[email protected]>
Cc Andi Kleen <[email protected]>
Cc Anshuman Khandual <[email protected]>
Cc Byungchul Park <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Gregory Price <[email protected]>
Cc Harry Yoo <[email protected]>
Cc "Huang, Ying" <[email protected]>
Cc Jann Horn <[email protected]>
Cc Josh Poimboeuf <[email protected]>
Cc Joshua Hahn <[email protected]>
Cc Jun'ichi "Nick" Nomura <[email protected]>
Cc Kiryl Shutsemau <[email protected]>
Cc Lance Yang <[email protected]>
Cc Liam R. Howlett <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Matthew Brost <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Naoya Horiguchi <[email protected]>
Cc Oscar Salvador <[email protected]>
Cc Pedro Falcato <[email protected]>
Cc Rakie Kim <[email protected]>
Cc Ralph Campbell <[email protected]>
Cc Rik van Riel <[email protected]>
Cc Ryan Roberts <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Will Deacon <[email protected]>
Cc Zi Yan <[email protected]>
---
 include/linux/hugetlb.h |    2 ++
 mm/rmap.c               |   16 ++++++++++------
 2 files changed, 12 insertions(+), 6 deletions(-)
include/linux/hugetlb.h +2 -0
@@ -1262,6 +1262,8 @@ static inline void hugetlb_count_sub(lon
 {
 }
 
+pte_t huge_ptep_get(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
+
 static inline pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
 					  unsigned long addr, pte_t *ptep)
 {
mm/rmap.c +10 -6
@@ -2095,14 +2095,19 @@ static bool try_to_unmap_one(struct foli
 		/* Unexpected PMD-mapped THP? */
 		VM_BUG_ON_FOLIO(!pvmw.pte, folio);
 
-		/*
-		 * Handle PFN swap PTEs, such as device-exclusive ones, that
-		 * actually map pages.
-		 */
-		pteval = ptep_get(pvmw.pte);
+		address = pvmw.address;
+		if (folio_test_hugetlb(folio)) {
+			pteval = huge_ptep_get(mm, address, pvmw.pte);
+		} else {
+			pteval = ptep_get(pvmw.pte);
+		}
 		if (likely(pte_present(pteval))) {
 			pfn = pte_pfn(pteval);
 		} else {
+			/*
+			 * Handle PFN swap PTEs, such as device-exclusive ones,
+			 * that actually map pages.
+			 */
 			const softleaf_t entry = softleaf_from_pte(pteval);
 
 			pfn = softleaf_to_pfn(entry);
@@ -2110,7 +2115,6 @@ static bool try_to_unmap_one(struct foli
 		}
 
 		subpage = folio_page(folio, pfn - folio_pfn(folio));
-		address = pvmw.address;
 		anon_exclusive = folio_test_anon(folio) &&
 				 PageAnonExclusive(subpage);
 
author maintainer
#65 lore raw

PATCH 65/713 mm/rmap: use huge_ptep_get() in try_to_migrate_one()

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Dev Jain <[email protected]>

commit 9be12ffa78cd087d41086f937a156435d4e588e9 upstream.

try_to_migrate_one() is used by folio migration to replace a present mapping with a migration entry. For hugetlb folios, page_vma_mapped_walk() returns the pte pointer to the hugetlb folio in pvmw.pte, but the code reads the huge pte entry with ptep_get().

On arches which provide their own huge_ptep_get() to dereference a huge pte pointer, accessing via ptep_get() would cause pte_pfn(), pte_present() etc to misbehave.

It is not clear whether this has a trivially visible effect to userspace.

Use huge_ptep_get() to dereference a huge pte pointer.

Commit a98a2f0c8ce1 copied the bug from try_to_unmap_one into try_to_migrate_one.

[[email protected]: coding-style cleanups]
Fixes a98a2f0c8ce1 ("mm/rmap: split migration into its own function")
Cc Alistair Popple <[email protected]>
Cc Andi Kleen <[email protected]>
Cc Anshuman Khandual <[email protected]>
Cc Byungchul Park <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Gregory Price <[email protected]>
Cc Harry Yoo <[email protected]>
Cc "Huang, Ying" <[email protected]>
Cc Jann Horn <[email protected]>
Cc Josh Poimboeuf <[email protected]>
Cc Joshua Hahn <[email protected]>
Cc Jun'ichi "Nick" Nomura <[email protected]>
Cc Kiryl Shutsemau <[email protected]>
Cc Lance Yang <[email protected]>
Cc Liam R. Howlett <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Matthew Brost <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Naoya Horiguchi <[email protected]>
Cc Oscar Salvador <[email protected]>
Cc Pedro Falcato <[email protected]>
Cc Rakie Kim <[email protected]>
Cc Ralph Campbell <[email protected]>
Cc Rik van Riel <[email protected]>
Cc Ryan Roberts <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Will Deacon <[email protected]>
Cc Zi Yan <[email protected]>
---
 mm/rmap.c |   15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)
mm/rmap.c +9 -6
@@ -2505,14 +2505,18 @@ static bool try_to_migrate_one(struct fo
 		/* Unexpected PMD-mapped THP? */
 		VM_BUG_ON_FOLIO(!pvmw.pte, folio);
 
-		/*
-		 * Handle PFN swap PTEs, such as device-exclusive ones, that
-		 * actually map pages.
-		 */
-		pteval = ptep_get(pvmw.pte);
+		address = pvmw.address;
+		if (folio_test_hugetlb(folio))
+			pteval = huge_ptep_get(mm, address, pvmw.pte);
+		else
+			pteval = ptep_get(pvmw.pte);
 		if (likely(pte_present(pteval))) {
 			pfn = pte_pfn(pteval);
 		} else {
+			/*
+			 * Handle PFN swap PTEs, such as device-exclusive ones,
+			 * that actually map pages.
+			 */
 			const softleaf_t entry = softleaf_from_pte(pteval);
 
 			pfn = softleaf_to_pfn(entry);
@@ -2520,7 +2524,6 @@ static bool try_to_migrate_one(struct fo
 		}
 
 		subpage = folio_page(folio, pfn - folio_pfn(folio));
-		address = pvmw.address;
 		anon_exclusive = folio_test_anon(folio) &&
 				 PageAnonExclusive(subpage);
 
author maintainer
#66 lore raw

PATCH 66/713 mm/slub: fix missing debugfs entries for caches created before sysfs init

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Li Xiasong <[email protected]>

commit 7e98f856395618011c517f767fb80ac3fe90de2b upstream.

slab_debugfs_init() creates the slab debugfs root at device initcall time, while slab_sysfs_init() moves slab_state to FULL at late initcall time. SLAB_STORE_USER caches created in this window miss their debugfs entries because do_kmem_cache_create() skips debugfs_slab_add() when slab_state <= UP. This was observed with MPTCP's request_sock_subflow_v6 cache, whose slab debugfs directory was missing.

The affected window is:

slab_debugfs_init()
slab_debugfs_root = debugfs_create_dir(...)
list_for_each_entry(s, &slab_caches, list)
debugfs_slab_add(s)

kmem_cache_create(..., SLAB_STORE_USER, ...)
do_kmem_cache_create()
if (slab_state <= UP)
return without debugfs entries

slab_sysfs_init()
slab_state = FULL

Initialize the debugfs root and add debugfs entries while holding slab_mutex, walking slab_caches exactly once and handling both sysfs and debugfs entries in the same pass. This gives the sysfs and debugfs initialization an explicit order and prevents caches from being created between the debugfs scan and slab_state reaching FULL.

Gate the new slab_late_init() on either sysfs or debugfs being enabled, with the slab_kset creation and alias_list processing factored into helpers that have empty no-sysfs variants, as suggested by Vlastimil Babka. On slab_kset_init() failure, slab_state stays below FULL so kmem_cache_create() keeps taking the early-boot path, matching prior behavior.

Guard debugfs_slab_release() against an uninitialized debugfs root, since the root is now created later and a cache may be released before it exists.

---
 mm/slub.c |   76 +++++++++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 48 insertions(+), 28 deletions(-)
mm/slub.c +48 -28
@@ -333,14 +333,20 @@ enum track_item { TRACK_ALLOC, TRACK_FRE
 
 #ifdef SLAB_SUPPORTS_SYSFS
 static int sysfs_slab_add(struct kmem_cache *);
+static int __init slab_kset_init(void);
+static void __init slab_sysfs_process_aliases(void);
 #else
 static inline int sysfs_slab_add(struct kmem_cache *s) { return 0; }
+static inline int slab_kset_init(void) { return 0; }
+static inline void slab_sysfs_process_aliases(void) { }
 #endif
 
 #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_SLUB_DEBUG)
 static void debugfs_slab_add(struct kmem_cache *);
+static void __init slab_debugfs_root_init(void);
 #else
 static inline void debugfs_slab_add(struct kmem_cache *s) { }
+static inline void slab_debugfs_root_init(void) { }
 #endif
 
 enum add_mode {
@@ -9734,28 +9740,20 @@ int sysfs_slab_alias(struct kmem_cache *
 	return 0;
 }
 
-static int __init slab_sysfs_init(void)
+static int __init slab_kset_init(void)
 {
-	struct kmem_cache *s;
-	int err;
-
-	mutex_lock(&slab_mutex);
-
 	slab_kset = kset_create_and_add("slab", NULL, kernel_kobj);
 	if (!slab_kset) {
-		mutex_unlock(&slab_mutex);
 		pr_err("Cannot register slab subsystem.\n");
 		return -ENOMEM;
 	}
 
-	slab_state = FULL;
+	return 0;
+}
 
-	list_for_each_entry(s, &slab_caches, list) {
-		err = sysfs_slab_add(s);
-		if (err)
-			pr_err("SLUB: Unable to add boot slab %s to sysfs\n",
-			       s->name);
-	}
+static void __init slab_sysfs_process_aliases(void)
+{
+	int err;
 
 	while (alias_list) {
 		struct saved_alias *al = alias_list;
@@ -9767,12 +9765,41 @@ static int __init slab_sysfs_init(void)
 			       al->name);
 		kfree(al);
 	}
+}
+#endif /* SLAB_SUPPORTS_SYSFS */
+
+#if defined(SLAB_SUPPORTS_SYSFS) || \
+	(defined(CONFIG_SLUB_DEBUG) && defined(CONFIG_DEBUG_FS))
+static int __init slab_late_init(void)
+{
+	struct kmem_cache *s;
+	int err;
 
+	mutex_lock(&slab_mutex);
+
+	err = slab_kset_init();
+	if (err)
+		goto out;
+
+	slab_debugfs_root_init();
+	slab_state = FULL;
+
+	list_for_each_entry(s, &slab_caches, list) {
+		if (sysfs_slab_add(s))
+			pr_err("SLUB: Unable to add boot slab %s to sysfs\n",
+			       s->name);
+
+		if (s->flags & SLAB_STORE_USER)
+			debugfs_slab_add(s);
+	}
+
+	slab_sysfs_process_aliases();
+out:
 	mutex_unlock(&slab_mutex);
-	return 0;
+	return err;
 }
-late_initcall(slab_sysfs_init);
-#endif /* SLAB_SUPPORTS_SYSFS */
+late_initcall(slab_late_init);
+#endif
 
 #if defined(CONFIG_SLUB_DEBUG) && defined(CONFIG_DEBUG_FS)
 static int slab_debugfs_show(struct seq_file *seq, void *v)
@@ -9964,23 +9991,16 @@ static void debugfs_slab_add(struct kmem
 
 void debugfs_slab_release(struct kmem_cache *s)
 {
+	if (unlikely(!slab_debugfs_root))
+		return;
+
 	debugfs_lookup_and_remove(s->name, slab_debugfs_root);
 }
 
-static int __init slab_debugfs_init(void)
+static void __init slab_debugfs_root_init(void)
 {
-	struct kmem_cache *s;
-
 	slab_debugfs_root = debugfs_create_dir("slab", NULL);
-
-	list_for_each_entry(s, &slab_caches, list)
-		if (s->flags & SLAB_STORE_USER)
-			debugfs_slab_add(s);
-
-	return 0;
-
 }
-__initcall(slab_debugfs_init);
 #endif
 /*
  * The /proc/slabinfo ABI
author maintainer
#67 lore raw

PATCH 67/713 mm/slub: prevent pfmemalloc objects from entering the barn

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Shengming Hu <[email protected]>

commit 9338b189be6895e45cf6fcf819c55cd3c47e4a18 upstream.

kmem_cache_return_sheaf() may refill a partially consumed sheaf before placing it in the barn. Without an explicit restriction, this refill may draw objects from pfmemalloc slabs and consume emergency reserves.

Add __GFP_NOMEMALLOC so that returned sheaves are refilled only from non-pfmemalloc slabs. Also add __GFP_NOWARN, as suggested by Hao Li, because this refill is a best-effort attempt and failure is acceptable. If the refill fails, flush and free the sheaf instead.

---
 mm/slub.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
mm/slub.c +1 -1
@@ -5153,7 +5153,7 @@ void kmem_cache_return_sheaf(struct kmem
 	 * simply flush and free it.
 	 */
 	if (!barn || data_race(barn->nr_full) >= MAX_FULL_SHEAVES ||
-	    refill_sheaf(s, sheaf, gfp)) {
+	    refill_sheaf(s, sheaf, gfp | __GFP_NOMEMALLOC | __GFP_NOWARN)) {
 		sheaf_flush_unused(s, sheaf);
 		free_empty_sheaf(s, sheaf);
 		return;
author maintainer
#68 lore raw

PATCH 68/713 mm/vmalloc: make vm_struct.nr_pages an unsigned long

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Artem Lytkin <[email protected]>

commit 272b0d84b17f72f6396254dbaa6264f2f74a7997 upstream.

vm_struct::nr_pages is an unsigned int, and the file keeps deriving byte counts from it as nr_pages << PAGE_SHIFT. A shift is evaluated in the type of its promoted left operand, so those are 32-bit arithmetic and wrap at 4 GiB of bytes, which is 2^20 pages. Every site depends on a cast being remembered; vmap() has one, two recent commits did not. vread_iter() then computes a size of zero for a 4 GiB VM_ALLOC area and /proc/kcore returns it as zeros while reporting a successful read, which drgn, crash or gdb cannot tell from real memory, and the vrealloc() grow-in-place check declines a request that would have fit.

Widen the field so the class of bug goes away instead of one site at a time. Everything feeding or consuming it widens too:
vm_area_alloc_pages() and its accumulators, nr_small_pages, new_nr_pages and old_nr_pages, the index range of vm_area_free_pages(), and three page indexes that were plain int. Five casts go. Two prints needed fixing as well, %u in vmalloc_dump_obj() and %d for the unsigned field in vmalloc_info_show().

No bug report behind this, I found it reading the code. The 4 GiB wrap needs only a machine with over 4 GiB of memory. Neither larger threshold is a practical concern: 2^32 pages, where the field itself truncates, is 16 TiB and beyond what hardware can populate, and 2^31, where the plain int indexes break, is 8 TiB and larger than anything in the tree asks for. The int *nr cursor in the mapping path is unchanged and is separate work. Users outside mm/vmalloc.c need no change either. Those handing the count to a narrower parameter cannot drive it near 2^31, and kho_preserve_vmalloc() stores it into a 32-bit ABI field that still receives the same low bits; above 2^32 pages the truncation just moves out of vm_struct into that store.

sizeof(struct vm_struct) on x86-64 stays 72 bytes with CONFIG_HAVE_ARCH_HUGE_VMALLOC=n and goes from 72 to 80 with it enabled, both inside the kmalloc-96 bucket it already comes from.

Fixes 0bca23804632 ("mm/vmalloc: use physical page count in vread_iter() for VM_ALLOC areas")
Fixes d57ac904ffdc ("mm/vmalloc: use physical page count for vrealloc() grow-in-place check")
Assisted-by Claude:claude-fable-5
Cc Matthew Wilcox (Oracle) <[email protected]>
---
 include/linux/vmalloc.h |    2 -
 mm/vmalloc.c            |   60 +++++++++++++++++++++++-------------------------
 2 files changed, 30 insertions(+), 32 deletions(-)
include/linux/vmalloc.h +1 -1
@@ -62,7 +62,7 @@ struct vm_struct {
 #ifdef CONFIG_HAVE_ARCH_HUGE_VMALLOC
 	unsigned int		page_order;
 #endif
-	unsigned int		nr_pages;
+	unsigned long		nr_pages;
 	phys_addr_t		phys_addr;
 	const void		*caller;
 	unsigned long		requested_size;
mm/vmalloc.c +29 -31

158 lines not on this page · raw message

author maintainer
#69 lore raw

PATCH 69/713 mm/vmscan: report RCU-tasks quiescent states in shrink_lruvec()

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Breno Leitao <[email protected]>

commit 25f52e81216884a7444bf07a606691feb09a94e3 upstream.

I am seeing some rcu_tasks stalls in the Meta fleet during reclaim.

  INFO: rcu_tasks detected stalls on tasks:
	0000000088620d09: .. nvcsw: 6735/6735 holdout: 1 idle_cpu: -1/8
	task:GlobalCPUThread state:R  running task  pid:2552016 tgid:2524552
  Call Trace:
   shrink_lruvec
   mem_cgroup_iter
   shrink_node
   do_try_to_free_pages
   try_to_free_pages
   __alloc_frozen_pages_noprof
   alloc_pages_noprof
   pte_alloc_one
   __pte_alloc
   handle_mm_fault

Nothing promises direct reclaim returns in bounded time, and the scan loop in shrink_lruvec() only calls cond_resched(), which is a no-op on PREEMPTION kernels. Involuntary preemption is not a Tasks-RCU quiescent state, so the reclaiming task never reports one and becomes a holdout.

Upgrade it to cond_resched_tasks_rcu_qs(), which reports a quiescent state even when cond_resched() does nothing.

PS: This has been discussed in [1]

---
 mm/vmscan.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
mm/vmscan.c +1 -1
@@ -5918,7 +5918,7 @@ static void shrink_lruvec(struct lruvec
 			}
 		}
 
-		cond_resched();
+		cond_resched_tasks_rcu_qs();
 
 		if (nr_reclaimed < nr_to_reclaim || proportional_reclaim)
 			continue;
author maintainer
#70 lore raw

PATCH 70/713 mm/zswap: fix global shrinker when memory cgroup is disabled

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Hao Jia <[email protected]>

commit dc8458f43fe964d8ade74c9b0fce54fe71d156de upstream.

Patch series "mm/zswap: Fixes and improves the zswap shrink", v4.

This series fixes and improves the zswap global shrinker (shrink_worker()): Patch 1: Fix missing global shrinker when memory cgroup is disabled. Patch 2: Extend shrink_memcg() to support batch writeback and thereby improving the writeback efficiency in the shrink_worker() and zswap_store() paths.

This patch (of 2):

Zswap writeback when the global pool limit is hit fails when memory cgroup is disabled. The pool remains full until it is organically drained by swapins or memory freeing, leading to zswap store failures and pages bypassing getting written directly to the backing swap device, causing LRU inversion (hotter pages with higher fault latency).

This happens because mem_cgroup_iter() always returns NULL when memory cgroups are disabled. As a result, the global shrinker shrink_worker() repeatedly takes empty walks. After MAX_RECLAIM_RETRIES failed attempts, the worker gives up without writing back any pages.

Therefore, when memory cgroup is disabled, fall through with the !memcg branch and shrink the root memcg directly.

With memcg disabled, shrink_memcg() only returns -ENOENT when the root LRU is empty, which means the total pages are already below thr. In the absence of heavy concurrent zswap stores, the loop then safely bails out via the zswap_total_pages() <= thr check; otherwise, it will resume shrinking the memcg after processing the reschedule check. For any other return value from shrink_memcg(), the loop is guaranteed to terminate, either after MAX_RECLAIM_RETRIES failures or once the threshold is met.

This is a potential performance regression for people using zswap without memcg that was introduced by the commit in "Fixes".

---
 mm/zswap.c |   13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)
mm/zswap.c +7 -6
@@ -1356,11 +1356,12 @@ static void shrink_worker(struct work_st
 		} while (memcg && !mem_cgroup_tryget_online(memcg));
 		spin_unlock(&zswap_shrink_lock);
 
-		if (!memcg) {
-			/*
-			 * Continue shrinking without incrementing failures if
-			 * we found candidate memcgs in the last tree walk.
-			 */
+		/*
+		 * A NULL memcg ends a full hierarchy pass (except when memcg is
+		 * disabled, where it is always NULL: fall through to the root LRU).
+		 * Count a failure only if the last pass found no candidates.
+		 */
+		if (!memcg && !mem_cgroup_disabled()) {
 			if (!attempts && ++failures == MAX_RECLAIM_RETRIES)
 				break;
 
@@ -1379,7 +1380,7 @@ static void shrink_worker(struct work_st
 		 * and failures.
 		 */
 		if (ret == -ENOENT)
-			continue;
+			goto resched;
 		++attempts;
 
 		if (ret && ++failures == MAX_RECLAIM_RETRIES)
author maintainer
#71 lore raw

PATCH 71/713 mm: compaction: support non-movable compaction for pageblock requests

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johannes Weiner <[email protected]>

commit 1b4b697a5743e624cc259d6c31a8d8716b796305 upstream.

While trying to fix a reclaim storm in defrag_mode, I noticed that non-movable direct compaction is extremely inefficient.

When searching for space to evacuate, compaction only allows blocks of the same type as the incoming request. This is to prevent migratetype pollution, where a small non-movable request frees space in a movable block and provokes the allocator to fall back and pollute it.

This protection is reasonable on one hand, but the downside is that it makes non-movable direct compaction nearly useless: if we get the type annotations right, by definition there aren't any movable pages inside the non-movable blocks it is allowed to scan.

With defrag_mode, the goal is the production of whole blocks, which are essentially type neutral: __rmqueue_claim() will convert them wholesale on alloc. This makes type mixing and pollution a non-issue.

Fix the pollution gates to take the requested order into account, and allow whole-block requests to scan blocks of other types.

The only exception is CMA blocks. That type is sticky and these blocks cannot be claimed to other types. Continue to be strict with them, and allow only explicit ALLOC_CMA requests and kcompactd to evacuate them.

Fixes e3aa7df331bc ("mm: page_alloc: defrag_mode")
Cc Brendan Jackman <[email protected]>
Cc Brendan Jackman <[email protected]>
Cc David Hildenbrand <[email protected]>
Cc Liam R. Howlett <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Mike Rapoport <[email protected]>
Cc Shakeel Butt <[email protected]>
Cc Suren Baghdasaryan <[email protected]>
Cc Zi Yan <[email protected]>
---
 mm/compaction.c |   46 +++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 39 insertions(+), 7 deletions(-)
mm/compaction.c +39 -7
@@ -1381,12 +1381,44 @@ static bool suitable_migration_source(st
 	if (pageblock_skip_persistent(page))
 		return false;
 
-	if ((cc->mode != MIGRATE_ASYNC) || !cc->direct_compaction)
+	/*
+	 * Background compaction produces blocks for the zone at
+	 * large, with no particular allocation context. Allow all
+	 * block types, including CMA.
+	 */
+	if (!cc->direct_compaction)
 		return true;
 
 	block_mt = get_pageblock_migratetype(page);
 
-	if (cc->migratetype == MIGRATE_MOVABLE)
+	/*
+	 * CMA pages can only be taken by ALLOC_CMA requests. For anybody
+	 * else, vacating a CMA block consumes free pages the caller
+	 * could have used, and produces free pages it cannot.
+	 */
+	if (is_migrate_cma(block_mt) && !(cc->alloc_flags & ALLOC_CMA))
+		return false;
+
+	/*
+	 * Per default, scans are restricted to blocks compatible with
+	 * the request, to prevent cross-contamination. Once
+	 * compaction priority escalates to synchronous scans, though,
+	 * scan all blocks to try to make forward progress. For
+	 * movable request, this likely helps little: there shouldn't
+	 * be many migratable pages inside non-movable blocks besides
+	 * allocator fallbacks. For non-movable requests, this helps a
+	 * lot, as they can finally scan movable blocks.
+	 */
+	if (cc->mode != MIGRATE_ASYNC)
+		return true;
+
+	/*
+	 * Prevent <pageblock_order unmovable/reclaimable requests from
+	 * polluting movable blocks through fallbacks. Whole-block production
+	 * (directly requested, or defrag_mode) is exempt as the allocator
+	 * claims and converts these.
+	 */
+	if (cc->migratetype == MIGRATE_MOVABLE || cc->order >= pageblock_order)
 		return is_migrate_movable(block_mt);
 	else
 		return block_mt == cc->migratetype;
@@ -1974,12 +2006,12 @@ static unsigned long fast_find_migratebl
 		return pfn;
 
 	/*
-	 * Only allow kcompactd and direct requests for movable pages to
-	 * quickly clear out a MOVABLE pageblock for allocation. This
-	 * reduces the risk that a large movable pageblock is freed for
-	 * an unmovable/reclaimable small allocation.
+	 * Prevent <pageblock_order unmovable/reclaimable requests from
+	 * polluting movable blocks through fallbacks. Whole-block production
+	 * is exempt as the allocator claims and converts these.
 	 */
-	if (cc->direct_compaction && cc->migratetype != MIGRATE_MOVABLE)
+	if (cc->direct_compaction && cc->migratetype != MIGRATE_MOVABLE &&
+	    cc->order < pageblock_order)
 		return pfn;
 
 	/*
author maintainer
#72 lore raw

PATCH 72/713 mm: memcg-v1: fix wrong linux-mm list address in deprecation warnings

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Guopeng Zhang <[email protected]>

commit 45b1ec4887bdcc58af885540d9fefa8b67d17d57 upstream.

The deprecation warnings for memory.oom_control and memory.pressure_level use [email protected] instead of the linux-mm mailing list address. Remove the extra hyphen.

---
 mm/memcontrol-v1.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
mm/memcontrol-v1.c +3 -3
@@ -1181,13 +1181,13 @@ static ssize_t memcg_write_event_control
 		event->unregister_event = mem_cgroup_usage_unregister_event;
 	} else if (!strcmp(name, "memory.oom_control")) {
 		pr_warn_once("oom_control is deprecated and will be removed. "
-			     "Please report your usecase to [email protected]"
+			     "Please report your usecase to [email protected]"
 			     " if you depend on this functionality.\n");
 		event->register_event = mem_cgroup_oom_register_event;
 		event->unregister_event = mem_cgroup_oom_unregister_event;
 	} else if (!strcmp(name, "memory.pressure_level")) {
 		pr_warn_once("pressure_level is deprecated and will be removed. "
-			     "Please report your usecase to [email protected] "
+			     "Please report your usecase to [email protected] "
 			     "if you depend on this functionality.\n");
 		event->register_event = vmpressure_register_event;
 		event->unregister_event = vmpressure_unregister_event;
@@ -2040,7 +2040,7 @@ static int mem_cgroup_oom_control_write(
 	struct mem_cgroup *memcg = mem_cgroup_from_css(css);
 
 	pr_warn_once("oom_control is deprecated and will be removed. "
-		     "Please report your usecase to [email protected] if you "
+		     "Please report your usecase to [email protected] if you "
 		     "depend on this functionality.\n");
 
 	/* cannot set to root cgroup and only 0 and 1 are allowed */
author maintainer
#73 lore raw

PATCH 73/713 mm: memcg-v1: fix memsw and TCP failcnt accounting

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Guopeng Zhang <[email protected]>

commit 92192e9c5ee07efc657d3654bc264081fb0aa01b upstream.

Commit 0e2759afcaf9 ("page_counter: track failcnt only for legacy cgroups") made failcnt accounting conditional on track_failcnt. It enabled the flag for memcg->memory, but not for memcg->memsw or memcg->tcpmem.

Consequently, memory.memsw.failcnt remains zero when the memory+swap limit is hit. memory.kmem.tcp.limit_in_bytes still sets memcg->tcpmem.max, but TCP charge failures are not reflected in memory.kmem.tcp.failcnt.

Enable failcnt accounting for both v1 counters.

To reproduce memory.memsw.failcnt:

    CG=/sys/fs/cgroup/memory/memsw-test
    LIMIT=33554432
    mkdir "$CG"
    echo "$LIMIT" > "$CG/memory.limit_in_bytes"
    echo "$LIMIT" > "$CG/memory.memsw.limit_in_bytes"

Start a child process in the cgroup and make it allocate and touch 96 MiB of memory, causing a memcg OOM.

cat "$CG/memory.memsw.failcnt"

Without the patch, memory.memsw.failcnt is 0. With the patch, memory.memsw.failcnt is greater than 0.

To reproduce memory.kmem.tcp.failcnt:

    CG=/sys/fs/cgroup/memory/tcpmem-test
    LIMIT=65536
    mkdir "$CG"
    echo "$LIMIT" > "$CG/memory.kmem.tcp.limit_in_bytes"

Start a child process in the cgroup, create a TCP socket, and reserve 1 MiB of socket memory with SO_RESERVE_MEM. The reservation fails with ENOMEM.

cat "$CG/memory.kmem.tcp.failcnt"

Without the patch, memory.kmem.tcp.failcnt is 0. With the patch, memory.kmem.tcp.failcnt is greater than 0.

---
 mm/memcontrol.c |    2 ++
 1 file changed, 2 insertions(+)
mm/memcontrol.c +2 -0
@@ -4180,9 +4180,11 @@ mem_cgroup_css_alloc(struct cgroup_subsy
 		page_counter_init(&memcg->swap, &parent->swap, false);
 #ifdef CONFIG_MEMCG_V1
 		memcg->memory.track_failcnt = !memcg_on_dfl;
+		memcg->memsw.track_failcnt = !memcg_on_dfl;
 		WRITE_ONCE(memcg->oom_kill_disable, READ_ONCE(parent->oom_kill_disable));
 		page_counter_init(&memcg->kmem, &parent->kmem, false);
 		page_counter_init(&memcg->tcpmem, &parent->tcpmem, false);
+		memcg->tcpmem.track_failcnt = !memcg_on_dfl;
 #endif
 	} else {
 		init_memcg_stats();
author maintainer
#74 lore raw

PATCH 74/713 mm: memcg: stop reclaim when a limit update is superseded

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Guopeng Zhang <[email protected]>

commit 9477820c63cbf4d97114238f3d1ff10dfd6bee3f upstream.

kernfs serializes file operations only per open file, so separate open files can update the same memory.high or memory.max file concurrently. Both handlers store the new limit before synchronous reclaim, but continue to use the writer's local target in the reclaim loop. If another writer raises or removes the limit, the first writer can continue reclaiming toward a stale target.

For memory.max, this can leave the writer looping indefinitely once reclaim retries are exhausted. The OOM path sees sufficient margin under the current limit and returns true without killing, while the writer still compares usage against its stale target and records another OOM event.

Check the current limit at the start of each reclaim iteration and stop if it no longer matches the writer's target.

Reproducer:

Populate a cgroup with anonymous memory and disable swapping. Lower memory.max from one open file, then restore it to "max" through another open file after the new limit becomes visible.

Without the patch, the first writer remains blocked and repeatedly increments the OOM event counter. With the patch, it returns normally.

This was not motivated by a reported production workload. We found it through automated randomized testing for our cgroup observability work and reduced it to the reproducer above.

Fixes 8c8c383c04f6 ("mm: memcontrol: try harder to set a new memory.high")
Fixes b6e6edcfa405 ("mm: memcontrol: reclaim and OOM kill when shrinking memory.max below usage")
Cc Michal Hocko <[email protected]>
Cc Muchun Song <[email protected]>
Cc Roman Gushchin <[email protected]>
Cc Shakeel Butt <[email protected]>
---
 mm/memcontrol.c |    6 ++++++
 1 file changed, 6 insertions(+)
mm/memcontrol.c +6 -0
@@ -4790,6 +4790,9 @@ static ssize_t memory_high_write(struct
 		unsigned long nr_pages = page_counter_read(&memcg->memory);
 		unsigned long reclaimed;
 
+		if (high != READ_ONCE(memcg->memory.high))
+			break;
+
 		if (nr_pages <= high)
 			break;
 
@@ -4841,6 +4844,9 @@ static ssize_t memory_max_write(struct k
 	for (;;) {
 		unsigned long nr_pages = page_counter_read(&memcg->memory);
 
+		if (max != READ_ONCE(memcg->memory.max))
+			break;
+
 		if (nr_pages <= max)
 			break;
 
author maintainer
#75 lore raw

PATCH 75/713 mm: memcontrol: update state_local when flushing NMI stats

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Guopeng Zhang <[email protected]>

commit 72f522bbf473f03a77e83547b677dc1505c5d41a upstream.

flush_nmi_stats() updates state[] for kmem and slab counters but leaves the corresponding state_local[] counters unchanged. Local kmem and slab statistics therefore miss updates collected through the NMI-safe atomic path.

Update state_local[] together with state[].

Fixes 940b01fc8dc1 ("memcg: nmi safe memcg stats for specific archs")
Cc Alexandre Ghiti <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Muchun Song <[email protected]>
Cc Roman Gushchin <[email protected]>
Cc Vlastimil Babka <[email protected]>
---
 mm/memcontrol.c |    5 +++++
 1 file changed, 5 insertions(+)
mm/memcontrol.c +5 -0
@@ -4440,6 +4440,7 @@ static void flush_nmi_stats(struct mem_c
 		int index = memcg_stats_index(MEMCG_KMEM);
 
 		memcg->vmstats->state[index] += kmem;
+		memcg->vmstats->state_local[index] += kmem;
 		if (parent)
 			parent->vmstats->state_pending[index] += kmem;
 	}
@@ -4457,9 +4458,11 @@ static void flush_nmi_stats(struct mem_c
 			int index = memcg_stats_index(NR_SLAB_RECLAIMABLE_B);
 
 			lstats->state[index] += slab;
+			lstats->state_local[index] += slab;
 			if (plstats)
 				plstats->state_pending[index] += slab;
 			memcg->vmstats->state[index] += slab;
+			memcg->vmstats->state_local[index] += slab;
 			if (parent)
 				parent->vmstats->state_pending[index] += slab;
 		}
@@ -4468,9 +4471,11 @@ static void flush_nmi_stats(struct mem_c
 			int index = memcg_stats_index(NR_SLAB_UNRECLAIMABLE_B);
 
 			lstats->state[index] += slab;
+			lstats->state_local[index] += slab;
 			if (plstats)
 				plstats->state_pending[index] += slab;
 			memcg->vmstats->state[index] += slab;
+			memcg->vmstats->state_local[index] += slab;
 			if (parent)
 				parent->vmstats->state_pending[index] += slab;
 		}
author maintainer
#76 lore raw

PATCH 76/713 mm: mempolicy: fix automatic numa balancing for shmem

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johannes Weiner <[email protected]>

commit d230991493b521eeff39f32434fddcbcdb109eb0 upstream.

Neha reports that mapped shmem aren't considered for NUMA balancing, noting convergence problems and bandwidth bottlenecking for cachelib based workloads on tiered memory systems.

Looking at the code and going through the git history, this doesn't actually seem intentional:

Commit fc3147245d19 ("mm: numa: Limit NUMA scanning to migrate-on-fault VMAs") added a vma_policy_mof() gate to task_numa_work() so VMAs whose policy lacks MPOL_F_MOF are skipped from NUMA balancing scans. The motivation was a real usecase: Oracle was pinning shared segments with mbind(MPOL_BIND) so trapping faults was both expensive and pointless.

The handling of NULL from vm_ops->get_policy, however, treated "user explicitly opted out" the same as "user never specified anything." For VMAs whose shared policy is absent - the common case for shmem - the scan was disabled too.

This issue is old. It probably hurts less in conventional NUMA. But it's very noticeable on tiered systems, where entire tmpfs workingsets can get stuck on lower-bandwidth memory.

Fix this by having vma_policy_mof() use __get_vma_policy() directly, and thereby handle the fallback to task policy (-> preferred_node_policy() has MPOL_F_MOF per default). Every other consumer of vm_ops->get_policy already handles it this way, the scan-eligibility check was the outlier.

This preserves Mel's intended fix: don't scan stuff the user explicitly pinned. But allow default policy vmas to participate in balancing.

---
 mm/mempolicy.c |   21 ++++++---------------
 1 file changed, 6 insertions(+), 15 deletions(-)
mm/mempolicy.c +6 -15
@@ -2059,24 +2059,15 @@ struct mempolicy *get_vma_policy(struct
 bool vma_policy_mof(struct vm_area_struct *vma)
 {
 	struct mempolicy *pol;
+	pgoff_t ilx;
+	bool mof;
 
-	if (vma->vm_ops && vma->vm_ops->get_policy) {
-		bool ret = false;
-		pgoff_t ilx;		/* ignored here */
-
-		pol = vma->vm_ops->get_policy(vma, vma->vm_start, &ilx);
-		if (pol && (pol->flags & MPOL_F_MOF))
-			ret = true;
-		mpol_cond_put(pol);
-
-		return ret;
-	}
-
-	pol = vma->vm_policy;
+	pol = __get_vma_policy(vma, vma->vm_start, &ilx);
 	if (!pol)
 		pol = get_task_policy(current);
-
-	return pol->flags & MPOL_F_MOF;
+	mof = pol->flags & MPOL_F_MOF;
+	mpol_cond_put(pol);
+	return mof;
 }
 
 bool apply_policy_zone(struct mempolicy *policy, enum zone_type zone)
author maintainer
#77 lore raw

PATCH 77/713 mm: page_alloc: __GFP_FS lockdep annotation for direct compaction

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johannes Weiner <[email protected]>

commit 37864d0bf5a4d60da6109b9078cc78ef3fc81216 upstream.

Patch series "mm: fix reclaim storms in defrag_mode", v2.

As we deployed vm.defrag_mode=1 in Meta production, some workloads regressed with recurring pressure spikes and swap storms (which in turn triggered userspace OOM rules on pressure and swap utilization levels).

Tracing pinned this to non-movable requests spinning and reclaiming unproductively when kswapd/kcompactd are overwhelmed. Direct reclaim predominantly frees up pages in movable blocks, but those requests cannot use that space under defrag_mode rules; and it is unlikely to free up whole blocks incidentally for __rmqueue_claim() to work.

This series fixes it by making non-movable requests participate in pageblock production in the allocator slowpath - meaning, they will invoke direct reclaim and direct compaction with pageblock_order.

That requires some small-ish adjustments up front in the allocator and the compaction code: three prep patches and the fix last.

The series has been in production against one of the affected workloads for several weeks and restores the OOM kill rate to !defrag_mode baseline.

This patch (of 4):

A subsequent patch will have some order-0 allocations participate in compaction under defrag_mode, to stave off extfrag events.

Since this is a sprawling expansion of entry points, and compaction can enter filesystem paths, add lockdep annotations that catches __GFP_FS passing errors.

Direct reclaim has had this annotation for a while, and since reclaim and compaction are usually used in conjunction, this is unlikely to unearth old bugs. It's more about future proofing and peace of mind.

Fixes e3aa7df331bc ("mm: page_alloc: defrag_mode")
Cc Brendan Jackman <[email protected]>
Cc Brendan Jackman <[email protected]>
Cc David Hildenbrand <[email protected]>
Cc Liam R. Howlett <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Mike Rapoport <[email protected]>
Cc Suren Baghdasaryan <[email protected]>
Cc Zi Yan <[email protected]>
Cc Brendan Jackman <[email protected]>
Cc Gregory Price <[email protected]>
---
 mm/page_alloc.c |    2 ++
 1 file changed, 2 insertions(+)
mm/page_alloc.c +2 -0
@@ -4152,12 +4152,14 @@ __alloc_pages_direct_compact(gfp_t gfp_m
 
 	psi_memstall_enter(&pflags);
 	delayacct_compact_start();
+	fs_reclaim_acquire(gfp_mask);
 	noreclaim_flag = memalloc_noreclaim_save();
 
 	*compact_result = try_to_compact_pages(gfp_mask, order, alloc_flags, ac,
 								prio, &page);
 
 	memalloc_noreclaim_restore(noreclaim_flag);
+	fs_reclaim_release(gfp_mask);
 	psi_memstall_leave(&pflags);
 	delayacct_compact_end();
 
author maintainer
#78 lore raw

PATCH 78/713 mm: page_alloc: move capture_control to the page allocator

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Vlastimil Babka (SUSE) <[email protected]>

commit aee220f565cce38f0efcff940ae2b44bdc495408 upstream.

The compaction capturing code assumes the allocation request order and compaction target order are the same. That won't be true once defrag_mode promotes sub-block allocations to pageblock-order compaction: compaction targets the larger order, while capture should remain at the original allocation order.

Move the capture_control to the page allocator and give it its own copies of what the page freeing path matches against - zone, migratetype and the allocation order - rather than reaching into compaction's live compact_control. __alloc_pages_direct_compact() fills in migratetype and order, and installs and hides current->capture_control around the whole compaction call; try_to_compact_pages() aims capc->zone at each zone while it is being compacted. compact_zone_order() no longer deals with capture at all.

Pass the capture_control through try_to_compact_pages() / compact_zone_order() in place of the bare struct page **.

No functional change.

Fixes e3aa7df331bc ("mm: page_alloc: defrag_mode")
Cc Brendan Jackman <[email protected]>
Cc Brendan Jackman <[email protected]>
Cc David Hildenbrand <[email protected]>
Cc Liam R. Howlett <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Mike Rapoport <[email protected]>
Cc Shakeel Butt <[email protected]>
Cc Suren Baghdasaryan <[email protected]>
Cc Zi Yan <[email protected]>
---
 include/linux/compaction.h |    3 +-
 mm/compaction.c            |   50 ++++++++++++---------------------------------
 mm/internal.h              |    4 ++-
 mm/page_alloc.c            |   45 ++++++++++++++++++++++++++++++++++------
 4 files changed, 57 insertions(+), 45 deletions(-)
include/linux/compaction.h +2 -1
@@ -58,6 +58,7 @@ enum compact_result {
 };
 
 struct alloc_context; /* in mm/internal.h */
+struct capture_control; /* in mm/internal.h */
 
 /*
  * Number of free order-0 pages that should be available above given watermark
@@ -92,7 +93,7 @@ extern int fragmentation_index(struct zo
 extern enum compact_result try_to_compact_pages(gfp_t gfp_mask,
 		unsigned int order, unsigned int alloc_flags,
 		const struct alloc_context *ac, enum compact_priority prio,
-		struct page **page);
+		struct capture_control *capc);
 extern void reset_isolation_suitable(pg_data_t *pgdat);
 extern bool compaction_suitable(struct zone *zone, int order,
 				unsigned long watermark, int highest_zoneidx);
mm/compaction.c +14 -36

82 lines not on this page · raw message

mm/internal.h +3 -1
@@ -1059,7 +1059,9 @@ struct compact_control {
  * immediately when one is created during the free path.
  */
 struct capture_control {
-	struct compact_control *cc;
+	struct zone *zone;
+	int migratetype;
+	int order;
 	struct page *page;
 };
 
mm/page_alloc.c +38 -7

78 lines not on this page · raw message

author maintainer
#79 lore raw

PATCH 79/713 mm: page_alloc: fix non-movable reclaim storm in defrag_mode

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johannes Weiner <[email protected]>

commit 7e8756d7ad22655b935c384f123071aa9de07a27 upstream.

As we deployed defrag_mode into Meta production, pressure spikes and excessive swapping were observed on some workloads. Tracing confirmed that this is unmovable/reclaimable requests spinning in the allocator and direct reclaim, causing excessive amounts of swap.

The initial plan for defrag_mode was to rely on kswapd/kcompactd to produce blocks, and if those are overwhelmed under high pressure, let the allocator fall back (__rmqueue_steal()) after its retry loops. However, that retrying results in more reclaim on some of these workloads than we'd hoped, sometimes excessively so, spurred on by the !costly order conditions in should_reclaim_retry().

The storms are dependent on the request type. Reclaim will inevitably make room in existing movable blocks, since that's where the LRU pages live. So if movable requests retry on reclaim, they make progress.

When non-movable requests spin in reclaim that isn't productive. They cannot use the individually freed pages, and the process is unlikely to accidentally free whole blocks to meet the ALLOC_NOFRAGMENT bar. They spin and overreclaim excessively, which tanks performance and triggers userspace guards like swap exhaustion or pressure based OOM.

To fix this, send non-movable requests, regardless of order, into pageblock reclaim/compaction. This way, they help move things along to meet the ALLOC_NOFRAGMENT bar. After this patch, the reclaim storms and excess OOM rates are no longer observed in production.

The longer-term plan is still to have all requests, including the movable ones, help make blocks to spread the cost of defragmenting more evenly and fairly; combined with proper watermarking to reduce allocation latencies in the common case. However, doing this naively unearths scaling and concurrency limitations in compaction that need to be addressed first. Promoting just non-movables for now is the minimally viable bug fix for the above issue.

[[email protected]: fix try_to_compact_pages() kerneldoc]
Fixes e3aa7df331bc ("mm: page_alloc: defrag_mode")
Cc Brendan Jackman <[email protected]>
Cc David Hildenbrand <[email protected]>
Cc Gregory Price <[email protected]>
Cc Liam R. Howlett <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Mike Rapoport <[email protected]>
Cc Shakeel Butt <[email protected]>
Cc Suren Baghdasaryan <[email protected]>
Cc Zi Yan <[email protected]>
---
 mm/compaction.c |    2 +-
 mm/internal.h   |    6 ++++++
 mm/page_alloc.c |   31 ++++++++++++++++++++++++++-----
 3 files changed, 33 insertions(+), 6 deletions(-)
mm/compaction.c +1 -1
@@ -2825,7 +2825,7 @@ static enum compact_result compact_zone_
 /**
  * try_to_compact_pages - Direct compact to satisfy a high-order allocation
  * @gfp_mask: The GFP mask of the current allocation
- * @order: The order of the current allocation
+ * @order: The order to try to make available
  * @alloc_flags: The allocation flags of the current allocation
  * @ac: The context of current allocation
  * @prio: Determines how hard direct compaction should try to succeed
mm/internal.h +6 -0
@@ -1061,6 +1061,12 @@ struct compact_control {
 struct capture_control {
 	struct zone *zone;
 	int migratetype;
+	/*
+	 * Allocation request order. May differ from the compaction
+	 * order: defrag_mode promotes sub-block allocations to
+	 * pageblock-order compaction; capture still matches at the
+	 * original allocation order so prep_new_page() is consistent.
+	 */
 	int order;
 	struct page *page;
 };
mm/page_alloc.c +26 -5
@@ -4152,8 +4152,24 @@ __alloc_pages_direct_compact(gfp_t gfp_m
 		.order = order,
 		.page = NULL,
 	};
+	int compact_order = order;
 
-	if (!order)
+	/*
+	 * If fallbacks are not permitted (defrag_mode), we either
+	 * need to reclaim space in a block of matching type, or clear
+	 * out an entire block to allow __rmqueue_claim() to convert.
+	 *
+	 * Reclaim by itself is primarily freeing space in movable
+	 * blocks, since that's where the LRU pages live. So this
+	 * works for movable requests, but not for others.
+	 *
+	 * For those, promote the order to help make blocks, instead
+	 * of spinning in reclaim alone unproductively.
+	 */
+	if ((alloc_flags & ALLOC_NOFRAGMENT) && ac->migratetype != MIGRATE_MOVABLE)
+		compact_order = max(order, pageblock_order);
+
+	if (!compact_order)
 		return NULL;
 
 	psi_memstall_enter(&pflags);
@@ -4169,8 +4185,8 @@ __alloc_pages_direct_compact(gfp_t gfp_m
 	barrier();
 	WRITE_ONCE(current->capture_control, &capc);
 
-	*compact_result = try_to_compact_pages(gfp_mask, order, alloc_flags, ac,
-							       prio, &capc);
+	*compact_result = try_to_compact_pages(gfp_mask, compact_order,
+					       alloc_flags, ac, prio, &capc);
 
 	/*
 	 * Make sure we hide capture control first before we read the captured
@@ -4215,7 +4231,7 @@ __alloc_pages_direct_compact(gfp_t gfp_m
 		struct zone *zone = page_zone(page);
 
 		zone->compact_blockskip_flush = false;
-		compaction_defer_reset(zone, order, true);
+		compaction_defer_reset(zone, compact_order, true);
 		count_vm_event(COMPACTSUCCESS);
 		return page;
 	}
@@ -4455,9 +4471,14 @@ __alloc_pages_direct_reclaim(gfp_t gfp_m
 	struct page *page = NULL;
 	unsigned long pflags;
 	bool drained = false;
+	int reclaim_order = order;
+
+	/* Match the slowpath compaction promotion in __alloc_pages_direct_compact */
+	if ((alloc_flags & ALLOC_NOFRAGMENT) && ac->migratetype != MIGRATE_MOVABLE)
+		reclaim_order = max(order, pageblock_order);
 
 	psi_memstall_enter(&pflags);
-	*did_some_progress = __perform_reclaim(gfp_mask, order, ac);
+	*did_some_progress = __perform_reclaim(gfp_mask, reclaim_order, ac);
 	if (unlikely(!(*did_some_progress)))
 		goto out;
 
author maintainer
#80 lore raw

PATCH 80/713 mm: vmscan: fix node reclaim ignoring swappiness parameter

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ridong Chen <[email protected]>

commit 8a905195850d383c0465ab5bdd3c91d94269b242 upstream.

sc_swappiness() had two separate definitions depending on CONFIG_MEMCG. The !CONFIG_MEMCG variant simply returned vm_swappiness, ignoring the proactive_swappiness value passed through scan_control. This caused the swappiness parameter written to /sys/devices/system/node/nodeX/reclaim to have no effect when CONFIG_MEMCG is disabled.

Fix this by consolidating sc_swappiness() into a single definition that checks sc->proactive_swappiness first, then falls back to mem_cgroup_swappiness() which already handles both CONFIG_MEMCG and !CONFIG_MEMCG.

Before fix (swappiness=max ignored, mostly file pages reclaimed):

    # cat /proc/sys/vm/swappiness
    60
    # cat /proc/vmstat | grep pgsteal
    pgsteal_kswapd 0
    pgsteal_direct 0
    pgsteal_khugepaged 0
    pgsteal_proactive 1840
    pgsteal_anon 25
    pgsteal_file 1815
    # echo "64M swappiness=max" > /sys/devices/system/node/node0/reclaim
    # cat /proc/vmstat | grep pgsteal
    pgsteal_kswapd 0
    pgsteal_direct 0
    pgsteal_khugepaged 0
    pgsteal_proactive 18013
    pgsteal_anon 337
    pgsteal_file 17676

After fix (swappiness=max honored, anon pages reclaimed as expected):

    # cat /proc/vmstat | grep pgsteal
    pgsteal_kswapd 0
    pgsteal_direct 0
    pgsteal_khugepaged 0
    pgsteal_proactive 0
    pgsteal_anon 0
    pgsteal_file 0
    # echo "64M swappiness=max" > /sys/devices/system/node/node0/reclaim
    # cat /proc/vmstat | grep pgsteal
    pgsteal_kswapd 0
    pgsteal_direct 0
    pgsteal_khugepaged 0
    pgsteal_proactive 16283
    pgsteal_anon 16283
    pgsteal_file 0
Fixes b980077899ea ("mm: introduce per-node proactive reclaim interface")
Cc Axel Rasmussen <[email protected]>
Cc Baoquan He <[email protected]>
Cc Chris Li <[email protected]>
Cc David Hildenbrand <[email protected]>
Cc Davidlohr Bueso <[email protected]>
Cc Kairui Song <[email protected]>
Cc Kemeng Shi <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Muchun Song <[email protected]>
Cc Nhat Pham <[email protected]>
Cc Roman Gushchin <[email protected]>
Cc Wei Xu <[email protected]>
Cc Yuanchu Xie <[email protected]>
Cc <[email protected]> [6.17+]
---
 mm/vmscan.c |   19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)
mm/vmscan.c +7 -12
@@ -198,6 +198,13 @@ struct scan_control {
  */
 int vm_swappiness = 60;
 
+static int sc_swappiness(struct scan_control *sc, struct mem_cgroup *memcg)
+{
+	if (sc->proactive && sc->proactive_swappiness)
+		return *sc->proactive_swappiness;
+	return mem_cgroup_swappiness(memcg);
+}
+
 #ifdef CONFIG_MEMCG
 
 /* Returns true for reclaim through cgroup limits or cgroup interfaces. */
@@ -238,13 +245,6 @@ static bool writeback_throttling_sane(st
 #endif
 	return false;
 }
-
-static int sc_swappiness(struct scan_control *sc, struct mem_cgroup *memcg)
-{
-	if (sc->proactive && sc->proactive_swappiness)
-		return *sc->proactive_swappiness;
-	return mem_cgroup_swappiness(memcg);
-}
 #else
 static bool cgroup_reclaim(struct scan_control *sc)
 {
@@ -260,11 +260,6 @@ static bool writeback_throttling_sane(st
 {
 	return true;
 }
-
-static int sc_swappiness(struct scan_control *sc, struct mem_cgroup *memcg)
-{
-	return READ_ONCE(vm_swappiness);
-}
 #endif
 
 static void set_task_reclaim_state(struct task_struct *task,
author maintainer
#81 lore raw

PATCH 81/713 tools/compiler: match glibc 2.42 definition of __attribute_const__

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Joy H.J. Lee <[email protected]>

commit 8700a4761beb219873956666cf91776a2c61e698 upstream.

glibc 2.42 added __attribute_const__ to sys/cdefs.h:

    # define __attribute_const__ __attribute__ ((__const__))

GCC 15 warns when a macro is redefined to a different replacement list (-Wbuiltin-macro-redefined). Since host tool Makefiles (resolve_btfids, objtool) pass -Werror, this conflict becomes fatal.

The warning is suppressed on standard native builds because GCC treats /usr/include as a system header path (-isystem), and macro-redefinition warnings from system headers are silently suppressed by GCC. It fires when glibc headers are on a regular include path (-I) instead, which is the case in cross-compilation setups such as NixOS, where the sysroot's glibc is passed explicitly via -I rather than -isystem.

Per (C11 6.10.3), identical replacement lists are accepted silently. Match the glibc definition exactly, including the space before "((", so the redefinition is accepted without warning regardless of whether glibc headers are treated as system or non-system includes.

---
 tools/include/linux/compiler.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
tools/include/linux/compiler.h +1 -1
@@ -119,7 +119,7 @@
 #define __read_mostly
 
 #ifndef __attribute_const__
-# define __attribute_const__
+# define __attribute_const__ __attribute__ ((__const__))
 #endif
 
 #ifndef __maybe_unused
author maintainer
#82 lore raw

PATCH 82/713 x86/locking: Use sfence for wmb() if SSE is available

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Yao Zi <[email protected]>

commit d824ed1307680dd482f607b0e707c575f70668c4 upstream.

When adding cc clobber to wmb()'s definition, the alternative() condition to use sfence was incorrectly raised from X86_FEATURE_XMM to X86_FEATURE_XMM2.

Restore the correct constraint for potential better performance on machines without SSE2.

---
 arch/x86/include/asm/barrier.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/include/asm/barrier.h +1 -1
@@ -17,7 +17,7 @@
 #define rmb() asm volatile(ALTERNATIVE("lock addl $0,-4(%%esp)", "lfence", \
 				       X86_FEATURE_XMM2) ::: "memory", "cc")
 #define wmb() asm volatile(ALTERNATIVE("lock addl $0,-4(%%esp)", "sfence", \
-				       X86_FEATURE_XMM2) ::: "memory", "cc")
+				       X86_FEATURE_XMM) ::: "memory", "cc")
 #else
 #define __mb()	asm volatile("mfence":::"memory")
 #define __rmb()	asm volatile("lfence":::"memory")
author maintainer
#83 lore raw

PATCH 83/713 x86/insn-eval: Move assign_register() out of KVM as insn_assign_reg()

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Kiryl Shutsemau (Meta) <[email protected]>

commit 1fe104b048d77d6cb25bd938e6a67450fb50e61d upstream.

KVM's instruction emulator has a small helper, assign_register(), that writes a value into a register following the x86 rules for writes to general-purpose registers: an 8- or 16-bit write leaves the rest of the register untouched, a 32-bit write zero-extends the result to 64 bits, and a 64-bit write replaces the whole register.

The TDX guest #VE handler needs the same logic for port I/O emulation to get 32-bit zero-extension right. Rather than add a third copy of the same switch, move the helper verbatim to <asm/insn-eval.h>, rename it to insn_assign_reg(), and route KVM's callers through it.

Add <asm/insn.h> to the header's includes so it builds standalone in callers that have not pulled it in transitively.

No functional change.

---
 arch/x86/include/asm/insn-eval.h |   36 ++++++++++++++++++++++++++++++++++++
 arch/x86/kvm/emulate.c           |   26 ++++----------------------
 2 files changed, 40 insertions(+), 22 deletions(-)
arch/x86/include/asm/insn-eval.h +36 -0
@@ -9,6 +9,7 @@
 #include <linux/compiler.h>
 #include <linux/bug.h>
 #include <linux/err.h>
+#include <asm/insn.h>
 #include <asm/ptrace.h>
 
 #define INSN_CODE_SEG_ADDR_SZ(params) ((params >> 4) & 0xf)
@@ -46,4 +47,39 @@ enum insn_mmio_type insn_decode_mmio(str
 
 bool insn_is_nop(struct insn *insn);
 
+/*
+ * Write @val into *@reg following the x86 rules for writes to
+ * general-purpose registers (Intel SDM Vol. 1, "General-Purpose
+ * Registers in 64-Bit Mode"): an 8- or 16-bit write leaves the rest of
+ * the register untouched, a 32-bit write zero-extends the result into
+ * the upper 32 bits, and a 64-bit write replaces the whole register.
+ *
+ * @bytes is the width of the write, not a property of the instruction:
+ * an instruction that, say, sign-extends a 32-bit immediate into a
+ * 64-bit register does a 64-bit write here.
+ *
+ * @reg need not be 8-byte aligned: KVM's instruction emulator offsets
+ * the pointer by one byte to address the high-byte registers (AH, CH,
+ * DH, BH).  Use narrow stores for the sub-word cases so the access
+ * width matches @bytes and the adjacent bytes are left alone.
+ */
+static inline void insn_assign_reg(unsigned long *reg, u64 val, int bytes)
+{
+	switch (bytes) {
+	case 1:
+		*(u8 *)reg = (u8)val;
+		break;
+	case 2:
+		*(u16 *)reg = (u16)val;
+		break;
+	case 4:
+		/* A 32-bit write zero-extends into the upper 32 bits. */
+		*reg = (u32)val;
+		break;
+	case 8:
+		*reg = val;
+		break;
+	}
+}
+
 #endif /* _ASM_X86_INSN_EVAL_H */
arch/x86/kvm/emulate.c +4 -22
@@ -24,6 +24,7 @@
 #include "kvm_emulate.h"
 #include <linux/stringify.h>
 #include <asm/debugreg.h>
+#include <asm/insn-eval.h>
 #include <asm/nospec-branch.h>
 #include <asm/ibt.h>
 #include <asm/text-patching.h>
@@ -439,25 +440,6 @@ static void assign_masked(ulong *dest, u
 	*dest = (*dest & ~mask) | (src & mask);
 }
 
-static void assign_register(unsigned long *reg, u64 val, int bytes)
-{
-	/* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */
-	switch (bytes) {
-	case 1:
-		*(u8 *)reg = (u8)val;
-		break;
-	case 2:
-		*(u16 *)reg = (u16)val;
-		break;
-	case 4:
-		*reg = (u32)val;
-		break;	/* 64b: zero-extend */
-	case 8:
-		*reg = val;
-		break;
-	}
-}
-
 static inline unsigned long ad_mask(struct x86_emulate_ctxt *ctxt)
 {
 	return (1UL << (ctxt->ad_bytes << 3)) - 1;
@@ -505,7 +487,7 @@ register_address_increment(struct x86_em
 {
 	ulong *preg = reg_rmw(ctxt, reg);
 
-	assign_register(preg, *preg + inc, ctxt->ad_bytes);
+	insn_assign_reg(preg, *preg + inc, ctxt->ad_bytes);
 }
 
 static void rsp_increment(struct x86_emulate_ctxt *ctxt, int inc)
@@ -1767,7 +1749,7 @@ static int load_segment_descriptor(struc
 
 static void write_register_operand(struct operand *op)
 {
-	return assign_register(op->addr.reg, op->val, op->bytes);
+	return insn_assign_reg(op->addr.reg, op->val, op->bytes);
 }
 
 static int writeback(struct x86_emulate_ctxt *ctxt, struct operand *op)
@@ -2008,7 +1990,7 @@ static int em_popa(struct x86_emulate_ct
 		rc = emulate_pop(ctxt, &val, ctxt->op_bytes);
 		if (rc != X86EMUL_CONTINUE)
 			break;
-		assign_register(reg_rmw(ctxt, reg), val, ctxt->op_bytes);
+		insn_assign_reg(reg_rmw(ctxt, reg), val, ctxt->op_bytes);
 		--reg;
 	}
 	return rc;
author maintainer
#84 lore raw

PATCH 84/713 x86/tdx: Fix off-by-one in port I/O handling

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Kiryl Shutsemau (Meta) <[email protected]>

commit 0f63e656b1c679d32ac595de29d10c03efca6a25 upstream.

handle_in() and handle_out() in arch/x86/coco/tdx/tdx.c use:

    u64 mask = GENMASK(BITS_PER_BYTE * size, 0);

GENMASK(h, l) includes bit h. For size=1 (INB), this produces GENMASK(8, 0) = 0x1FF (9 bits) instead of GENMASK(7, 0) = 0xFF (8 bits). The mask is one bit too wide for all I/O sizes.

Fix the mask calculation.

---
 arch/x86/coco/tdx/tdx.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/coco/tdx/tdx.c +2 -2
@@ -694,7 +694,7 @@ static bool handle_in(struct pt_regs *re
 		.r13 = PORT_READ,
 		.r14 = port,
 	};
-	u64 mask = GENMASK(BITS_PER_BYTE * size, 0);
+	u64 mask = GENMASK(BITS_PER_BYTE * size - 1, 0);
 	bool success;
 
 	/*
@@ -714,7 +714,7 @@ static bool handle_in(struct pt_regs *re
 
 static bool handle_out(struct pt_regs *regs, int size, int port)
 {
-	u64 mask = GENMASK(BITS_PER_BYTE * size, 0);
+	u64 mask = GENMASK(BITS_PER_BYTE * size - 1, 0);
 
 	/*
 	 * Emulate the I/O write via hypercall. More info about ABI can be found
author maintainer
#85 lore raw

PATCH 85/713 x86/tdx: Fix zero-extension for 32-bit port I/O

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Kiryl Shutsemau (Meta) <[email protected]>

commit 941370fc93cc3474e26811f4d3b062903eefe2cf upstream.

According to x86 architecture rules, 32-bit operations zero-extend the result to 64 bits. The current implementation of handle_in() only masks the lower 32 bits, which preserves the upper 32 bits of RAX when a 32-bit port IN instruction is emulated.

Use insn_assign_reg() to write the result back into RAX with proper partial-register-write semantics: 1- and 2-byte forms leave the upper bits untouched, the 4-byte form zero-extends to the full register.

---
 arch/x86/coco/tdx/tdx.c |    8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)
arch/x86/coco/tdx/tdx.c +3 -5
@@ -694,8 +694,8 @@ static bool handle_in(struct pt_regs *re
 		.r13 = PORT_READ,
 		.r14 = port,
 	};
-	u64 mask = GENMASK(BITS_PER_BYTE * size - 1, 0);
 	bool success;
+	u64 val;
 
 	/*
 	 * Emulate the I/O read via hypercall. More info about ABI can be found
@@ -703,11 +703,9 @@ static bool handle_in(struct pt_regs *re
 	 * "TDG.VP.VMCALL<Instruction.IO>".
 	 */
 	success = !__tdx_hypercall(&args);
+	val = success ? args.r11 : 0;
 
-	/* Update part of the register affected by the emulated instruction */
-	regs->ax &= ~mask;
-	if (success)
-		regs->ax |= args.r11 & mask;
+	insn_assign_reg(&regs->ax, val, size);
 
 	return success;
 }
author maintainer
#86 lore raw

PATCH 86/713 x86/xen: fix init of balloon stats again

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Roger Pau Monne <[email protected]>

commit 5d00a11d484e7b31a358cd81afebccb4602dbe8c upstream.

The handling of extra memory regions done in balloon_add_regions() is not correct for PV guests, since the initial target is set to reflect the real memory the system has, not what's described on the memory map, which can be higher if memory != maxmem.

Introduce separate logic for addition vs subtraction in balloon_add_regions() and handle extra regions correctly by adding them to the total amount of pages, instead of subtracting from the current and target pages amounts.

In the common case PV domU/dom0 and PVH dom0 will use the addition path, since the initial target reflects the real assigned memory. HVM and PVH domUs use the subtraction path, since the target is set based on the amount of memory reported in the memory map, without accounting for released regions.

Fixes 87af633689ce ("x86/xen: fix balloon target initialization for PVH dom0")
Fixes 0949c646d646 ("Partial revert "x86/xen: fix balloon target initialization for PVH dom0"")

Message-ID: <[email protected]>

---
 drivers/xen/balloon.c |   29 +++++++++++++++++++----------
 1 file changed, 19 insertions(+), 10 deletions(-)
drivers/xen/balloon.c +19 -10
@@ -679,7 +679,7 @@ void xen_free_ballooned_pages(unsigned i
 }
 EXPORT_SYMBOL(xen_free_ballooned_pages);
 
-static int __init balloon_add_regions(void)
+static int __init balloon_add_regions(bool append)
 {
 	unsigned long start_pfn, pages;
 	unsigned long pfn, extra_pfn_end;
@@ -703,19 +703,26 @@ static int __init balloon_add_regions(vo
 			balloon_append(pfn_to_page(pfn));
 
 		/*
-		 * Extra regions are accounted for in the physmap, but need
-		 * decreasing from current_pages and target_pages to balloon
-		 * down the initial allocation, because they are already
-		 * accounted for in total_pages.
+		 * There are two different use-cases depending on how the
+		 * initial memory target is fetched.  For PVH dom0 and PV the
+		 * target is usually set to reflect the domain assigned memory,
+		 * and hence extra regions need adding.
+		 *
+		 * OTOH for HVM and PVH domU the target is set to the amount of
+		 * RAM reported in the memory map, and hence extra regions need
+		 * subtracting to reflect the real memory usage.
 		 */
 		pages = extra_pfn_end - start_pfn;
-		if (pages >= balloon_stats.current_pages ||
-		    pages >= balloon_stats.target_pages) {
+		if (append) {
+			balloon_stats.total_pages += pages;
+		} else if (pages >= balloon_stats.current_pages ||
+		           pages >= balloon_stats.target_pages) {
 			WARN(1, "Extra pages underflow current target");
 			return -ERANGE;
+		} else {
+			balloon_stats.current_pages -= pages;
+			balloon_stats.target_pages -= pages;
 		}
-		balloon_stats.current_pages -= pages;
-		balloon_stats.target_pages -= pages;
 	}
 
 	return 0;
@@ -726,6 +733,7 @@ static int __init balloon_init(void)
 	struct task_struct *task;
 	long current_pages = 0;
 	domid_t domid = DOMID_SELF;
+	bool append = true;
 	int rc;
 
 	if (!xen_domain())
@@ -745,6 +753,7 @@ static int __init balloon_init(void)
 		} else {
 			if (xen_unpopulated_pages >= get_num_physpages())
 				goto underflow;
+			append = false;
 			current_pages = get_num_physpages() -
 			                xen_unpopulated_pages;
 		}
@@ -767,7 +776,7 @@ static int __init balloon_init(void)
 	register_sysctl_init("xen/balloon", balloon_table);
 #endif
 
-	rc = balloon_add_regions();
+	rc = balloon_add_regions(append);
 	if (rc)
 		return rc;
 
author maintainer
#87 lore raw

PATCH 87/713 hwtracing: hisi_ptt: Propagate DMA reset timeout in trace_start()

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sanman Pradhan <[email protected]>

commit 75d42d990335322852ed5f7ce324b701c0949d79 upstream.

hisi_ptt_wait_dma_reset_done() discards the return value of readl_poll_timeout_atomic(). If the DMA engine does not complete its reset within the timeout, hisi_ptt_trace_start() proceeds to start tracing regardless.

Return a bool from hisi_ptt_wait_dma_reset_done(), consistent with the other wait helpers in this driver. On timeout, log an error, de-assert the reset bit, and return -ETIMEDOUT. Move ctrl->started to the successful path so a failed start does not leave the trace marked as active.

Fixes ff0de066b463 ("hwtracing: hisi_ptt: Add trace function support for HiSilicon PCIe Tune and Trace device")
---
 drivers/hwtracing/ptt/hisi_ptt.c |   20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)
drivers/hwtracing/ptt/hisi_ptt.c +13 -7
@@ -171,13 +171,13 @@ static bool hisi_ptt_wait_trace_hw_idle(
 					  HISI_PTT_WAIT_TRACE_TIMEOUT_US);
 }
 
-static void hisi_ptt_wait_dma_reset_done(struct hisi_ptt *hisi_ptt)
+static bool hisi_ptt_wait_dma_reset_done(struct hisi_ptt *hisi_ptt)
 {
 	u32 val;
 
-	readl_poll_timeout_atomic(hisi_ptt->iobase + HISI_PTT_TRACE_WR_STS,
-				  val, !val, HISI_PTT_RESET_POLL_INTERVAL_US,
-				  HISI_PTT_RESET_TIMEOUT_US);
+	return !readl_poll_timeout_atomic(hisi_ptt->iobase + HISI_PTT_TRACE_WR_STS,
+					  val, !val, HISI_PTT_RESET_POLL_INTERVAL_US,
+					  HISI_PTT_RESET_TIMEOUT_US);
 }
 
 static void hisi_ptt_trace_end(struct hisi_ptt *hisi_ptt)
@@ -202,14 +202,18 @@ static int hisi_ptt_trace_start(struct h
 		return -EBUSY;
 	}
 
-	ctrl->started = true;
-
 	/* Reset the DMA before start tracing */
 	val = readl(hisi_ptt->iobase + HISI_PTT_TRACE_CTRL);
 	val |= HISI_PTT_TRACE_CTRL_RST;
 	writel(val, hisi_ptt->iobase + HISI_PTT_TRACE_CTRL);
 
-	hisi_ptt_wait_dma_reset_done(hisi_ptt);
+	if (!hisi_ptt_wait_dma_reset_done(hisi_ptt)) {
+		pci_err(hisi_ptt->pdev, "timed out waiting for DMA reset\n");
+		val = readl(hisi_ptt->iobase + HISI_PTT_TRACE_CTRL);
+		val &= ~HISI_PTT_TRACE_CTRL_RST;
+		writel(val, hisi_ptt->iobase + HISI_PTT_TRACE_CTRL);
+		return -ETIMEDOUT;
+	}
 
 	val = readl(hisi_ptt->iobase + HISI_PTT_TRACE_CTRL);
 	val &= ~HISI_PTT_TRACE_CTRL_RST;
@@ -234,6 +238,8 @@ static int hisi_ptt_trace_start(struct h
 	if (!hisi_ptt->trace_ctrl.is_port)
 		val |= HISI_PTT_TRACE_CTRL_FILTER_MODE;
 
+	ctrl->started = true;
+
 	/* Start the Trace */
 	val |= HISI_PTT_TRACE_CTRL_EN;
 	writel(val, hisi_ptt->iobase + HISI_PTT_TRACE_CTRL);
author maintainer
#88 lore raw

PATCH 88/713 tracing/user_events: Clear copied tracing state before fork duplication

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jérémy Jean <[email protected]>

commit 390f6bd8583d177029d9df4bea6667509e55a765 upstream.

dup_task_struct() copies user_event_mm from the parent into the child, without grabbing a reference to it. user_event_mm_dup() should replace it, but it leaves that copied pointer unmodified if user_event_mm_alloc() fails.

When the child exits, user_event_mm_remove() decrements a reference the child never owned, which ultimately frees user_event_mm, while the parent still as a stale pointer to it. This creates a UAF, which KASAN reports as:

    BUG: KASAN: slab-use-after-free in
    current_user_event_mm+0x51/0x1d0 Write of size 4 at addr
    ffff888005010d30 by task init/44

    Call Trace:
     <TASK>
     kasan_report+0xce/0x100
     kasan_check_range+0x10f/0x1e0
     current_user_event_mm+0x51/0x1d0
     user_events_ioctl+0x82e/0x15c0
     __x64_sys_ioctl+0x139/0x1c0
     do_syscall_64+0xce/0x450
     entry_SYSCALL_64_after_hwframe+0x77/0x7f

    Allocated by task 44:
     __kasan_kmalloc+0x8f/0xa0
     __kmalloc_cache_noprof+0x180/0x3a0
     user_event_mm_alloc+0x3c/0x1f0
     current_user_event_mm+0x88/0x1d0

    Freed by task 42:
     __kasan_slab_free+0x43/0x70
     kfree+0x13a/0x390
     process_one_work+0x696/0xf90
     worker_thread+0x420/0xba0

The fix simply clears the copied pointer before any possible failure. In case of failure, the child then has nothing to free.

Fixes 7235759084a4 ("tracing/user_events: Use remote writes for event enablement")
Assisted-by Codex:gpt-5
---
 kernel/trace/trace_events_user.c |    3 +++
 1 file changed, 3 insertions(+)
kernel/trace/trace_events_user.c +3 -0
@@ -868,6 +868,9 @@ void user_event_mm_dup(struct task_struc
 	struct user_event_mm *mm = user_event_mm_alloc(t);
 	struct user_event_enabler *enabler;
 
+	/* On failure, do not free parent's copy */
+	t->user_event_mm = NULL;
+
 	if (!mm)
 		return;
 
author maintainer
#89 lore raw

PATCH 89/713 tracing: Fix crash passing ERR_PTR to kthread_stop()

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Hui Su <[email protected]>

commit 649bc7df3e5d7be6f7996a95084037dbf3cad1e5 upstream.

event_test_stuff() calls kthread_run() and unconditionally passes the returned task_struct pointer to kthread_stop(). kthread_run() returns an error pointer such as ERR_PTR(-ENOMEM) when kthread creation fails, for example under memory pressure during the boot-time event self-test. kthread_stop() then dereferences the invalid pointer, crashing the kernel.

Check the result of kthread_run() before passing it to kthread_stop(). Use WARN_ON() so that a failure to create the self-test thread does not go unnoticed, matching the ring-buffer self-test fix in commit 91542863abad ("ring-buffer: Fix crash passing ERR_PTR to kthread_stop()").

Fixes e6187007d6c3 ("tracing/events: add startup tests for events")
---
 kernel/trace/trace_events.c |    2 ++
 1 file changed, 2 insertions(+)
kernel/trace/trace_events.c +2 -0
@@ -4901,6 +4901,8 @@ static __init void event_test_stuff(void
 	struct task_struct *test_thread;
 
 	test_thread = kthread_run(event_test_thread, NULL, "test-events");
+	if (WARN_ON(IS_ERR(test_thread)))
+		return;
 	msleep(1);
 	kthread_stop(test_thread);
 }
author maintainer
#90 lore raw

PATCH 90/713 tracing: Fix logged instance name on creation failure

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Vincent Donnefort <[email protected]>

commit a9a01be2834a529cbd490ccbab02643f0c1735f2 upstream.

When boot instance creation fails, the kernel incorrectly logs "(null)" as the instance name because strsep() consumes curr_str entirely during parsing.

Print the properly parsed name variable instead. And while at it log the error code.

---
 kernel/trace/trace.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/trace/trace.c +2 -1
@@ -9726,7 +9726,8 @@ __init static void enable_instances(void
 
 		tr = trace_array_create_systems(name, NULL, addr, size);
 		if (IS_ERR(tr)) {
-			pr_warn("Tracing: Failed to create instance buffer %s\n", curr_str);
+			pr_warn("Tracing: Failed to create instance buffer '%s' (%ld)\n", name,
+				PTR_ERR(tr));
 			continue;
 		}
 
author maintainer
#91 lore raw

PATCH 91/713 tracing: Fix retry exhaustion in simple ring buffer reader swap

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ivan Immanuel Shaji <[email protected]>

commit e0d3aed7b12cf37b74c7cc5265073d0263b49cde upstream.

simple_ring_buffer_swap_reader_page() starts with retry set to 8 and post-decrements it only after a failed link replacement. On the final attempt, a successful replacement leaves retry at zero, while a failed replacement leaves it at -1.

The current !retry test reverses both outcomes. It returns an error after a successful final replacement, leaving the link update complete but the reader bookkeeping unfinished. After a failed final replacement, it falls through and updates the head and reader pointers as though the replacement succeeded, which can corrupt the ring.

Treat only a negative counter as exhaustion and return the documented -EBUSY error.

---
 kernel/trace/simple_ring_buffer.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/trace/simple_ring_buffer.c +2 -2
@@ -160,8 +160,8 @@ int simple_ring_buffer_swap_reader_page(
 		overrun = cpu_buffer->meta->overrun;
 	} while (!simple_bpage_unset_head_link(last, reader, SIMPLE_RB_LINK_NORMAL) && retry--);
 
-	if (!retry)
-		return -EINVAL;
+	if (retry < 0)
+		return -EBUSY;
 
 	cpu_buffer->head_page = simple_bpage_from_link(reader->link.next);
 	cpu_buffer->head_page->link.prev = &reader->link;
author maintainer
#92 lore raw

PATCH 92/713 tracing: Fix use-after-free in trace_pipe read on sub-buffer order change

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Deepanshu Kartikey <[email protected]>

commit 372f8534244d632ad5118e8a87a11291b01712d3 upstream.

Writing to buffer_subbuf_size_kb calls ring_buffer_subbuf_order_set(), which frees every sub-buffer of the ring buffer, including the reader page, and replaces them with newly allocated ones.

Readers of trace_pipe hold pointers into those pages. ring_buffer_peek() looks up an event under cpu_buffer->reader_lock but returns the event pointer after dropping the lock, and peek_next_entry() then calls ring_buffer_event_length() and ring_buffer_event_data() on it. If the sub-buffer order is changed in that window, the reader dereferences freed memory:

  BUG: KASAN: use-after-free in ring_buffer_peek+0x3e0/0x430
  Read of size 1 at addr ffff88802a4cf010 by task syz-executor989/6002

Freed by:

   free_buffer_page kernel/trace/ring_buffer.c:398 [inline]
   ring_buffer_subbuf_order_set+0x1325/0x18e0 kernel/trace/ring_buffer.c:7444
   buffer_subbuf_size_write+0x182/0x280 kernel/trace/trace.c:8221

Take trace_access_lock(RING_BUFFER_ALL_CPUS) around the order change. This is the lock trace_pipe readers already hold across their entire peek-and-print loop, so the swap can no longer race with a reader that is dereferencing a peeked event.

---
 kernel/trace/trace.c |    3 +++
 1 file changed, 3 insertions(+)
kernel/trace/trace.c +3 -0
@@ -8214,6 +8214,8 @@ buffer_subbuf_size_write(struct file *fi
 	/* Do not allow tracing while changing the order of the ring buffer */
 	tracing_stop_tr(tr);
 
+	trace_access_lock(RING_BUFFER_ALL_CPUS);
+
 	old_order = ring_buffer_subbuf_order_get(tr->array_buffer.buffer);
 	if (old_order == order)
 		goto out;
@@ -8253,6 +8255,7 @@ buffer_subbuf_size_write(struct file *fi
 #endif
 	(*ppos)++;
  out:
+	trace_access_unlock(RING_BUFFER_ALL_CPUS);
 	if (ret)
 		cnt = ret;
 	tracing_start_tr(tr);
author maintainer
#93 lore raw

PATCH 93/713 tracing: Fix use-after-free with same-name named triggers

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Hui Su <[email protected]>

commit a7318172aa332a161fb9618286e64454c827f8fd upstream.

When two hist triggers on different events are registered with the same name=, the second one reuses the first as named_data. Both are added to tr->hist_vars by save_hist_vars() during event_hist_trigger_parse(), because save_hist_vars() is called before event_trigger_register() while the named reuse is only detected later, in hist_register_trigger().

In the named-data branch hist_register_trigger() then frees the second histogram's hist_data via destroy_hist_data(), but never removes its tr->hist_vars list entry, leaving a dangling pointer and leaking the trace_array reference it holds.

A later hist trigger that references a variable makes find_var_file() walk tr->hist_vars and dereference the freed hist_data. The bug is reproducible from userspace by writing three hist triggers to tracefs:

cd /sys/kernel/tracing
echo 'hist:keys=common_pid:x=common_pid:name=mh' > events/sched/sched_switch/trigger echo 'hist:keys=common_pid:x=common_pid:name=mh' > events/sched/sched_process_fork/trigger echo 'hist:keys=common_pid:vals=$x' > events/sched/sched_process_exit/trigger

The third write panics the kernel:

  BUG: KASAN: slab-use-after-free in find_var_file.part.0+0x272/0x290
  Read of size 8 at addr ffff888001f8a0e0 by task sh/1
  CPU: 1 UID: 0 PID: 1 Comm: sh Tainted: G      D          N
  Call Trace:
    find_var_file.part.0
    find_event_var
    parse_atom
    parse_expr
    __create_val_field
    event_hist_trigger_parse
    trigger_process_regex
    event_trigger_write
    vfs_write
    ksys_write
    do_syscall_64
    entry_SYSCALL_64_after_hwframe
  Allocated by task 1:
    event_hist_trigger_parse
  Freed by task 1:
    hist_register_trigger+0x618/0xa30
    event_hist_trigger_parse
  The buggy address belongs to freed 2048-byte region
  Oops: general protection fault ... RIP: find_var_file.part.0
  Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b

Fix by removing the hist_data from tr->hist_vars and releasing the trace_array reference in the named-data branch of hist_register_trigger() before freeing the hist_data.

Fixes 6f86bdeab633 ("tracing: Fix bad hist from corrupting named_triggers list")
---
 kernel/trace/trace_events_hist.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
kernel/trace/trace_events_hist.c +3 -1
@@ -6641,8 +6641,10 @@ static int hist_register_trigger(char *g
 		tracing_set_filter_buffering(file->tr, true);
 	}
 
-	if (named_data)
+	if (named_data) {
+		remove_hist_vars(hist_data);
 		destroy_hist_data(hist_data);
+	}
  out:
 	return ret;
 }
author maintainer
#94 lore raw

PATCH 94/713 cdx: Fix double free when sysfs file creation fails

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Prasanna Kumar T S M <[email protected]>

commit 6f4acc3a3c300e174e3f586b97b04ed8f5948c36 upstream.

In cdx_create_res_attr(), if sysfs_create_bin_file() fails, the code frees res_attr but doesn't set cdx_dev->res_attr[num] to NULL. This leaves a dangling pointer in the array. Then cdx_destroy_res_attr() frees the already-freed memory. Fix the double free by initializing cdx_dev->res_attr[num] after sysfs_create_bin_file() completes.

---
 drivers/cdx/cdx.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/cdx/cdx.c +5 -2
@@ -738,7 +738,6 @@ static int cdx_create_res_attr(struct cd
 
 	sysfs_bin_attr_init(res_attr);
 
-	cdx_dev->res_attr[num] = res_attr;
 	sprintf(res_attr_name, "resource%d", num);
 
 	res_attr->mmap = cdx_mmap_resource;
@@ -747,8 +746,12 @@ static int cdx_create_res_attr(struct cd
 	res_attr->size = cdx_resource_len(cdx_dev, num);
 	res_attr->private = (void *)(unsigned long)num;
 	ret = sysfs_create_bin_file(&cdx_dev->dev.kobj, res_attr);
-	if (ret)
+	if (ret) {
 		kfree(res_attr);
+		return ret;
+	}
+
+	cdx_dev->res_attr[num] = res_attr;
 
 	return ret;
 }
author maintainer
#95 lore raw

PATCH 95/713 debugfs: Fix lockdown check for mmap_prepare

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Chun-Yi Lee <[email protected]>

commit f81808de37338aac8e167f99bfae647b1b835c70 upstream.

Commit 651fdda8406d ("relay: update relay to use mmap_prepare") changed the mmap file operation to mmap_prepare for relayfs, but the lockdown check in debugfs was not updated accordingly.

This prevents debugfs from being locked down when the kernel is in integrity mode if a file uses mmap_prepare but not mmap.

Since the conversion to mmap_prepare across the kernel is not yet complete, update the lockdown check to look for both mmap and mmap_prepare to ensure comprehensive coverage.

Fixes 651fdda8406d ("relay: update relay to use mmap_prepare")
Cc David Howells <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Andy Shevchenko <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
Cc Matthew Garrett <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Danilo Krummrich <[email protected]>
---
 fs/debugfs/file.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
fs/debugfs/file.c +2 -1
@@ -273,7 +273,8 @@ static int debugfs_locked_down(struct in
 	    (!real_fops ||
 	     (!real_fops->unlocked_ioctl &&
 	      !real_fops->compat_ioctl &&
-	      !real_fops->mmap)))
+	      !real_fops->mmap &&
+	      !real_fops->mmap_prepare)))
 		return 0;
 
 	if (security_locked_down(LOCKDOWN_DEBUGFS))
author maintainer
#96 lore raw

PATCH 96/713 device property: fix infinite loop in fwnode_for_each_child_node()

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Xu Yang <[email protected]>

commit 1900692555826753adab8799a1a8d50bb1ee200c upstream.

When iterate over children of a fwnode that has a secondary fwnode, fwnode_get_next_child_node() can enter an infinite loop if the secondary fwnode has more than one child.

                       Parent        Child
      (Primary fwnode)   FWa:   {FWa1, FWa2, FWa3}
    (Secondary fwnode)   FWb:   {FWb1, FWb2}

In this case:

 ┌─> fwnode_get_next_child_node(FWa, FWa1)
 │    - fwnode_call_ptr_op(FWa, get_next_child_node, FWa1) returns FWa2
 │
 │   ...
 │
 │   fwnode_get_next_child_node(FWa, FWa3)
 │    - fwnode_call_ptr_op(FWa, get_next_child_node, FWa3) returns NULL
 │    - fwnode_call_ptr_op(FWb, get_next_child_node, FWa3) returns FWb1
 │
 │   fwnode_get_next_child_node(FWa, FWb1)
 │    - fwnode_call_ptr_op(FWa, get_next_child_node, FWb1) returns FWa1
 └────┘

This cause fwnode_for_each_child_node() to loop indefinitely, reapeatedly output {FWa1, FWa2, FWa3, FWb1, FWa1, ...}.

The root cause is that when the current child (FWb1) belongs to the secondary fwnode, calling get_next_child_node() on the parimary fwnode incorrectly returns the first child (FWa1) again instead of NULL.

Fix this by dynamically checking the parent fwnode of the current child before calling get_next_child_node(). This approach follows the pattern established in commit b5b41ab6b0c1 ("device property: Check fwnode->secondary in fwnode_graph_get_next_endpoint()").

Fixes 2692c614f8f0 ("device property: Allow secondary lookup in fwnode_get_next_child_node()")
---
 drivers/base/property.c |   19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)
drivers/base/property.c +16 -3
@@ -807,18 +807,31 @@ struct fwnode_handle *
 fwnode_get_next_child_node(const struct fwnode_handle *fwnode,
 			   struct fwnode_handle *child)
 {
+	const struct fwnode_handle *parent;
+	struct fwnode_handle *child_parent __free(fwnode_handle) = NULL;
 	struct fwnode_handle *next;
 
-	if (IS_ERR_OR_NULL(fwnode))
+	/*
+	 * If this function is in a loop and the previous iteration returned
+	 * an child from fwnode->secondary, then we need to use the secondary
+	 * as parent rather than @fwnode.
+	 */
+	if (child) {
+		child_parent = fwnode_get_parent(child);
+		parent = child_parent;
+	} else {
+		parent = fwnode;
+	}
+	if (IS_ERR_OR_NULL(parent))
 		return NULL;
 
 	/* Try to find a child in primary fwnode */
-	next = fwnode_call_ptr_op(fwnode, get_next_child_node, child);
+	next = fwnode_call_ptr_op(parent, get_next_child_node, child);
 	if (next)
 		return next;
 
 	/* When no more children in primary, continue with secondary */
-	return fwnode_call_ptr_op(fwnode->secondary, get_next_child_node, child);
+	return fwnode_get_next_child_node(parent->secondary, NULL);
 }
 EXPORT_SYMBOL_GPL(fwnode_get_next_child_node);
 
author maintainer
#97 lore raw

PATCH 97/713 misc: nsm: bound the device-reported response length

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Bryam Vargas <[email protected]>

commit 808e530654a5354e6df78863a5d61e4d44e67235 upstream.

nsm_sendrecv_msg_locked() stores the virtqueue used-ring length reported by the NSM device into msg->resp.len without bounding it to the response buffer. A malicious or buggy backend can report a length larger than the response buffer; parse_resp_raw() then copies that many bytes out of the fixed buffer to user space, disclosing adjacent kernel heap (an out-of-bounds read). The request path already floors its length in fill_req_raw(); the response path lacks the symmetric check.

Clamp the stored length to the size of the response buffer. Well-behaved devices report no more than the posted buffer size, so conforming traffic is unaffected.

---
 drivers/misc/nsm.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/misc/nsm.c +1 -1
@@ -243,7 +243,7 @@ static int nsm_sendrecv_msg_locked(struc
 		goto cleanup;
 	}
 
-	msg->resp.len = len;
+	msg->resp.len = min_t(unsigned int, len, sizeof(msg->resp.data));
 
 	rc = 0;
 
author maintainer
#98 lore raw

PATCH 98/713 powerpc/powermac: fix OF node refcount

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Bartosz Golaszewski <[email protected]>

commit bd0abfe6b013aeb2a1aebc5fbc7ceeb50355bda3 upstream.

Platform devices created with platform_device_alloc() call platform_device_release() when the last reference to the device's kobject is dropped. This function calls of_node_put() unconditionally. This works fine for devices created with platform_device_register_full() but users of the split approach (platform_device_alloc() + platform_device_add()) must bump the reference of the of_node they assign manually. Add the missing call to of_node_get().

---
 arch/powerpc/platforms/powermac/low_i2c.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/platforms/powermac/low_i2c.c +1 -1
@@ -1471,7 +1471,7 @@ static int __init pmac_i2c_create_platfo
 		if (bus->platform_dev == NULL)
 			return -ENOMEM;
 		bus->platform_dev->dev.platform_data = bus;
-		bus->platform_dev->dev.of_node = bus->busnode;
+		bus->platform_dev->dev.of_node = of_node_get(bus->busnode);
 		platform_device_add(bus->platform_dev);
 	}
 
author maintainer
#99 lore raw

PATCH 99/713 rapidio: mport_cdev: fix use-after-free in dma_req_free()

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: James Kim <[email protected]>

commit 5cbef379a94b161726c5f504598bf4791d45cedc upstream.

dma_req_free() acquires buf_mutex through req->map, drops the mapping reference with kref_put(), and then dereferences req->map again to unlock the mutex.

If kref_put() drops the last reference, mport_release_mapping() frees the mapping, and the subsequent mutex_unlock() dereferences a freed object. This is a use-after-free.

Fix this by caching map and md before kref_put(), clearing req->map while holding buf_mutex, and using the cached md for mutex unlocking.

The bug is reachable from userspace via the RapidIO mport character device interface.

Fixes e8de370188d0 ("rapidio: add mport char device driver")
Cc Alexandre Bounine <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Matt Porter <[email protected]>
---
 drivers/rapidio/devices/rio_mport_cdev.c |   10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/rapidio/devices/rio_mport_cdev.c +7 -3
@@ -564,9 +564,13 @@ static void dma_req_free(struct kref *re
 	}
 
 	if (req->map) {
-		mutex_lock(&req->map->md->buf_mutex);
-		kref_put(&req->map->ref, mport_release_mapping);
-		mutex_unlock(&req->map->md->buf_mutex);
+		struct rio_mport_mapping *map = req->map;
+		struct mport_dev *md = map->md;
+
+		mutex_lock(&md->buf_mutex);
+		req->map = NULL;
+		kref_put(&map->ref, mport_release_mapping);
+		mutex_unlock(&md->buf_mutex);
 	}
 
 	kref_put(&priv->dma_ref, mport_release_dma);
author maintainer
#100 lore raw

PATCH 100/713 Revert "media: v4l2-dev: fix error handling in __video_register_device()"

In reply to Greg Kroah-Hartman

7.2-stable review patch. If anyone has any objections, please let me know.

------------------

From: Hans Verkuil <[email protected]>

commit e7600f5cee5de14065f950807931d6e6d40fb2d7 upstream.

This reverts commit 2a934fdb01db6458288fc9386d3d8ceba6dd551a.

The intentions of that patch were good, but it doesn't work.

The idea is that if device_register fails, you have to do a put_device to let the ref counter release resources.

However, the V4L2 API says that if video_register_device() fails, then you have to call video_device_release(), which kfree()s the video_device struct.

But the put_device() will already have freed the struct, so you end up in a double-free scenario.

There is not really a good way of fixing this without breaking video_register_device() into two parts, one that initializes everything, and one that does the actual device_register, and then converting all V4L2 drivers to this new model.

That is a massive job, and it is very unlikely that device_register will fail.

So rather than ending up in a double-free scenario, just revert this patch, and in that case we'll have a small memory leak. Which is a lot more robust.

---
 drivers/media/v4l2-core/v4l2-dev.c |   14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/media/v4l2-core/v4l2-dev.c +7 -7
@@ -1071,25 +1071,25 @@ int __video_register_device(struct video
 	vdev->dev.class = &video_class;
 	vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor);
 	vdev->dev.parent = vdev->dev_parent;
-	vdev->dev.release = v4l2_device_release;
 	dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num);
-
-	/* Increase v4l2_device refcount */
-	v4l2_device_get(vdev->v4l2_dev);
-
 	mutex_lock(&videodev_lock);
 	ret = device_register(&vdev->dev);
 	if (ret < 0) {
 		mutex_unlock(&videodev_lock);
 		pr_err("%s: device_register failed\n", __func__);
-		put_device(&vdev->dev);
-		return ret;
+		goto cleanup;
 	}
+	/* Register the release callback that will be called when the last
+	   reference to the device goes away. */
+	vdev->dev.release = v4l2_device_release;
 
 	if (nr != -1 && nr != vdev->num && warn_if_nr_in_use)
 		pr_warn("%s: requested %s%d, got %s\n", __func__,
 			name_base, nr, video_device_node_name(vdev));
 
+	/* Increase v4l2_device refcount */
+	v4l2_device_get(vdev->v4l2_dev);
+
 	/* Part 5: Register the entity. */
 	ret = video_register_media_controller(vdev);