6.12.55-rc1 review
Subsystems (2)
Greg Kroah-Hartman
maintainercover 6.12.55-rc1 review
This is the start of the stable review cycle for the 6.12.55 release. There are 136 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 Thu, 23 Oct 2025 19:49:51 +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/v6.x/stable-review/patch-6.12.55-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-6.12.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 6.12.55-rc1
Guenter Roeck <[email protected]>
dmaengine: Add missing cleanup on module unload
Mark Rutland <[email protected]>
arm64: errata: Apply workarounds for Neoverse-V3AE
Mark Rutland <[email protected]>
arm64: cputype: Add Neoverse-V3AE definitions
Jakub Acs <[email protected]>
mm/ksm: fix flag-dropping behavior in ksm_madvise
Chuck Lever <[email protected]>
NFSD: Define a proc_layoutcommit for the FlexFiles layout type
Devarsh Thakkar <[email protected]>
phy: cadence: cdns-dphy: Update calibration wait time for startup state machine
Matthieu Baerts (NGI0) <[email protected]>
mptcp: reset blackhole on success with non-loopback ifaces
Kuniyuki Iwashima <[email protected]>
mptcp: Use __sk_dst_get() and dst_dev_rcu() in mptcp_active_enable().
Kuniyuki Iwashima <[email protected]>
mptcp: Call dst_release() in mptcp_active_enable().
Sharath Chandra Vurukala <[email protected]>
net: Add locking to protect skb->dev access in ip_output
Eric Dumazet <[email protected]>
ipv4: adopt dst_dev, skb_dst_dev and skb_dst_dev_net[_rcu]
Eric Dumazet <[email protected]>
net: dst: add four helpers to annotate data-races around dst->dev
Eric Dumazet <[email protected]>
tcp: cache RTAX_QUICKACK metric in a hot cache line
Eric Dumazet <[email protected]>
tcp: convert to dev_net_rcu()
Jedrzej Jagielski <[email protected]>
ixgbevf: fix mailbox API compatibility by negotiating supported features
Jedrzej Jagielski <[email protected]>
ixgbevf: fix getting link speed data for E610 devices
Piotr Kwapulinski <[email protected]>
ixgbevf: Add support for Intel(R) E610 device
Piotr Kwapulinski <[email protected]>
PCI: Add PCI_VDEVICE_SUB helper macro
Jan Kara <[email protected]>
vfs: Don't leak disconnected dentries on umount
Al Viro <[email protected]>
d_alloc_parallel(): set DCACHE_PAR_LOOKUP earlier
Babu Moger <[email protected]>
x86/resctrl: Fix miscount of bandwidth event when reactivating previously unavailable RMID
Babu Moger <[email protected]>
x86/resctrl: Refactor resctrl_arch_rmid_read()
Yu Kuai <[email protected]>
md: fix mssing blktrace bio split events
John Garry <[email protected]>
md/raid10: Handle bio_split() errors
John Garry <[email protected]>
md/raid1: Handle bio_split() errors
John Garry <[email protected]>
md/raid0: Handle bio_split() errors
Xiao Liang <[email protected]>
padata: Reset next CPU when reorder sequence wraps around
Darrick J. Wong <[email protected]>
xfs: use deferred intent items for reaping crosslinked blocks
Fedor Pchelkin <[email protected]>
wifi: rtw89: avoid possible TX wait initialization race
Sergey Bashirov <[email protected]>
NFSD: Fix last write offset handling in layoutcommit
Sergey Bashirov <[email protected]>
NFSD: Implement large extent array support in pNFS
Sergey Bashirov <[email protected]>
NFSD: Minor cleanup in layoutcommit processing
Sergey Bashirov <[email protected]>
NFSD: Rework encoding and decoding of nfsd4_deviceid
Sergey Bashirov <[email protected]>
nfsd: Drop dprintk in blocklayout xdr functions
Sergey Bashirov <[email protected]>
nfsd: Use correct error code when decoding extents
Sean Nyekjaer <[email protected]>
iio: imu: inv_icm42600: Avoid configuring if already pm_runtime suspended
Sean Nyekjaer <[email protected]>
iio: imu: inv_icm42600: Simplify pm_runtime setup
Bence Csókás <[email protected]>
PM: runtime: Add new devm functions
Devarsh Thakkar <[email protected]>
phy: cadence: cdns-dphy: Fix PLL lock and O_CMN_READY polling
Tomi Valkeinen <[email protected]>
phy: cdns-dphy: Store hs_clk_rate and return it
Christoph Hellwig <[email protected]>
xfs: fix log CRC mismatches between i386 and other architectures
Christoph Hellwig <[email protected]>
xfs: rename the old_crc variable in xlog_recover_process
Viacheslav Dubeyko <[email protected]>
hfsplus: fix slab-out-of-bounds read in hfsplus_strcasecmp()
Wilfred Mallawa <[email protected]>
nvme/tcp: handle tls partially sent records in write_space()
Xing Guo <[email protected]>
selftests: arg_parsing: Ensure data is flushed to disk before reading.
Li Qiang <[email protected]>
ASoC: amd/sdw_utils: avoid NULL deref when devm_kasprintf() fails
Thadeu Lima de Souza Cascardo <[email protected]>
HID: multitouch: fix name of Stylus input devices
Dmitry Torokhov <[email protected]>
HID: hid-input: only ignore 0 battery events for digitizers
Jiaming Zhang <[email protected]>
ALSA: usb-audio: Fix NULL pointer deference in try_to_register_card
Andrii Nakryiko <[email protected]>
selftests/bpf: make arg_parsing.c more robust to crashes
Pranjal Ramajor Asha Kanojiya <[email protected]>
accel/qaic: Synchronize access to DBC request queue head & tail pointer
Youssef Samir <[email protected]>
accel/qaic: Treat remaining == 0 as error in find_and_map_user_pages()
Jeffrey Hugo <[email protected]>
accel/qaic: Fix bootlog initialization ordering
Randy Dunlap <[email protected]>
ALSA: firewire: amdtp-stream: fix enum kernel-doc warnings
Vincent Guittot <[email protected]>
sched/fair: Fix pelt lost idle time detection
Alok Tiwari <[email protected]>
drm/rockchip: vop2: use correct destination rectangle height check
Francesco Valla <[email protected]>
drm/draw: fix color truncation in drm_draw_fill24
Timur Kristóf <[email protected]>
drm/amd/powerplay: Fix CIK shutdown temperature
Alex Deucher <[email protected]>
drm/amdgpu: fix handling of harvesting for ip_discovery firmware
Alex Deucher <[email protected]>
drm/amdgpu: add support for cyan skillfish without IP discovery
Alex Deucher <[email protected]>
drm/amdgpu: add ip offset support for cyan skillfish
Zhanjun Dong <[email protected]>
drm/i915/guc: Skip communication warning on reset in progress
Cristian Ciocaltea <[email protected]>
ASoC: nau8821: Add DMI quirk to bypass jack debounce circuit
Cristian Ciocaltea <[email protected]>
ASoC: nau8821: Generalize helper to clear IRQ status
Cristian Ciocaltea <[email protected]>
ASoC: nau8821: Cancel jdet_work before handling jack ejection
Christophe Leroy <[email protected]>
ASoC: codecs: Fix gain setting ranges for Renesas IDT821034 codec
Marek Vasut <[email protected]>
drm/bridge: lt9211: Drop check for last nibble of version register
Fabian Vogt <[email protected]>
riscv: kprobes: Fix probe address validation
Amit Chaudhary <[email protected]>
nvme-multipath: Skip nr_active increments in RETRY disposition
Ketil Johnsen <[email protected]>
drm/panthor: Ensure MCU is disabled on suspend
I Viswanath <[email protected]>
net: usb: lan78xx: fix use of improperly initialized dev->chipid in lan78xx_reset
Oleksij Rempel <[email protected]>
net: usb: lan78xx: Add error handling to lan78xx_init_mac_address
Breno Leitao <[email protected]>
netdevsim: set the carrier when the device goes up
Sabrina Dubroca <[email protected]>
tls: don't rely on tx_work during send()
Sabrina Dubroca <[email protected]>
tls: wait for pending async decryptions if tls_strp_msg_hold fails
Sabrina Dubroca <[email protected]>
tls: always set record_type in tls_process_cmsg
Sabrina Dubroca <[email protected]>
tls: wait for async encrypt in case of error during latter iterations of sendmsg
Sabrina Dubroca <[email protected]>
tls: trim encrypted message to match the plaintext on short splice
Alexey Simakov <[email protected]>
tg3: prevent use of uninitialized remote_adv and local_adv variables
Marios Makassikis <[email protected]>
ksmbd: fix recursive locking in RPC handle list access
Eric Dumazet <[email protected]>
tcp: fix tcp_tso_should_defer() vs large RTT
Raju Rangoju <[email protected]>
amd-xgbe: Avoid spurious link down messages during interface toggle
Dmitry Safonov <[email protected]>
net/ip6_tunnel: Prevent perpetual tunnel growth
Linmao Li <[email protected]>
r8169: fix packet truncation after S4 resume on RTL8168H/RTL8111H
Nicolas Dichtel <[email protected]>
doc: fix seg6_flowlabel path
Yeounsu Moon <[email protected]>
net: dlink: handle dma_map_single() failure properly
Marc Kleine-Budde <[email protected]>
can: m_can: fix CAN state in system PM
Sean Nyekjaer <[email protected]>
can: m_can: call deinit/init callback when going into suspend/resume
Sean Nyekjaer <[email protected]>
can: m_can: add deinit callback
Marc Kleine-Budde <[email protected]>
can: m_can: m_can_chip_config(): bring up interface in correct state
Marc Kleine-Budde <[email protected]>
can: m_can: m_can_handle_state_errors(): fix CAN state transition to Error Active
Marc Kleine-Budde <[email protected]>
can: m_can: m_can_plat_remove(): add missing pm_runtime_disable()
Yuezhang Mo <[email protected]>
dax: skip read lock assertion for read-only filesystems
Benjamin Tissoires <[email protected]>
HID: multitouch: fix sticky fingers
Jens Axboe <[email protected]>
Revert "io_uring/rw: drop -EOPNOTSUPP check in __io_complete_rw_common()"
Rafael J. Wysocki <[email protected]>
cpufreq: CPPC: Avoid using CPUFREQ_ETERNAL as transition delay
Kuen-Han Tsai <[email protected]>
usb: gadget: f_rndis: Refactor bind path to use __free()
Kuen-Han Tsai <[email protected]>
usb: gadget: f_ecm: Refactor bind path to use __free()
Kuen-Han Tsai <[email protected]>
usb: gadget: f_acm: Refactor bind path to use __free()
Kuen-Han Tsai <[email protected]>
usb: gadget: f_ncm: Refactor bind path to use __free()
Kuen-Han Tsai <[email protected]>
usb: gadget: Introduce free_usb_request helper
Kuen-Han Tsai <[email protected]>
usb: gadget: Store endpoint pointer in usb_request
Kaustabh Chakraborty <[email protected]>
drm/exynos: exynos7_drm_decon: remove ctx->suspended
Kaustabh Chakraborty <[email protected]>
drm/exynos: exynos7_drm_decon: properly clear channels during bind
Kaustabh Chakraborty <[email protected]>
drm/exynos: exynos7_drm_decon: fix uninitialized crtc reference in functions
Guoniu Zhou <[email protected]>
media: nxp: imx8-isi: m2m: Fix streaming cleanup on release
Laurent Pinchart <[email protected]>
media: nxp: imx8-isi: Drop unused argument to mxc_isi_channel_chain()
Akhil P Oommen <[email protected]>
drm/msm/a6xx: Fix PDC sleep sequence
Miaoqian Lin <[email protected]>
cdx: Fix device node reference leak in cdx_msi_domain_init
Jiri Slaby (SUSE) <[email protected]>
irqdomain: cdx: Switch to of_fwnode_handle()
Mario Limonciello <[email protected]>
drm/amd: Check whether secure display TA loaded successfully
Adrian Hunter <[email protected]>
perf/core: Fix MMAP2 event device with backing files
Adrian Hunter <[email protected]>
perf/core: Fix MMAP event path names with backing files
Adrian Hunter <[email protected]>
perf/core: Fix address filter match with backing files
Jonathan Kim <[email protected]>
drm/amdgpu: fix gfx12 mes packet status return check
Gui-Dong Han <[email protected]>
drm/amdgpu: use atomic functions with memory barriers for vm fault info
Thomas Zimmermann <[email protected]>
drm/ast: Blank with VGACR17 sync enable, always clear VGACRB6 sync off
Tvrtko Ursulin <[email protected]>
drm/sched: Fix potential double free in drm_sched_job_add_resv_dependencies
Eugene Korenevsky <[email protected]>
cifs: parse_dfs_referrals: prevent oob on malformed input
Celeste Liu <[email protected]>
can: gs_usb: increase max interface to U8_MAX
Celeste Liu <[email protected]>
can: gs_usb: gs_make_candev(): populate net_device->dev_port
Filipe Manana <[email protected]>
btrfs: do not assert we found block group item when creating free space tree
Miquel Sabaté Solà <[email protected]>
btrfs: fix memory leaks when rejecting a non SINGLE data profile without an RST
Boris Burkov <[email protected]>
btrfs: fix incorrect readahead expansion length
Miquel Sabaté Solà <[email protected]>
btrfs: fix memory leak on duplicated memory in the qgroup assign ioctl
Filipe Manana <[email protected]>
btrfs: fix clearing of BTRFS_FS_RELOC_RUNNING if relocation already running
Deepanshu Kartikey <[email protected]>
ext4: detect invalid INLINE_DATA + EXTENTS flag combination
Zhang Yi <[email protected]>
ext4: wait for ongoing I/O to complete before freeing blocks
Zhang Yi <[email protected]>
jbd2: ensure that all ongoing I/O complete before freeing blocks
Jaegeuk Kim <[email protected]>
f2fs: fix wrong block mapping for multi-devices
Oliver Upton <[email protected]>
KVM: arm64: Prevent access to vCPU events before init
Yi Cong <[email protected]>
r8152: add error handling in rtl8152_driver_init
Hao Ge <[email protected]>
slab: reset slab->obj_ext when freeing and it is OBJEXTS_ALLOC_FAIL
Shuhao Fu <[email protected]>
smb: client: Fix refcount leak for cifs_sb_tlink
Conor Dooley <[email protected]>
rust: cfi: only 64-bit arm and x86 support CFI_CLANG
Shuicheng Lin <[email protected]>
drm/xe/guc: Check GuC running state before deregistering exec queue
-------------
Diffstat:
Documentation/arch/arm64/silicon-errata.rst | 2 + Documentation/networking/seg6-sysctl.rst | 3 + Makefile | 4 +- arch/Kconfig | 1 + arch/arm64/Kconfig | 1 + arch/arm64/include/asm/cputype.h | 2 + arch/arm64/kernel/cpu_errata.c | 1 + arch/arm64/kvm/arm.c | 6 + arch/riscv/kernel/probes/kprobes.c | 13 +- arch/x86/kernel/cpu/resctrl/monitor.c | 46 +++-- drivers/accel/qaic/qaic.h | 2 + drivers/accel/qaic/qaic_control.c | 2 +- drivers/accel/qaic/qaic_data.c | 12 +- drivers/accel/qaic/qaic_debugfs.c | 5 +- drivers/accel/qaic/qaic_drv.c | 3 + drivers/base/power/runtime.c | 44 ++++ drivers/cdx/cdx_msi.c | 5 +- drivers/cpufreq/cppc_cpufreq.c | 14 +- drivers/dma/idxd/init.c | 2 + drivers/gpu/drm/amd/amdgpu/Makefile | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 5 +- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 48 ++++- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 2 +- .../gpu/drm/amd/amdgpu/cyan_skillfish_reg_init.c | 56 +++++ drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 7 +- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 7 +- drivers/gpu/drm/amd/amdgpu/mes_v12_0.c | 7 +- drivers/gpu/drm/amd/amdgpu/nv.h | 1 + .../gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 3 +- drivers/gpu/drm/ast/ast_mode.c | 18 +- drivers/gpu/drm/ast/ast_reg.h | 1 + drivers/gpu/drm/bridge/lontium-lt9211.c | 3 +- drivers/gpu/drm/drm_draw.c | 2 +- drivers/gpu/drm/drm_draw_internal.h | 2 +- drivers/gpu/drm/exynos/exynos7_drm_decon.c | 98 ++++----- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 9 +- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 28 ++- drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 6 + drivers/gpu/drm/panthor/panthor_fw.c | 1 + drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 2 +- drivers/gpu/drm/scheduler/sched_main.c | 13 +- drivers/gpu/drm/xe/xe_guc_submit.c | 13 +- drivers/hid/hid-input.c | 5 +- drivers/hid/hid-multitouch.c | 28 +-- drivers/iio/imu/inv_icm42600/inv_icm42600_core.c | 35 ++-- drivers/md/md-linear.c | 1 + drivers/md/raid0.c | 16 ++ drivers/md/raid1.c | 37 +++- drivers/md/raid10.c | 55 ++++- drivers/md/raid5.c | 2 + .../media/platform/nxp/imx8-isi/imx8-isi-core.h | 2 +- drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c | 2 +- drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c | 225 +++++++++------------ .../media/platform/nxp/imx8-isi/imx8-isi-pipe.c | 2 +- drivers/net/can/m_can/m_can.c | 86 +++++--- drivers/net/can/m_can/m_can.h | 1 + drivers/net/can/m_can/m_can_platform.c | 2 +- drivers/net/can/usb/gs_usb.c | 23 +-- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 1 - drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 1 + drivers/net/ethernet/broadcom/tg3.c | 5 +- drivers/net/ethernet/dlink/dl2k.c | 23 ++- drivers/net/ethernet/intel/ixgbevf/defines.h | 6 +- drivers/net/ethernet/intel/ixgbevf/ipsec.c | 10 + drivers/net/ethernet/intel/ixgbevf/ixgbevf.h | 13 +- drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 46 ++++- drivers/net/ethernet/intel/ixgbevf/mbx.h | 8 + drivers/net/ethernet/intel/ixgbevf/vf.c | 194 +++++++++++++++--- drivers/net/ethernet/intel/ixgbevf/vf.h | 5 +- drivers/net/ethernet/realtek/r8169_main.c | 5 +- drivers/net/netdevsim/netdev.c | 7 + drivers/net/usb/lan78xx.c | 38 +++- drivers/net/usb/r8152.c | 7 +- drivers/net/wireless/realtek/rtw89/core.c | 39 ++-- drivers/net/wireless/realtek/rtw89/core.h | 6 +- drivers/net/wireless/realtek/rtw89/mac80211.c | 2 +- drivers/net/wireless/realtek/rtw89/pci.c | 2 - drivers/nvme/host/multipath.c | 6 +- drivers/nvme/host/tcp.c | 3 + drivers/phy/cadence/cdns-dphy.c | 133 +++++++++--- drivers/usb/gadget/function/f_acm.c | 42 ++-- drivers/usb/gadget/function/f_ecm.c | 48 ++--- drivers/usb/gadget/function/f_ncm.c | 78 +++---- drivers/usb/gadget/function/f_rndis.c | 85 ++++---- drivers/usb/gadget/udc/core.c | 3 + fs/btrfs/extent_io.c | 2 +- fs/btrfs/free-space-tree.c | 15 +- fs/btrfs/ioctl.c | 2 +- fs/btrfs/relocation.c | 13 +- fs/btrfs/zoned.c | 2 +- fs/dax.c | 2 +- fs/dcache.c | 12 +- fs/ext4/ext4_jbd2.c | 11 +- fs/ext4/inode.c | 8 + fs/f2fs/data.c | 2 +- fs/hfsplus/unicode.c | 24 +++ fs/jbd2/transaction.c | 13 +- fs/nfsd/blocklayout.c | 33 +-- fs/nfsd/blocklayoutxdr.c | 171 ++++++++++------ fs/nfsd/blocklayoutxdr.h | 8 +- fs/nfsd/flexfilelayout.c | 8 + fs/nfsd/flexfilelayoutxdr.c | 3 +- fs/nfsd/nfs4layouts.c | 1 - fs/nfsd/nfs4proc.c | 36 ++-- fs/nfsd/nfs4xdr.c | 25 +-- fs/nfsd/nfsd.h | 1 + fs/nfsd/pnfs.h | 1 + fs/nfsd/xdr4.h | 39 +++- fs/smb/client/inode.c | 6 +- fs/smb/client/misc.c | 17 ++ fs/smb/client/smb2ops.c | 8 +- fs/smb/server/mgmt/user_session.c | 7 +- fs/smb/server/smb2pdu.c | 9 +- fs/smb/server/transport_ipc.c | 12 ++ fs/xfs/libxfs/xfs_log_format.h | 30 ++- fs/xfs/libxfs/xfs_ondisk.h | 2 + fs/xfs/scrub/reap.c | 9 +- fs/xfs/xfs_log.c | 8 +- fs/xfs/xfs_log_priv.h | 4 +- fs/xfs/xfs_log_recover.c | 34 +++- include/linux/mm.h | 2 +- include/linux/pci.h | 14 ++ include/linux/pm_runtime.h | 4 + include/linux/usb/gadget.h | 25 +++ include/net/dst.h | 32 +++ include/net/inet6_hashtables.h | 2 +- include/net/inet_connection_sock.h | 3 +- include/net/inet_hashtables.h | 2 +- include/net/ip.h | 11 +- include/net/ip_tunnels.h | 15 ++ include/net/route.h | 2 +- io_uring/rw.c | 2 +- kernel/events/core.c | 8 +- kernel/padata.c | 6 +- kernel/sched/fair.c | 26 +-- mm/slub.c | 9 +- net/core/dst.c | 4 +- net/core/sock.c | 14 +- net/ipv4/icmp.c | 24 ++- net/ipv4/igmp.c | 2 +- net/ipv4/ip_fragment.c | 2 +- net/ipv4/ip_output.c | 19 +- net/ipv4/ip_tunnel.c | 14 -- net/ipv4/ip_vti.c | 4 +- net/ipv4/netfilter.c | 4 +- net/ipv4/route.c | 8 +- net/ipv4/tcp_fastopen.c | 4 +- net/ipv4/tcp_input.c | 3 +- net/ipv4/tcp_ipv4.c | 12 +- net/ipv4/tcp_metrics.c | 8 +- net/ipv4/tcp_output.c | 19 +- net/ipv4/xfrm4_output.c | 2 +- net/ipv6/ip6_tunnel.c | 3 +- net/ipv6/tcp_ipv6.c | 22 +- net/mptcp/ctrl.c | 9 +- net/tls/tls_main.c | 7 +- net/tls/tls_sw.c | 31 ++- rust/bindings/bindings_helper.h | 1 + sound/firewire/amdtp-stream.h | 2 +- sound/soc/amd/acp/acp-sdw-sof-mach.c | 2 +- sound/soc/codecs/idt821034.c | 12 +- sound/soc/codecs/nau8821.c | 53 +++-- sound/usb/card.c | 10 +- .../testing/selftests/bpf/prog_tests/arg_parsing.c | 12 +- 164 files changed, 1922 insertions(+), 967 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/136 drm/xe/guc: Check GuC running state before deregistering exec queue
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shuicheng Lin <[email protected]>
commit 9f64b3cd051b825de0a2a9f145c8e003200cedd5 upstream.
In normal operation, a registered exec queue is disabled and deregistered through the GuC, and freed only after the GuC confirms completion. However, if the driver is forced to unbind while the exec queue is still running, the user may call exec_destroy() after the GuC has already been stopped and CT communication disabled.
In this case, the driver cannot receive a response from the GuC, preventing proper cleanup of exec queue resources. Fix this by directly releasing the resources when GuC is not running.
Here is the failure dmesg log:
"
[ 468.089581] ---[ end trace 0000000000000000 ]--- [ 468.089608] pci 0000:03:00.0: [drm] *ERROR* GT0: GUC ID manager unclean (1/65535) [ 468.090558] pci 0000:03:00.0: [drm] GT0: total 65535 [ 468.090562] pci 0000:03:00.0: [drm] GT0: used 1 [ 468.090564] pci 0000:03:00.0: [drm] GT0: range 1..1 (1) [ 468.092716] ------------[ cut here ]------------ [ 468.092719] WARNING: CPU: 14 PID: 4775 at drivers/gpu/drm/xe/xe_ttm_vram_mgr.c:298 ttm_vram_mgr_fini+0xf8/0x130 [xe]
"
v2: use xe_uc_fw_is_running() instead of xe_guc_ct_enabled().
As CT may go down and come back during VF migration.
--- drivers/gpu/drm/xe/xe_guc_submit.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
drivers/gpu/drm/xe/xe_guc_submit.c +12 -1
@@ -41,6 +41,7 @@#include "xe_ring_ops_types.h" #include "xe_sched_job.h" #include "xe_trace.h" +#include "xe_uc_fw.h" #include "xe_vm.h" static struct xe_guc *
@@ -1285,7 +1286,17 @@ static void __guc_exec_queue_process_msgxe_assert (xe, !(q->flags &EXEC_QUEUE_FLAG_PERMANENT ));trace_xe_exec_queue_cleanup_entity (q); -if (exec_queue_registered (q)) +/* +* Expected state transitions for cleanup: +* - If the exec queue is registered and GuC firmware is running, we must first +* disable scheduling and deregister the queue to ensure proper teardown and +* resource release in the GuC, then destroy the exec queue on driver side. +* - If the GuC is already stopped (e.g., during driver unload or GPU reset), +* we cannot expect a response for the deregister request. In this case, +* it is safe to directly destroy the exec queue on driver side, as the GuC +* will not process further requests and all resources must be cleaned up locally. +*/ +if (exec_queue_registered (q) &&xe_uc_fw_is_running (&guc->fw))disable_scheduling_deregister (guc, q);else __guc_exec_queue_fini (guc, q);
Greg Kroah-Hartman
maintainerPATCH 2/136 rust: cfi: only 64-bit arm and x86 support CFI_CLANG
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Conor Dooley <[email protected]>
commit 812258ff4166bcd41c7d44707e0591f9ae32ac8c upstream.
The kernel uses the standard rustc targets for non-x86 targets, and out of those only 64-bit arm's target has kcfi support enabled. For x86, the custom 64-bit target enables kcfi.
The HAVE_CFI_ICALL_NORMALIZE_INTEGERS_RUSTC config option that allows CFI_CLANG to be used in combination with RUST does not check whether the rustc target supports kcfi. This breaks the build on riscv (and presumably 32-bit arm) when CFI_CLANG and RUST are enabled at the same time.
Ordinarily, a rustc-option check would be used to detect target support but unfortunately rustc-option filters out the target for reasons given in commit 46e24a545cdb4 ("rust: kasan/kbuild: fix missing flags on first build"). As a result, if the host supports kcfi but the target does not, e.g. when building for riscv on x86_64, the build would remain broken.
Instead, make HAVE_CFI_ICALL_NORMALIZE_INTEGERS_RUSTC depend on the only two architectures where the target used supports it to fix the build.
--- arch/Kconfig | 1 + 1 file changed, 1 insertion(+)
arch/Kconfig +1 -0
@@ -861,6 +861,7 @@ config HAVE_CFI_ICALL_NORMALIZE_INTEGERS def_bool y depends on HAVE_CFI_ICALL_NORMALIZE_INTEGERS_CLANG depends on RUSTC_VERSION >= 107900 + depends on ARM64 || X86_64 # With GCOV/KASAN we need this fix: https://github.com/rust-lang/rust/pull/129373 depends on (RUSTC_LLVM_VERSION >= 190103 && RUSTC_VERSION >= 108200) || \ (!GCOV_KERNEL && !KASAN_GENERIC && !KASAN_SW_TAGS)
Greg Kroah-Hartman
maintainerPATCH 3/136 smb: client: Fix refcount leak for cifs_sb_tlink
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shuhao Fu <[email protected]>
commit c2b77f42205ef485a647f62082c442c1cd69d3fc upstream.
Fix three refcount inconsistency issues related to cifs_sb_tlink.
Comments for cifs_sb_tlink state that cifs_put_tlink() needs to be called after successful calls to cifs_sb_tlink(). Three calls fail to update refcount accordingly, leading to possible resource leaks.
--- fs/smb/client/inode.c | 6 ++++-- fs/smb/client/smb2ops.c | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-)
fs/smb/client/inode.c +4 -2
@@ -2381,8 +2381,10 @@ cifs_do_rename(const unsigned int xid, s tcon =tlink_tcon (tlink); server = tcon->ses->server; -if (!server->ops->rename) -return -ENOSYS ; +if (!server->ops->rename) { + rc = -ENOSYS ; + goto do_rename_exit; + }/* try path-based rename first */ rc = server->ops->rename(xid, tcon, from_dentry,
fs/smb/client/smb2ops.c +4 -4
@@ -3134,8 +3134,7 @@ get_smb2_acl_by_path(struct cifs_sb_info utf16_path =cifs_convert_path_to_utf16 (path, cifs_sb);if (!utf16_path) { rc = -ENOMEM ; -free_xid (xid); -return ERR_PTR (rc); + goto put_tlink; } oparms = (struct cifs_open_parms ) {
@@ -3167,6 +3166,7 @@ get_smb2_acl_by_path(struct cifs_sb_infoSMB2_close (xid, tcon, fid.persistent_fid, fid.volatile_fid); } +put_tlink:cifs_put_tlink (tlink);free_xid (xid);
@@ -3207,8 +3207,7 @@ set_smb2_acl(struct smb_ntsd *pnntsd, __ utf16_path =cifs_convert_path_to_utf16 (path, cifs_sb);if (!utf16_path) { rc = -ENOMEM ; -free_xid (xid); -return rc; + goto put_tlink; } oparms = (struct cifs_open_parms ) {
@@ -3229,6 +3228,7 @@ set_smb2_acl(struct smb_ntsd *pnntsd, __SMB2_close (xid, tcon, fid.persistent_fid, fid.volatile_fid); } +put_tlink:cifs_put_tlink (tlink);free_xid (xid);return rc;
Greg Kroah-Hartman
maintainerPATCH 4/136 slab: reset slab->obj_ext when freeing and it is OBJEXTS_ALLOC_FAIL
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hao Ge <[email protected]>
commit 86f54f9b6c17d6567c69e3a6fed52fdf5d7dbe93 upstream.
If obj_exts allocation failed, slab->obj_exts is set to OBJEXTS_ALLOC_FAIL, But we do not clear it when freeing the slab. Since OBJEXTS_ALLOC_FAIL and MEMCG_DATA_OBJEXTS currently share the same bit position, during the release of the associated folio, a VM_BUG_ON_FOLIO() check in folio_memcg_kmem() is triggered because the OBJEXTS_ALLOC_FAIL flag was not cleared, causing it to be interpreted as a kmem folio (non-slab) with MEMCG_OBJEXTS_DATA flag set, which is invalid because MEMCG_OBJEXTS_DATA is supposed to be set only on slabs.
Another problem that predates sharing the OBJEXTS_ALLOC_FAIL and MEMCG_DATA_OBJEXTS bits is that on configurations with is_check_pages_enabled(), the non-cleared bit in page->memcg_data will trigger a free_page_is_bad() failure "page still charged to cgroup"
When freeing a slab, we clear slab->obj_exts if the obj_ext array has been successfully allocated. So let's clear it also when the allocation has failed.
--- mm/slub.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
mm/slub.c +8 -1
@@ -2038,8 +2038,15 @@ static inline void free_slab_obj_exts(ststruct slabobj_ext *obj_exts; obj_exts =slab_obj_exts (slab); -if (!obj_exts) +if (!obj_exts) { +/* +* If obj_exts allocation failed, slab->obj_exts is set to +* OBJEXTS_ALLOC_FAIL. In this case, we end up here and should +* clear the flag. +*/ + slab->obj_exts =0 ;return ; + }/* * obj_exts was created with __GFP_NO_OBJ_EXT flag, therefore its
Greg Kroah-Hartman
maintainerPATCH 5/136 r8152: add error handling in rtl8152_driver_init
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yi Cong <[email protected]>
commit 75527d61d60d493d1eb064f335071a20ca581f54 upstream.
rtl8152_driver_init() is missing the error handling. When rtl8152_driver registration fails, rtl8152_cfgselector_driver should be deregistered.
--- drivers/net/usb/r8152.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/net/usb/r8152.c +6 -1
@@ -10151,7 +10151,12 @@ static int __init rtl8152_driver_init(vo ret =usb_register_device_driver (&rtl8152_cfgselector_driver,THIS_MODULE );if (ret)return ret; -return usb_register (&rtl8152_driver); + + ret =usb_register (&rtl8152_driver); +if (ret) +usb_deregister_device_driver (&rtl8152_cfgselector_driver); + +return ret; } static void __exit rtl8152_driver_exit(void)
Greg Kroah-Hartman
maintainerPATCH 6/136 KVM: arm64: Prevent access to vCPU events before init
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oliver Upton <[email protected]>
commit 0aa1b76fe1429629215a7c79820e4b96233ac4a3 upstream.
Another day, another syzkaller bug. KVM erroneously allows userspace to pend vCPU events for a vCPU that hasn't been initialized yet, leading to KVM interpreting a bunch of uninitialized garbage for routing / injecting the exception.
In one case the injection code and the hyp disagree on whether the vCPU has a 32bit EL1 and put the vCPU into an illegal mode for AArch64, tripping the BUG() in exception_target_el() during the next injection:
kernel BUG at arch/arm64/kvm/inject_fault.c:40!
Internal error: Oops - BUG: 00000000f2000800 [#1] SMP CPU: 3 UID: 0 PID: 318 Comm: repro Not tainted 6.17.0-rc4-00104-g10fd0285305d #6 PREEMPT Hardware name: linux,dummy-virt (DT) pstate: 21402009 (nzCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--) pc : exception_target_el+0x88/0x8c lr : pend_serror_exception+0x18/0x13c sp : ffff800082f03a10 x29: ffff800082f03a10 x28: ffff0000cb132280 x27: 0000000000000000 x26: 0000000000000000 x25: ffff0000c2a99c20 x24: 0000000000000000 x23: 0000000000008000 x22: 0000000000000002 x21: 0000000000000004 x20: 0000000000008000 x19: ffff0000c2a99c20 x18: 0000000000000000 x17: 0000000000000000 x16: 0000000000000000 x15: 00000000200000c0 x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000 x11: 0000000000000000 x10: 0000000000000000 x9 : 0000000000000000 x8 : ffff800082f03af8 x7 : 0000000000000000 x6 : 0000000000000000 x5 : ffff800080f621f0 x4 : 0000000000000000 x3 : 0000000000000000 x2 : 000000000040009b x1 : 0000000000000003 x0 : ffff0000c2a99c20 Call trace: exception_target_el+0x88/0x8c (P) kvm_inject_serror_esr+0x40/0x3b4 __kvm_arm_vcpu_set_events+0xf0/0x100 kvm_arch_vcpu_ioctl+0x180/0x9d4 kvm_vcpu_ioctl+0x60c/0x9f4 __arm64_sys_ioctl+0xac/0x104 invoke_syscall+0x48/0x110 el0_svc_common.constprop.0+0x40/0xe0 do_el0_svc+0x1c/0x28 el0_svc+0x34/0xf0 el0t_64_sync_handler+0xa0/0xe4 el0t_64_sync+0x198/0x19c Code: f946bc01 b4fffe61 9101e020 17fffff2 (d4210000)
Reject the ioctls outright as no sane VMM would call these before KVM_ARM_VCPU_INIT anyway. Even if it did the exception would've been thrown away by the eventual reset of the vCPU's state.
--- arch/arm64/kvm/arm.c | 6 ++++++ 1 file changed, 6 insertions(+)
arch/arm64/kvm/arm.c +6 -0
@@ -1760,6 +1760,9 @@ long kvm_arch_vcpu_ioctl(struct file *ficase KVM_GET_VCPU_EVENTS : {struct kvm_vcpu_events events; +if (!kvm_vcpu_initialized (vcpu)) +return -ENOEXEC ; +if (kvm_arm_vcpu_get_events (vcpu, &events))return -EINVAL ;
@@ -1771,6 +1774,9 @@ long kvm_arch_vcpu_ioctl(struct file *ficase KVM_SET_VCPU_EVENTS : {struct kvm_vcpu_events events; +if (!kvm_vcpu_initialized (vcpu)) +return -ENOEXEC ; +if (copy_from_user (&events, argp,sizeof (events)))return -EFAULT ;
Re: [PATCH 6.12 006/136] KVM: arm64: Prevent access to vCPU events before init
Hey,
Can you please drop this patch from all but 6.17?
On Tue, Oct 21, 2025 at 09:49:54PM +0200, Greg Kroah-Hartman wrote:
[...]
Quoted 1 line
Cc [email protected] # 6.17
FWIW, I called this out here.
Thanks,
Oliver
Quoted 32 lines
Fixes b7b27facc7b5 ("arm/arm64: KVM: Add KVM_GET/SET_VCPU_EVENTS")Signed-off-by Oliver Upton <[email protected]>Signed-off-by Marc Zyngier <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- arch/arm64/kvm/arm.c | 6 ++++++ 1 file changed, 6 insertions(+)arch/arm64/kvm/arm.c +6
-0@@ -1760,6 +1760,9 @@ long kvm_arch_vcpu_ioctl(struct file *ficase KVM_GET_VCPU_EVENTS : {struct kvm_vcpu_events events; +if (!kvm_vcpu_initialized (vcpu)) +return -ENOEXEC ; +if (kvm_arm_vcpu_get_events (vcpu, &events))return -EINVAL ;@@ -1771,6 +1774,9 @@ long kvm_arch_vcpu_ioctl(struct file *ficase KVM_SET_VCPU_EVENTS : {struct kvm_vcpu_events events; +if (!kvm_vcpu_initialized (vcpu)) +return -ENOEXEC ; +if (copy_from_user (&events, argp,sizeof (events)))return -EFAULT ;
Greg Kroah-Hartman
maintainerRe: [PATCH 6.12 006/136] KVM: arm64: Prevent access to vCPU events before init
Quoted 6 lines · Oliver Upton
Hey,
Can you please drop this patch from all but 6.17?
On Tue, Oct 21, 2025 at 09:49:54PM +0200, Greg Kroah-Hartman wrote:
Quoted 10 lines
[...]
Quoted 1 line
Cc [email protected] # 6.17FWIW, I called this out here.
Thanks,
OliverQuoted 1 line
Fixes b7b27facc7b5 ("arm/arm64: KVM: Add KVM_GET/SET_VCPU_EVENTS")
Ok, but note that this Fixes: tag references a much much older kernel release, hence my confusion as to where this should be backported to :)
I'll go drop it from older queues now, thanks.
greg k-h
Re: [PATCH 6.12 006/136] KVM: arm64: Prevent access to vCPU events before init
Quoted 13 lines · Greg Kroah-Hartman
Quoted 12 lines · Oliver Upton
Hey,
Can you please drop this patch from all but 6.17?
On Tue, Oct 21, 2025 at 09:49:54PM +0200, Greg Kroah-Hartman wrote:
[...]
Quoted 1 line
Cc [email protected] # 6.17FWIW, I called this out here.
Quoted 7 lines
Quoted 4 lines
Thanks,
OliverQuoted 1 line
Fixes b7b27facc7b5 ("arm/arm64: KVM: Add KVM_GET/SET_VCPU_EVENTS")Ok, but note that this Fixes: tag references a much much older kernel release, hence my confusion as to where this should be backported to :)
Yeah, this is a bit confusing. The blame is correct, 6.17 added some (correct) fireworks to the situation.
Quoted 1 line
I'll go drop it from older queues now, thanks.
Appreciated!
Signature · 1 line
Oliver
Greg Kroah-Hartman
maintainerPATCH 7/136 f2fs: fix wrong block mapping for multi-devices
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jaegeuk Kim <[email protected]>
commit 9d5c4f5c7a2c7677e1b3942772122b032c265aae upstream.
Assuming the disk layout as below,
disk0: 0 --- 0x00035abfff
disk1: 0x00035ac000 --- 0x00037abfff
disk2: 0x00037ac000 --- 0x00037ebfff
and we want to read data from offset=13568 having len=128 across the block devices, we can illustrate the block addresses like below.
0 .. 0x00037ac000 ------------------- 0x00037ebfff, 0x00037ec000 -------
| ^ ^ ^
| fofs 0 13568 13568+128
| ------------------------------------------------------
| LBA 0x37e8aa9 0x37ebfa9 0x37ec029
--- map 0x3caa9 0x3ffa9In this example, we should give the relative map of the target block device ranging from 0x3caa9 to 0x3ffa9 where the length should be calculated by 0x37ebfff + 1 - 0x37ebfa9.
In the below equation, however, map->m_pblk was supposed to be the original address instead of the one from the target block address.
- map->m_len = min(map->m_len, dev->end_blk + 1 - map->m_pblk);
--- fs/f2fs/data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/f2fs/data.c +1 -1
@@ -1508,8 +1508,8 @@ static bool f2fs_map_blocks_cached(strucstruct f2fs_dev_info *dev = &sbi->devs[bidx]; map->m_bdev = dev->bdev; - map->m_pblk -= dev->start_blk; map->m_len =min (map->m_len, dev->end_blk +1 - map->m_pblk); + map->m_pblk -= dev->start_blk; }else { map->m_bdev = inode->i_sb->s_bdev; }
Greg Kroah-Hartman
maintainerPATCH 8/136 jbd2: ensure that all ongoing I/O complete before freeing blocks
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Yi <[email protected]>
commit 3c652c3a71de1d30d72dc82c3bead8deb48eb749 upstream.
When releasing file system metadata blocks in jbd2_journal_forget(), if this buffer has not yet been checkpointed, it may have already been written back, currently be in the process of being written back, or has not yet written back. jbd2_journal_forget() calls jbd2_journal_try_remove_checkpoint() to check the buffer's status and add it to the current transaction if it has not been written back. This buffer can only be reallocated after the transaction is committed.
jbd2_journal_try_remove_checkpoint() attempts to lock the buffer and check its dirty status while holding the buffer lock. If the buffer has already been written back, everything proceeds normally. However, there are two issues. First, the function returns immediately if the buffer is locked by the write-back process. It does not wait for the write-back to complete. Consequently, until the current transaction is committed and the block is reallocated, there is no guarantee that the I/O will complete. This means that ongoing I/O could write stale metadata to the newly allocated block, potentially corrupting data. Second, the function unlocks the buffer as soon as it detects that the buffer is still dirty. If a concurrent write-back occurs immediately after this unlocking and before clear_buffer_dirty() is called in jbd2_journal_forget(), data corruption can theoretically still occur.
Although these two issues are unlikely to occur in practice since the undergoing metadata writeback I/O does not take this long to complete, it's better to explicitly ensure that all ongoing I/O operations are completed.
Message-ID: <[email protected]>
--- fs/jbd2/transaction.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
fs/jbd2/transaction.c +9 -4
@@ -1663,6 +1663,7 @@ int jbd2_journal_forget(handle_t *handleint drop_reserve =0 ;int err =0 ;int was_modified =0 ; +int wait_for_writeback =0 ;if (is_handle_aborted (handle))return -EROFS ;
@@ -1786,18 +1787,22 @@ int jbd2_journal_forget(handle_t *handle }/* -* The buffer is still not written to disk, we should -* attach this buffer to current transaction so that the -* buffer can be checkpointed only after the current -* transaction commits. +* The buffer has not yet been written to disk. We should +* either clear the buffer or ensure that the ongoing I/O +* is completed, and attach this buffer to current +* transaction so that the buffer can be checkpointed only +* after the current transaction commits. */ clear_buffer_dirty (bh); + wait_for_writeback =1 ;__jbd2_journal_file_buffer (jh, transaction, BJ_Forget);spin_unlock (&journal->j_list_lock); } drop:__brelse (bh);spin_unlock (&jh->b_state_lock); +if (wait_for_writeback) +wait_on_buffer (bh);jbd2_journal_put_journal_head (jh);if (drop_reserve) {/* no need to reserve log space for this block -bzzz */
Greg Kroah-Hartman
maintainerPATCH 9/136 ext4: wait for ongoing I/O to complete before freeing blocks
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Yi <[email protected]>
commit 328a782cb138029182e521c08f50eb1587db955d upstream.
When freeing metadata blocks in nojournal mode, ext4_forget() calls bforget() to clear the dirty flag on the buffer_head and remvoe associated mappings. This is acceptable if the metadata has not yet begun to be written back. However, if the write-back has already started but is not yet completed, ext4_forget() will have no effect. Subsequently, ext4_mb_clear_bb() will immediately return the block to the mb allocator. This block can then be reallocated immediately, potentially causing an data corruption issue.
Fix this by clearing the buffer's dirty flag and waiting for the ongoing I/O to complete, ensuring that no further writes to stale data will occur.
Message-ID: <[email protected]>
--- fs/ext4/ext4_jbd2.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
fs/ext4/ext4_jbd2.c +9 -2
@@ -276,9 +276,16 @@ int __ext4_forget(const char *where, uns bh, is_metadata, inode->i_mode, test_opt(inode->i_sb, DATA_FLAGS)); -/* In the no journal case, we can just do a bforget and return */ +/* +* In the no journal case, we should wait for the ongoing buffer +* to complete and do a forget. +*/ if (!ext4_handle_valid (handle)) { -bforget (bh); +if (bh) { +clear_buffer_dirty (bh); +wait_on_buffer (bh); +__bforget (bh); + }return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 10/136 ext4: detect invalid INLINE_DATA + EXTENTS flag combination
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Deepanshu Kartikey <[email protected]>
commit 1d3ad183943b38eec2acf72a0ae98e635dc8456b upstream.
syzbot reported a BUG_ON in ext4_es_cache_extent() when opening a verity file on a corrupted ext4 filesystem mounted without a journal.
The issue is that the filesystem has an inode with both the INLINE_DATA and EXTENTS flags set:
EXT4-fs error (device loop0): ext4_cache_extents:545: inode #15:
comm syz.0.17: corrupted extent tree: lblk 0 < prev 66
Investigation revealed that the inode has both flags set:
DEBUG: inode 15 - flag=1, i_inline_off=164, has_inline=1, extents_flag=1
This is an invalid combination since an inode should have either:
- INLINE_DATA: data stored directly in the inode
- EXTENTS: data stored in extent-mapped blocks
Having both flags causes ext4_has_inline_data() to return true, skipping extent tree validation in __ext4_iget(). The unvalidated out-of-order extents then trigger a BUG_ON in ext4_es_cache_extent() due to integer underflow when calculating hole sizes.
Fix this by detecting this invalid flag combination early in ext4_iget() and rejecting the corrupted inode.
Message-ID: <[email protected]>
--- fs/ext4/inode.c | 8 ++++++++ 1 file changed, 8 insertions(+)
fs/ext4/inode.c +8 -0
@@ -4904,6 +4904,14 @@ struct inode *__ext4_iget(struct super_b } ei->i_flags =le32_to_cpu (raw_inode->i_flags);ext4_set_inode_flags (inode, true); +/* Detect invalid flag combination - can't have both inline data and extents */ +if (ext4_test_inode_flag (inode,EXT4_INODE_INLINE_DATA ) && +ext4_test_inode_flag (inode,EXT4_INODE_EXTENTS )) { +ext4_error_inode (inode, function, line,0 , +"inode has both inline data and extents flags" ); + ret = -EFSCORRUPTED ; + goto bad_inode; + } inode->i_blocks =ext4_inode_blocks (raw_inode, ei); ei->i_file_acl =le32_to_cpu (raw_inode->i_file_acl_lo);if (ext4_has_feature_64bit (sb))
Greg Kroah-Hartman
maintainerPATCH 11/136 btrfs: fix clearing of BTRFS_FS_RELOC_RUNNING if relocation already running
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <[email protected]>
commit 7e5a5983edda664e8e4bb20af17b80f5135c655c upstream.
When starting relocation, at reloc_chunk_start(), if we happen to find the flag BTRFS_FS_RELOC_RUNNING is already set we return an error (-EINPROGRESS) to the callers, however the callers call reloc_chunk_end() which will clear the flag BTRFS_FS_RELOC_RUNNING, which is wrong since relocation was started by another task and still running.
Finding the BTRFS_FS_RELOC_RUNNING flag already set is an unexpected scenario, but still our current behaviour is not correct.
Fix this by never calling reloc_chunk_end() if reloc_chunk_start() has returned an error, which is what logically makes sense, since the general widespread pattern is to have end functions called only if the counterpart start functions succeeded. This requires changing reloc_chunk_start() to clear BTRFS_FS_RELOC_RUNNING if there's a pending cancel request.
--- fs/btrfs/relocation.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
fs/btrfs/relocation.c +7 -6
@@ -3906,6 +3906,7 @@ out:/* * Mark start of chunk relocation that is cancellable. Check if the cancellation * has been requested meanwhile and don't start in that case. +* NOTE: if this returns an error, reloc_chunk_end() must not be called. * * Return: * 0 success
@@ -3922,10 +3923,8 @@ static int reloc_chunk_start(struct btrfif (atomic_read (&fs_info->reloc_cancel_req) >0 ) {btrfs_info (fs_info,"chunk relocation canceled on start" ); -/* -* On cancel, clear all requests but let the caller mark -* the end after cleanup operations. -*/ +/* On cancel, clear all requests. */ +clear_and_wake_up_bit (BTRFS_FS_RELOC_RUNNING , &fs_info->flags);atomic_set (&fs_info->reloc_cancel_req,0 );return -ECANCELED ; }
@@ -3934,9 +3933,11 @@ static int reloc_chunk_start(struct btrf/* * Mark end of chunk relocation that is cancellable and wake any waiters. +* NOTE: call only if a previous call to reloc_chunk_start() succeeded. */ static void reloc_chunk_end (struct btrfs_fs_info *fs_info) { +ASSERT (test_bit (BTRFS_FS_RELOC_RUNNING , &fs_info->flags));/* Requested after start, clear bit first so any waiters can continue */ if (atomic_read (&fs_info->reloc_cancel_req) >0 )btrfs_info (fs_info,"chunk relocation canceled during operation" );
@@ -4145,9 +4146,9 @@ out:if (err && rw)btrfs_dec_block_group_ro (rc->block_group);iput (rc->data_inode); +reloc_chunk_end (fs_info); out_put_bg:btrfs_put_block_group (bg); -reloc_chunk_end (fs_info);free_reloc_control (rc);return err; }
@@ -4331,8 +4332,8 @@ out_clean: ret = ret2; out_unset:unset_reloc_control (rc); -out_end:reloc_chunk_end (fs_info); +out_end:free_reloc_control (rc); out:free_reloc_roots (&reloc_roots);
Greg Kroah-Hartman
maintainerPATCH 12/136 btrfs: fix memory leak on duplicated memory in the qgroup assign ioctl
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miquel Sabaté Solà <[email protected]>
commit 53a4acbfc1de85fa637521ffab4f4e2ee03cbeeb upstream.
On 'btrfs_ioctl_qgroup_assign' we first duplicate the argument as provided by the user, which is kfree'd in the end. But this was not the case when allocating memory for 'prealloc'. In this case, if it somehow failed, then the previous code would go directly into calling 'mnt_drop_write_file', without freeing the string duplicated from the user space.
--- fs/btrfs/ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/btrfs/ioctl.c +1 -1
@@ -3852,7 +3852,7 @@ static long btrfs_ioctl_qgroup_assign(st prealloc =kzalloc (sizeof (*prealloc),GFP_KERNEL );if (!prealloc) { ret = -ENOMEM ; - goto drop_write; + goto out; } }
Greg Kroah-Hartman
maintainerPATCH 13/136 btrfs: fix incorrect readahead expansion length
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Boris Burkov <[email protected]>
commit 8ab2fa69691b2913a67f3c54fbb991247b3755be upstream.
The intent of btrfs_readahead_expand() was to expand to the length of the current compressed extent being read. However, "ram_bytes" is *not* that, in the case where a single physical compressed extent is used for multiple file extents.
Consider this case with a large compressed extent C and then later two non-compressed extents N1 and N2 written over C, leaving C1 and C2 pointing to offset/len pairs of C:
[ C ]
[ N1 ][ C1 ][ N2 ][ C2 ]
In such a case, ram_bytes for both C1 and C2 is the full uncompressed length of C. So starting readahead in C1 will expand the readahead past the end of C1, past N2, and into C2. This will then expand readahead again, to C2_start + ram_bytes, way past EOF. First of all, this is totally undesirable, we don't want to read the whole file in arbitrary chunks of the large underlying extent if it happens to exist. Secondly, it results in zeroing the range past the end of C2 up to ram_bytes. This is particularly unpleasant with fs-verity as it can zero and set uptodate pages in the verity virtual space past EOF. This incorrect readahead behavior can lead to verity verification errors, if we iterate in a way that happens to do the wrong readahead.
Fix this by using em->len for readahead expansion, not em->ram_bytes, resulting in the expected behavior of stopping readahead at the extent boundary.
--- fs/btrfs/extent_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/btrfs/extent_io.c +1 -1
@@ -962,7 +962,7 @@ static void btrfs_readahead_expand(struc {const u64 ra_pos =readahead_pos (ractl);const u64 ra_end = ra_pos +readahead_length (ractl); -const u64 em_end = em->start + em->ram_bytes; +const u64 em_end = em->start + em->len;/* No expansion for holes and inline extents. */ if (em->disk_bytenr >EXTENT_MAP_LAST_BYTE )
Greg Kroah-Hartman
maintainerPATCH 14/136 btrfs: fix memory leaks when rejecting a non SINGLE data profile without an RST
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miquel Sabaté Solà <[email protected]>
commit fec9b9d3ced39f16be8d7afdf81f4dd2653da319 upstream.
At the end of btrfs_load_block_group_zone_info() the first thing we do is to ensure that if the mapping type is not a SINGLE one and there is no RAID stripe tree, then we return early with an error.
Doing that, though, prevents the code from running the last calls from this function which are about freeing memory allocated during its run. Hence, in this case, instead of returning early, we set the ret value and fall through the rest of the cleanup code.
--- fs/btrfs/zoned.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/btrfs/zoned.c +1 -1
@@ -1664,7 +1664,7 @@ out: !fs_info->stripe_root) {btrfs_err (fs_info,"zoned: data %s needs raid-stripe-tree" ,btrfs_bg_type_to_raid_name (map->type)); -return -EINVAL ; + ret = -EINVAL ; }if (cache->alloc_offset > cache->zone_capacity) {
Greg Kroah-Hartman
maintainerPATCH 15/136 btrfs: do not assert we found block group item when creating free space tree
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <[email protected]>
commit a5a51bf4e9b7354ce7cd697e610d72c1b33fd949 upstream.
Currently, when building a free space tree at populate_free_space_tree(), if we are not using the block group tree feature, we always expect to find block group items (either extent items or a block group item with key type BTRFS_BLOCK_GROUP_ITEM_KEY) when we search the extent tree with btrfs_search_slot_for_read(), so we assert that we found an item. However this expectation is wrong since we can have a new block group created in the current transaction which is still empty and for which we still have not added the block group's item to the extent tree, in which case we do not have any items in the extent tree associated to the block group.
The insertion of a new block group's block group item in the extent tree happens at btrfs_create_pending_block_groups() when it calls the helper insert_block_group_item(). This typically is done when a transaction handle is released, committed or when running delayed refs (either as part of a transaction commit or when serving tickets for space reservation if we are low on free space).
So remove the assertion at populate_free_space_tree() even when the block group tree feature is not enabled and update the comment to mention this case.
Syzbot reported this with the following stack trace:
BTRFS info (device loop3 state M): rebuilding free space tree assertion failed: ret == 0 :: 0, in fs/btrfs/free-space-tree.c:1115
------------[ cut here ]------------ kernel BUG at fs/btrfs/free-space-tree.c:1115! Oops: invalid opcode: 0000 [#1] SMP KASAN PTI CPU: 1 UID: 0 PID: 6352 Comm: syz.3.25 Not tainted syzkaller #0 PREEMPT(full) Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 08/18/2025 RIP: 0010:populate_free_space_tree+0x700/0x710 fs/btrfs/free-space-tree.c:1115 Code: ff ff e8 d3 (...) RSP: 0018:ffffc9000430f780 EFLAGS: 00010246 RAX: 0000000000000043 RBX: ffff88805b709630 RCX: fea61d0e2e79d000 RDX: 0000000000000000 RSI: 0000000080000000 RDI: 0000000000000000 RBP: ffffc9000430f8b0 R08: ffffc9000430f4a7 R09: 1ffff92000861e94 R10: dffffc0000000000 R11: fffff52000861e95 R12: 0000000000000001 R13: 1ffff92000861f00 R14: dffffc0000000000 R15: 0000000000000000 FS: 00007f424d9fe6c0(0000) GS:ffff888125afc000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fd78ad212c0 CR3: 0000000076d68000 CR4: 00000000003526f0 Call Trace: <TASK> btrfs_rebuild_free_space_tree+0x1ba/0x6d0 fs/btrfs/free-space-tree.c:1364 btrfs_start_pre_rw_mount+0x128f/0x1bf0 fs/btrfs/disk-io.c:3062 btrfs_remount_rw fs/btrfs/super.c:1334 [inline] btrfs_reconfigure+0xaed/0x2160 fs/btrfs/super.c:1559 reconfigure_super+0x227/0x890 fs/super.c:1076 do_remount fs/namespace.c:3279 [inline] path_mount+0xd1a/0xfe0 fs/namespace.c:4027 do_mount fs/namespace.c:4048 [inline] __do_sys_mount fs/namespace.c:4236 [inline] __se_sys_mount+0x313/0x410 fs/namespace.c:4213 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f424e39066a Code: d8 64 89 02 (...) RSP: 002b:00007f424d9fde68 EFLAGS: 00000246 ORIG_RAX: 00000000000000a5 RAX: ffffffffffffffda RBX: 00007f424d9fdef0 RCX: 00007f424e39066a RDX: 0000200000000180 RSI: 0000200000000380 RDI: 0000000000000000 RBP: 0000200000000180 R08: 00007f424d9fdef0 R09: 0000000000000020 R10: 0000000000000020 R11: 0000000000000246 R12: 0000200000000380 R13: 00007f424d9fdeb0 R14: 0000000000000000 R15: 00002000000002c0 </TASK> Modules linked in: ---[ end trace 0000000000000000 ]---
--- fs/btrfs/free-space-tree.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
fs/btrfs/free-space-tree.c +8 -7
@@ -1108,14 +1108,15 @@ static int populate_free_space_tree(stru* If ret is 1 (no key found), it means this is an empty block group, * without any extents allocated from it and there's no block group * item (key BTRFS_BLOCK_GROUP_ITEM_KEY) located in the extent tree -* because we are using the block group tree feature, so block group -* items are stored in the block group tree. It also means there are no -* extents allocated for block groups with a start offset beyond this -* block group's end offset (this is the last, highest, block group). +* because we are using the block group tree feature (so block group +* items are stored in the block group tree) or this is a new block +* group created in the current transaction and its block group item +* was not yet inserted in the extent tree (that happens in +* btrfs_create_pending_block_groups() -> insert_block_group_item()). +* It also means there are no extents allocated for block groups with a +* start offset beyond this block group's end offset (this is the last, +* highest, block group). */ -if (!btrfs_fs_compat_ro (trans->fs_info,BLOCK_GROUP_TREE )) -ASSERT (ret ==0 ); - start = block_group->start; end = block_group->start + block_group->length;while (ret ==0 ) {
Greg Kroah-Hartman
maintainerPATCH 16/136 can: gs_usb: gs_make_candev(): populate net_device->dev_port
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Celeste Liu <[email protected]>
commit a12f0bc764da3781da2019c60826f47a6d7ed64f upstream.
The gs_usb driver supports USB devices with more than 1 CAN channel. In old kernel before 3.15, it uses net_device->dev_id to distinguish different channel in userspace, which was done in commit acff76fa45b4 ("can: gs_usb: gs_make_candev(): set netdev->dev_id"). But since 3.15, the correct way is populating net_device->dev_port. And according to documentation, if network device support multiple interface, lack of net_device->dev_port SHALL be treated as a bug.
--- drivers/net/can/usb/gs_usb.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/can/usb/gs_usb.c +1 -0
@@ -1246,6 +1246,7 @@ static struct gs_can *gs_make_candev(uns netdev->flags |=IFF_ECHO ;/* we support full roundtrip echo */ netdev->dev_id = channel; + netdev->dev_port = channel;/* dev setup */ strcpy (dev->bt_const.name,KBUILD_MODNAME );
Greg Kroah-Hartman
maintainerPATCH 17/136 can: gs_usb: increase max interface to U8_MAX
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Celeste Liu <[email protected]>
commit 2a27f6a8fb5722223d526843040f747e9b0e8060 upstream.
This issue was found by Runcheng Lu when develop HSCanT USB to CAN FD converter[1]. The original developers may have only 3 interfaces device to test so they write 3 here and wait for future change.
During the HSCanT development, we actually used 4 interfaces, so the limitation of 3 is not enough now. But just increase one is not future-proofed. Since the channel index type in gs_host_frame is u8, just make canch[] become a flexible array with a u8 index, so it naturally constraint by U8_MAX and avoid statically allocate 256 pointer for every gs_usb device.
[1]: https://github.com/cherry-embedded/HSCanT-hardware
--- drivers/net/can/usb/gs_usb.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-)
drivers/net/can/usb/gs_usb.c +10 -12
@@ -286,11 +286,6 @@ struct gs_host_frame {#define GS_MAX_RX_URBS 30#define GS_NAPI_WEIGHT 32 -/* Maximum number of interfaces the driver supports per device. -* Current hardware only supports 3 interfaces. The future may vary. -*/ -#define GS_MAX_INTF 3 -struct gs_tx_context {struct gs_can *dev;unsigned int echo_id;
@@ -321,7 +316,6 @@ struct gs_can {/* usb interface struct */ struct gs_usb { -struct gs_can *canch[GS_MAX_INTF ];struct usb_anchor rx_submitted;struct usb_device *udev;
@@ -333,9 +327,11 @@ struct gs_usb {unsigned int hf_size_rx;u8 active_channels; +u8 channel_cnt;unsigned int pipe_in;unsigned int pipe_out; + struct gs_can *canch[] __counted_by(channel_cnt); };/* 'allocate' a tx context.
@@ -596,7 +592,7 @@ static void gs_usb_receive_bulk_callback }/* device reports out of range channel id */ -if (hf->channel >=GS_MAX_INTF ) +if (hf->channel >= parent->channel_cnt) goto device_detach; dev = parent->canch[hf->channel];
@@ -696,7 +692,7 @@ resubmit_urb:/* USB failure take down all interfaces */ if (rc == -ENODEV ) { device_detach: -for (rc =0 ; rc <GS_MAX_INTF ; rc++) { +for (rc =0 ; rc < parent->channel_cnt; rc++) {if (parent->canch[rc])netif_device_detach (parent->canch[rc]->netdev); }
@@ -1458,17 +1454,19 @@ static int gs_usb_probe(struct usb_inter icount = dconf.icount +1 ;dev_info (&intf->dev,"Configuring for %u interfaces\n" , icount); -if (icount >GS_MAX_INTF ) { +if (icount >type_max (parent->channel_cnt)) {dev_err (&intf->dev,"Driver cannot handle more that %u CAN interfaces\n" , -GS_MAX_INTF ); +type_max (parent->channel_cnt));return -EINVAL ; } - parent =kzalloc (sizeof (*parent),GFP_KERNEL ); + parent =kzalloc (struct_size (parent, canch, icount),GFP_KERNEL );if (!parent)return -ENOMEM ; + parent->channel_cnt = icount; +init_usb_anchor (&parent->rx_submitted);usb_set_intfdata (intf, parent);
@@ -1529,7 +1527,7 @@ static void gs_usb_disconnect(struct usbreturn ; } -for (i =0 ; i <GS_MAX_INTF ; i++) +for (i =0 ; i < parent->channel_cnt; i++)if (parent->canch[i])gs_destroy_candev (parent->canch[i]);
Greg Kroah-Hartman
maintainerPATCH 18/136 cifs: parse_dfs_referrals: prevent oob on malformed input
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eugene Korenevsky <[email protected]>
commit 6447b0e355562a1ff748c4a2ffb89aae7e84d2c9 upstream.
Malicious SMB server can send invalid reply to FSCTL_DFS_GET_REFERRALS
- reply smaller than sizeof(struct get_dfs_referral_rsp)
- reply with number of referrals smaller than NumberOfReferrals in the header
Processing of such replies will cause oob.
Return -EINVAL error on such replies to prevent oob-s.
--- fs/smb/client/misc.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
fs/smb/client/misc.c +17 -0
@@ -913,6 +913,14 @@ parse_dfs_referrals(struct get_dfs_referchar *data_end;struct dfs_referral_level_3 *ref; +if (rsp_size <sizeof (*rsp)) { +cifs_dbg (VFS |ONCE , +"%s: header is malformed (size is %u, must be %zu)\n" , + __func__, rsp_size,sizeof (*rsp)); + rc = -EINVAL ; + goto parse_DFS_referrals_exit; + } + *num_of_nodes =le16_to_cpu (rsp->NumberOfReferrals);if (*num_of_nodes <1 ) {
@@ -921,6 +929,15 @@ parse_dfs_referrals(struct get_dfs_refer rc = -EINVAL ; goto parse_DFS_referrals_exit; } + +if (sizeof (*rsp) + *num_of_nodes *sizeof (REFERRAL3 ) > rsp_size) { +cifs_dbg (VFS |ONCE , +"%s: malformed buffer (size is %u, must be at least %zu)\n" , + __func__, rsp_size, +sizeof (*rsp) + *num_of_nodes *sizeof (REFERRAL3 )); + rc = -EINVAL ; + goto parse_DFS_referrals_exit; + } ref = (struct dfs_referral_level_3 *) &(rsp->referrals);if (ref->VersionNumber !=cpu_to_le16 (3 )) {
Greg Kroah-Hartman
maintainerPATCH 19/136 drm/sched: Fix potential double free in drm_sched_job_add_resv_dependencies
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tvrtko Ursulin <[email protected]>
commit 5801e65206b065b0b2af032f7f1eef222aa2fd83 upstream.
When adding dependencies with drm_sched_job_add_dependency(), that function consumes the fence reference both on success and failure, so in the latter case the dma_fence_put() on the error path (xarray failed to expand) is a double free.
Interestingly this bug appears to have been present ever since commit ebd5f74255b9 ("drm/sched: Add dependency tracking"), since the code back then looked like this:
drm_sched_job_add_implicit_dependencies():
...
for (i = 0; i < fence_count; i++) {
ret = drm_sched_job_add_dependency(job, fences[i]);
if (ret)
break;
}
for (; i < fence_count; i++)
dma_fence_put(fences[i]);Which means for the failing 'i' the dma_fence_put was already a double free. Possibly there were no users at that time, or the test cases were insufficient to hit it.
The bug was then only noticed and fixed after
commit 9c2ba265352a ("drm/scheduler: use new iterator in drm_sched_job_add_implicit_dependencies v2") landed, with its fixup of
commit 4eaf02d6076c ("drm/scheduler: fix drm_sched_job_add_implicit_dependencies").
At that point it was a slightly different flavour of a double free, which commit 963d0b356935 ("drm/scheduler: fix drm_sched_job_add_implicit_dependencies harder") noticed and attempted to fix.
But it only moved the double free from happening inside the drm_sched_job_add_dependency(), when releasing the reference not yet obtained, to the caller, when releasing the reference already released by the former in the failure case.
As such it is not easy to identify the right target for the fixes tag so lets keep it simple and just continue the chain.
While fixing we also improve the comment and explain the reason for taking the reference and not dropping it.
--- drivers/gpu/drm/scheduler/sched_main.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/gpu/drm/scheduler/sched_main.c +7 -6
@@ -952,13 +952,14 @@ int drm_sched_job_add_resv_dependencies(dma_resv_assert_held (resv);dma_resv_for_each_fence (&cursor, resv, usage, fence) { -/* Make sure to grab an additional ref on the added fence */ -dma_fence_get (fence); - ret =drm_sched_job_add_dependency (job, fence); -if (ret) { -dma_fence_put (fence); +/* +* As drm_sched_job_add_dependency always consumes the fence +* reference (even when it fails), and dma_resv_for_each_fence +* is not obtaining one, we need to grab one before calling. +*/ + ret =drm_sched_job_add_dependency (job,dma_fence_get (fence)); +if (ret)return ret; - } }return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 20/136 drm/ast: Blank with VGACR17 sync enable, always clear VGACRB6 sync off
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Zimmermann <[email protected]>
commit 6f719373b943a955fee6fc2012aed207b65e2854 upstream.
Blank the display by disabling sync pulses with VGACR17<7>. Unblank by reenabling them. This VGA setting should be supported by all Aspeed hardware.
Ast currently blanks via sync-off bits in VGACRB6. Not all BMCs handle VGACRB6 correctly. After disabling sync during a reboot, some BMCs do not reenable it after the soft reset. The display output remains dark. When the display is off during boot, some BMCs set the sync-off bits in VGACRB6, so the display remains dark. Observed with Blackbird AST2500 BMCs. Clearing the sync-off bits unconditionally fixes these issues.
Also do not modify VGASR1's SD bit for blanking, as it only disables GPU access to video memory.
v2:
- init vgacrb6 correctly (Jocelyn)
--- drivers/gpu/drm/ast/ast_mode.c | 18 ++++++++++-------- drivers/gpu/drm/ast/ast_reg.h | 1 + 2 files changed, 11 insertions(+), 8 deletions(-)
drivers/gpu/drm/ast/ast_mode.c +10 -8
@@ -1195,22 +1195,24 @@ ast_crtc_helper_atomic_flush(struct drm_static void ast_crtc_helper_atomic_enable (struct drm_crtc *crtc,struct drm_atomic_state *state) {struct ast_device *ast =to_ast_device (crtc->dev); +u8 vgacr17 =0x00 ; +u8 vgacrb6 =0xff ; -ast_set_index_reg_mask (ast,AST_IO_VGACRI ,0xb6 ,0xfc ,0x00 ); -ast_set_index_reg_mask (ast,AST_IO_VGASRI ,0x01 ,0xdf ,0x00 ); + vgacr17 |=AST_IO_VGACR17_SYNC_ENABLE ; + vgacrb6 &= ~(AST_IO_VGACRB6_VSYNC_OFF |AST_IO_VGACRB6_HSYNC_OFF ); + +ast_set_index_reg_mask (ast,AST_IO_VGACRI ,0x17 ,0x7f , vgacr17); +ast_set_index_reg_mask (ast,AST_IO_VGACRI ,0xb6 ,0xfc , vgacrb6); }static void ast_crtc_helper_atomic_disable (struct drm_crtc *crtc,struct drm_atomic_state *state) {struct drm_crtc_state *old_crtc_state =drm_atomic_get_old_crtc_state (state, crtc);struct ast_device *ast =to_ast_device (crtc->dev); -u8 vgacrb6; +u8 vgacr17 =0xff ; -ast_set_index_reg_mask (ast,AST_IO_VGASRI ,0x01 ,0xdf ,AST_IO_VGASR1_SD ); - - vgacrb6 =AST_IO_VGACRB6_VSYNC_OFF | -AST_IO_VGACRB6_HSYNC_OFF ; -ast_set_index_reg_mask (ast,AST_IO_VGACRI ,0xb6 ,0xfc , vgacrb6); + vgacr17 &= ~AST_IO_VGACR17_SYNC_ENABLE ; +ast_set_index_reg_mask (ast,AST_IO_VGACRI ,0x17 ,0x7f , vgacr17);/* * HW cursors require the underlying primary plane and CRTC to
drivers/gpu/drm/ast/ast_reg.h +1 -0
@@ -29,6 +29,7 @@#define AST_IO_VGAGRI (0x4E)#define AST_IO_VGACRI (0x54) +#define AST_IO_VGACR17_SYNC_ENABLE BIT(7)/* called "Hardware reset" in docs */ #define AST_IO_VGACR80_PASSWORD (0xa8)#define AST_IO_VGACRA1_VGAIO_DISABLED BIT(1)#define AST_IO_VGACRA1_MMIO_ENABLED BIT(2)
Re: [PATCH 6.12 020/136] drm/ast: Blank with VGACR17 sync enable, always clear VGACRB6 sync off
Hi Greg,
Am 21.10.2025 um 21:50 schrieb Greg Kroah-Hartman:
Quoted 11 lines
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Zimmermann <[email protected]>
commit
6f719373b943a955fee6fc2012aed207b65e2854upstream.Blank the display by disabling sync pulses with VGACR17<7>. Unblank by reenabling them. This VGA setting should be supported by all Aspeed hardware.
This patch breaks VGA output on my machine. I have already reported this regression against mainline 6.18-rc2, see here:
https://lore.kernel.org/all/[email protected]/
When I revert this patch from 6.12.55-rc1, the issue goes away, just as in mainline. I'm still going to test 6.17.5-rc1 too and report back, but I guess it will be just the same.
Beste Grüße,
Peter Schneider
Signature · 8 lines
Climb the mountain not to plant your flag, but to embrace the challenge, enjoy the air and behold the view. Climb it so you can see the world, not so the world can see you. -- David McCullough Jr. OpenPGP: 0xA3828BD796CCE11A8CADE8866E3A92C92C3FF244 Download: https://www.peters-netzplatz.de/download/pschneider1968_pub.asc https://keys.mailvelope.com/pks/lookup?op=get&[email protected] https://keys.mailvelope.com/pks/lookup?op=get&[email protected]
Greg Kroah-Hartman
maintainerRe: [PATCH 6.12 020/136] drm/ast: Blank with VGACR17 sync enable, always clear VGACRB6 sync off
Quoted 15 lines · Peter Schneider
Hi Greg,
Am 21.10.2025 um 21:50 schrieb Greg Kroah-Hartman:
Quoted 11 lines
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Zimmermann <[email protected]>
commit
6f719373b943a955fee6fc2012aed207b65e2854upstream.Blank the display by disabling sync pulses with VGACR17<7>. Unblank by reenabling them. This VGA setting should be supported by all Aspeed hardware.
Quoted 7 lines
This patch breaks VGA output on my machine. I have already reported this regression against mainline 6.18-rc2, see here:
https://lore.kernel.org/all/[email protected]/
When I revert this patch from 6.12.55-rc1, the issue goes away, just as in mainline. I'm still going to test 6.17.5-rc1 too and report back, but I guess it will be just the same.
Now dropped from this queue as well. I'll go push out a -rc2 to be safe.
thanks,
greg k-h
Greg Kroah-Hartman
maintainerPATCH 21/136 drm/amdgpu: use atomic functions with memory barriers for vm fault info
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gui-Dong Han <[email protected]>
commit 6df8e84aa6b5b1812cc2cacd6b3f5ccbb18cda2b upstream.
The atomic variable vm_fault_info_updated is used to synchronize access to adev->gmc.vm_fault_info between the interrupt handler and get_vm_fault_info().
The default atomic functions like atomic_set() and atomic_read() do not provide memory barriers. This allows for CPU instruction reordering, meaning the memory accesses to vm_fault_info and the vm_fault_info_updated flag are not guaranteed to occur in the intended order. This creates a race condition that can lead to inconsistent or stale data being used.
The previous implementation, which used an explicit mb(), was incomplete and inefficient. It failed to account for all potential CPU reorderings, such as the access of vm_fault_info being reordered before the atomic_read of the flag. This approach is also more verbose and less performant than using the proper atomic functions with acquire/release semantics.
Fix this by switching to atomic_set_release() and atomic_read_acquire(). These functions provide the necessary acquire and release semantics, which act as memory barriers to ensure the correct order of operations. It is also more efficient and idiomatic than using explicit full memory barriers.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 5 ++--- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 7 +++---- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 7 +++---- 3 files changed, 8 insertions(+), 11 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +2 -3
@@ -2353,10 +2353,9 @@ void amdgpu_amdkfd_gpuvm_unmap_gtt_bo_frint amdgpu_amdkfd_gpuvm_get_vm_fault_info (struct amdgpu_device *adev,struct kfd_vm_fault_info *mem) { -if (atomic_read (&adev->gmc.vm_fault_info_updated) ==1 ) { +if (atomic_read_acquire (&adev->gmc.vm_fault_info_updated) ==1 ) { *mem = *adev->gmc.vm_fault_info; -mb ();/* make sure read happened */ -atomic_set (&adev->gmc.vm_fault_info_updated,0 ); +atomic_set_release (&adev->gmc.vm_fault_info_updated,0 ); }return 0 ; }
drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +3 -4
@@ -1055,7 +1055,7 @@ static int gmc_v7_0_sw_init(void *handle GFP_KERNEL);if (!adev->gmc.vm_fault_info)return -ENOMEM ; -atomic_set (&adev->gmc.vm_fault_info_updated,0 ); +atomic_set_release (&adev->gmc.vm_fault_info_updated,0 );return 0 ; }
@@ -1287,7 +1287,7 @@ static int gmc_v7_0_process_interrupt(st vmid =REG_GET_FIELD (status,VM_CONTEXT1_PROTECTION_FAULT_STATUS ,VMID );if (amdgpu_amdkfd_is_kfd_vmid (adev, vmid) - && !atomic_read (&adev->gmc.vm_fault_info_updated)) { + && !atomic_read_acquire (&adev->gmc.vm_fault_info_updated)) {struct kfd_vm_fault_info *info = adev->gmc.vm_fault_info; u32 protections = REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS,
@@ -1303,8 +1303,7 @@ static int gmc_v7_0_process_interrupt(st info->prot_read = protections &0x8 ? true : false; info->prot_write = protections &0x10 ? true : false; info->prot_exec = protections &0x20 ? true : false; -mb (); -atomic_set (&adev->gmc.vm_fault_info_updated,1 ); +atomic_set_release (&adev->gmc.vm_fault_info_updated,1 ); }return 0 ;
drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +3 -4
@@ -1168,7 +1168,7 @@ static int gmc_v8_0_sw_init(void *handle GFP_KERNEL);if (!adev->gmc.vm_fault_info)return -ENOMEM ; -atomic_set (&adev->gmc.vm_fault_info_updated,0 ); +atomic_set_release (&adev->gmc.vm_fault_info_updated,0 );return 0 ; }
@@ -1468,7 +1468,7 @@ static int gmc_v8_0_process_interrupt(st vmid =REG_GET_FIELD (status,VM_CONTEXT1_PROTECTION_FAULT_STATUS ,VMID );if (amdgpu_amdkfd_is_kfd_vmid (adev, vmid) - && !atomic_read (&adev->gmc.vm_fault_info_updated)) { + && !atomic_read_acquire (&adev->gmc.vm_fault_info_updated)) {struct kfd_vm_fault_info *info = adev->gmc.vm_fault_info; u32 protections = REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS,
@@ -1484,8 +1484,7 @@ static int gmc_v8_0_process_interrupt(st info->prot_read = protections &0x8 ? true : false; info->prot_write = protections &0x10 ? true : false; info->prot_exec = protections &0x20 ? true : false; -mb (); -atomic_set (&adev->gmc.vm_fault_info_updated,1 ); +atomic_set_release (&adev->gmc.vm_fault_info_updated,1 ); }return 0 ;
Greg Kroah-Hartman
maintainerPATCH 22/136 drm/amdgpu: fix gfx12 mes packet status return check
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonathan Kim <[email protected]>
commit d0de79f66a80eeb849033fae34bd07a69ce72235 upstream.
GFX12 MES uses low 32 bits of status return for success (1 or 0) and high bits for debug information if low bits are 0.
GFX11 MES doesn't do this so checking full 64-bit status return for 1 or 0 is still valid.
--- drivers/gpu/drm/amd/amdgpu/mes_v12_0.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/mes_v12_0.c +6 -1
@@ -224,7 +224,12 @@ static int mes_v12_0_submit_pkt_and_poll pipe, x_pkt->header.opcode); r =amdgpu_fence_wait_polling (ring, seq, timeout); -if (r <1 || !*status_ptr) { + +/* +* status_ptr[31:0] == 0 (fail) or status_ptr[63:0] == 1 (success). +* If status_ptr[31:0] == 0 then status_ptr[63:32] will have debug error information. +*/ +if (r <1 || !(lower_32_bits (*status_ptr))) {if (misc_op_str) dev_err(adev->dev, "MES(%d) failed to respond to msg=%s (%s)\n",
Greg Kroah-Hartman
maintainerPATCH 23/136 perf/core: Fix address filter match with backing files
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adrian Hunter <[email protected]>
commit ebfc8542ad62d066771e46c8aa30f5624b89cad8 upstream.
It was reported that Intel PT address filters do not work in Docker containers. That relates to the use of overlayfs.
overlayfs records the backing file in struct vm_area_struct vm_file, instead of the user file that the user mmapped. In order for an address filter to match, it must compare to the user file inode. There is an existing helper file_user_inode() for that situation.
Use file_user_inode() instead of file_inode() to get the inode for address filter matching.
Example:
Setup:
# cd /root
# mkdir test ; cd test ; mkdir lower upper work merged
# cp `which cat` lower
# mount -t overlay overlay -olowerdir=lower,upperdir=upper,workdir=work merged
# perf record --buildid-mmap -e intel_pt//u --filter 'filter * @ /root/test/merged/cat' -- /root/test/merged/cat /proc/self/maps
...
55d61d246000-55d61d2e1000 r-xp 00018000 00:1a 3418 /root/test/merged/cat
...
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.015 MB perf.data ]
# perf buildid-cache --add /root/test/merged/catBefore:
Address filter does not match so there are no control flow packets
# perf script --itrace=e
# perf script --itrace=b | wc -l
0
# perf script -D | grep 'TIP.PGE' | wc -l
0
#After:
Address filter does match so there are control flow packets
# perf script --itrace=e
# perf script --itrace=b | wc -l
235
# perf script -D | grep 'TIP.PGE' | wc -l
57
#With respect to stable kernels, overlayfs mmap function ovl_mmap() was added in v4.19 but file_user_inode() was not added until v6.8 and never back-ported to stable kernels. FMODE_BACKING that it depends on was added in v6.5. This issue has gone largely unnoticed, so back-porting before v6.8 is probably not worth it, so put 6.8 as the stable kernel prerequisite version, although in practice the next long term kernel is 6.12.
--- kernel/events/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/events/core.c +1 -1
@@ -9086,7 +9086,7 @@ static bool perf_addr_filter_match(strucif (!filter->path.dentry)return false; -if (d_inode (filter->path.dentry) !=file_inode (file)) +if (d_inode (filter->path.dentry) !=file_user_inode (file))return false;if (filter->offset > offset + size)
Greg Kroah-Hartman
maintainerPATCH 24/136 perf/core: Fix MMAP event path names with backing files
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adrian Hunter <[email protected]>
commit 8818f507a9391019a3ec7c57b1a32e4b386e48a5 upstream.
Some file systems like FUSE-based ones or overlayfs may record the backing file in struct vm_area_struct vm_file, instead of the user file that the user mmapped.
Since commit def3ae83da02f ("fs: store real path instead of fake path in backing file f_path"), file_path() no longer returns the user file path when applied to a backing file. There is an existing helper file_user_path() for that situation.
Use file_user_path() instead of file_path() to get the path for MMAP and MMAP2 events.
Example:
Setup:
# cd /root
# mkdir test ; cd test ; mkdir lower upper work merged
# cp `which cat` lower
# mount -t overlay overlay -olowerdir=lower,upperdir=upper,workdir=work merged
# perf record -e intel_pt//u -- /root/test/merged/cat /proc/self/maps
...
55b0ba399000-55b0ba434000 r-xp 00018000 00:1a 3419 /root/test/merged/cat
...
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.060 MB perf.data ]
#Before:
File name is wrong (/cat), so decoding fails:
# perf script --no-itrace --show-mmap-events
cat 367 [016] 100.491492: PERF_RECORD_MMAP2 367/367: [0x55b0ba399000(0x9b000) @ 0x18000 00:02 3419 489959280]: r-xp /cat
...
# perf script --itrace=e | wc -l
Warning:
19 instruction trace errors
19
#After:
File name is correct (/root/test/merged/cat), so decoding is ok:
# perf script --no-itrace --show-mmap-events
cat 364 [016] 72.153006: PERF_RECORD_MMAP2 364/364: [0x55ce4003d000(0x9b000) @ 0x18000 00:02 3419 3132534314]: r-xp /root/test/merged/cat
# perf script --itrace=e
# perf script --itrace=e | wc -l
0
#--- kernel/events/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/events/core.c +1 -1
@@ -9010,7 +9010,7 @@ static void perf_event_mmap_event(struct* need to add enough zero bytes after the string to handle * the 64bit alignment we do later. */ - name =file_path (file, buf,PATH_MAX -sizeof (u64)); + name =d_path (file_user_path (file), buf,PATH_MAX -sizeof (u64));if (IS_ERR (name)) { name ="//toolong" ; goto cpy_name;
Greg Kroah-Hartman
maintainerPATCH 25/136 perf/core: Fix MMAP2 event device with backing files
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adrian Hunter <[email protected]>
commit fa4f4bae893fbce8a3edfff1ab7ece0c01dc1328 upstream.
Some file systems like FUSE-based ones or overlayfs may record the backing file in struct vm_area_struct vm_file, instead of the user file that the user mmapped.
That causes perf to misreport the device major/minor numbers of the file system of the file, and the generation of the file, and potentially other inode details. There is an existing helper file_user_inode() for that situation.
Use file_user_inode() instead of file_inode() to get the inode for MMAP2 events.
Example:
Setup:
# cd /root
# mkdir test ; cd test ; mkdir lower upper work merged
# cp `which cat` lower
# mount -t overlay overlay -olowerdir=lower,upperdir=upper,workdir=work merged
# perf record -e cycles:u -- /root/test/merged/cat /proc/self/maps
...
55b2c91d0000-55b2c926b000 r-xp 00018000 00:1a 3419 /root/test/merged/cat
...
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.004 MB perf.data (5 samples) ]
#
# stat /root/test/merged/cat
File: /root/test/merged/cat
Size: 1127792 Blocks: 2208 IO Block: 4096 regular file
Device: 0,26 Inode: 3419 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2025-09-08 12:23:59.453309624 +0000
Modify: 2025-09-08 12:23:59.454309624 +0000
Change: 2025-09-08 12:23:59.454309624 +0000
Birth: 2025-09-08 12:23:59.453309624 +0000Before:
Device reported 00:02 differs from stat output and /proc/self/maps
# perf script --show-mmap-events | grep /root/test/merged/cat
cat 377 [-01] 243.078558: PERF_RECORD_MMAP2 377/377: [0x55b2c91d0000(0x9b000) @ 0x18000 00:02 3419 2068525940]: r-xp /root/test/merged/catAfter:
Device reported 00:1a is the same as stat output and /proc/self/maps
# perf script --show-mmap-events | grep /root/test/merged/cat
cat 362 [-01] 127.755167: PERF_RECORD_MMAP2 362/362: [0x55ba6e781000(0x9b000) @ 0x18000 00:1a 3419 0]: r-xp /root/test/merged/catWith respect to stable kernels, overlayfs mmap function ovl_mmap() was added in v4.19 but file_user_inode() was not added until v6.8 and never back-ported to stable kernels. FMODE_BACKING that it depends on was added in v6.5. This issue has gone largely unnoticed, so back-porting before v6.8 is probably not worth it, so put 6.8 as the stable kernel prerequisite version, although in practice the next long term kernel is 6.12.
--- kernel/events/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/events/core.c +2 -2
@@ -8997,7 +8997,7 @@ static void perf_event_mmap_event(struct flags |=MAP_HUGETLB ;if (file) { -struct inode *inode; +const struct inode *inode;dev_t dev; buf =kmalloc (PATH_MAX ,GFP_KERNEL );
@@ -9015,7 +9015,7 @@ static void perf_event_mmap_event(struct name ="//toolong" ; goto cpy_name; } - inode =file_inode (vma->vm_file); + inode =file_user_inode (vma->vm_file); dev = inode->i_sb->s_dev; ino = inode->i_ino; gen = inode->i_generation;
Greg Kroah-Hartman
maintainerPATCH 26/136 drm/amd: Check whether secure display TA loaded successfully
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello <[email protected]>
commit c760bcda83571e07b72c10d9da175db5051ed971 upstream.
[Why]
Not all renoir hardware supports secure display. If the TA is present but the feature isn't supported it will fail to load or send commands. This shows ERR messages to the user that make it seems like there is a problem.
[How]
Check the resp_status of the context to see if there was an error before trying to send any secure display commands.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +1 -1
@@ -2171,7 +2171,7 @@ static int psp_securedisplay_initialize( } ret =psp_ta_load (psp, &psp->securedisplay_context.context); -if (!ret) { +if (!ret && !psp->securedisplay_context.context.resp_status) { psp->securedisplay_context.context.initialized = true;mutex_init (&psp->securedisplay_context.mutex); }else
Greg Kroah-Hartman
maintainerPATCH 27/136 irqdomain: cdx: Switch to of_fwnode_handle()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Jiri Slaby (SUSE)" <[email protected]>
[ Upstream commit 2a87a55f2281a1096d9e77ac6309b9128c107d97 ]
of_node_to_fwnode() is irqdomain's reimplementation of the "officially" defined of_fwnode_handle(). The former is in the process of being removed, so use the latter instead.
Stable-dep-of: 76254bc489d3 ("cdx: Fix device node reference leak in cdx_msi_domain_init")
--- drivers/cdx/cdx_msi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/cdx/cdx_msi.c +2 -2
@@ -165,7 +165,7 @@ struct irq_domain *cdx_msi_domain_init(sstruct device_node *parent_node;struct irq_domain *parent; - fwnode_handle =of_node_to_fwnode (np); + fwnode_handle =of_fwnode_handle (np); parent_node =of_parse_phandle (np,"msi-map" ,1 );if (!parent_node) {
@@ -173,7 +173,7 @@ struct irq_domain *cdx_msi_domain_init(sreturn NULL ; } - parent =irq_find_matching_fwnode (of_node_to_fwnode (parent_node),DOMAIN_BUS_NEXUS ); + parent =irq_find_matching_fwnode (of_fwnode_handle (parent_node),DOMAIN_BUS_NEXUS );if (!parent || !msi_get_domain_info (parent)) {dev_err (dev,"unable to locate ITS domain\n" );return NULL ;
Greg Kroah-Hartman
maintainerPATCH 28/136 cdx: Fix device node reference leak in cdx_msi_domain_init
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miaoqian Lin <[email protected]>
[ Upstream commit 76254bc489d39dae9a3427f0984fe64213d20548 ]
Add missing of_node_put() call to release
the device node reference obtained via of_parse_phandle().
--- drivers/cdx/cdx_msi.c | 1 + 1 file changed, 1 insertion(+)
drivers/cdx/cdx_msi.c +1 -0
@@ -174,6 +174,7 @@ struct irq_domain *cdx_msi_domain_init(s } parent =irq_find_matching_fwnode (of_fwnode_handle (parent_node),DOMAIN_BUS_NEXUS ); +of_node_put (parent_node);if (!parent || !msi_get_domain_info (parent)) {dev_err (dev,"unable to locate ITS domain\n" );return NULL ;
Greg Kroah-Hartman
maintainerPATCH 29/136 drm/msm/a6xx: Fix PDC sleep sequence
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Akhil P Oommen <[email protected]>
[ Upstream commit f248d5d5159a88ded55329f0b1b463d0f4094228 ]
Since the PDC resides out of the GPU subsystem and cannot be reset in case it enters bad state, utmost care must be taken to trigger the PDC wake/sleep routines in the correct order.
The PDC wake sequence can be exercised only after a PDC sleep sequence. Additionally, GMU firmware should initialize a few registers before the KMD can trigger a PDC sleep sequence. So PDC sleep can't be done if the GMU firmware has not initialized. Track these dependencies using a new status variable and trigger PDC sleep/wake sequences appropriately.
Patchwork: https://patchwork.freedesktop.org/patch/673362/
--- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 28 +++++++++++++++++----------- drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 6 ++++++ 2 files changed, 23 insertions(+), 11 deletions(-)
drivers/gpu/drm/msm/adreno/a6xx_gmu.c +17 -11
@@ -236,6 +236,8 @@ static int a6xx_gmu_start(struct a6xx_gmif (ret)DRM_DEV_ERROR (gmu->dev,"GMU firmware initialization timed out\n" ); +set_bit (GMU_STATUS_FW_START , &gmu->status); +return ret; }
@@ -482,6 +484,9 @@ static int a6xx_rpmh_start(struct a6xx_gint ret;u32 val; +if (!test_and_clear_bit (GMU_STATUS_PDC_SLEEP , &gmu->status)) +return 0 ; +gmu_write (gmu,REG_A6XX_GMU_RSCC_CONTROL_REQ ,BIT (1 )); ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_RSCC_CONTROL_ACK, val,
@@ -509,6 +514,9 @@ static void a6xx_rpmh_stop(struct a6xx_gint ret;u32 val; +if (test_and_clear_bit (GMU_STATUS_FW_START , &gmu->status)) +return ; +gmu_write (gmu,REG_A6XX_GMU_RSCC_CONTROL_REQ ,1 ); ret = gmu_poll_timeout_rscc(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0,
@@ -517,6 +525,8 @@ static void a6xx_rpmh_stop(struct a6xx_gDRM_DEV_ERROR (gmu->dev,"Unable to power off the GPU RSC\n" );gmu_write (gmu,REG_A6XX_GMU_RSCC_CONTROL_REQ ,0 ); + +set_bit (GMU_STATUS_PDC_SLEEP , &gmu->status); }static inline void pdc_write (void __iomem *ptr,u32 offset,u32 value)
@@ -645,8 +655,6 @@ setup_pdc:/* ensure no writes happen before the uCode is fully written */ wmb (); -a6xx_rpmh_stop (gmu); - err:if (!IS_ERR_OR_NULL (pdcptr))iounmap (pdcptr);
@@ -799,19 +807,15 @@ static int a6xx_gmu_fw_start(struct a6xxelse gmu_write (gmu,REG_A6XX_GMU_GENERAL_7 ,1 ); -if (state ==GMU_WARM_BOOT ) { - ret =a6xx_rpmh_start (gmu); -if (ret) -return ret; - }else { + ret =a6xx_rpmh_start (gmu); +if (ret) +return ret; + +if (state ==GMU_COLD_BOOT ) {if (WARN (!adreno_gpu->fw[ADRENO_FW_GMU ],"GMU firmware is not loaded\n" ))return -ENOENT ; - ret =a6xx_rpmh_start (gmu); -if (ret) -return ret; - ret =a6xx_gmu_fw_load (gmu);if (ret)return ret;
@@ -980,6 +984,8 @@ static void a6xx_gmu_force_off(struct a6/* Reset GPU core blocks */ a6xx_gpu_sw_reset (gpu, true); + +a6xx_rpmh_stop (gmu); }static void a6xx_gmu_set_initial_freq (struct msm_gpu *gpu,struct a6xx_gmu *gmu)
drivers/gpu/drm/msm/adreno/a6xx_gmu.h +6 -0
@@ -99,6 +99,12 @@ struct a6xx_gmu {struct completion pd_gate;struct qmp *qmp; + +/* To check if we can trigger sleep seq at PDC. Cleared in a6xx_rpmh_stop() */ +#define GMU_STATUS_FW_START 0 +/* To track if PDC sleep seq was done */ +#define GMU_STATUS_PDC_SLEEP 1 +unsigned long status; };static inline u32 gmu_read (struct a6xx_gmu *gmu,u32 offset)
Greg Kroah-Hartman
maintainerPATCH 30/136 media: nxp: imx8-isi: Drop unused argument to mxc_isi_channel_chain()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Laurent Pinchart <[email protected]>
[ Upstream commit 9a21ffeade25cbf310f5db39a1f9932695dd41bb ]
The bypass argument to the mxc_isi_channel_chain() function is unused. Drop it.
Stable-dep-of: 178aa3360220 ("media: nxp: imx8-isi: m2m: Fix streaming cleanup on release")
--- drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h | 2 +- drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c | 2 +- drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c | 11 +++++------ drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c | 2 +- 4 files changed, 8 insertions(+), 9 deletions(-)
drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h +1 -1
@@ -361,7 +361,7 @@ void mxc_isi_channel_get(struct mxc_isi_void mxc_isi_channel_put (struct mxc_isi_pipe *pipe);void mxc_isi_channel_enable (struct mxc_isi_pipe *pipe);void mxc_isi_channel_disable (struct mxc_isi_pipe *pipe); -int mxc_isi_channel_chain (struct mxc_isi_pipe *pipe,bool bypass); +int mxc_isi_channel_chain (struct mxc_isi_pipe *pipe);void mxc_isi_channel_unchain (struct mxc_isi_pipe *pipe); void mxc_isi_channel_config(struct mxc_isi_pipe *pipe,
drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c +1 -1
@@ -587,7 +587,7 @@ void mxc_isi_channel_release(struct mxc_* * TODO: Support secondary line buffer for downscaling YUV420 images. */ -int mxc_isi_channel_chain (struct mxc_isi_pipe *pipe,bool bypass) +int mxc_isi_channel_chain (struct mxc_isi_pipe *pipe) {/* Channel chaining requires both line and output buffer. */ const u8 resources =MXC_ISI_CHANNEL_RES_OUTPUT_BUF
drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c +5 -6
@@ -493,7 +493,6 @@ static int mxc_isi_m2m_streamon(struct fconst struct mxc_isi_format_info *cap_info = ctx->queues.cap.info;const struct mxc_isi_format_info *out_info = ctx->queues.out.info;struct mxc_isi_m2m *m2m = ctx->m2m; -bool bypass;int ret;if (q->streaming)
@@ -506,15 +505,15 @@ static int mxc_isi_m2m_streamon(struct f goto unlock; } - bypass = cap_pix->width == out_pix->width && - cap_pix->height == out_pix->height && - cap_info->encoding == out_info->encoding; -/* * Acquire the pipe and initialize the channel with the first user of * the M2M device. */ if (m2m->usage_count ==0 ) { +bool bypass = cap_pix->width == out_pix->width && + cap_pix->height == out_pix->height && + cap_info->encoding == out_info->encoding; + ret =mxc_isi_channel_acquire (m2m->pipe, &mxc_isi_m2m_frame_write_done, bypass);
@@ -531,7 +530,7 @@ static int mxc_isi_m2m_streamon(struct f* buffer chaining. */ if (!ctx->chained && out_pix->width >MXC_ISI_MAX_WIDTH_UNCHAINED ) { - ret =mxc_isi_channel_chain (m2m->pipe, bypass); + ret =mxc_isi_channel_chain (m2m->pipe);if (ret) goto deinit;
drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c +1 -1
@@ -855,7 +855,7 @@ int mxc_isi_pipe_acquire(struct mxc_isi_/* Chain the channel if needed for wide resolutions. */ if (sink_fmt->width >MXC_ISI_MAX_WIDTH_UNCHAINED ) { - ret =mxc_isi_channel_chain (pipe, bypass); + ret =mxc_isi_channel_chain (pipe);if (ret)mxc_isi_channel_release (pipe); }
Greg Kroah-Hartman
maintainerPATCH 31/136 media: nxp: imx8-isi: m2m: Fix streaming cleanup on release
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guoniu Zhou <[email protected]>
[ Upstream commit 178aa3360220231dd91e7dbc2eb984525886c9c1 ]
If streamon/streamoff calls are imbalanced, such as when exiting an application with Ctrl+C when streaming, the m2m usage_count will never reach zero and the ISI channel won't be freed. Besides from that, if the input line width is more than 2K, it will trigger a WARN_ON():
[ 59.222120] ------------[ cut here ]------------ [ 59.226758] WARNING: drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c:631 at mxc_isi_channel_chain+0xa4/0x120, CPU#4: v4l2-ctl/654 [ 59.238569] Modules linked in: ap1302 [ 59.242231] CPU: 4 UID: 0 PID: 654 Comm: v4l2-ctl Not tainted 6.16.0-rc4-next-20250704-06511-gff0e002d480a-dirty #258 PREEMPT [ 59.253597] Hardware name: NXP i.MX95 15X15 board (DT) [ 59.258720] pstate: 80400009 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 59.265669] pc : mxc_isi_channel_chain+0xa4/0x120 [ 59.270358] lr : mxc_isi_channel_chain+0x44/0x120 [ 59.275047] sp : ffff8000848c3b40 [ 59.278348] x29: ffff8000848c3b40 x28: ffff0000859b4c98 x27: ffff800081939f00 [ 59.285472] x26: 000000000000000a x25: ffff0000859b4cb8 x24: 0000000000000001 [ 59.292597] x23: ffff0000816f4760 x22: ffff0000816f4258 x21: ffff000084ceb780 [ 59.299720] x20: ffff000084342ff8 x19: ffff000084340000 x18: 0000000000000000 [ 59.306845] x17: 0000000000000000 x16: 0000000000000000 x15: 0000ffffdb369e1c [ 59.313969] x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000 [ 59.321093] x11: 0000000000000000 x10: 0000000000000000 x9 : 0000000000000000 [ 59.328217] x8 : ffff8000848c3d48 x7 : ffff800081930b30 x6 : ffff800081930b30 [ 59.335340] x5 : ffff0000859b6000 x4 : ffff80008193ae80 x3 : ffff800081022420 [ 59.342464] x2 : ffff0000852f6900 x1 : 0000000000000001 x0 : ffff000084341000 [ 59.349590] Call trace: [ 59.352025] mxc_isi_channel_chain+0xa4/0x120 (P) [ 59.356722] mxc_isi_m2m_streamon+0x160/0x20c [ 59.361072] v4l_streamon+0x24/0x30 [ 59.364556] __video_do_ioctl+0x40c/0x4a0 [ 59.368560] video_usercopy+0x2bc/0x690 [ 59.372382] video_ioctl2+0x18/0x24 [ 59.375857] v4l2_ioctl+0x40/0x60 [ 59.379168] __arm64_sys_ioctl+0xac/0x104 [ 59.383172] invoke_syscall+0x48/0x104 [ 59.386916] el0_svc_common.constprop.0+0xc0/0xe0 [ 59.391613] do_el0_svc+0x1c/0x28 [ 59.394915] el0_svc+0x34/0xf4 [ 59.397966] el0t_64_sync_handler+0xa0/0xe4 [ 59.402143] el0t_64_sync+0x198/0x19c [ 59.405801] ---[ end trace 0000000000000000 ]---
Address this issue by moving the streaming preparation and cleanup to the vb2 .prepare_streaming() and .unprepare_streaming() operations. This also simplifies the driver by allowing direct usage of the v4l2_m2m_ioctl_streamon() and v4l2_m2m_ioctl_streamoff() helpers.
--- drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c | 224 ++++++++------------- 1 file changed, 92 insertions(+), 132 deletions(-)
drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c +92 -132
@@ -43,7 +43,6 @@ struct mxc_isi_m2m_ctx_queue_data {struct v4l2_pix_format_mplane format;const struct mxc_isi_format_info *info;u32 sequence; -bool streaming; };struct mxc_isi_m2m_ctx {
@@ -236,6 +235,65 @@ static void mxc_isi_m2m_vb2_buffer_queuev4l2_m2m_buf_queue (ctx->fh.m2m_ctx, vbuf); } +static int mxc_isi_m2m_vb2_prepare_streaming (struct vb2_queue *q) +{ +struct mxc_isi_m2m_ctx *ctx =vb2_get_drv_priv (q); +const struct v4l2_pix_format_mplane *out_pix = &ctx->queues.out.format; +const struct v4l2_pix_format_mplane *cap_pix = &ctx->queues.cap.format; +const struct mxc_isi_format_info *cap_info = ctx->queues.cap.info; +const struct mxc_isi_format_info *out_info = ctx->queues.out.info; +struct mxc_isi_m2m *m2m = ctx->m2m; +int ret; + +guard (mutex)(&m2m->lock); + +if (m2m->usage_count ==INT_MAX ) +return -EOVERFLOW ; + +/* +* Acquire the pipe and initialize the channel with the first user of +* the M2M device. +*/ +if (m2m->usage_count ==0 ) { +bool bypass = cap_pix->width == out_pix->width && + cap_pix->height == out_pix->height && + cap_info->encoding == out_info->encoding; + + ret =mxc_isi_channel_acquire (m2m->pipe, + &mxc_isi_m2m_frame_write_done, + bypass); +if (ret) +return ret; + +mxc_isi_channel_get (m2m->pipe); + } + + m2m->usage_count++; + +/* +* Allocate resources for the channel, counting how many users require +* buffer chaining. +*/ +if (!ctx->chained && out_pix->width >MXC_ISI_MAX_WIDTH_UNCHAINED ) { + ret =mxc_isi_channel_chain (m2m->pipe); +if (ret) + goto err_deinit; + + m2m->chained_count++; + ctx->chained = true; + } + +return 0 ; + +err_deinit: +if (--m2m->usage_count ==0 ) { +mxc_isi_channel_put (m2m->pipe); +mxc_isi_channel_release (m2m->pipe); + } + +return ret; +} +static int mxc_isi_m2m_vb2_start_streaming (struct vb2_queue *q,unsigned int count) {
@@ -265,6 +323,35 @@ static void mxc_isi_m2m_vb2_stop_streami } } +static void mxc_isi_m2m_vb2_unprepare_streaming (struct vb2_queue *q) +{ +struct mxc_isi_m2m_ctx *ctx =vb2_get_drv_priv (q); +struct mxc_isi_m2m *m2m = ctx->m2m; + +guard (mutex)(&m2m->lock); + +/* +* If the last context is this one, reset it to make sure the device +* will be reconfigured when streaming is restarted. +*/ +if (m2m->last_ctx == ctx) + m2m->last_ctx =NULL ; + +/* Free the channel resources if this is the last chained context. */ +if (ctx->chained && --m2m->chained_count ==0 ) +mxc_isi_channel_unchain (m2m->pipe); + ctx->chained = false; + +/* Turn off the light with the last user. */ +if (--m2m->usage_count ==0 ) { +mxc_isi_channel_disable (m2m->pipe); +mxc_isi_channel_put (m2m->pipe); +mxc_isi_channel_release (m2m->pipe); + } + +WARN_ON (m2m->usage_count <0 ); +} +static const struct vb2_ops mxc_isi_m2m_vb2_qops = { .queue_setup = mxc_isi_m2m_vb2_queue_setup, .buf_init = mxc_isi_m2m_vb2_buffer_init,
@@ -272,8 +359,10 @@ static const struct vb2_ops mxc_isi_m2m_ .buf_queue = mxc_isi_m2m_vb2_buffer_queue, .wait_prepare = vb2_ops_wait_prepare, .wait_finish = vb2_ops_wait_finish, + .prepare_streaming = mxc_isi_m2m_vb2_prepare_streaming, .start_streaming = mxc_isi_m2m_vb2_start_streaming, .stop_streaming = mxc_isi_m2m_vb2_stop_streaming, + .unprepare_streaming = mxc_isi_m2m_vb2_unprepare_streaming, }; static int mxc_isi_m2m_queue_init(void *priv, struct vb2_queue *src_vq,
@@ -483,135 +572,6 @@ static int mxc_isi_m2m_s_fmt_vid(structreturn 0 ; } -static int mxc_isi_m2m_streamon (struct file *file,void *fh, -enum v4l2_buf_type type) -{ -struct mxc_isi_m2m_ctx *ctx =to_isi_m2m_ctx (fh); -struct mxc_isi_m2m_ctx_queue_data *q =mxc_isi_m2m_ctx_qdata (ctx, type); -const struct v4l2_pix_format_mplane *out_pix = &ctx->queues.out.format; -const struct v4l2_pix_format_mplane *cap_pix = &ctx->queues.cap.format; -const struct mxc_isi_format_info *cap_info = ctx->queues.cap.info; -const struct mxc_isi_format_info *out_info = ctx->queues.out.info; -struct mxc_isi_m2m *m2m = ctx->m2m; -int ret; - -if (q->streaming) -return 0 ; - -mutex_lock (&m2m->lock); - -if (m2m->usage_count ==INT_MAX ) { - ret = -EOVERFLOW ; - goto unlock; - } - -/* -* Acquire the pipe and initialize the channel with the first user of -* the M2M device. -*/ -if (m2m->usage_count ==0 ) { -bool bypass = cap_pix->width == out_pix->width && - cap_pix->height == out_pix->height && - cap_info->encoding == out_info->encoding; - - ret =mxc_isi_channel_acquire (m2m->pipe, - &mxc_isi_m2m_frame_write_done, - bypass); -if (ret) - goto unlock; - -mxc_isi_channel_get (m2m->pipe); - } - - m2m->usage_count++; - -/* -* Allocate resources for the channel, counting how many users require -* buffer chaining. -*/ -if (!ctx->chained && out_pix->width >MXC_ISI_MAX_WIDTH_UNCHAINED ) { - ret =mxc_isi_channel_chain (m2m->pipe); -if (ret) - goto deinit; - - m2m->chained_count++; - ctx->chained = true; - } - -/* -* Drop the lock to start the stream, as the .device_run() operation -* needs to acquire it. -*/ -mutex_unlock (&m2m->lock); - ret =v4l2_m2m_ioctl_streamon (file, fh, type); -if (ret) { -/* Reacquire the lock for the cleanup path. */ -mutex_lock (&m2m->lock); - goto unchain; - } - - q->streaming = true; - -return 0 ; - -unchain: -if (ctx->chained && --m2m->chained_count ==0 ) -mxc_isi_channel_unchain (m2m->pipe); - ctx->chained = false; - -deinit: -if (--m2m->usage_count ==0 ) { -mxc_isi_channel_put (m2m->pipe); -mxc_isi_channel_release (m2m->pipe); - } - -unlock: -mutex_unlock (&m2m->lock); -return ret; -} - -static int mxc_isi_m2m_streamoff (struct file *file,void *fh, -enum v4l2_buf_type type) -{ -struct mxc_isi_m2m_ctx *ctx =to_isi_m2m_ctx (fh); -struct mxc_isi_m2m_ctx_queue_data *q =mxc_isi_m2m_ctx_qdata (ctx, type); -struct mxc_isi_m2m *m2m = ctx->m2m; - -v4l2_m2m_ioctl_streamoff (file, fh, type); - -if (!q->streaming) -return 0 ; - -mutex_lock (&m2m->lock); - -/* -* If the last context is this one, reset it to make sure the device -* will be reconfigured when streaming is restarted. -*/ -if (m2m->last_ctx == ctx) - m2m->last_ctx =NULL ; - -/* Free the channel resources if this is the last chained context. */ -if (ctx->chained && --m2m->chained_count ==0 ) -mxc_isi_channel_unchain (m2m->pipe); - ctx->chained = false; - -/* Turn off the light with the last user. */ -if (--m2m->usage_count ==0 ) { -mxc_isi_channel_disable (m2m->pipe); -mxc_isi_channel_put (m2m->pipe); -mxc_isi_channel_release (m2m->pipe); - } - -WARN_ON (m2m->usage_count <0 ); - -mutex_unlock (&m2m->lock); - - q->streaming = false; - -return 0 ; -} -static const struct v4l2_ioctl_ops mxc_isi_m2m_ioctl_ops = { .vidioc_querycap = mxc_isi_m2m_querycap,
@@ -632,8 +592,8 @@ static const struct v4l2_ioctl_ops mxc_i .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, - .vidioc_streamon = mxc_isi_m2m_streamon, - .vidioc_streamoff = mxc_isi_m2m_streamoff, + .vidioc_streamon = v4l2_m2m_ioctl_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Greg Kroah-Hartman
maintainerPATCH 32/136 drm/exynos: exynos7_drm_decon: fix uninitialized crtc reference in functions
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kaustabh Chakraborty <[email protected]>
[ Upstream commit d31bbacf783daf1e71fbe5c68df93550c446bf44 ]
Modify the functions to accept a pointer to struct decon_context instead.
Stable-dep-of: e1361a4f1be9 ("drm/exynos: exynos7_drm_decon: remove ctx->suspended")
--- drivers/gpu/drm/exynos/exynos7_drm_decon.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
drivers/gpu/drm/exynos/exynos7_drm_decon.c +4 -7
@@ -81,10 +81,8 @@ static const enum drm_plane_type decon_w DRM_PLANE_TYPE_CURSOR, }; -static void decon_wait_for_vblank (struct exynos_drm_crtc *crtc) +static void decon_wait_for_vblank (struct decon_context *ctx) { -struct decon_context *ctx = crtc->ctx; -if (ctx->suspended)return ;
@@ -100,9 +98,8 @@ static void decon_wait_for_vblank(structDRM_DEV_DEBUG_KMS (ctx->dev,"vblank wait timed out.\n" ); } -static void decon_clear_channels (struct exynos_drm_crtc *crtc) +static void decon_clear_channels (struct decon_context *ctx) { -struct decon_context *ctx = crtc->ctx;unsigned int win, ch_enabled =0 ;/* Check if any channel is enabled. */
@@ -118,7 +115,7 @@ static void decon_clear_channels(struct/* Wait for vsync, as disable channel takes effect at next vsync */ if (ch_enabled) -decon_wait_for_vblank (ctx->crtc); +decon_wait_for_vblank (ctx); } static int decon_ctx_initialize(struct decon_context *ctx,
@@ -126,7 +123,7 @@ static int decon_ctx_initialize(struct d { ctx->drm_dev = drm_dev; -decon_clear_channels (ctx->crtc); +decon_clear_channels (ctx);return exynos_drm_register_dma (drm_dev, ctx->dev, &ctx->dma_priv); }
Greg Kroah-Hartman
maintainerPATCH 33/136 drm/exynos: exynos7_drm_decon: properly clear channels during bind
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kaustabh Chakraborty <[email protected]>
[ Upstream commit 5f1a453974204175f20b3788824a0fe23cc36f79 ]
The DECON channels are not cleared properly as the windows aren't shadow protected. When accompanied with an IOMMU, it pagefaults, and the kernel panics.
Implement shadow protect/unprotect, along with a standalone update, for channel clearing to properly take effect.
Stable-dep-of: e1361a4f1be9 ("drm/exynos: exynos7_drm_decon: remove ctx->suspended")
--- drivers/gpu/drm/exynos/exynos7_drm_decon.c | 55 ++++++++++++++++------------- 1 file changed, 32 insertions(+), 23 deletions(-)
drivers/gpu/drm/exynos/exynos7_drm_decon.c +32 -23
@@ -81,6 +81,28 @@ static const enum drm_plane_type decon_w DRM_PLANE_TYPE_CURSOR, }; +/** +* decon_shadow_protect_win() - disable updating values from shadow registers at vsync +* +* @ctx: display and enhancement controller context +* @win: window to protect registers for +* @protect: 1 to protect (disable updates) +*/ +static void decon_shadow_protect_win (struct decon_context *ctx, +unsigned int win,bool protect) +{ +u32 bits, val; + + bits =SHADOWCON_WINx_PROTECT (win); + + val =readl (ctx->regs +SHADOWCON ); +if (protect) + val |= bits; +else + val &= ~bits; +writel (val, ctx->regs +SHADOWCON ); +} +static void decon_wait_for_vblank (struct decon_context *ctx) {if (ctx->suspended)
@@ -101,18 +123,27 @@ static void decon_wait_for_vblank(structstatic void decon_clear_channels (struct decon_context *ctx) {unsigned int win, ch_enabled =0 ; +u32 val;/* Check if any channel is enabled. */ for (win =0 ; win <WINDOWS_NR ; win++) { -u32 val =readl (ctx->regs +WINCON (win)); + val =readl (ctx->regs +WINCON (win));if (val & WINCONx_ENWIN) { +decon_shadow_protect_win (ctx, win, true); + val &= ~WINCONx_ENWIN;writel (val, ctx->regs +WINCON (win)); ch_enabled =1 ; + +decon_shadow_protect_win (ctx, win, false); } } + val =readl (ctx->regs +DECON_UPDATE ); + val |=DECON_UPDATE_STANDALONE_F ; +writel (val, ctx->regs +DECON_UPDATE ); +/* Wait for vsync, as disable channel takes effect at next vsync */ if (ch_enabled)decon_wait_for_vblank (ctx);
@@ -340,28 +371,6 @@ static void decon_win_set_colkey(structwritel (keycon1, ctx->regs +WKEYCON1_BASE (win)); } -/** -* decon_shadow_protect_win() - disable updating values from shadow registers at vsync -* -* @ctx: display and enhancement controller context -* @win: window to protect registers for -* @protect: 1 to protect (disable updates) -*/ -static void decon_shadow_protect_win (struct decon_context *ctx, -unsigned int win,bool protect) -{ -u32 bits, val; - - bits =SHADOWCON_WINx_PROTECT (win); - - val =readl (ctx->regs +SHADOWCON ); -if (protect) - val |= bits; -else - val &= ~bits; -writel (val, ctx->regs +SHADOWCON ); -} -static void decon_atomic_begin (struct exynos_drm_crtc *crtc) {struct decon_context *ctx = crtc->ctx;
Greg Kroah-Hartman
maintainerPATCH 34/136 drm/exynos: exynos7_drm_decon: remove ctx->suspended
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kaustabh Chakraborty <[email protected]>
[ Upstream commit e1361a4f1be9cb69a662c6d7b5ce218007d6e82b ]
Condition guards are found to be redundant, as the call flow is properly managed now, as also observed in the Exynos5433 DECON driver. Since state checking is no longer necessary, remove it.
This also fixes an issue which prevented decon_commit() from decon_atomic_enable() due to an incorrect state change setting.
--- drivers/gpu/drm/exynos/exynos7_drm_decon.c | 36 ----------------------------- 1 file changed, 36 deletions(-)
drivers/gpu/drm/exynos/exynos7_drm_decon.c +0 -36
@@ -51,7 +51,6 @@ struct decon_context {void __iomem *regs;unsigned long irq_flags;bool i80_if; -bool suspended;wait_queue_head_t wait_vsync_queue;atomic_t wait_vsync_event;
@@ -105,9 +104,6 @@ static void decon_shadow_protect_win(strstatic void decon_wait_for_vblank (struct decon_context *ctx) { -if (ctx->suspended) -return ; -atomic_set (&ctx->wait_vsync_event,1 );/*
@@ -183,9 +179,6 @@ static void decon_commit(struct exynos_dstruct drm_display_mode *mode = &crtc->base.state->adjusted_mode;u32 val, clkdiv; -if (ctx->suspended) -return ; -/* nothing to do if we haven't set the mode yet */ if (mode->htotal ==0 || mode->vtotal ==0 )return ;
@@ -247,9 +240,6 @@ static int decon_enable_vblank(struct exstruct decon_context *ctx = crtc->ctx;u32 val; -if (ctx->suspended) -return -EPERM ; -if (!test_and_set_bit (0 , &ctx->irq_flags)) { val =readl (ctx->regs +VIDINTCON0 );
@@ -272,9 +262,6 @@ static void decon_disable_vblank(structstruct decon_context *ctx = crtc->ctx;u32 val; -if (ctx->suspended) -return ; -if (test_and_clear_bit (0 , &ctx->irq_flags)) { val =readl (ctx->regs +VIDINTCON0 );
@@ -376,9 +363,6 @@ static void decon_atomic_begin(struct exstruct decon_context *ctx = crtc->ctx;int i; -if (ctx->suspended) -return ; -for (i =0 ; i <WINDOWS_NR ; i++)decon_shadow_protect_win (ctx, i, true); }
@@ -398,9 +382,6 @@ static void decon_update_plane(struct exunsigned int cpp = fb->format->cpp[0 ];unsigned int pitch = fb->pitches[0 ]; -if (ctx->suspended) -return ; -/* * SHADOWCON/PRTCON register is used for enabling timing. *
@@ -488,9 +469,6 @@ static void decon_disable_plane(struct eunsigned int win = plane->index;u32 val; -if (ctx->suspended) -return ; -/* protect windows */ decon_shadow_protect_win (ctx, win, true);
@@ -509,9 +487,6 @@ static void decon_atomic_flush(struct exstruct decon_context *ctx = crtc->ctx;int i; -if (ctx->suspended) -return ; -for (i =0 ; i <WINDOWS_NR ; i++)decon_shadow_protect_win (ctx, i, false);exynos_crtc_handle_event (crtc);
@@ -539,9 +514,6 @@ static void decon_atomic_enable(struct estruct decon_context *ctx = crtc->ctx;int ret; -if (!ctx->suspended) -return ; - ret =pm_runtime_resume_and_get (ctx->dev);if (ret <0 ) {DRM_DEV_ERROR (ctx->dev,"failed to enable DECON device.\n" );
@@ -555,8 +527,6 @@ static void decon_atomic_enable(struct edecon_enable_vblank (ctx->crtc);decon_commit (ctx->crtc); - - ctx->suspended = false; }static void decon_atomic_disable (struct exynos_drm_crtc *crtc)
@@ -564,9 +534,6 @@ static void decon_atomic_disable(structstruct decon_context *ctx = crtc->ctx;int i; -if (ctx->suspended) -return ; -/* * We need to make sure that all windows are disabled before we * suspend that connector. Otherwise we might try to scan from
@@ -576,8 +543,6 @@ static void decon_atomic_disable(structdecon_disable_plane (crtc, &ctx->planes[i]);pm_runtime_put_sync (ctx->dev); - - ctx->suspended = true; }static const struct exynos_drm_crtc_ops decon_crtc_ops = {
@@ -698,7 +663,6 @@ static int decon_probe(struct platform_dreturn -ENOMEM ; ctx->dev = dev; - ctx->suspended = true; i80_if_timings =of_get_child_by_name (dev->of_node,"i80-if-timings" );if (i80_if_timings)
Greg Kroah-Hartman
maintainerPATCH 35/136 usb: gadget: Store endpoint pointer in usb_request
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuen-Han Tsai <[email protected]>
[ Upstream commit bfb1d99d969fe3b892db30848aeebfa19d21f57f ]
Gadget function drivers often have goto-based error handling in their bind paths, which can be bug-prone. Refactoring these paths to use __free() scope-based cleanup is desirable, but currently blocked.
The blocker is that usb_ep_free_request(ep, req) requires two parameters, while the __free() mechanism can only pass a pointer to the request itself.
Store an endpoint pointer in the struct usb_request. The pointer is populated centrally in usb_ep_alloc_request() on every successful allocation, making the request object self-contained.
Stable-dep-of: 75a5b8d4ddd4 ("usb: gadget: f_ncm: Refactor bind path to use __free()")
--- drivers/usb/gadget/udc/core.c | 3 +++ include/linux/usb/gadget.h | 2 ++ 2 files changed, 5 insertions(+)
drivers/usb/gadget/udc/core.c +3 -0
@@ -194,6 +194,9 @@ struct usb_request *usb_ep_alloc_request req = ep->ops->alloc_request (ep, gfp_flags); +if (req) + req->ep = ep; +trace_usb_ep_alloc_request (ep, req, req ?0 : -ENOMEM );return req;
include/linux/usb/gadget.h +2 -0
@@ -32,6 +32,7 @@ struct usb_ep;/** * struct usb_request - describes one i/o request +* @ep: The associated endpoint set by usb_ep_alloc_request(). * @buf: Buffer used for data. Always provide this; some controllers * only use PIO, or don't use DMA for some endpoints. * @dma: DMA address corresponding to 'buf'. If you don't set this
@@ -98,6 +99,7 @@ struct usb_ep;*/ struct usb_request { +struct usb_ep *ep;void *buf;unsigned length;dma_addr_t dma;
Greg Kroah-Hartman
maintainerPATCH 36/136 usb: gadget: Introduce free_usb_request helper
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuen-Han Tsai <[email protected]>
[ Upstream commit 201c53c687f2b55a7cc6d9f4000af4797860174b ]
Introduce the free_usb_request() function that frees both the request's buffer and the request itself.
This function serves as the cleanup callback for DEFINE_FREE() to enable automatic, scope-based cleanup for usb_request pointers.
Stable-dep-of: 75a5b8d4ddd4 ("usb: gadget: f_ncm: Refactor bind path to use __free()")
--- include/linux/usb/gadget.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
include/linux/usb/gadget.h +23 -0
@@ -15,6 +15,7 @@#ifndef __LINUX_USB_GADGET_H#define __LINUX_USB_GADGET_H +#include <linux/cleanup.h> #include <linux/configfs.h> #include <linux/device.h> #include <linux/errno.h>
@@ -293,6 +294,28 @@ static inline void usb_ep_fifo_flush(str/*-------------------------------------------------------------------------*/ +/** +* free_usb_request - frees a usb_request object and its buffer +* @req: the request being freed +* +* This helper function frees both the request's buffer and the request object +* itself by calling usb_ep_free_request(). Its signature is designed to be used +* with DEFINE_FREE() to enable automatic, scope-based cleanup for usb_request +* pointers. +*/ +static inline void free_usb_request (struct usb_request *req) +{ +if (!req) +return ; + +kfree (req->buf); +usb_ep_free_request (req->ep, req); +} + +DEFINE_FREE(free_usb_request, struct usb_request *, free_usb_request(_T)) + +/*-------------------------------------------------------------------------*/ +struct usb_dcd_config_params {__u8 bU1devExitLat;/* U1 Device exit Latency */ #define USB_DEFAULT_U1_DEV_EXIT_LAT 0x01/* Less then 1 microsec */
Greg Kroah-Hartman
maintainerPATCH 37/136 usb: gadget: f_ncm: Refactor bind path to use __free()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuen-Han Tsai <[email protected]>
[ Upstream commit 75a5b8d4ddd4eb6b16cb0b475d14ff4ae64295ef ]
After an bind/unbind cycle, the ncm->notify_req is left stale. If a subsequent bind fails, the unified error label attempts to free this stale request, leading to a NULL pointer dereference when accessing ep->ops->free_request.
Refactor the error handling in the bind path to use the __free() automatic cleanup mechanism.
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000020 Call trace: usb_ep_free_request+0x2c/0xec ncm_bind+0x39c/0x3dc usb_add_function+0xcc/0x1f0 configfs_composite_bind+0x468/0x588 gadget_bind_driver+0x104/0x270 really_probe+0x190/0x374 __driver_probe_device+0xa0/0x12c driver_probe_device+0x3c/0x218 __device_attach_driver+0x14c/0x188 bus_for_each_drv+0x10c/0x168 __device_attach+0xfc/0x198 device_initial_probe+0x14/0x24 bus_probe_device+0x94/0x11c device_add+0x268/0x48c usb_add_gadget+0x198/0x28c dwc3_gadget_init+0x700/0x858 __dwc3_set_mode+0x3cc/0x664 process_scheduled_works+0x1d8/0x488 worker_thread+0x244/0x334 kthread+0x114/0x1bc ret_from_fork+0x10/0x20
--- drivers/usb/gadget/function/f_ncm.c | 78 +++++++++++++++--------------------- 1 file changed, 33 insertions(+), 45 deletions(-)
drivers/usb/gadget/function/f_ncm.c +33 -45
@@ -11,6 +11,7 @@* Copyright (C) 2008 Nokia Corporation */ +#include <linux/cleanup.h> #include <linux/kernel.h> #include <linux/interrupt.h> #include <linux/module.h>
@@ -19,6 +20,7 @@#include <linux/crc32.h> #include <linux/usb/cdc.h> +#include <linux/usb/gadget.h> #include "u_ether.h" #include "u_ether_configfs.h"
@@ -1435,18 +1437,18 @@ static int ncm_bind(struct usb_configurastruct usb_ep *ep;struct f_ncm_opts *ncm_opts; + struct usb_os_desc_table *os_desc_table __free(kfree) = NULL; + struct usb_request *request __free(free_usb_request) = NULL; +if (!can_support_ecm (cdev->gadget))return -EINVAL ; ncm_opts = container_of(f->fi, struct f_ncm_opts, func_inst);if (cdev->use_os_string) { - f->os_desc_table =kzalloc (sizeof (*f->os_desc_table), -GFP_KERNEL ); -if (!f->os_desc_table) + os_desc_table =kzalloc (sizeof (*os_desc_table),GFP_KERNEL ); +if (!os_desc_table)return -ENOMEM ; - f->os_desc_n =1 ; - f->os_desc_table[0 ].os_desc = &ncm_opts->ncm_os_desc; }mutex_lock (&ncm_opts->lock);
@@ -1458,16 +1460,15 @@ static int ncm_bind(struct usb_configuramutex_unlock (&ncm_opts->lock);if (status) - goto fail; +return status; ncm_opts->bound = true; us =usb_gstrings_attach (cdev, ncm_strings,ARRAY_SIZE (ncm_string_defs)); -if (IS_ERR (us)) { - status =PTR_ERR (us); - goto fail; - } +if (IS_ERR (us)) +return PTR_ERR (us); + ncm_control_intf.iInterface = us[STRING_CTRL_IDX ].id; ncm_data_nop_intf.iInterface = us[STRING_DATA_IDX ].id; ncm_data_intf.iInterface = us[STRING_DATA_IDX ].id;
@@ -1477,20 +1478,16 @@ static int ncm_bind(struct usb_configura/* allocate instance-specific interface IDs */ status =usb_interface_id (c, f);if (status <0 ) - goto fail; +return status; ncm->ctrl_id = status; ncm_iad_desc.bFirstInterface = status; ncm_control_intf.bInterfaceNumber = status; ncm_union_desc.bMasterInterface0 = status; -if (cdev->use_os_string) - f->os_desc_table[0 ].if_id = - ncm_iad_desc.bFirstInterface; - status =usb_interface_id (c, f);if (status <0 ) - goto fail; +return status; ncm->data_id = status; ncm_data_nop_intf.bInterfaceNumber = status;
@@ -1499,35 +1496,31 @@ static int ncm_bind(struct usb_configura ecm_desc.wMaxSegmentSize =cpu_to_le16 (ncm_opts->max_segment_size); - status = -ENODEV ; -/* allocate instance-specific endpoints */ ep =usb_ep_autoconfig (cdev->gadget, &fs_ncm_in_desc);if (!ep) - goto fail; +return -ENODEV ; ncm->port.in_ep = ep; ep =usb_ep_autoconfig (cdev->gadget, &fs_ncm_out_desc);if (!ep) - goto fail; +return -ENODEV ; ncm->port.out_ep = ep; ep =usb_ep_autoconfig (cdev->gadget, &fs_ncm_notify_desc);if (!ep) - goto fail; +return -ENODEV ; ncm->notify = ep; - status = -ENOMEM ; -/* allocate notification request and buffer */ - ncm->notify_req =usb_ep_alloc_request (ep,GFP_KERNEL ); -if (!ncm->notify_req) - goto fail; - ncm->notify_req->buf =kmalloc (NCM_STATUS_BYTECOUNT ,GFP_KERNEL ); -if (!ncm->notify_req->buf) - goto fail; - ncm->notify_req->context = ncm; - ncm->notify_req->complete = ncm_notify_complete; + request =usb_ep_alloc_request (ep,GFP_KERNEL ); +if (!request) +return -ENOMEM ; + request->buf =kmalloc (NCM_STATUS_BYTECOUNT ,GFP_KERNEL ); +if (!request->buf) +return -ENOMEM ; + request->context = ncm; + request->complete = ncm_notify_complete;/* * support all relevant hardware speeds... we expect that when
@@ -1547,7 +1540,7 @@ static int ncm_bind(struct usb_configura status =usb_assign_descriptors (f, ncm_fs_function, ncm_hs_function, ncm_ss_function, ncm_ss_function);if (status) - goto fail; +return status;/* * NOTE: all that is done without knowing or caring about
@@ -1561,23 +1554,18 @@ static int ncm_bind(struct usb_configurahrtimer_init (&ncm->task_timer,CLOCK_MONOTONIC ,HRTIMER_MODE_REL_SOFT ); ncm->task_timer.function = ncm_tx_timeout; +if (cdev->use_os_string) { + os_desc_table[0 ].os_desc = &ncm_opts->ncm_os_desc; + os_desc_table[0 ].if_id = ncm_iad_desc.bFirstInterface; + f->os_desc_table =no_free_ptr (os_desc_table); + f->os_desc_n =1 ; + } + ncm->notify_req =no_free_ptr (request); +DBG (cdev,"CDC Network: IN/%s OUT/%s NOTIFY/%s\n" , ncm->port.in_ep->name, ncm->port.out_ep->name, ncm->notify->name);return 0 ; - -fail: -kfree (f->os_desc_table); - f->os_desc_n =0 ; - -if (ncm->notify_req) { -kfree (ncm->notify_req->buf); -usb_ep_free_request (ncm->notify, ncm->notify_req); - } - -ERROR (cdev,"%s: can't bind, err %d\n" , f->name, status); - -return status; }static inline struct f_ncm_opts *to_f_ncm_opts (struct config_item *item)
Greg Kroah-Hartman
maintainerPATCH 38/136 usb: gadget: f_acm: Refactor bind path to use __free()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuen-Han Tsai <[email protected]>
[ Upstream commit 47b2116e54b4a854600341487e8b55249e926324 ]
After an bind/unbind cycle, the acm->notify_req is left stale. If a subsequent bind fails, the unified error label attempts to free this stale request, leading to a NULL pointer dereference when accessing ep->ops->free_request.
Refactor the error handling in the bind path to use the __free() automatic cleanup mechanism.
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000020 Call trace: usb_ep_free_request+0x2c/0xec gs_free_req+0x30/0x44 acm_bind+0x1b8/0x1f4 usb_add_function+0xcc/0x1f0 configfs_composite_bind+0x468/0x588 gadget_bind_driver+0x104/0x270 really_probe+0x190/0x374 __driver_probe_device+0xa0/0x12c driver_probe_device+0x3c/0x218 __device_attach_driver+0x14c/0x188 bus_for_each_drv+0x10c/0x168 __device_attach+0xfc/0x198 device_initial_probe+0x14/0x24 bus_probe_device+0x94/0x11c device_add+0x268/0x48c usb_add_gadget+0x198/0x28c dwc3_gadget_init+0x700/0x858 __dwc3_set_mode+0x3cc/0x664 process_scheduled_works+0x1d8/0x488 worker_thread+0x244/0x334 kthread+0x114/0x1bc ret_from_fork+0x10/0x20
--- drivers/usb/gadget/function/f_acm.c | 42 ++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 23 deletions(-)
drivers/usb/gadget/function/f_acm.c +19 -23
@@ -11,12 +11,15 @@/* #define VERBOSE_DEBUG */ +#include <linux/cleanup.h> #include <linux/slab.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/device.h> #include <linux/err.h> +#include <linux/usb/gadget.h> +#include "u_serial.h"
@@ -613,6 +616,7 @@ acm_bind(struct usb_configuration *c, ststruct usb_string *us;int status;struct usb_ep *ep; + struct usb_request *request __free(free_usb_request) = NULL;/* REVISIT might want instance-specific strings to help * distinguish instances ...
@@ -630,7 +634,7 @@ acm_bind(struct usb_configuration *c, st/* allocate instance-specific interface IDs, and patch descriptors */ status =usb_interface_id (c, f);if (status <0 ) - goto fail; +return status; acm->ctrl_id = status; acm_iad_descriptor.bFirstInterface = status;
@@ -639,43 +643,41 @@ acm_bind(struct usb_configuration *c, st status =usb_interface_id (c, f);if (status <0 ) - goto fail; +return status; acm->data_id = status; acm_data_interface_desc.bInterfaceNumber = status; acm_union_desc.bSlaveInterface0 = status; acm_call_mgmt_descriptor.bDataInterface = status; - status = -ENODEV ; -/* allocate instance-specific endpoints */ ep =usb_ep_autoconfig (cdev->gadget, &acm_fs_in_desc);if (!ep) - goto fail; +return -ENODEV ; acm->port.in = ep; ep =usb_ep_autoconfig (cdev->gadget, &acm_fs_out_desc);if (!ep) - goto fail; +return -ENODEV ; acm->port.out = ep; ep =usb_ep_autoconfig (cdev->gadget, &acm_fs_notify_desc);if (!ep) - goto fail; +return -ENODEV ; acm->notify = ep; acm_iad_descriptor.bFunctionProtocol = acm->bInterfaceProtocol; acm_control_interface_desc.bInterfaceProtocol = acm->bInterfaceProtocol;/* allocate notification */ - acm->notify_req =gs_alloc_req (ep, -sizeof (struct usb_cdc_notification ) +2 , -GFP_KERNEL ); -if (!acm->notify_req) - goto fail; + request =gs_alloc_req (ep, +sizeof (struct usb_cdc_notification ) +2 , +GFP_KERNEL ); +if (!request) +return -ENODEV ; - acm->notify_req->complete = acm_cdc_notify_complete; - acm->notify_req->context = acm; + request->complete = acm_cdc_notify_complete; + request->context = acm;/* support all relevant hardware speeds... we expect that when * hardware is dual speed, all bulk-capable endpoints work at
@@ -692,7 +694,9 @@ acm_bind(struct usb_configuration *c, st status =usb_assign_descriptors (f, acm_fs_function, acm_hs_function, acm_ss_function, acm_ss_function);if (status) - goto fail; +return status; + + acm->notify_req =no_free_ptr (request); dev_dbg(&cdev->gadget->dev, "acm ttyGS%d: IN/%s OUT/%s NOTIFY/%s\n",
@@ -700,14 +704,6 @@ acm_bind(struct usb_configuration *c, st acm->port.in->name, acm->port.out->name, acm->notify->name);return 0 ; - -fail: -if (acm->notify_req) -gs_free_req (acm->notify, acm->notify_req); - -ERROR (cdev,"%s/%p: can't bind, err %d\n" , f->name, f, status); - -return status; }static void acm_unbind (struct usb_configuration *c,struct usb_function *f)
Greg Kroah-Hartman
maintainerPATCH 39/136 usb: gadget: f_ecm: Refactor bind path to use __free()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuen-Han Tsai <[email protected]>
[ Upstream commit 42988380ac67c76bb9dff8f77d7ef3eefd50b7b5 ]
After an bind/unbind cycle, the ecm->notify_req is left stale. If a subsequent bind fails, the unified error label attempts to free this stale request, leading to a NULL pointer dereference when accessing ep->ops->free_request.
Refactor the error handling in the bind path to use the __free() automatic cleanup mechanism.
--- drivers/usb/gadget/function/f_ecm.c | 48 +++++++++++++++--------------------- 1 file changed, 20 insertions(+), 28 deletions(-)
drivers/usb/gadget/function/f_ecm.c +20 -28
@@ -8,12 +8,15 @@/* #define VERBOSE_DEBUG */ +#include <linux/cleanup.h> #include <linux/slab.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/device.h> #include <linux/etherdevice.h> +#include <linux/usb/gadget.h> +#include "u_ether.h" #include "u_ether_configfs.h" #include "u_ecm.h"
@@ -678,6 +681,7 @@ ecm_bind(struct usb_configuration *c, ststruct usb_ep *ep;struct f_ecm_opts *ecm_opts; + struct usb_request *request __free(free_usb_request) = NULL;if (!can_support_ecm (cdev->gadget))return -EINVAL ;
@@ -711,7 +715,7 @@ ecm_bind(struct usb_configuration *c, st/* allocate instance-specific interface IDs */ status =usb_interface_id (c, f);if (status <0 ) - goto fail; +return status; ecm->ctrl_id = status; ecm_iad_descriptor.bFirstInterface = status;
@@ -720,24 +724,22 @@ ecm_bind(struct usb_configuration *c, st status =usb_interface_id (c, f);if (status <0 ) - goto fail; +return status; ecm->data_id = status; ecm_data_nop_intf.bInterfaceNumber = status; ecm_data_intf.bInterfaceNumber = status; ecm_union_desc.bSlaveInterface0 = status; - status = -ENODEV ; -/* allocate instance-specific endpoints */ ep =usb_ep_autoconfig (cdev->gadget, &fs_ecm_in_desc);if (!ep) - goto fail; +return -ENODEV ; ecm->port.in_ep = ep; ep =usb_ep_autoconfig (cdev->gadget, &fs_ecm_out_desc);if (!ep) - goto fail; +return -ENODEV ; ecm->port.out_ep = ep;/* NOTE: a status/notification endpoint is *OPTIONAL* but we
@@ -746,20 +748,18 @@ ecm_bind(struct usb_configuration *c, st*/ ep =usb_ep_autoconfig (cdev->gadget, &fs_ecm_notify_desc);if (!ep) - goto fail; +return -ENODEV ; ecm->notify = ep; - status = -ENOMEM ; -/* allocate notification request and buffer */ - ecm->notify_req =usb_ep_alloc_request (ep,GFP_KERNEL ); -if (!ecm->notify_req) - goto fail; - ecm->notify_req->buf =kmalloc (ECM_STATUS_BYTECOUNT ,GFP_KERNEL ); -if (!ecm->notify_req->buf) - goto fail; - ecm->notify_req->context = ecm; - ecm->notify_req->complete = ecm_notify_complete; + request =usb_ep_alloc_request (ep,GFP_KERNEL ); +if (!request) +return -ENOMEM ; + request->buf =kmalloc (ECM_STATUS_BYTECOUNT ,GFP_KERNEL ); +if (!request->buf) +return -ENOMEM ; + request->context = ecm; + request->complete = ecm_notify_complete;/* support all relevant hardware speeds... we expect that when * hardware is dual speed, all bulk-capable endpoints work at
@@ -778,7 +778,7 @@ ecm_bind(struct usb_configuration *c, st status =usb_assign_descriptors (f, ecm_fs_function, ecm_hs_function, ecm_ss_function, ecm_ss_function);if (status) - goto fail; +return status;/* NOTE: all that is done without knowing or caring about * the network link ... which is unavailable to this code
@@ -788,20 +788,12 @@ ecm_bind(struct usb_configuration *c, st ecm->port.open = ecm_open; ecm->port.close = ecm_close; + ecm->notify_req =no_free_ptr (request); +DBG (cdev,"CDC Ethernet: IN/%s OUT/%s NOTIFY/%s\n" , ecm->port.in_ep->name, ecm->port.out_ep->name, ecm->notify->name);return 0 ; - -fail: -if (ecm->notify_req) { -kfree (ecm->notify_req->buf); -usb_ep_free_request (ecm->notify, ecm->notify_req); - } - -ERROR (cdev,"%s: can't bind, err %d\n" , f->name, status); - -return status; }static inline struct f_ecm_opts *to_f_ecm_opts (struct config_item *item)
Greg Kroah-Hartman
maintainerPATCH 40/136 usb: gadget: f_rndis: Refactor bind path to use __free()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuen-Han Tsai <[email protected]>
[ Upstream commit 08228941436047bdcd35a612c1aec0912a29d8cd ]
After an bind/unbind cycle, the rndis->notify_req is left stale. If a subsequent bind fails, the unified error label attempts to free this stale request, leading to a NULL pointer dereference when accessing ep->ops->free_request.
Refactor the error handling in the bind path to use the __free() automatic cleanup mechanism.
--- drivers/usb/gadget/function/f_rndis.c | 85 ++++++++++++++-------------------- 1 file changed, 35 insertions(+), 50 deletions(-)
drivers/usb/gadget/function/f_rndis.c +35 -50
@@ -19,6 +19,8 @@#include <linux/atomic.h> +#include <linux/usb/gadget.h> +#include "u_ether.h" #include "u_ether_configfs.h" #include "u_rndis.h"
@@ -662,6 +664,8 @@ rndis_bind(struct usb_configuration *c,struct usb_ep *ep;struct f_rndis_opts *rndis_opts; + struct usb_os_desc_table *os_desc_table __free(kfree) = NULL; + struct usb_request *request __free(free_usb_request) = NULL;if (!can_support_rndis (c))return -EINVAL ;
@@ -669,12 +673,9 @@ rndis_bind(struct usb_configuration *c, rndis_opts = container_of(f->fi, struct f_rndis_opts, func_inst);if (cdev->use_os_string) { - f->os_desc_table =kzalloc (sizeof (*f->os_desc_table), -GFP_KERNEL ); -if (!f->os_desc_table) + os_desc_table =kzalloc (sizeof (*os_desc_table),GFP_KERNEL ); +if (!os_desc_table)return -ENOMEM ; - f->os_desc_n =1 ; - f->os_desc_table[0 ].os_desc = &rndis_opts->rndis_os_desc; } rndis_iad_descriptor.bFunctionClass = rndis_opts->class;
@@ -692,16 +693,14 @@ rndis_bind(struct usb_configuration *c,gether_set_gadget (rndis_opts->net, cdev->gadget); status =gether_register_netdev (rndis_opts->net);if (status) - goto fail; +return status; rndis_opts->bound = true; } us =usb_gstrings_attach (cdev, rndis_strings,ARRAY_SIZE (rndis_string_defs)); -if (IS_ERR (us)) { - status =PTR_ERR (us); - goto fail; - } +if (IS_ERR (us)) +return PTR_ERR (us); rndis_control_intf.iInterface = us[0 ].id; rndis_data_intf.iInterface = us[1 ].id; rndis_iad_descriptor.iFunction = us[2 ].id;
@@ -709,36 +708,30 @@ rndis_bind(struct usb_configuration *c,/* allocate instance-specific interface IDs */ status =usb_interface_id (c, f);if (status <0 ) - goto fail; +return status; rndis->ctrl_id = status; rndis_iad_descriptor.bFirstInterface = status; rndis_control_intf.bInterfaceNumber = status; rndis_union_desc.bMasterInterface0 = status; -if (cdev->use_os_string) - f->os_desc_table[0 ].if_id = - rndis_iad_descriptor.bFirstInterface; - status =usb_interface_id (c, f);if (status <0 ) - goto fail; +return status; rndis->data_id = status; rndis_data_intf.bInterfaceNumber = status; rndis_union_desc.bSlaveInterface0 = status; - status = -ENODEV ; -/* allocate instance-specific endpoints */ ep =usb_ep_autoconfig (cdev->gadget, &fs_in_desc);if (!ep) - goto fail; +return -ENODEV ; rndis->port.in_ep = ep; ep =usb_ep_autoconfig (cdev->gadget, &fs_out_desc);if (!ep) - goto fail; +return -ENODEV ; rndis->port.out_ep = ep;/* NOTE: a status/notification endpoint is, strictly speaking,
@@ -747,21 +740,19 @@ rndis_bind(struct usb_configuration *c,*/ ep =usb_ep_autoconfig (cdev->gadget, &fs_notify_desc);if (!ep) - goto fail; +return -ENODEV ; rndis->notify = ep; - status = -ENOMEM ; -/* allocate notification request and buffer */ - rndis->notify_req =usb_ep_alloc_request (ep,GFP_KERNEL ); -if (!rndis->notify_req) - goto fail; - rndis->notify_req->buf =kmalloc (STATUS_BYTECOUNT ,GFP_KERNEL ); -if (!rndis->notify_req->buf) - goto fail; - rndis->notify_req->length =STATUS_BYTECOUNT ; - rndis->notify_req->context = rndis; - rndis->notify_req->complete = rndis_response_complete; + request =usb_ep_alloc_request (ep,GFP_KERNEL ); +if (!request) +return -ENOMEM ; + request->buf =kmalloc (STATUS_BYTECOUNT ,GFP_KERNEL ); +if (!request->buf) +return -ENOMEM ; + request->length =STATUS_BYTECOUNT ; + request->context = rndis; + request->complete = rndis_response_complete;/* support all relevant hardware speeds... we expect that when * hardware is dual speed, all bulk-capable endpoints work at
@@ -778,7 +769,7 @@ rndis_bind(struct usb_configuration *c, status =usb_assign_descriptors (f, eth_fs_function, eth_hs_function, eth_ss_function, eth_ss_function);if (status) - goto fail; +return status; rndis->port.open = rndis_open; rndis->port.close = rndis_close;
@@ -789,9 +780,18 @@ rndis_bind(struct usb_configuration *c,if (rndis->manufacturer && rndis->vendorID &&rndis_set_param_vendor (rndis->params, rndis->vendorID, rndis->manufacturer)) { - status = -EINVAL ; - goto fail_free_descs; +usb_free_all_descriptors (f); +return -EINVAL ; + } + +if (cdev->use_os_string) { + os_desc_table[0 ].os_desc = &rndis_opts->rndis_os_desc; + os_desc_table[0 ].if_id = rndis_iad_descriptor.bFirstInterface; + f->os_desc_table =no_free_ptr (os_desc_table); + f->os_desc_n =1 ; + } + rndis->notify_req =no_free_ptr (request);/* NOTE: all that is done without knowing or caring about * the network link ... which is unavailable to this code
@@ -802,21 +802,6 @@ rndis_bind(struct usb_configuration *c, rndis->port.in_ep->name, rndis->port.out_ep->name, rndis->notify->name);return 0 ; - -fail_free_descs: -usb_free_all_descriptors (f); -fail: -kfree (f->os_desc_table); - f->os_desc_n =0 ; - -if (rndis->notify_req) { -kfree (rndis->notify_req->buf); -usb_ep_free_request (rndis->notify, rndis->notify_req); - } - -ERROR (cdev,"%s: can't bind, err %d\n" , f->name, status); - -return status; }void rndis_borrow_net (struct usb_function_instance *f,struct net_device *net)
Greg Kroah-Hartman
maintainerPATCH 41/136 cpufreq: CPPC: Avoid using CPUFREQ_ETERNAL as transition delay
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Rafael J. Wysocki" <[email protected]>
[ Upstream commit f965d111e68f4a993cc44d487d416e3d954eea11 ]
If cppc_get_transition_latency() returns CPUFREQ_ETERNAL to indicate a failure to retrieve the transition latency value from the platform firmware, the CPPC cpufreq driver will use that value (converted to microseconds) as the policy transition delay, but it is way too large for any practical use.
Address this by making the driver use the cpufreq's default transition latency value (in microseconds) as the transition delay if CPUFREQ_ETERNAL is returned by cppc_get_transition_latency().
--- drivers/cpufreq/cppc_cpufreq.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
drivers/cpufreq/cppc_cpufreq.c +12 -2
@@ -339,6 +339,16 @@ static int cppc_verify_policy(struct cpureturn 0 ; } +static unsigned int __cppc_cpufreq_get_transition_delay_us (unsigned int cpu) +{ +unsigned int transition_latency_ns =cppc_get_transition_latency (cpu); + +if (transition_latency_ns ==CPUFREQ_ETERNAL ) +return CPUFREQ_DEFAULT_TRANSITION_LATENCY_NS /NSEC_PER_USEC ; + +return transition_latency_ns /NSEC_PER_USEC ; +} +/* * The PCC subspace describes the rate at which platform can accept commands * on the shared PCC channel (including READs which do not count towards freq
@@ -361,12 +371,12 @@ static unsigned int cppc_cpufreq_get_tra return 10000; } } -return cppc_get_transition_latency (cpu) /NSEC_PER_USEC ; +return __cppc_cpufreq_get_transition_delay_us (cpu); }#else static unsigned int cppc_cpufreq_get_transition_delay_us (unsigned int cpu) { -return cppc_get_transition_latency (cpu) /NSEC_PER_USEC ; +return __cppc_cpufreq_get_transition_delay_us (cpu); }#endif
Greg Kroah-Hartman
maintainerPATCH 42/136 Revert "io_uring/rw: drop -EOPNOTSUPP check in __io_complete_rw_common()"
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jens Axboe <[email protected]>
Commit 927069c4ac2cd1a37efa468596fb5b8f86db9df0 upstream.
This reverts commit 90bfb28d5fa8127a113a140c9791ea0b40ab156a.
Kevin reports that this commit causes an issue for him with LVM snapshots, most likely because of turning off NOWAIT support while a snapshot is being created. This makes -EOPNOTSUPP bubble back through the completion handler, where io_uring read/write handling should just retry it.
Reinstate the previous check removed by the referenced commit.
--- io_uring/rw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
io_uring/rw.c +1 -1
@@ -477,7 +477,7 @@ static void io_req_io_end(struct io_kiocstatic bool __io_complete_rw_common (struct io_kiocb *req,long res) {if (unlikely (res != req->cqe.res)) { -if (res == -EAGAIN &&io_rw_should_reissue (req)) { +if ((res == -EOPNOTSUPP || res == -EAGAIN ) &&io_rw_should_reissue (req)) {/* * Reissue will start accounting again, finish the * current cycle.
Greg Kroah-Hartman
maintainerPATCH 43/136 HID: multitouch: fix sticky fingers
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Tissoires <[email protected]>
commit 46f781e0d151844589dc2125c8cce3300546f92a upstream.
The sticky fingers quirk (MT_QUIRK_STICKY_FINGERS) was only considering the case when slots were not released during the last report. This can be problematic if the firmware forgets to release a finger while others are still present.
This was observed on the Synaptics DLL0945 touchpad found on the Dell XPS 9310 and the Dell Inspiron 5406.
--- drivers/hid/hid-multitouch.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-)
drivers/hid/hid-multitouch.c +14 -13
@@ -83,9 +83,8 @@ enum latency_mode { HID_LATENCY_HIGH = 1, }; -#define MT_IO_FLAGS_RUNNING 0 -#define MT_IO_FLAGS_ACTIVE_SLOTS 1 -#define MT_IO_FLAGS_PENDING_SLOTS 2 +#define MT_IO_SLOTS_MASK GENMASK(7, 0)/* reserve first 8 bits for slot tracking */ +#define MT_IO_FLAGS_RUNNING 32static const bool mtrue = true;/* default for true */ static const bool mfalse;/* default for false */
@@ -160,7 +159,11 @@ struct mt_device {struct mt_class mtclass;/* our mt device class */ struct timer_list release_timer;/* to release sticky fingers */ struct hid_device *hdev;/* hid_device we're attached to */ -unsigned long mt_io_flags;/* mt flags (MT_IO_FLAGS_*) */ +unsigned long mt_io_flags;/* mt flags (MT_IO_FLAGS_RUNNING) +* first 8 bits are reserved for keeping the slot +* states, this is fine because we only support up +* to 250 slots (MT_MAX_MAXCONTACT) +*/ __u8 inputmode_value;/* InputMode HID feature value */ __u8 maxcontacts;bool is_buttonpad;/* is this device a button pad? */
@@ -941,6 +944,7 @@ static void mt_release_pending_palms(strfor_each_set_bit (slotnum, app->pending_palm_slots, td->maxcontacts) {clear_bit (slotnum, app->pending_palm_slots); +clear_bit (slotnum, &td->mt_io_flags);input_mt_slot (input, slotnum);input_mt_report_slot_inactive (input);
@@ -972,12 +976,6 @@ static void mt_sync_frame(struct mt_devi app->num_received =0 ; app->left_button_state =0 ; - -if (test_bit (MT_IO_FLAGS_ACTIVE_SLOTS , &td->mt_io_flags)) -set_bit (MT_IO_FLAGS_PENDING_SLOTS , &td->mt_io_flags); -else -clear_bit (MT_IO_FLAGS_PENDING_SLOTS , &td->mt_io_flags); -clear_bit (MT_IO_FLAGS_ACTIVE_SLOTS , &td->mt_io_flags); }static int mt_compute_timestamp (struct mt_application *app,__s32 value)
@@ -1152,7 +1150,9 @@ static int mt_process_slot(struct mt_devinput_event (input,EV_ABS ,ABS_MT_TOUCH_MAJOR , major);input_event (input,EV_ABS ,ABS_MT_TOUCH_MINOR , minor); -set_bit (MT_IO_FLAGS_ACTIVE_SLOTS , &td->mt_io_flags); +set_bit (slotnum, &td->mt_io_flags); + }else { +clear_bit (slotnum, &td->mt_io_flags); }return 0 ;
@@ -1287,7 +1287,7 @@ static void mt_touch_report(struct hid_d* defect. */ if (app->quirks &MT_QUIRK_STICKY_FINGERS ) { -if (test_bit (MT_IO_FLAGS_PENDING_SLOTS , &td->mt_io_flags)) +if (td->mt_io_flags &MT_IO_SLOTS_MASK )mod_timer (&td->release_timer, jiffies +msecs_to_jiffies (100 ));else
@@ -1734,6 +1734,7 @@ static void mt_release_contacts(struct hfor (i =0 ; i < mt->num_slots; i++) {input_mt_slot (input_dev, i);input_mt_report_slot_inactive (input_dev); +clear_bit (i, &td->mt_io_flags); }input_mt_sync_frame (input_dev);input_sync (input_dev);
@@ -1756,7 +1757,7 @@ static void mt_expired_timeout(struct ti*/ if (test_and_set_bit_lock (MT_IO_FLAGS_RUNNING , &td->mt_io_flags))return ; -if (test_bit (MT_IO_FLAGS_PENDING_SLOTS , &td->mt_io_flags)) +if (td->mt_io_flags &MT_IO_SLOTS_MASK )mt_release_contacts (hdev);clear_bit_unlock (MT_IO_FLAGS_RUNNING , &td->mt_io_flags); }
Greg Kroah-Hartman
maintainerPATCH 44/136 dax: skip read lock assertion for read-only filesystems
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuezhang Mo <[email protected]>
[ Upstream commit 154d1e7ad9e5ce4b2aaefd3862b3dba545ad978d ]
The commit 168316db3583("dax: assert that i_rwsem is held exclusive for writes") added lock assertions to ensure proper locking in DAX operations. However, these assertions trigger false-positive lockdep warnings since read lock is unnecessary on read-only filesystems(e.g., erofs).
This patch skips the read lock assertion for read-only filesystems, eliminating the spurious warnings while maintaining the integrity checks for writable filesystems.
--- fs/dax.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/dax.c +1 -1
@@ -1578,7 +1578,7 @@ dax_iomap_rw(struct kiocb *iocb, struct iov_iter *iter,if (iov_iter_rw (iter) ==WRITE ) {lockdep_assert_held_write (&iomi.inode->i_rwsem); iomi.flags |=IOMAP_WRITE ; - }else { + }else if (!sb_rdonly (iomi.inode->i_sb)) {lockdep_assert_held (&iomi.inode->i_rwsem); }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 45/136 can: m_can: m_can_plat_remove(): add missing pm_runtime_disable()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marc Kleine-Budde <[email protected]>
[ Upstream commit ba569fb07a7e9e9b71e9282e27e993ba859295c2 ]
Commit 227619c3ff7c ("can: m_can: move runtime PM enable/disable to m_can_platform") moved the PM runtime enable from the m_can core driver into the m_can_platform.
That patch forgot to move the pm_runtime_disable() to m_can_plat_remove(), so that unloading the m_can_platform driver causes an "Unbalanced pm_runtime_enable!" error message.
Add the missing pm_runtime_disable() to m_can_plat_remove() to fix the problem.
--- drivers/net/can/m_can/m_can_platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/can/m_can/m_can_platform.c +1 -1
@@ -180,7 +180,7 @@ static void m_can_plat_remove(struct platform_device *pdev)struct m_can_classdev *mcan_class = &priv->cdev;m_can_class_unregister (mcan_class); - +pm_runtime_disable (mcan_class->dev);m_can_class_free_dev (mcan_class->net); }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 46/136 can: m_can: m_can_handle_state_errors(): fix CAN state transition to Error Active
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marc Kleine-Budde <[email protected]>
[ Upstream commit 3d9db29b45f970d81acf61cf91a65442efbeb997 ]
The CAN Error State is determined by the receive and transmit error counters. The CAN error counters decrease when reception/transmission is successful, so that a status transition back to the Error Active status is possible. This transition is not handled by m_can_handle_state_errors().
Add the missing detection of the Error Active state to m_can_handle_state_errors() and extend the handling of this state in m_can_handle_state_change().
Stable-dep-of: 4942c42fe184 ("can: m_can: m_can_chip_config(): bring up interface in correct state")
--- drivers/net/can/m_can/m_can.c | 53 +++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 21 deletions(-)
drivers/net/can/m_can/m_can.c +32 -21
@@ -812,6 +812,9 @@ static int m_can_handle_state_change(struct net_device *dev,u32 timestamp =0 ;switch (new_state) { +case CAN_STATE_ERROR_ACTIVE : + cdev->can.state =CAN_STATE_ERROR_ACTIVE ; +break ;case CAN_STATE_ERROR_WARNING :/* error warning state */ cdev->can.can_stats.error_warning++;
@@ -841,6 +844,12 @@ static int m_can_handle_state_change(struct net_device *dev,__m_can_get_berr_counter (dev, &bec);switch (new_state) { +case CAN_STATE_ERROR_ACTIVE : + cf->can_id |=CAN_ERR_CRTL |CAN_ERR_CNT ; + cf->data[1 ] =CAN_ERR_CRTL_ACTIVE ; + cf->data[6 ] = bec.txerr; + cf->data[7 ] = bec.rxerr; +break ;case CAN_STATE_ERROR_WARNING :/* error warning state */ cf->can_id |=CAN_ERR_CRTL |CAN_ERR_CNT ;
@@ -877,30 +886,33 @@ static int m_can_handle_state_change(struct net_device *dev,return 1 ; } -static int m_can_handle_state_errors (struct net_device *dev,u32 psr) +static enum can_state +m_can_state_get_by_psr (struct m_can_classdev *cdev) { -struct m_can_classdev *cdev =netdev_priv (dev); -int work_done =0 ; +u32 reg_psr; -if (psr &PSR_EW && cdev->can.state !=CAN_STATE_ERROR_WARNING ) { -netdev_dbg (dev,"entered error warning state\n" ); - work_done +=m_can_handle_state_change (dev, -CAN_STATE_ERROR_WARNING ); - } + reg_psr =m_can_read (cdev,M_CAN_PSR ); -if (psr &PSR_EP && cdev->can.state !=CAN_STATE_ERROR_PASSIVE ) { -netdev_dbg (dev,"entered error passive state\n" ); - work_done +=m_can_handle_state_change (dev, -CAN_STATE_ERROR_PASSIVE ); - } +if (reg_psr &PSR_BO ) +return CAN_STATE_BUS_OFF ; +if (reg_psr &PSR_EP ) +return CAN_STATE_ERROR_PASSIVE ; +if (reg_psr &PSR_EW ) +return CAN_STATE_ERROR_WARNING ; -if (psr &PSR_BO && cdev->can.state !=CAN_STATE_BUS_OFF ) { -netdev_dbg (dev,"entered error bus off state\n" ); - work_done +=m_can_handle_state_change (dev, -CAN_STATE_BUS_OFF ); - } +return CAN_STATE_ERROR_ACTIVE ; +} -return work_done; +static int m_can_handle_state_errors (struct net_device *dev) +{ +struct m_can_classdev *cdev =netdev_priv (dev); +enum can_state new_state; + + new_state =m_can_state_get_by_psr (cdev); +if (new_state == cdev->can.state) +return 0 ; + +return m_can_handle_state_change (dev, new_state); }static void m_can_handle_other_err (struct net_device *dev,u32 irqstatus)
@@ -1031,8 +1043,7 @@ static int m_can_rx_handler(struct net_device *dev, int quota, u32 irqstatus) }if (irqstatus &IR_ERR_STATE ) - work_done +=m_can_handle_state_errors (dev, -m_can_read (cdev,M_CAN_PSR )); + work_done +=m_can_handle_state_errors (dev);if (irqstatus &IR_ERR_BUS_30X ) work_done += m_can_handle_bus_errors(dev, irqstatus,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 47/136 can: m_can: m_can_chip_config(): bring up interface in correct state
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marc Kleine-Budde <[email protected]>
[ Upstream commit 4942c42fe1849e6d68dfb5b36ccba344a9fac016 ]
In some SoCs (observed on the STM32MP15) the M_CAN IP core keeps the CAN state and CAN error counters over an internal reset cycle. An external reset is not always possible, due to the shared reset with the other CAN core. This caused the core not always be in Error Active state when bringing up the controller.
Instead of always setting the CAN state to Error Active in m_can_chip_config(), fix this by reading and decoding the Protocol Status Regitser (PSR) and set the CAN state accordingly.
--- drivers/net/can/m_can/m_can.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/can/m_can/m_can.c +1 -1
@@ -1617,7 +1617,7 @@ static int m_can_start(struct net_device *dev)netdev_queue_set_dql_min_limit (netdev_get_tx_queue (cdev->net,0 ), cdev->tx_max_coalesced_frames); - cdev->can.state =CAN_STATE_ERROR_ACTIVE ; + cdev->can.state =m_can_state_get_by_psr (cdev);m_can_enable_all_interrupts (cdev);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 48/136 can: m_can: add deinit callback
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Nyekjaer <[email protected]>
[ Upstream commit baa8aaf79768b72eb7a181c476ca0291613f59e6 ]
This is added in preparation for calling standby mode in the tcan4x5x driver or other users of m_can.
For the tcan4x5x; If Vsup 12V, standby mode will save 7-8mA, when the interface is down.
Stable-dep-of: a9e30a22d6f2 ("can: m_can: fix CAN state in system PM")
--- drivers/net/can/m_can/m_can.c | 7 +++++++ drivers/net/can/m_can/m_can.h | 1 + 2 files changed, 8 insertions(+)
drivers/net/can/m_can/m_can.c +7 -0
@@ -1796,6 +1796,13 @@ static void m_can_stop(struct net_device *dev)/* set the state as STOPPED */ cdev->can.state =CAN_STATE_STOPPED ; + +if (cdev->ops->deinit) { + ret = cdev->ops->deinit (cdev); +if (ret) +netdev_err (dev,"failed to deinitialize: %pe\n" , +ERR_PTR (ret)); + } }static int m_can_close (struct net_device *dev)
drivers/net/can/m_can/m_can.h +1 -0
@@ -68,6 +68,7 @@ struct m_can_ops {int (*write_fifo)(struct m_can_classdev *cdev,int addr_offset,const void *val,size_t val_count);int (*init)(struct m_can_classdev *cdev); +int (*deinit)(struct m_can_classdev *cdev); };struct m_can_tx_op {
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 49/136 can: m_can: call deinit/init callback when going into suspend/resume
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Nyekjaer <[email protected]>
[ Upstream commit ad1ddb3bfb0c9193eb19d4788192904350c7e51a ]
m_can user like the tcan4x5x device, can go into standby mode. Low power RX mode is enabled to allow wake on can.
Stable-dep-of: a9e30a22d6f2 ("can: m_can: fix CAN state in system PM")
--- drivers/net/can/m_can/m_can.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
drivers/net/can/m_can/m_can.c +11 -4
@@ -2485,6 +2485,7 @@ int m_can_class_suspend(struct device *dev) {struct m_can_classdev *cdev =dev_get_drvdata (dev);struct net_device *ndev = cdev->net; +int ret =0 ;if (netif_running (ndev)) {netif_stop_queue (ndev);
@@ -2497,6 +2498,9 @@ int m_can_class_suspend(struct device *dev)if (cdev->pm_wake_source) {hrtimer_cancel (&cdev->hrtimer);m_can_write (cdev,M_CAN_IE ,IR_RF0N ); + +if (cdev->ops->deinit) + ret = cdev->ops->deinit (cdev); }else {m_can_stop (ndev); }
@@ -2508,7 +2512,7 @@ int m_can_class_suspend(struct device *dev) cdev->can.state =CAN_STATE_SLEEPING ; -return 0 ; +return ret; }EXPORT_SYMBOL_GPL (m_can_class_suspend);
@@ -2516,14 +2520,13 @@ int m_can_class_resume(struct device *dev) {struct m_can_classdev *cdev =dev_get_drvdata (dev);struct net_device *ndev = cdev->net; +int ret =0 ;pinctrl_pm_select_default_state (dev); cdev->can.state =CAN_STATE_ERROR_ACTIVE ;if (netif_running (ndev)) { -int ret; - ret =m_can_clk_start (cdev);if (ret)return ret;
@@ -2536,6 +2539,10 @@ int m_can_class_resume(struct device *dev)* again. */ cdev->active_interrupts |=IR_RF0N |IR_TEFN ; + +if (cdev->ops->init) + ret = cdev->ops->init (cdev); +m_can_write (cdev,M_CAN_IE , cdev->active_interrupts); }else { ret =m_can_start (ndev);
@@ -2549,7 +2556,7 @@ int m_can_class_resume(struct device *dev)netif_start_queue (ndev); } -return 0 ; +return ret; }EXPORT_SYMBOL_GPL (m_can_class_resume);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 50/136 can: m_can: fix CAN state in system PM
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marc Kleine-Budde <[email protected]>
[ Upstream commit a9e30a22d6f23a2684c248871cad4c3061181639 ]
A suspend/resume cycle on a down interface results in the interface coming up in Error Active state. A suspend/resume cycle on an Up interface will always result in Error Active state, regardless of the actual CAN state.
During suspend, only set running interfaces to CAN_STATE_SLEEPING. During resume only touch the CAN state of running interfaces. For wakeup sources, set the CAN state depending on the Protocol Status Regitser (PSR), for non wakeup source interfaces m_can_start() will do the same.
--- drivers/net/can/m_can/m_can.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
drivers/net/can/m_can/m_can.c +3 -4
@@ -2506,12 +2506,11 @@ int m_can_class_suspend(struct device *dev) }m_can_clk_stop (cdev); + cdev->can.state =CAN_STATE_SLEEPING ; }pinctrl_pm_select_sleep_state (dev); - cdev->can.state =CAN_STATE_SLEEPING ; -return ret; }EXPORT_SYMBOL_GPL (m_can_class_suspend);
@@ -2524,8 +2523,6 @@ int m_can_class_resume(struct device *dev)pinctrl_pm_select_default_state (dev); - cdev->can.state =CAN_STATE_ERROR_ACTIVE ; -if (netif_running (ndev)) { ret =m_can_clk_start (cdev);if (ret)
@@ -2543,6 +2540,8 @@ int m_can_class_resume(struct device *dev)if (cdev->ops->init) ret = cdev->ops->init (cdev); + cdev->can.state =m_can_state_get_by_psr (cdev); +m_can_write (cdev,M_CAN_IE , cdev->active_interrupts); }else { ret =m_can_start (ndev);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 51/136 net: dlink: handle dma_map_single() failure properly
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yeounsu Moon <[email protected]>
[ Upstream commit 65946eac6d888d50ae527c4e5c237dbe5cc3a2f2 ]
There is no error handling for dma_map_single() failures.
Add error handling by checking dma_mapping_error() and freeing the skb using dev_kfree_skb() (process context) when it fails.
Tested-on: D-Link DGE-550T Rev-A3
--- drivers/net/ethernet/dlink/dl2k.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-)
drivers/net/ethernet/dlink/dl2k.c +16 -7
@@ -498,25 +498,34 @@ static int alloc_list(struct net_device *dev)for (i =0 ; i <RX_RING_SIZE ; i++) {/* Allocated fixed size of skbuff */ struct sk_buff *skb; +dma_addr_t addr; skb =netdev_alloc_skb_ip_align (dev, np->rx_buf_sz); np->rx_skbuff[i] = skb; -if (!skb) { -free_list (dev); -return -ENOMEM ; - } +if (!skb) + goto err_free_list; + + addr =dma_map_single (&np->pdev->dev, skb->data, + np->rx_buf_sz,DMA_FROM_DEVICE ); +if (dma_mapping_error (&np->pdev->dev, addr)) + goto err_kfree_skb; np->rx_ring[i].next_desc =cpu_to_le64 (np->rx_ring_dma + ((i +1 ) %RX_RING_SIZE ) *sizeof (struct netdev_desc ));/* Rubicon now supports 40 bits of addressing space. */ - np->rx_ring[i].fraginfo = -cpu_to_le64 (dma_map_single (&np->pdev->dev, skb->data, - np->rx_buf_sz,DMA_FROM_DEVICE )); + np->rx_ring[i].fraginfo =cpu_to_le64 (addr); np->rx_ring[i].fraginfo |=cpu_to_le64 ((u64 )np->rx_buf_sz <<48 ); }return 0 ; + +err_kfree_skb: +dev_kfree_skb (np->rx_skbuff[i]); + np->rx_skbuff[i] =NULL ; +err_free_list: +free_list (dev); +return -ENOMEM ; }static void rio_hw_init (struct net_device *dev)
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 52/136 doc: fix seg6_flowlabel path
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolas Dichtel <[email protected]>
[ Upstream commit 0b4b77eff5f8cd9be062783a1c1e198d46d0a753 ]
This sysctl is not per interface; it's global per netns.
--- Documentation/networking/seg6-sysctl.rst | 3 +++ 1 file changed, 3 insertions(+)
Documentation/networking/seg6-sysctl.rst +3 -0
@@ -25,6 +25,9 @@ seg6_require_hmac - INTEGER Default is 0. +/proc/sys/net/ipv6/seg6_* variables: +==================================== + seg6_flowlabel - INTEGER Controls the behaviour of computing the flowlabel of outer IPv6 header in case of SR T.encaps
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 53/136 r8169: fix packet truncation after S4 resume on RTL8168H/RTL8111H
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linmao Li <[email protected]>
[ Upstream commit 70f92ab97042f243e1c8da1c457ff56b9b3e49f1 ]
After resume from S4 (hibernate), RTL8168H/RTL8111H truncates incoming packets. Packet captures show messages like "IP truncated-ip - 146 bytes missing!".
The issue is caused by RxConfig not being properly re-initialized after resume. Re-initializing the RxConfig register before the chip re-initialization sequence avoids the truncation and restores correct packet reception.
This follows the same pattern as commit ef9da46ddef0 ("r8169: fix data corruption issue on RTL8402").
--- drivers/net/ethernet/realtek/r8169_main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/net/ethernet/realtek/r8169_main.c +3 -2
@@ -5060,8 +5060,9 @@ static int rtl8169_resume(struct device *device)if (!device_may_wakeup (tp_to_dev (tp)))clk_prepare_enable (tp->clk); -/* Reportedly at least Asus X453MA truncates packets otherwise */ -if (tp->mac_version ==RTL_GIGA_MAC_VER_37 ) +/* Some chip versions may truncate packets without this initialization */ +if (tp->mac_version ==RTL_GIGA_MAC_VER_37 || + tp->mac_version ==RTL_GIGA_MAC_VER_46 )rtl_init_rxcfg (tp);return rtl8169_runtime_resume (device);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 54/136 net/ip6_tunnel: Prevent perpetual tunnel growth
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Safonov <[email protected]>
[ Upstream commit 21f4d45eba0b2dcae5dbc9e5e0ad08735c993f16 ]
Similarly to ipv4 tunnel, ipv6 version updates dev->needed_headroom, too. While ipv4 tunnel headroom adjustment growth was limited in commit 5ae1e9922bbd ("net: ip_tunnel: prevent perpetual headroom growth"), ipv6 tunnel yet increases the headroom without any ceiling.
Reflect ipv4 tunnel headroom adjustment limit on ipv6 version.
Credits to Francesco Ruggeri, who was originally debugging this issue and wrote local Arista-specific patch and a reproducer.
--- include/net/ip_tunnels.h | 15 +++++++++++++++ net/ipv4/ip_tunnel.c | 14 -------------- net/ipv6/ip6_tunnel.c | 3 +-- 3 files changed, 16 insertions(+), 16 deletions(-)
include/net/ip_tunnels.h +15 -0
@@ -605,6 +605,21 @@ struct metadata_dst *iptunnel_metadata_reply(struct metadata_dst *md,int skb_tunnel_check_pmtu (struct sk_buff *skb,struct dst_entry *encap_dst,int headroom,bool reply); +static inline void ip_tunnel_adj_headroom (struct net_device *dev, +unsigned int headroom) +{ +/* we must cap headroom to some upperlimit, else pskb_expand_head +* will overflow header offsets in skb_headers_offset_update(). +*/ +const unsigned int max_allowed =512 ; + +if (headroom > max_allowed) + headroom = max_allowed; + +if (headroom >READ_ONCE (dev->needed_headroom)) +WRITE_ONCE (dev->needed_headroom, headroom); +} +int iptunnel_handle_offloads (struct sk_buff *skb,int gso_type_mask);static inline int iptunnel_pull_offloads (struct sk_buff *skb)
net/ipv4/ip_tunnel.c +0 -14
@@ -567,20 +567,6 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,return 0 ; } -static void ip_tunnel_adj_headroom (struct net_device *dev,unsigned int headroom) -{ -/* we must cap headroom to some upperlimit, else pskb_expand_head -* will overflow header offsets in skb_headers_offset_update(). -*/ -static const unsigned int max_allowed =512 ; - -if (headroom > max_allowed) - headroom = max_allowed; - -if (headroom >READ_ONCE (dev->needed_headroom)) -WRITE_ONCE (dev->needed_headroom, headroom); -} -void ip_md_tunnel_xmit (struct sk_buff *skb,struct net_device *dev,u8 proto,int tunnel_hlen) {
net/ipv6/ip6_tunnel.c +1 -2
@@ -1257,8 +1257,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,*/ max_headroom =LL_RESERVED_SPACE (dst->dev) +sizeof (struct ipv6hdr ) + dst->header_len + t->hlen; -if (max_headroom >READ_ONCE (dev->needed_headroom)) -WRITE_ONCE (dev->needed_headroom, max_headroom); +ip_tunnel_adj_headroom (dev, max_headroom); err =ip6_tnl_encap (skb, t, &proto, fl6);if (err)
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 55/136 amd-xgbe: Avoid spurious link down messages during interface toggle
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Raju Rangoju <[email protected]>
[ Upstream commit 2616222e423398bb374ffcb5d23dea4ba2c3e524 ]
During interface toggle operations (ifdown/ifup), the driver currently resets the local helper variable 'phy_link' to -1. This causes the link state machine to incorrectly interpret the state as a link change event, resulting in spurious "Link is down" messages being logged when the interface is brought back up.
Preserve the phy_link state across interface toggles to avoid treating the -1 sentinel value as a legitimate link state transition.
--- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 1 - drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/amd/xgbe/xgbe-drv.c +0 -1
@@ -1172,7 +1172,6 @@ static void xgbe_free_rx_data(struct xgbe_prv_data *pdata)static int xgbe_phy_reset (struct xgbe_prv_data *pdata) { - pdata->phy_link =-1 ; pdata->phy_speed =SPEED_UNKNOWN ;return pdata->phy_if.phy_reset (pdata);
drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +1 -0
@@ -1664,6 +1664,7 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata) pdata->phy.duplex =DUPLEX_FULL ; } + pdata->phy_link =0 ; pdata->phy.link =0 ; pdata->phy.pause_autoneg = pdata->pause_autoneg;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 56/136 tcp: fix tcp_tso_should_defer() vs large RTT
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 295ce1eb36ae47dc862d6c8a1012618a25516208 ]
Neal reported that using neper tcp_stream with TCP_TX_DELAY set to 50ms would often lead to flows stuck in a small cwnd mode, regardless of the congestion control.
While tcp_stream sets TCP_TX_DELAY too late after the connect(), it highlighted two kernel bugs.
The following heuristic in tcp_tso_should_defer() seems wrong for large RTT:
delta = tp->tcp_clock_cache - head->tstamp;
/* If next ACK is likely to come too late (half srtt), do not defer */ if ((s64)(delta - (u64)NSEC_PER_USEC * (tp->srtt_us >> 4)) < 0)
goto send_now;
If next ACK is expected to come in more than 1 ms, we should not defer because we prefer a smooth ACK clocking.
While blamed commit was a step in the good direction, it was not generic enough.
Another patch fixing TCP_TX_DELAY for established flows will be proposed when net-next reopens.
--- net/ipv4/tcp_output.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-)
net/ipv4/tcp_output.c +15 -4
@@ -2217,7 +2217,8 @@ static bool tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb, u32 max_segs) {const struct inet_connection_sock *icsk =inet_csk (sk); -u32 send_win, cong_win, limit, in_flight; +u32 send_win, cong_win, limit, in_flight, threshold; +u64 srtt_in_ns, expected_ack, how_far_is_the_ack;struct tcp_sock *tp =tcp_sk (sk);struct sk_buff *head;int win_divisor;
@@ -2279,9 +2280,19 @@ static bool tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb, head =tcp_rtx_queue_head (sk);if (!head) goto send_now; - delta = tp->tcp_clock_cache - head->tstamp; -/* If next ACK is likely to come too late (half srtt), do not defer */ -if ((s64)(delta - (u64 )NSEC_PER_USEC * (tp->srtt_us >>4 )) <0 ) + + srtt_in_ns = (u64)(NSEC_PER_USEC >>3 ) * tp->srtt_us; +/* When is the ACK expected ? */ + expected_ack = head->tstamp + srtt_in_ns; +/* How far from now is the ACK expected ? */ + how_far_is_the_ack = expected_ack - tp->tcp_clock_cache; + +/* If next ACK is likely to come too late, +* ie in more than min(1ms, half srtt), do not defer. +*/ + threshold =min (srtt_in_ns >>1 ,NSEC_PER_MSEC ); + +if ((s64)(how_far_is_the_ack - threshold) >0 ) goto send_now;/* Ok, it looks like it is advisable to defer.
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 57/136 ksmbd: fix recursive locking in RPC handle list access
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marios Makassikis <[email protected]>
[ Upstream commit 88f170814fea74911ceab798a43cbd7c5599bed4 ]
Since commit 305853cce3794 ("ksmbd: Fix race condition in RPC handle list access"), ksmbd_session_rpc_method() attempts to lock sess->rpc_lock.
This causes hung connections / tasks when a client attempts to open a named pipe. Using Samba's rpcclient tool:
$ rpcclient //192.168.1.254 -U user%password $ rpcclient $> srvinfo <connection hung here>
Kernel side:
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. task:kworker/0:0 state:D stack:0 pid:5021 tgid:5021 ppid:2 flags:0x00200000
Workqueue: ksmbd-io handle_ksmbd_work Call trace: __schedule from schedule+0x3c/0x58 schedule from schedule_preempt_disabled+0xc/0x10 schedule_preempt_disabled from rwsem_down_read_slowpath+0x1b0/0x1d8 rwsem_down_read_slowpath from down_read+0x28/0x30 down_read from ksmbd_session_rpc_method+0x18/0x3c ksmbd_session_rpc_method from ksmbd_rpc_open+0x34/0x68 ksmbd_rpc_open from ksmbd_session_rpc_open+0x194/0x228 ksmbd_session_rpc_open from create_smb2_pipe+0x8c/0x2c8 create_smb2_pipe from smb2_open+0x10c/0x27ac smb2_open from handle_ksmbd_work+0x238/0x3dc handle_ksmbd_work from process_scheduled_works+0x160/0x25c process_scheduled_works from worker_thread+0x16c/0x1e8 worker_thread from kthread+0xa8/0xb8 kthread from ret_from_fork+0x14/0x38 Exception stack(0x8529ffb0 to 0x8529fff8)
The task deadlocks because the lock is already held:
ksmbd_session_rpc_open
down_write(&sess->rpc_lock)
ksmbd_rpc_open
ksmbd_session_rpc_method
down_read(&sess->rpc_lock) <-- deadlockAdjust ksmbd_session_rpc_method() callers to take the lock when necessary.
--- fs/smb/server/mgmt/user_session.c | 7 ++----- fs/smb/server/smb2pdu.c | 9 ++++++++- fs/smb/server/transport_ipc.c | 12 ++++++++++++ 3 files changed, 22 insertions(+), 6 deletions(-)
fs/smb/server/mgmt/user_session.c +2 -5
@@ -147,14 +147,11 @@ void ksmbd_session_rpc_close(struct ksmbd_session *sess, int id)int ksmbd_session_rpc_method (struct ksmbd_session *sess,int id) {struct ksmbd_session_rpc *entry; -int method; -down_read (&sess->rpc_lock); +lockdep_assert_held (&sess->rpc_lock); entry =xa_load (&sess->rpc_handle_list, id); - method = entry ? entry->method :0 ; -up_read (&sess->rpc_lock); -return method; +return entry ? entry->method :0 ; }void ksmbd_session_destroy (struct ksmbd_session *sess)
fs/smb/server/smb2pdu.c +8 -1
@@ -4623,8 +4623,15 @@ static int smb2_get_info_file_pipe(struct ksmbd_session *sess,* pipe without opening it, checking error condition here */ id = req->VolatileFileId; -if (!ksmbd_session_rpc_method (sess, id)) + +lockdep_assert_not_held (&sess->rpc_lock); + +down_read (&sess->rpc_lock); +if (!ksmbd_session_rpc_method (sess, id)) { +up_read (&sess->rpc_lock);return -ENOENT ; + } +up_read (&sess->rpc_lock);ksmbd_debug (SMB ,"FileInfoClass %u, FileId 0x%llx\n" , req->FileInfoClass, req->VolatileFileId);
fs/smb/server/transport_ipc.c +12 -0
@@ -825,6 +825,9 @@ struct ksmbd_rpc_command *ksmbd_rpc_write(struct ksmbd_session *sess, int handleif (!msg)return NULL ; +lockdep_assert_not_held (&sess->rpc_lock); + +down_read (&sess->rpc_lock); msg->type =KSMBD_EVENT_RPC_REQUEST ; req = (struct ksmbd_rpc_command *)msg->payload; req->handle = handle;
@@ -833,6 +836,7 @@ struct ksmbd_rpc_command *ksmbd_rpc_write(struct ksmbd_session *sess, int handle req->flags |=KSMBD_RPC_WRITE_METHOD ; req->payload_sz = payload_sz;memcpy (req->payload, payload, payload_sz); +up_read (&sess->rpc_lock); resp =ipc_msg_send_request (msg, req->handle);ipc_msg_free (msg);
@@ -849,6 +853,9 @@ struct ksmbd_rpc_command *ksmbd_rpc_read(struct ksmbd_session *sess, int handle)if (!msg)return NULL ; +lockdep_assert_not_held (&sess->rpc_lock); + +down_read (&sess->rpc_lock); msg->type =KSMBD_EVENT_RPC_REQUEST ; req = (struct ksmbd_rpc_command *)msg->payload; req->handle = handle;
@@ -856,6 +863,7 @@ struct ksmbd_rpc_command *ksmbd_rpc_read(struct ksmbd_session *sess, int handle) req->flags |=rpc_context_flags (sess); req->flags |=KSMBD_RPC_READ_METHOD ; req->payload_sz =0 ; +up_read (&sess->rpc_lock); resp =ipc_msg_send_request (msg, req->handle);ipc_msg_free (msg);
@@ -876,6 +884,9 @@ struct ksmbd_rpc_command *ksmbd_rpc_ioctl(struct ksmbd_session *sess, int handleif (!msg)return NULL ; +lockdep_assert_not_held (&sess->rpc_lock); + +down_read (&sess->rpc_lock); msg->type =KSMBD_EVENT_RPC_REQUEST ; req = (struct ksmbd_rpc_command *)msg->payload; req->handle = handle;
@@ -884,6 +895,7 @@ struct ksmbd_rpc_command *ksmbd_rpc_ioctl(struct ksmbd_session *sess, int handle req->flags |=KSMBD_RPC_IOCTL_METHOD ; req->payload_sz = payload_sz;memcpy (req->payload, payload, payload_sz); +up_read (&sess->rpc_lock); resp =ipc_msg_send_request (msg, req->handle);ipc_msg_free (msg);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 58/136 tg3: prevent use of uninitialized remote_adv and local_adv variables
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexey Simakov <[email protected]>
[ Upstream commit 0c3f2e62815a43628e748b1e4ad97a1c46cce703 ]
Some execution paths that jump to the fiber_setup_done label could leave the remote_adv and local_adv variables uninitialized and then use it.
Initialize this variables at the point of definition to avoid this.
--- drivers/net/ethernet/broadcom/tg3.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
drivers/net/ethernet/broadcom/tg3.c +1 -4
@@ -5803,7 +5803,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, bool force_reset)u32 current_speed =SPEED_UNKNOWN ;u8 current_duplex =DUPLEX_UNKNOWN ;bool current_link_up = false; -u32 local_adv, remote_adv, sgsr; +u32 local_adv =0 , remote_adv =0 , sgsr; if ((tg3_asic_rev(tp) == ASIC_REV_5719 || tg3_asic_rev(tp) == ASIC_REV_5720) &&
@@ -5944,9 +5944,6 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, bool force_reset)else current_duplex =DUPLEX_HALF ; - local_adv =0 ; - remote_adv =0 ; -if (bmcr &BMCR_ANENABLE ) {u32 common;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 59/136 tls: trim encrypted message to match the plaintext on short splice
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sabrina Dubroca <[email protected]>
[ Upstream commit ce5af41e3234425a40974696682163edfd21128c ]
During tls_sw_sendmsg_locked, we pre-allocate the encrypted message for the size we're expecting to send during the current iteration, but we may end up sending less, for example when splicing: if we're getting the data from small fragments of memory, we may fill up all the slots in the skmsg with less data than expected.
In this case, we need to trim the encrypted message to only the length we actually need, to avoid pushing uninitialized bytes down the underlying TCP socket.
--- net/tls/tls_sw.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
net/tls/tls_sw.c +4 -1
@@ -1112,8 +1112,11 @@ static int tls_sw_sendmsg_locked(struct sock *sk, struct msghdr *msg, goto send_end; tls_ctx->pending_open_record_frags = true; -if (sk_msg_full (msg_pl)) +if (sk_msg_full (msg_pl)) { full_record = true; +sk_msg_trim (sk, msg_en, + msg_pl->sg.size + prot->overhead_size); + }if (full_record || eor) goto copied;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 60/136 tls: wait for async encrypt in case of error during latter iterations of sendmsg
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sabrina Dubroca <[email protected]>
[ Upstream commit b014a4e066c555185b7c367efacdc33f16695495 ]
If we hit an error during the main loop of tls_sw_sendmsg_locked (eg failed allocation), we jump to send_end and immediately return. Previous iterations may have queued async encryption requests that are still pending. We should wait for those before returning, as we could otherwise be reading from memory that userspace believes we're not using anymore, which would be a sort of use-after-free.
This is similar to what tls_sw_recvmsg already does: failures during the main loop jump to the "wait for async" code, not straight to the unlock/return.
--- net/tls/tls_sw.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
net/tls/tls_sw.c +4 -3
@@ -1054,7 +1054,7 @@ static int tls_sw_sendmsg_locked(struct sock *sk, struct msghdr *msg,if (ret == -EINPROGRESS ) num_async++;else if (ret != -EAGAIN ) - goto send_end; + goto end; } }
@@ -1226,8 +1226,9 @@ static int tls_sw_sendmsg_locked(struct sock *sk, struct msghdr *msg, goto alloc_encrypted; } +send_end:if (!num_async) { - goto send_end; + goto end; }else if (num_zc || eor) {int err;
@@ -1245,7 +1246,7 @@ static int tls_sw_sendmsg_locked(struct sock *sk, struct msghdr *msg,tls_tx_records (sk, msg->msg_flags); } -send_end: +end: ret =sk_stream_error (sk, msg->msg_flags, ret);return copied >0 ? copied : ret; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 61/136 tls: always set record_type in tls_process_cmsg
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sabrina Dubroca <[email protected]>
[ Upstream commit b6fe4c29bb51cf239ecf48eacf72b924565cb619 ]
When userspace wants to send a non-DATA record (via the TLS_SET_RECORD_TYPE cmsg), we need to send any pending data from a previous MSG_MORE send() as a separate DATA record. If that DATA record is encrypted asynchronously, tls_handle_open_record will return -EINPROGRESS. This is currently treated as an error by tls_process_cmsg, and it will skip setting record_type to the correct value, but the caller (tls_sw_sendmsg_locked) handles that return value correctly and proceeds with sending the new message with an incorrect record_type (DATA instead of whatever was requested in the cmsg).
Always set record_type before handling the open record. If tls_handle_open_record returns an error, record_type will be ignored. If it succeeds, whether with synchronous crypto (returning 0) or asynchronous (returning -EINPROGRESS), the caller will proceed correctly.
--- net/tls/tls_main.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
net/tls/tls_main.c +2 -5
@@ -255,12 +255,9 @@ int tls_process_cmsg(struct sock *sk, struct msghdr *msg,if (msg->msg_flags &MSG_MORE )return -EINVAL ; - rc =tls_handle_open_record (sk, msg->msg_flags); -if (rc) -return rc; - *record_type = *(unsigned char *)CMSG_DATA (cmsg); - rc =0 ; + + rc =tls_handle_open_record (sk, msg->msg_flags);break ;default :return -EINVAL ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 62/136 tls: wait for pending async decryptions if tls_strp_msg_hold fails
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sabrina Dubroca <[email protected]>
[ Upstream commit b8a6ff84abbcbbc445463de58704686011edc8e1 ]
Async decryption calls tls_strp_msg_hold to create a clone of the input skb to hold references to the memory it uses. If we fail to allocate that clone, proceeding with async decryption can lead to various issues (UAF on the skb, writing into userspace memory after the recv() call has returned).
In this case, wait for all pending decryption requests.
--- net/tls/tls_sw.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
net/tls/tls_sw.c +4 -2
@@ -1637,8 +1637,10 @@ static int tls_decrypt_sg(struct sock *sk, struct iov_iter *out_iov,if (unlikely (darg->async)) { err =tls_strp_msg_hold (&ctx->strp, &ctx->async_hold); -if (err) -__skb_queue_tail (&ctx->async_hold, darg->skb); +if (err) { + err =tls_decrypt_async_wait (ctx); + darg->async = false; + }return err; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 63/136 tls: dont rely on tx_work during send()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sabrina Dubroca <[email protected]>
[ Upstream commit 7f846c65ca11e63d2409868ff039081f80e42ae4 ]
With async crypto, we rely on tx_work to actually transmit records once encryption completes. But while send() is running, both the tx_lock and socket lock are held, so tx_work_handler cannot process the queue of encrypted records, and simply reschedules itself. During a large send(), this could last a long time, and use a lot of memory.
Transmit any pending encrypted records before restarting the main loop of tls_sw_sendmsg_locked.
--- net/tls/tls_sw.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
net/tls/tls_sw.c +13 -0
@@ -1152,6 +1152,13 @@ static int tls_sw_sendmsg_locked(struct sock *sk, struct msghdr *msg, }else if (ret != -EAGAIN ) goto send_end; } + +/* Transmit if any encryptions have completed */ +if (test_and_clear_bit (BIT_TX_SCHEDULED , &ctx->tx_bitmask)) { +cancel_delayed_work (&ctx->tx_work.work); +tls_tx_records (sk, msg->msg_flags); + } +continue ; rollback_iter: copied -= try_to_copy;
@@ -1207,6 +1214,12 @@ static int tls_sw_sendmsg_locked(struct sock *sk, struct msghdr *msg, goto send_end; } } + +/* Transmit if any encryptions have completed */ +if (test_and_clear_bit (BIT_TX_SCHEDULED , &ctx->tx_bitmask)) { +cancel_delayed_work (&ctx->tx_work.work); +tls_tx_records (sk, msg->msg_flags); + } }continue ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 64/136 netdevsim: set the carrier when the device goes up
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <[email protected]>
[ Upstream commit 1a8fed52f7be14e45785e8e54d0d0b50fc17dbd8 ]
Bringing a linked netdevsim device down and then up causes communication failure because both interfaces lack carrier. Basically a ifdown/ifup on the interface make the link broken.
Commit 3762ec05a9fbda ("netdevsim: add NAPI support") added supported for NAPI, calling netif_carrier_off() in nsim_stop(). This patch re-enables the carrier symmetrically on nsim_open(), in case the device is linked and the peer is up.
--- drivers/net/netdevsim/netdev.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/net/netdevsim/netdev.c +7 -0
@@ -433,6 +433,7 @@ static void nsim_enable_napi(struct netdevsim *ns)static int nsim_open (struct net_device *dev) {struct netdevsim *ns =netdev_priv (dev); +struct netdevsim *peer;int err; err =nsim_init_napi (ns);
@@ -441,6 +442,12 @@ static int nsim_open(struct net_device *dev)nsim_enable_napi (ns); + peer =rtnl_dereference (ns->peer); +if (peer &&netif_running (peer->netdev)) { +netif_carrier_on (dev); +netif_carrier_on (peer->netdev); + } +return 0 ; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 65/136 net: usb: lan78xx: Add error handling to lan78xx_init_mac_address
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oleksij Rempel <[email protected]>
[ Upstream commit 6f31135894ec96481e2bda93a1da70712f5e57c1 ]
Convert lan78xx_init_mac_address to return error codes and handle failures in register read and write operations. Update lan78xx_reset to check for errors during MAC address initialization and propagate them appropriately.
Stable-dep-of: 8d93ff40d49d ("net: usb: lan78xx: fix use of improperly initialized dev->chipid in lan78xx_reset")
--- drivers/net/usb/lan78xx.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-)
drivers/net/usb/lan78xx.c +28 -8
@@ -1920,13 +1920,19 @@ static const struct ethtool_ops lan78xx_ethtool_ops = { .get_regs = lan78xx_get_regs, }; -static void lan78xx_init_mac_address (struct lan78xx_net *dev) +static int lan78xx_init_mac_address (struct lan78xx_net *dev) {u32 addr_lo, addr_hi;u8 addr[6 ]; +int ret; + + ret =lan78xx_read_reg (dev,RX_ADDRL , &addr_lo); +if (ret <0 ) +return ret; -lan78xx_read_reg (dev,RX_ADDRL , &addr_lo); -lan78xx_read_reg (dev,RX_ADDRH , &addr_hi); + ret =lan78xx_read_reg (dev,RX_ADDRH , &addr_hi); +if (ret <0 ) +return ret; addr[0 ] = addr_lo &0xFF ; addr[1 ] = (addr_lo >>8 ) &0xFF ;
@@ -1959,14 +1965,26 @@ static void lan78xx_init_mac_address(struct lan78xx_net *dev) (addr[2 ] <<16 ) | (addr[3 ] <<24 ); addr_hi = addr[4 ] | (addr[5 ] <<8 ); -lan78xx_write_reg (dev,RX_ADDRL , addr_lo); -lan78xx_write_reg (dev,RX_ADDRH , addr_hi); + ret =lan78xx_write_reg (dev,RX_ADDRL , addr_lo); +if (ret <0 ) +return ret; + + ret =lan78xx_write_reg (dev,RX_ADDRH , addr_hi); +if (ret <0 ) +return ret; } -lan78xx_write_reg (dev,MAF_LO (0 ), addr_lo); -lan78xx_write_reg (dev,MAF_HI (0 ), addr_hi |MAF_HI_VALID_ ); + ret =lan78xx_write_reg (dev,MAF_LO (0 ), addr_lo); +if (ret <0 ) +return ret; + + ret =lan78xx_write_reg (dev,MAF_HI (0 ), addr_hi |MAF_HI_VALID_ ); +if (ret <0 ) +return ret;eth_hw_addr_set (dev->net, addr); + +return 0 ; }/* MDIO read and write wrappers for phylib */
@@ -2905,7 +2923,9 @@ static int lan78xx_reset(struct lan78xx_net *dev) } }while (buf &HW_CFG_LRST_ ); -lan78xx_init_mac_address (dev); + ret =lan78xx_init_mac_address (dev); +if (ret <0 ) +return ret;/* save DEVID for later usage */ ret =lan78xx_read_reg (dev,ID_REV , &buf);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 66/136 net: usb: lan78xx: fix use of improperly initialized dev->chipid in lan78xx_reset
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: I Viswanath <[email protected]>
[ Upstream commit 8d93ff40d49d70e05c82a74beae31f883fe0eaf8 ]
dev->chipid is used in lan78xx_init_mac_address before it's initialized:
lan78xx_reset() {
lan78xx_init_mac_address()
lan78xx_read_eeprom()
lan78xx_read_raw_eeprom() <- dev->chipid is used here
dev->chipid = ... <- dev->chipid is initialized correctly here
}Reorder initialization so that dev->chipid is set before calling lan78xx_init_mac_address().
--- drivers/net/usb/lan78xx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/net/usb/lan78xx.c +4 -4
@@ -2923,10 +2923,6 @@ static int lan78xx_reset(struct lan78xx_net *dev) } }while (buf &HW_CFG_LRST_ ); - ret =lan78xx_init_mac_address (dev); -if (ret <0 ) -return ret; -/* save DEVID for later usage */ ret =lan78xx_read_reg (dev,ID_REV , &buf);if (ret <0 )
@@ -2935,6 +2931,10 @@ static int lan78xx_reset(struct lan78xx_net *dev) dev->chipid = (buf &ID_REV_CHIP_ID_MASK_ ) >>16 ; dev->chiprev = buf &ID_REV_CHIP_REV_MASK_ ; + ret =lan78xx_init_mac_address (dev); +if (ret <0 ) +return ret; +/* Respond to the IN token with a NAK */ ret =lan78xx_read_reg (dev,USB_CFG0 , &buf);if (ret <0 )
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 67/136 drm/panthor: Ensure MCU is disabled on suspend
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ketil Johnsen <[email protected]>
[ Upstream commit e07e10ae83bdf429f59c8c149173a8c4f29c481e ]
Currently the Panthor driver needs the GPU to be powered down between suspend and resume. If this is not done, then the MCU_CONTROL register will be preserved as AUTO, which again will cause a premature FW boot on resume. The FW will go directly into fatal state in this case.
This case needs to be handled as there is no guarantee that the GPU will be powered down after the suspend callback on all platforms.
The fix is to call panthor_fw_stop() in "pre-reset" path to ensure the MCU_CONTROL register is cleared (set DISABLE). This matches well with the already existing call to panthor_fw_start() from the "post-reset" path.
--- drivers/gpu/drm/panthor/panthor_fw.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/panthor/panthor_fw.c +1 -0
@@ -1057,6 +1057,7 @@ void panthor_fw_pre_reset(struct panthor_device *ptdev, bool on_hang) }panthor_job_irq_suspend (&ptdev->fw->irq); +panthor_fw_stop (ptdev); }/**
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 68/136 nvme-multipath: Skip nr_active increments in RETRY disposition
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amit Chaudhary <[email protected]>
[ Upstream commit bb642e2d300ee27dcede65cda7ffc47a7047bd69 ]
For queue-depth I/O policy, this patch fixes unbalanced I/Os across nvme multipaths.
Issue Description:
The RETRY disposition incorrectly increments ns->ctrl->nr_active counter and reinitializes iostat start-time. In such cases nr_active counter never goes back to zero until that path disconnects and reconnects.
Such a path is not chosen for new I/Os if multiple RETRY cases on a given a path cause its queue-depth counter to be artificially higher compared to other paths. This leads to unbalanced I/Os across paths.
The patch skips incrementing nr_active if NVME_MPATH_CNT_ACTIVE is already set. And it skips restarting io stats if NVME_MPATH_IO_STATS is already set.
base-commit: e989a3da2d371a4b6597ee8dee5c72e407b4db7a
--- drivers/nvme/host/multipath.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/nvme/host/multipath.c +4 -2
@@ -131,12 +131,14 @@ void nvme_mpath_start_request(struct request *rq)struct nvme_ns *ns = rq->q->queuedata;struct gendisk *disk = ns->head->disk; -if (READ_ONCE (ns->head->subsys->iopolicy) ==NVME_IOPOLICY_QD ) { +if ((READ_ONCE (ns->head->subsys->iopolicy) ==NVME_IOPOLICY_QD ) && + !(nvme_req (rq)->flags &NVME_MPATH_CNT_ACTIVE )) {atomic_inc (&ns->ctrl->nr_active);nvme_req (rq)->flags |=NVME_MPATH_CNT_ACTIVE ; } -if (!blk_queue_io_stat (disk->queue) ||blk_rq_is_passthrough (rq)) +if (!blk_queue_io_stat (disk->queue) ||blk_rq_is_passthrough (rq) || + (nvme_req (rq)->flags &NVME_MPATH_IO_STATS ))return ;nvme_req (rq)->flags |=NVME_MPATH_IO_STATS ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 69/136 riscv: kprobes: Fix probe address validation
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fabian Vogt <[email protected]>
[ Upstream commit 9e68bd803fac49274fde914466fd3b07c4d602c8 ]
When adding a kprobe such as "p:probe/tcp_sendmsg _text+15392192", arch_check_kprobe would start iterating all instructions starting from _text until the probed address. Not only is this very inefficient, but literal values in there (e.g. left by function patching) are misinterpreted in a way that causes a desync.
Fix this by doing it like x86: start the iteration at the closest preceding symbol instead of the given starting point.
--- arch/riscv/kernel/probes/kprobes.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
arch/riscv/kernel/probes/kprobes.c +9 -4
@@ -49,10 +49,15 @@ static void __kprobes arch_simulate_insn(struct kprobe *p, struct pt_regs *regs)post_kprobe_handler (p, kcb, regs); } -static bool __kprobes arch_check_kprobe (struct kprobe *p) +static bool __kprobes arch_check_kprobe (unsigned long addr) { -unsigned long tmp = (unsigned long )p->addr - p->offset; -unsigned long addr = (unsigned long )p->addr; +unsigned long tmp, offset; + +/* start iterating at the closest preceding symbol */ +if (!kallsyms_lookup_size_offset (addr,NULL , &offset)) +return false; + + tmp = addr - offset;while (tmp <= addr) {if (tmp == addr)
@@ -71,7 +76,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)if ((unsigned long )insn &0x1 )return -EILSEQ ; -if (!arch_check_kprobe (p)) +if (!arch_check_kprobe ((unsigned long )p->addr))return -EILSEQ ;/* copy instruction */
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 70/136 drm/bridge: lt9211: Drop check for last nibble of version register
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marek Vasut <[email protected]>
[ Upstream commit db74b04edce1bc86b9a5acc724c7ca06f427ab60 ]
There is now a new LT9211 rev. U5, which reports chip ID 0x18 0x01 0xe4 . The previous LT9211 reported chip ID 0x18 0x01 0xe3 , which is what the driver checks for right now. Since there is a possibility there will be yet another revision of the LT9211 in the future, drop the last version nibble check to allow all future revisions of the chip to work with this driver.
This fix makes LT9211 rev. U5 work with this driver.
--- drivers/gpu/drm/bridge/lontium-lt9211.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/gpu/drm/bridge/lontium-lt9211.c +1 -2
@@ -120,8 +120,7 @@ static int lt9211_read_chipid(struct lt9211 *ctx) }/* Test for known Chip ID. */ -if (chipid[0 ] !=REG_CHIPID0_VALUE || chipid[1 ] !=REG_CHIPID1_VALUE || - chipid[2 ] !=REG_CHIPID2_VALUE ) { +if (chipid[0 ] !=REG_CHIPID0_VALUE || chipid[1 ] !=REG_CHIPID1_VALUE ) {dev_err (ctx->dev,"Unknown Chip ID: 0x%02x 0x%02x 0x%02x\n" , chipid[0 ], chipid[1 ], chipid[2 ]);return -EINVAL ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 71/136 ASoC: codecs: Fix gain setting ranges for Renesas IDT821034 codec
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christophe Leroy <[email protected]>
[ Upstream commit 6370a996f308ea3276030769b7482b346e7cc7c1 ]
The gain ranges specified in Renesas IDT821034 codec documentation are [-3dB;+13dB] in the transmit path (ADC) and [-13dB;+3dB] in the receive path (DAC). Allthough the registers allow programming values outside those ranges, the signal S/N and distorsion are only guaranteed in the specified ranges.
Set ranges to the specified ones.
--- sound/soc/codecs/idt821034.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
sound/soc/codecs/idt821034.c +6 -6
@@ -548,14 +548,14 @@ static int idt821034_kctrl_mute_put(struct snd_kcontrol *kcontrol,return ret; } -static const DECLARE_TLV_DB_LINEAR(idt821034_gain_in, -6520, 1306); -#define IDT821034_GAIN_IN_MIN_RAW 1/* -65.20 dB -> 10^(-65.2/20.0) * 1820 = 1 */ -#define IDT821034_GAIN_IN_MAX_RAW 8191/* 13.06 dB -> 10^(13.06/20.0) * 1820 = 8191 */ +static const DECLARE_TLV_DB_LINEAR(idt821034_gain_in, -300, 1300); +#define IDT821034_GAIN_IN_MIN_RAW 1288/* -3.0 dB -> 10^(-3.0/20.0) * 1820 = 1288 */ +#define IDT821034_GAIN_IN_MAX_RAW 8130/* 13.0 dB -> 10^(13.0/20.0) * 1820 = 8130 */ #define IDT821034_GAIN_IN_INIT_RAW 1820/* 0dB -> 10^(0/20) * 1820 = 1820 */ -static const DECLARE_TLV_DB_LINEAR(idt821034_gain_out, -6798, 1029); -#define IDT821034_GAIN_OUT_MIN_RAW 1/* -67.98 dB -> 10^(-67.98/20.0) * 2506 = 1*/ -#define IDT821034_GAIN_OUT_MAX_RAW 8191/* 10.29 dB -> 10^(10.29/20.0) * 2506 = 8191 */ +static const DECLARE_TLV_DB_LINEAR(idt821034_gain_out, -1300, 300); +#define IDT821034_GAIN_OUT_MIN_RAW 561/* -13.0 dB -> 10^(-13.0/20.0) * 2506 = 561 */ +#define IDT821034_GAIN_OUT_MAX_RAW 3540/* 3.0 dB -> 10^(3.0/20.0) * 2506 = 3540 */ #define IDT821034_GAIN_OUT_INIT_RAW 2506/* 0dB -> 10^(0/20) * 2506 = 2506 */ static const struct snd_kcontrol_new idt821034_controls[] = {
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 72/136 ASoC: nau8821: Cancel jdet_work before handling jack ejection
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cristian Ciocaltea <[email protected]>
[ Upstream commit 6e54919cb541fdf1063b16f3254c28d01bc9e5ff ]
The microphone detection work scheduled by a prior jack insertion interrupt may still be in a pending state or under execution when a jack ejection interrupt has been fired.
This might lead to a racing condition or nau8821_jdet_work() completing after nau8821_eject_jack(), which will override the currently disconnected state of the jack and incorrectly report the headphone or the headset as being connected.
Cancel any pending jdet_work or wait for its execution to finish before attempting to handle the ejection interrupt.
Proceed similarly before launching the eject handler as a consequence of detecting an invalid insert interrupt.
--- sound/soc/codecs/nau8821.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
sound/soc/codecs/nau8821.c +2 -1
@@ -1186,6 +1186,7 @@ static irqreturn_t nau8821_interrupt(int irq, void *data)if ((active_irq &NAU8821_JACK_EJECT_IRQ_MASK ) ==NAU8821_JACK_EJECT_DETECTED ) { +cancel_work_sync (&nau8821->jdet_work);regmap_update_bits (regmap,NAU8821_R71_ANALOG_ADC_1 ,NAU8821_MICDET_MASK ,NAU8821_MICDET_DIS );nau8821_eject_jack (nau8821);
@@ -1200,11 +1201,11 @@ static irqreturn_t nau8821_interrupt(int irq, void *data) clear_irq =NAU8821_KEY_RELEASE_IRQ ; }else if ((active_irq &NAU8821_JACK_INSERT_IRQ_MASK ) ==NAU8821_JACK_INSERT_DETECTED ) { +cancel_work_sync (&nau8821->jdet_work);regmap_update_bits (regmap,NAU8821_R71_ANALOG_ADC_1 ,NAU8821_MICDET_MASK ,NAU8821_MICDET_EN );if (nau8821_is_jack_inserted (regmap)) {/* detect microphone and jack type */ -cancel_work_sync (&nau8821->jdet_work);schedule_work (&nau8821->jdet_work);/* Turn off insertion interruption at manual mode */ regmap_update_bits(regmap,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 73/136 ASoC: nau8821: Generalize helper to clear IRQ status
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cristian Ciocaltea <[email protected]>
[ Upstream commit 9273aa85b35cc02d0953a1ba3b7bd694e5a2c10e ]
Instead of adding yet another utility function for dealing with the interrupt clearing register, generalize nau8821_int_status_clear_all() by renaming it to nau8821_irq_status_clear(), whilst introducing a second parameter to allow restricting the operation scope to a single interrupt instead of the whole range of active IRQs.
While at it, also fix a spelling typo in the comment block.
Note this is mainly a prerequisite for subsequent patches aiming to address some deficiencies in the implementation of the interrupt handler. Thus the presence of the Fixes tag below is intentional, to facilitate backporting.
--- sound/soc/codecs/nau8821.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
sound/soc/codecs/nau8821.c +11 -6
@@ -1022,12 +1022,17 @@ static bool nau8821_is_jack_inserted(struct regmap *regmap)return active_high == is_high; } -static void nau8821_int_status_clear_all (struct regmap *regmap) +static void nau8821_irq_status_clear (struct regmap *regmap,int active_irq) { -int active_irq, clear_irq, i; +int clear_irq, i; -/* Reset the intrruption status from rightmost bit if the corres- -* ponding irq event occurs. +if (active_irq) { +regmap_write (regmap,NAU8821_R11_INT_CLR_KEY_STATUS , active_irq); +return ; + } + +/* Reset the interruption status from rightmost bit if the +* corresponding irq event occurs. */ regmap_read (regmap,NAU8821_R10_IRQ_STATUS , &active_irq);for (i =0 ; i <NAU8821_REG_DATA_LEN ; i++) {
@@ -1054,7 +1059,7 @@ static void nau8821_eject_jack(struct nau8821 *nau8821)snd_soc_dapm_sync (dapm);/* Clear all interruption status */ -nau8821_int_status_clear_all (regmap); +nau8821_irq_status_clear (regmap,0 );/* Enable the insertion interruption, disable the ejection inter- * ruption, and then bypass de-bounce circuit.
@@ -1523,7 +1528,7 @@ static int nau8821_resume_setup(struct nau8821 *nau8821)nau8821_configure_sysclk (nau8821,NAU8821_CLK_DIS ,0 );if (nau8821->irq) {/* Clear all interruption status */ -nau8821_int_status_clear_all (regmap); +nau8821_irq_status_clear (regmap,0 );/* Enable both insertion and ejection interruptions, and then * bypass de-bounce circuit.
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 74/136 ASoC: nau8821: Add DMI quirk to bypass jack debounce circuit
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cristian Ciocaltea <[email protected]>
[ Upstream commit 2b4eda7bf7d8a4e2f7575a98f55d8336dec0f302 ]
Stress testing the audio jack hotplug handling on a few Steam Deck units revealed that the debounce circuit is responsible for having a negative impact on the detection reliability, e.g. in some cases the ejection interrupt is not fired, while in other instances it goes into a kind of invalid state and generates a flood of misleading interrupts.
Add new entries to the DMI table introduced via commit 1bc40efdaf4a ("ASoC: nau8821: Add DMI quirk mechanism for active-high jack-detect") and extend the quirk logic to allow bypassing the debounce circuit used for jack detection on Valve Steam Deck LCD and OLED models.
While at it, rename existing NAU8821_JD_ACTIVE_HIGH quirk bitfield to NAU8821_QUIRK_JD_ACTIVE_HIGH. This should help improve code readability by differentiating from similarly named register bits.
--- sound/soc/codecs/nau8821.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-)
sound/soc/codecs/nau8821.c +27 -6
@@ -26,7 +26,8 @@#include <sound/tlv.h> #include "nau8821.h" -#define NAU8821_JD_ACTIVE_HIGH BIT(0) +#define NAU8821_QUIRK_JD_ACTIVE_HIGH BIT(0) +#define NAU8821_QUIRK_JD_DB_BYPASS BIT(1)static int nau8821_quirk;static int quirk_override =-1 ;
@@ -1166,9 +1167,10 @@ static void nau8821_setup_inserted_irq(struct nau8821 *nau8821)regmap_update_bits (regmap,NAU8821_R1D_I2S_PCM_CTRL2 ,NAU8821_I2S_MS_MASK ,NAU8821_I2S_MS_SLAVE ); -/* Not bypass de-bounce circuit */ -regmap_update_bits (regmap,NAU8821_R0D_JACK_DET_CTRL , -NAU8821_JACK_DET_DB_BYPASS ,0 ); +/* Do not bypass de-bounce circuit */ +if (!(nau8821_quirk &NAU8821_QUIRK_JD_DB_BYPASS )) +regmap_update_bits (regmap,NAU8821_R0D_JACK_DET_CTRL , +NAU8821_JACK_DET_DB_BYPASS ,0 );regmap_update_bits (regmap,NAU8821_R0F_INTERRUPT_MASK ,NAU8821_IRQ_EJECT_EN ,0 );
@@ -1863,7 +1865,23 @@ static const struct dmi_system_id nau8821_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Positivo Tecnologia SA"), DMI_MATCH(DMI_BOARD_NAME, "CW14Q01P-V2"), }, - .driver_data = (void *)(NAU8821_JD_ACTIVE_HIGH), + .driver_data = (void *)(NAU8821_QUIRK_JD_ACTIVE_HIGH), + }, + { + /* Valve Steam Deck LCD */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Valve"), + DMI_MATCH(DMI_PRODUCT_NAME, "Jupiter"), + }, + .driver_data = (void *)(NAU8821_QUIRK_JD_DB_BYPASS), + }, + { + /* Valve Steam Deck OLED */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Valve"), + DMI_MATCH(DMI_PRODUCT_NAME, "Galileo"), + }, + .driver_data = (void *)(NAU8821_QUIRK_JD_DB_BYPASS), }, {} };
@@ -1905,9 +1923,12 @@ static int nau8821_i2c_probe(struct i2c_client *i2c)nau8821_check_quirks (); -if (nau8821_quirk &NAU8821_JD_ACTIVE_HIGH ) +if (nau8821_quirk &NAU8821_QUIRK_JD_ACTIVE_HIGH ) nau8821->jkdet_polarity =0 ; +if (nau8821_quirk &NAU8821_QUIRK_JD_DB_BYPASS ) +dev_dbg (dev,"Force bypassing jack detection debounce circuit\n" ); +nau8821_print_device_properties (nau8821);nau8821_reset_chip (nau8821->regmap);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 75/136 drm/i915/guc: Skip communication warning on reset in progress
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhanjun Dong <[email protected]>
[ Upstream commit 1696b0cfcf004a3af34ffe4c57a14e837ef18144 ]
GuC IRQ and tasklet handler receive just single G2H message, and let other messages to be received from next tasklet. During this chained tasklet process, if reset process started, communication will be disabled. Skip warning for this condition.
--- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +8 -1
@@ -1324,9 +1324,16 @@ static int ct_receive(struct intel_guc_ct *ct)static void ct_try_receive_message (struct intel_guc_ct *ct) { +struct intel_guc *guc =ct_to_guc (ct);int ret; -if (GEM_WARN_ON (!ct->enabled)) +if (!ct->enabled) { +GEM_WARN_ON (!guc_to_gt (guc)->uc.reset_in_progress); +return ; + } + +/* When interrupt disabled, message handling is not expected */ +if (!guc->interrupts.enabled)return ; ret =ct_receive (ct);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 76/136 drm/amdgpu: add ip offset support for cyan skillfish
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
[ Upstream commit e8529dbc75cab56fc3c57830d0fd48cbd8911e6c ]
For chips that don't have IP discovery tables.
Stable-dep-of: 357d90be2c7a ("drm/amdgpu: fix handling of harvesting for ip_discovery firmware")
--- drivers/gpu/drm/amd/amdgpu/Makefile | 3 +- .../drm/amd/amdgpu/cyan_skillfish_reg_init.c | 56 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/nv.h | 1 + 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/cyan_skillfish_reg_init.c
drivers/gpu/drm/amd/amdgpu/Makefile +2 -1
@@ -83,7 +83,8 @@ amdgpu-y += \ vega20_reg_init.o nbio_v7_4.o nbio_v2_3.o nv.o arct_reg_init.o mxgpu_nv.o \ nbio_v7_2.o hdp_v4_0.o hdp_v5_0.o aldebaran_reg_init.o aldebaran.o soc21.o soc24.o \ sienna_cichlid.o smu_v13_0_10.o nbio_v4_3.o hdp_v6_0.o nbio_v7_7.o hdp_v5_2.o lsdma_v6_0.o \ - nbio_v7_9.o aqua_vanjaram.o nbio_v7_11.o lsdma_v7_0.o hdp_v7_0.o nbif_v6_3_1.o + nbio_v7_9.o aqua_vanjaram.o nbio_v7_11.o lsdma_v7_0.o hdp_v7_0.o nbif_v6_3_1.o \ + cyan_skillfish_reg_init.o # add DF block amdgpu-y += \
drivers/gpu/drm/amd/amdgpu/cyan_skillfish_reg_init.c new file +56 -0
56 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/nv.h +1 -0
@@ -31,5 +31,6 @@ extern const struct amdgpu_ip_block_version nv_common_ip_block;void nv_grbm_select (struct amdgpu_device *adev,u32 me,u32 pipe,u32 queue,u32 vmid);void nv_set_virt_ops (struct amdgpu_device *adev); +int cyan_skillfish_reg_base_init (struct amdgpu_device *adev);#endif
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 77/136 drm/amdgpu: add support for cyan skillfish without IP discovery
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
[ Upstream commit 9e6a5cf1a23bf575e93544ae05585659063b1c18 ]
For platforms without an IP discovery table.
Stable-dep-of: 357d90be2c7a ("drm/amdgpu: fix handling of harvesting for ip_discovery firmware")
--- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +30 -0
@@ -2644,6 +2644,36 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev) adev->ip_versions[UVD_HWIP ][1 ] =IP_VERSION (2 ,6 ,0 ); adev->ip_versions[XGMI_HWIP ][0 ] =IP_VERSION (6 ,1 ,0 );break ; +case CHIP_CYAN_SKILLFISH : +if (adev->apu_flags &AMD_APU_IS_CYAN_SKILLFISH2 ) { + r =amdgpu_discovery_reg_base_init (adev); +if (r) +return -EINVAL ; + +amdgpu_discovery_harvest_ip (adev); +amdgpu_discovery_get_gfx_info (adev); +amdgpu_discovery_get_mall_info (adev); +amdgpu_discovery_get_vcn_info (adev); + }else { +cyan_skillfish_reg_base_init (adev); + adev->sdma.num_instances =2 ; + adev->ip_versions[MMHUB_HWIP ][0 ] =IP_VERSION (2 ,0 ,3 ); + adev->ip_versions[ATHUB_HWIP ][0 ] =IP_VERSION (2 ,0 ,3 ); + adev->ip_versions[OSSSYS_HWIP ][0 ] =IP_VERSION (5 ,0 ,1 ); + adev->ip_versions[HDP_HWIP ][0 ] =IP_VERSION (5 ,0 ,1 ); + adev->ip_versions[SDMA0_HWIP ][0 ] =IP_VERSION (5 ,0 ,1 ); + adev->ip_versions[SDMA1_HWIP ][1 ] =IP_VERSION (5 ,0 ,1 ); + adev->ip_versions[DF_HWIP ][0 ] =IP_VERSION (3 ,5 ,0 ); + adev->ip_versions[NBIO_HWIP ][0 ] =IP_VERSION (2 ,1 ,1 ); + adev->ip_versions[UMC_HWIP ][0 ] =IP_VERSION (8 ,1 ,1 ); + adev->ip_versions[MP0_HWIP ][0 ] =IP_VERSION (11 ,0 ,8 ); + adev->ip_versions[MP1_HWIP ][0 ] =IP_VERSION (11 ,0 ,8 ); + adev->ip_versions[THM_HWIP ][0 ] =IP_VERSION (11 ,0 ,1 ); + adev->ip_versions[SMUIO_HWIP ][0 ] =IP_VERSION (11 ,0 ,8 ); + adev->ip_versions[GC_HWIP ][0 ] =IP_VERSION (10 ,1 ,3 ); + adev->ip_versions[UVD_HWIP ][0 ] =IP_VERSION (2 ,0 ,3 ); + } +break ;default : r =amdgpu_discovery_reg_base_init (adev);if (r) {
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 78/136 drm/amdgpu: fix handling of harvesting for ip_discovery firmware
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
[ Upstream commit 357d90be2c7aaa526a840cddffd2b8d676fe75a6 ]
Chips which use the IP discovery firmware loaded by the driver reported incorrect harvesting information in the ip discovery table in sysfs because the driver only uses the ip discovery firmware for populating sysfs and not for direct parsing for the driver itself as such, the fields that are used to print the harvesting info in sysfs report incorrect data for some IPs. Populate the relevant fields for this case as well.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +17 -1
@@ -1016,7 +1016,9 @@ static uint8_t amdgpu_discovery_get_harvest_info(struct amdgpu_device *adev,/* Until a uniform way is figured, get mask based on hwid */ switch (hw_id) {case VCN_HWID : - harvest = ((1 << inst) & adev->vcn.inst_mask) ==0 ; +/* VCN vs UVD+VCE */ +if (!amdgpu_ip_version (adev,VCE_HWIP ,0 )) + harvest = ((1 << inst) & adev->vcn.inst_mask) ==0 ;break ;case DMU_HWID :if (adev->harvest_ip_mask &AMD_HARVEST_IP_DMU_MASK )
@@ -2462,7 +2464,9 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)amdgpu_discovery_init (adev);vega10_reg_base_init (adev); adev->sdma.num_instances =2 ; + adev->sdma.sdma_mask =3 ; adev->gmc.num_umc =4 ; + adev->gfx.xcc_mask =1 ; adev->ip_versions[MMHUB_HWIP ][0 ] =IP_VERSION (9 ,0 ,0 ); adev->ip_versions[ATHUB_HWIP ][0 ] =IP_VERSION (9 ,0 ,0 ); adev->ip_versions[OSSSYS_HWIP ][0 ] =IP_VERSION (4 ,0 ,0 );
@@ -2489,7 +2493,9 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)amdgpu_discovery_init (adev);vega10_reg_base_init (adev); adev->sdma.num_instances =2 ; + adev->sdma.sdma_mask =3 ; adev->gmc.num_umc =4 ; + adev->gfx.xcc_mask =1 ; adev->ip_versions[MMHUB_HWIP ][0 ] =IP_VERSION (9 ,3 ,0 ); adev->ip_versions[ATHUB_HWIP ][0 ] =IP_VERSION (9 ,3 ,0 ); adev->ip_versions[OSSSYS_HWIP ][0 ] =IP_VERSION (4 ,0 ,1 );
@@ -2516,8 +2522,10 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)amdgpu_discovery_init (adev);vega10_reg_base_init (adev); adev->sdma.num_instances =1 ; + adev->sdma.sdma_mask =1 ; adev->vcn.num_vcn_inst =1 ; adev->gmc.num_umc =2 ; + adev->gfx.xcc_mask =1 ;if (adev->apu_flags &AMD_APU_IS_RAVEN2 ) { adev->ip_versions[MMHUB_HWIP ][0 ] =IP_VERSION (9 ,2 ,0 ); adev->ip_versions[ATHUB_HWIP ][0 ] =IP_VERSION (9 ,2 ,0 );
@@ -2560,7 +2568,9 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)amdgpu_discovery_init (adev);vega20_reg_base_init (adev); adev->sdma.num_instances =2 ; + adev->sdma.sdma_mask =3 ; adev->gmc.num_umc =8 ; + adev->gfx.xcc_mask =1 ; adev->ip_versions[MMHUB_HWIP ][0 ] =IP_VERSION (9 ,4 ,0 ); adev->ip_versions[ATHUB_HWIP ][0 ] =IP_VERSION (9 ,4 ,0 ); adev->ip_versions[OSSSYS_HWIP ][0 ] =IP_VERSION (4 ,2 ,0 );
@@ -2588,8 +2598,10 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)amdgpu_discovery_init (adev);arct_reg_base_init (adev); adev->sdma.num_instances =8 ; + adev->sdma.sdma_mask =0xff ; adev->vcn.num_vcn_inst =2 ; adev->gmc.num_umc =8 ; + adev->gfx.xcc_mask =1 ; adev->ip_versions[MMHUB_HWIP ][0 ] =IP_VERSION (9 ,4 ,1 ); adev->ip_versions[ATHUB_HWIP ][0 ] =IP_VERSION (9 ,4 ,1 ); adev->ip_versions[OSSSYS_HWIP ][0 ] =IP_VERSION (4 ,2 ,1 );
@@ -2621,8 +2633,10 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)amdgpu_discovery_init (adev);aldebaran_reg_base_init (adev); adev->sdma.num_instances =5 ; + adev->sdma.sdma_mask =0x1f ; adev->vcn.num_vcn_inst =2 ; adev->gmc.num_umc =4 ; + adev->gfx.xcc_mask =1 ; adev->ip_versions[MMHUB_HWIP ][0 ] =IP_VERSION (9 ,4 ,2 ); adev->ip_versions[ATHUB_HWIP ][0 ] =IP_VERSION (9 ,4 ,2 ); adev->ip_versions[OSSSYS_HWIP ][0 ] =IP_VERSION (4 ,4 ,0 );
@@ -2657,6 +2671,8 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev) }else {cyan_skillfish_reg_base_init (adev); adev->sdma.num_instances =2 ; + adev->sdma.sdma_mask =3 ; + adev->gfx.xcc_mask =1 ; adev->ip_versions[MMHUB_HWIP ][0 ] =IP_VERSION (2 ,0 ,3 ); adev->ip_versions[ATHUB_HWIP ][0 ] =IP_VERSION (2 ,0 ,3 ); adev->ip_versions[OSSSYS_HWIP ][0 ] =IP_VERSION (5 ,0 ,1 );
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 79/136 drm/amd/powerplay: Fix CIK shutdown temperature
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf <[email protected]>
[ Upstream commit 6917112af2ba36c5f19075eb9f2933ffd07e55bf ]
Remove extra multiplication.
CIK GPUs such as Hawaii appear to use PP_TABLE_V0 in which case the shutdown temperature is hardcoded in smu7_init_dpm_defaults and is already multiplied by 1000. The value was mistakenly multiplied another time by smu7_get_thermal_temperature_range.
--- drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c +1 -2
@@ -5444,8 +5444,7 @@ static int smu7_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, thermal_data->max = table_info->cac_dtp_table->usSoftwareShutdownTemp *PP_TEMPERATURE_UNITS_PER_CENTIGRADES ; else if (hwmgr->pp_table_version == PP_TABLE_V0) - thermal_data->max = data->thermal_temp_setting.temperature_shutdown * -PP_TEMPERATURE_UNITS_PER_CENTIGRADES ; + thermal_data->max = data->thermal_temp_setting.temperature_shutdown; thermal_data->sw_ctf_threshold = thermal_data->max;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 80/136 drm/draw: fix color truncation in drm_draw_fill24
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Francesco Valla <[email protected]>
[ Upstream commit 095232711f23179053ca26bcf046ca121a91a465 ]
The color parameter passed to drm_draw_fill24() was truncated to 16 bits, leading to an incorrect color drawn to the target iosys_map. Fix this behavior, widening the parameter to 32 bits.
--- drivers/gpu/drm/drm_draw.c | 2 +- drivers/gpu/drm/drm_draw_internal.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/drm_draw.c +1 -1
@@ -125,7 +125,7 @@ EXPORT_SYMBOL(drm_draw_fill16);void drm_draw_fill24 (struct iosys_map *dmap,unsigned int dpitch,unsigned int height,unsigned int width, -u16 color) +u32 color) {unsigned int y, x;
drivers/gpu/drm/drm_draw_internal.h +1 -1
@@ -47,7 +47,7 @@ void drm_draw_fill16(struct iosys_map *dmap, unsigned int dpitch,void drm_draw_fill24 (struct iosys_map *dmap,unsigned int dpitch,unsigned int height,unsigned int width, -u16 color); +u32 color); void drm_draw_fill32(struct iosys_map *dmap, unsigned int dpitch, unsigned int height, unsigned int width,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 81/136 drm/rockchip: vop2: use correct destination rectangle height check
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alok Tiwari <[email protected]>
[ Upstream commit 7f38a1487555604bc4e210fa7cc9b1bce981c40e ]
The vop2_plane_atomic_check() function incorrectly checks drm_rect_width(dest) twice instead of verifying both width and height. Fix the second condition to use drm_rect_height(dest) so that invalid destination rectangles with height < 4 are correctly rejected.
--- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +1 -1
@@ -1118,7 +1118,7 @@ static int vop2_plane_atomic_check(struct drm_plane *plane,return format;if (drm_rect_width (src) >>16 <4 ||drm_rect_height (src) >>16 <4 || -drm_rect_width (dest) <4 ||drm_rect_width (dest) <4 ) { +drm_rect_width (dest) <4 ||drm_rect_height (dest) <4 ) {drm_err (vop2->drm,"Invalid size: %dx%d->%dx%d, min size is 4x4\n" ,drm_rect_width (src) >>16 ,drm_rect_height (src) >>16 ,drm_rect_width (dest),drm_rect_height (dest));
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 82/136 sched/fair: Fix pelt lost idle time detection
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vincent Guittot <[email protected]>
[ Upstream commit 17e3e88ed0b6318fde0d1c14df1a804711cab1b5 ]
The check for some lost idle pelt time should be always done when pick_next_task_fair() fails to pick a task and not only when we call it from the fair fast-path.
The case happens when the last running task on rq is a RT or DL task. When the latter goes to sleep and the /Sum of util_sum of the rq is at the max value, we don't account the lost of idle time whereas we should.
--- kernel/sched/fair.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-)
kernel/sched/fair.c +13 -13
@@ -9059,21 +9059,21 @@ pick_next_task_fair(struct rq *rq, struct task_struct *prev, struct rq_flags *rfreturn p; idle: -if (!rf) -return NULL ; - - new_tasks =sched_balance_newidle (rq, rf); +if (rf) { + new_tasks =sched_balance_newidle (rq, rf); -/* -* Because sched_balance_newidle() releases (and re-acquires) rq->lock, it is -* possible for any higher priority task to appear. In that case we -* must re-start the pick_next_entity() loop. -*/ -if (new_tasks <0 ) -return RETRY_TASK ; +/* +* Because sched_balance_newidle() releases (and re-acquires) +* rq->lock, it is possible for any higher priority task to +* appear. In that case we must re-start the pick_next_entity() +* loop. +*/ +if (new_tasks <0 ) +return RETRY_TASK ; -if (new_tasks >0 ) - goto again; +if (new_tasks >0 ) + goto again; + }/* * rq is about to be idle, check if we need to update the
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 83/136 ALSA: firewire: amdtp-stream: fix enum kernel-doc warnings
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Randy Dunlap <[email protected]>
[ Upstream commit d41f68dff783d181a8fd462e612bda0fbab7f735 ]
Fix spelling of CIP_NO_HEADER to prevent a kernel-doc warning.
Warning: amdtp-stream.h:57 Enum value 'CIP_NO_HEADER' not described in enum 'cip_flags'
Warning: amdtp-stream.h:57 Excess enum value '%CIP_NO_HEADERS' description in 'cip_flags'
--- sound/firewire/amdtp-stream.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/firewire/amdtp-stream.h +1 -1
@@ -32,7 +32,7 @@* allows 5 times as large as IEC 61883-6 defines. * @CIP_HEADER_WITHOUT_EOH: Only for in-stream. CIP Header doesn't include * valid EOH. -* @CIP_NO_HEADERS: a lack of headers in packets +* @CIP_NO_HEADER: a lack of headers in packets * @CIP_UNALIGHED_DBC: Only for in-stream. The value of dbc is not alighed to * the value of current SYT_INTERVAL; e.g. initial value is not zero. * @CIP_UNAWARE_SYT: For outgoing packet, the value in SYT field of CIP is 0xffff.
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 84/136 accel/qaic: Fix bootlog initialization ordering
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeffrey Hugo <[email protected]>
[ Upstream commit fd6e385528d8f85993b7bfc6430576136bb14c65 ]
As soon as we queue MHI buffers to receive the bootlog from the device, we could be receiving data. Therefore all the resources needed to process that data need to be setup prior to queuing the buffers.
We currently initialize some of the resources after queuing the buffers which creates a race between the probe() and any data that comes back from the device. If the uninitialized resources are accessed, we could see page faults.
Fix the init ordering to close the race.
--- drivers/accel/qaic/qaic_debugfs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/accel/qaic/qaic_debugfs.c +3 -2
@@ -251,6 +251,9 @@ static int qaic_bootlog_mhi_probe(struct mhi_device *mhi_dev, const struct mhi_dif (ret) goto destroy_workqueue; +dev_set_drvdata (&mhi_dev->dev, qdev); + qdev->bootlog_ch = mhi_dev; +for (i =0 ; i <BOOTLOG_POOL_SIZE ; i++) { msg =devm_kzalloc (&qdev->pdev->dev,sizeof (*msg),GFP_KERNEL );if (!msg) {
@@ -266,8 +269,6 @@ static int qaic_bootlog_mhi_probe(struct mhi_device *mhi_dev, const struct mhi_d goto mhi_unprepare; } -dev_set_drvdata (&mhi_dev->dev, qdev); - qdev->bootlog_ch = mhi_dev;return 0 ; mhi_unprepare:
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 85/136 accel/qaic: Treat remaining == 0 as error in find_and_map_user_pages()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Youssef Samir <[email protected]>
[ Upstream commit 11f08c30a3e4157305ba692f1d44cca5fc9a8fca ]
Currently, if find_and_map_user_pages() takes a DMA xfer request from the user with a length field set to 0, or in a rare case, the host receives QAIC_TRANS_DMA_XFER_CONT from the device where resources->xferred_dma_size is equal to the requested transaction size, the function will return 0 before allocating an sgt or setting the fields of the dma_xfer struct. In that case, encode_addr_size_pairs() will try to access the sgt which will lead to a general protection fault.
Return an EINVAL in case the user provides a zero-sized ALP, or the device requests continuation after all of the bytes have been transferred.
--- drivers/accel/qaic/qaic_control.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/accel/qaic/qaic_control.c +1 -1
@@ -407,7 +407,7 @@ static int find_and_map_user_pages(struct qaic_device *qdev,return -EINVAL ; remaining = in_trans->size - resources->xferred_dma_size;if (remaining ==0 ) -return 0 ; +return -EINVAL ;if (check_add_overflow (xfer_start_addr, remaining, &end))return -EINVAL ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 86/136 accel/qaic: Synchronize access to DBC request queue head & tail pointer
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pranjal Ramajor Asha Kanojiya <[email protected]>
[ Upstream commit 52e59f7740ba23bbb664914967df9a00208ca10c ]
Two threads of the same process can potential read and write parallelly to head and tail pointers of the same DBC request queue. This could lead to a race condition and corrupt the DBC request queue.
--- drivers/accel/qaic/qaic.h | 2 ++ drivers/accel/qaic/qaic_data.c | 12 ++++++++++-- drivers/accel/qaic/qaic_drv.c | 3 +++ 3 files changed, 15 insertions(+), 2 deletions(-)
drivers/accel/qaic/qaic.h +2 -0
@@ -91,6 +91,8 @@ struct dma_bridge_chan {* response queue's head and tail pointer of this DBC. */ void __iomem *dbc_base; +/* Synchronizes access to Request queue's head and tail pointer */ +struct mutex req_lock;/* Head of list where each node is a memory handle queued in request queue */ struct list_head xfer_list;/* Synchronizes DBC readers during cleanup */
drivers/accel/qaic/qaic_data.c +10 -2
@@ -1357,13 +1357,17 @@ static int __qaic_execute_bo_ioctl(struct drm_device *dev, void *data, struct dr goto release_ch_rcu; } + ret =mutex_lock_interruptible (&dbc->req_lock); +if (ret) + goto release_ch_rcu; + head =readl (dbc->dbc_base +REQHP_OFF ); tail =readl (dbc->dbc_base +REQTP_OFF );if (head ==U32_MAX || tail ==U32_MAX ) {/* PCI link error */ ret = -ENODEV ; - goto release_ch_rcu; + goto unlock_req_lock; } queue_level = head <= tail ? tail - head : dbc->nelem - (head - tail);
@@ -1371,11 +1375,12 @@ static int __qaic_execute_bo_ioctl(struct drm_device *dev, void *data, struct dr ret =send_bo_list_to_device (qdev, file_priv, exec, args->hdr.count, is_partial, dbc, head, &tail);if (ret) - goto release_ch_rcu; + goto unlock_req_lock;/* Finalize commit to hardware */ submit_ts =ktime_get_ns ();writel (tail, dbc->dbc_base +REQTP_OFF ); +mutex_unlock (&dbc->req_lock);update_profiling_data (file_priv, exec, args->hdr.count, is_partial, received_ts, submit_ts, queue_level);
@@ -1383,6 +1388,9 @@ static int __qaic_execute_bo_ioctl(struct drm_device *dev, void *data, struct drif (datapath_polling)schedule_work (&dbc->poll_work); +unlock_req_lock: +if (ret) +mutex_unlock (&dbc->req_lock); release_ch_rcu:srcu_read_unlock (&dbc->ch_lock, rcu_id); unlock_dev_srcu:
drivers/accel/qaic/qaic_drv.c +3 -0
@@ -422,6 +422,9 @@ static struct qaic_device *create_qdev(struct pci_dev *pdev, const struct pci_dereturn NULL ;init_waitqueue_head (&qdev->dbc[i].dbc_release);INIT_LIST_HEAD (&qdev->dbc[i].bo_lists); + ret =drmm_mutex_init (drm, &qdev->dbc[i].req_lock); +if (ret) +return NULL ; }return qdev;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 87/136 selftests/bpf: make arg_parsing.c more robust to crashes
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrii Nakryiko <[email protected]>
[ Upstream commit e603a342cf7ecd64ef8f36207dfe1caacb9e2583 ]
We started getting a crash in BPF CI, which seems to originate from test_parse_test_list_file() test and is happening at this line:
ASSERT_OK(strcmp("test_with_spaces", set.tests[0].name), "test 0 name");One way we can crash there is if set.cnt zero, which is checked for with ASSERT_EQ() above, but we proceed after this regardless of the outcome. Instead of crashing, we should bail out with test failure early.
Similarly, if parse_test_list_file() fails, we shouldn't be even looking at set, so bail even earlier if ASSERT_OK() fails.
--- tools/testing/selftests/bpf/prog_tests/arg_parsing.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
tools/testing/selftests/bpf/prog_tests/arg_parsing.c +6 -3
@@ -146,9 +146,12 @@ static void test_parse_test_list_file(void)init_test_filter_set (&set); -ASSERT_OK (parse_test_list_file (tmpfile, &set, true),"parse file" ); +if (!ASSERT_OK (parse_test_list_file (tmpfile, &set, true),"parse file" )) + goto out_fclose; + +if (!ASSERT_EQ (set.cnt,4 ,"test count" )) + goto out_free_set; -ASSERT_EQ (set.cnt,4 ,"test count" );ASSERT_OK (strcmp ("test_with_spaces" , set.tests[0 ].name),"test 0 name" );ASSERT_EQ (set.tests[0 ].subtest_cnt,0 ,"test 0 subtest count" );ASSERT_OK (strcmp ("testA" , set.tests[1 ].name),"test 1 name" );
@@ -158,8 +161,8 @@ static void test_parse_test_list_file(void)ASSERT_OK (strcmp ("testB" , set.tests[2 ].name),"test 2 name" );ASSERT_OK (strcmp ("testC_no_eof_newline" , set.tests[3 ].name),"test 3 name" ); +out_free_set:free_test_filter_set (&set); - out_fclose:fclose (fp); out_remove:
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 88/136 ALSA: usb-audio: Fix NULL pointer deference in try_to_register_card
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiaming Zhang <[email protected]>
[ Upstream commit 28412b489b088fb88dff488305fd4e56bd47f6e4 ]
In try_to_register_card(), the return value of usb_ifnum_to_if() is passed directly to usb_interface_claimed() without a NULL check, which will lead to a NULL pointer dereference when creating an invalid USB audio device. Fix this by adding a check to ensure the interface pointer is valid before passing it to usb_interface_claimed().
--- sound/usb/card.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
sound/usb/card.c +8 -2
@@ -760,10 +760,16 @@ get_alias_quirk(struct usb_device *dev, unsigned int id)*/ static int try_to_register_card (struct snd_usb_audio *chip,int ifnum) { +struct usb_interface *iface; +if (check_delayed_register_option (chip) == ifnum || - chip->last_iface == ifnum || -usb_interface_claimed (usb_ifnum_to_if (chip->dev, chip->last_iface))) + chip->last_iface == ifnum) +return snd_card_register (chip->card); + + iface =usb_ifnum_to_if (chip->dev, chip->last_iface); +if (iface &&usb_interface_claimed (iface))return snd_card_register (chip->card); +return 0 ; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 89/136 HID: hid-input: only ignore 0 battery events for digitizers
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
[ Upstream commit 0187c08058da3e7f11b356ac27e0c427d36f33f2 ]
Commit 581c4484769e ("HID: input: map digitizer battery usage") added handling of battery events for digitizers (typically for batteries presented in stylii). Digitizers typically report correct battery levels only when stylus is actively touching the surface, and in other cases they may report battery level of 0. To avoid confusing consumers of the battery information the code was added to filer out reports with 0 battery levels.
However there exist other kinds of devices that may legitimately report 0 battery levels. Fix this by filtering out 0-level reports only for digitizer usages, and continue reporting them for other kinds of devices (Smart Batteries, etc).
--- drivers/hid/hid-input.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/hid/hid-input.c +4 -1
@@ -622,7 +622,10 @@ static void hidinput_update_battery(struct hid_device *dev, unsigned int usage,return ; } -if (value ==0 || value < dev->battery_min || value > dev->battery_max) +if ((usage &HID_USAGE_PAGE ) ==HID_UP_DIGITIZER && value ==0 ) +return ; + +if (value < dev->battery_min || value > dev->battery_max)return ; capacity =hidinput_scale_battery_capacity (dev, value);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 90/136 HID: multitouch: fix name of Stylus input devices
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thadeu Lima de Souza Cascardo <[email protected]>
[ Upstream commit aa4daea418ee4215dca5c8636090660c545cb233 ]
HID_DG_PEN devices should have a suffix of "Stylus", as pointed out by commit c0ee1d571626 ("HID: hid-input: Add suffix also for HID_DG_PEN"). However, on multitouch devices, these suffixes may be overridden. Before that commit, HID_DG_PEN devices would get the "Stylus" suffix, but after that, multitouch would override them to have an "UNKNOWN" suffix. Just add HID_DG_PEN to the list of non-overriden suffixes in multitouch.
Before this fix:
[ 0.470981] input: ELAN9008:00 04F3:2E14 UNKNOWN as /devices/pci0000:00/0000:00:15.1/i2c_designware.1/i2c-16/i2c-ELAN9008:00/0018:04F3:2E14.0001/input/input8
ELAN9008:00 04F3:2E14 UNKNOWN
After this fix:
[ 0.474332] input: ELAN9008:00 04F3:2E14 Stylus as /devices/pci0000:00/0000:00:15.1/i2c_designware.1/i2c-16/i2c-ELAN9008:00/0018:04F3:2E14.0001/input/input8
ELAN9008:00 04F3:2E14 Stylus
--- drivers/hid/hid-multitouch.c | 1 + 1 file changed, 1 insertion(+)
drivers/hid/hid-multitouch.c +1 -0
@@ -1663,6 +1663,7 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)case HID_CP_CONSUMER_CONTROL :case HID_GD_WIRELESS_RADIO_CTLS :case HID_GD_SYSTEM_MULTIAXIS : +case HID_DG_PEN :/* already handled by hid core */ break ;case HID_DG_TOUCHSCREEN :
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 91/136 ASoC: amd/sdw_utils: avoid NULL deref when devm_kasprintf() fails
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li Qiang <[email protected]>
[ Upstream commit 5726b68473f7153a7f6294185e5998b7e2a230a2 ]
devm_kasprintf() may return NULL on memory allocation failure, but the debug message prints cpus->dai_name before checking it. Move the dev_dbg() call after the NULL check to prevent potential NULL pointer dereference.
--- sound/soc/amd/acp/acp-sdw-sof-mach.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/amd/acp/acp-sdw-sof-mach.c +1 -1
@@ -216,9 +216,9 @@ static int create_sdw_dailink(struct snd_soc_card *card, cpus->dai_name =devm_kasprintf (dev,GFP_KERNEL ,"SDW%d Pin%d" , link_num, cpu_pin_id); -dev_dbg (dev,"cpu->dai_name:%s\n" , cpus->dai_name);if (!cpus->dai_name)return -ENOMEM ; +dev_dbg (dev,"cpu->dai_name:%s\n" , cpus->dai_name); codec_maps[j].cpu =0 ; codec_maps[j].codec = j;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 92/136 selftests: arg_parsing: Ensure data is flushed to disk before reading.
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xing Guo <[email protected]>
[ Upstream commit 0c1999ed33722f85476a248186d6e0eb2bf3dd2a ]
test_parse_test_list_file writes some data to /tmp/bpf_arg_parsing_test.XXXXXX and parse_test_list_file() will read the data back. However, after writing data to that file, we forget to call fsync() and it's causing testing failure in my laptop. This patch helps fix it by adding the missing fsync() call.
--- tools/testing/selftests/bpf/prog_tests/arg_parsing.c | 3 +++ 1 file changed, 3 insertions(+)
tools/testing/selftests/bpf/prog_tests/arg_parsing.c +3 -0
@@ -144,6 +144,9 @@ static void test_parse_test_list_file(void)if (!ASSERT_OK (ferror (fp),"prepare tmp" )) goto out_fclose; +if (!ASSERT_OK (fsync (fileno (fp)),"fsync tmp" )) + goto out_fclose; +init_test_filter_set (&set);if (!ASSERT_OK (parse_test_list_file (tmpfile, &set, true),"parse file" ))
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 93/136 nvme/tcp: handle tls partially sent records in write_space()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wilfred Mallawa <[email protected]>
[ Upstream commit 5a869d017793399fd1d2609ff27e900534173eb3 ]
With TLS enabled, records that are encrypted and appended to TLS TX list can fail to see a retry if the underlying TCP socket is busy, for example, hitting an EAGAIN from tcp_sendmsg_locked(). This is not known to the NVMe TCP driver, as the TLS layer successfully generated a record.
Typically, the TLS write_space() callback would ensure such records are retried, but in the NVMe TCP Host driver, write_space() invokes nvme_tcp_write_space(). This causes a partially sent record in the TLS TX list to timeout after not being retried.
This patch fixes the above by calling queue->write_space(), which calls into the TLS layer to retry any pending records.
--- drivers/nvme/host/tcp.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/nvme/host/tcp.c +3 -0
@@ -1075,6 +1075,9 @@ static void nvme_tcp_write_space(struct sock *sk) queue = sk->sk_user_data;if (likely (queue &&sk_stream_is_writeable (sk))) {clear_bit (SOCK_NOSPACE , &sk->sk_socket->flags); +/* Ensure pending TLS partial records are retried */ +if (nvme_tcp_queue_tls (queue)) + queue->write_space (sk);queue_work_on (queue->io_cpu, nvme_tcp_wq, &queue->io_work); }read_unlock_bh (&sk->sk_callback_lock);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 94/136 hfsplus: fix slab-out-of-bounds read in hfsplus_strcasecmp()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Viacheslav Dubeyko <[email protected]>
commit 42520df65bf67189541a425f7d36b0b3e7bd7844 upstream.
The hfsplus_strcasecmp() logic can trigger the issue:
[ 117.317703][ T9855] ================================================================== [ 117.318353][ T9855] BUG: KASAN: slab-out-of-bounds in hfsplus_strcasecmp+0x1bc/0x490 [ 117.318991][ T9855] Read of size 2 at addr ffff88802160f40c by task repro/9855 [ 117.319577][ T9855] [ 117.319773][ T9855] CPU: 0 UID: 0 PID: 9855 Comm: repro Not tainted 6.17.0-rc6 #33 PREEMPT(full) [ 117.319780][ T9855] Hardware name: QEMU Ubuntu 24.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 [ 117.319783][ T9855] Call Trace: [ 117.319785][ T9855] <TASK> [ 117.319788][ T9855] dump_stack_lvl+0x1c1/0x2a0 [ 117.319795][ T9855] ? __virt_addr_valid+0x1c8/0x5c0 [ 117.319803][ T9855] ? __pfx_dump_stack_lvl+0x10/0x10 [ 117.319808][ T9855] ? rcu_is_watching+0x15/0xb0 [ 117.319816][ T9855] ? lock_release+0x4b/0x3e0 [ 117.319821][ T9855] ? __kasan_check_byte+0x12/0x40 [ 117.319828][ T9855] ? __virt_addr_valid+0x1c8/0x5c0 [ 117.319835][ T9855] ? __virt_addr_valid+0x4a5/0x5c0 [ 117.319842][ T9855] print_report+0x17e/0x7e0 [ 117.319848][ T9855] ? __virt_addr_valid+0x1c8/0x5c0 [ 117.319855][ T9855] ? __virt_addr_valid+0x4a5/0x5c0 [ 117.319862][ T9855] ? __phys_addr+0xd3/0x180 [ 117.319869][ T9855] ? hfsplus_strcasecmp+0x1bc/0x490 [ 117.319876][ T9855] kasan_report+0x147/0x180 [ 117.319882][ T9855] ? hfsplus_strcasecmp+0x1bc/0x490 [ 117.319891][ T9855] hfsplus_strcasecmp+0x1bc/0x490 [ 117.319900][ T9855] ? __pfx_hfsplus_cat_case_cmp_key+0x10/0x10 [ 117.319906][ T9855] hfs_find_rec_by_key+0xa9/0x1e0 [ 117.319913][ T9855] __hfsplus_brec_find+0x18e/0x470 [ 117.319920][ T9855] ? __pfx_hfsplus_bnode_find+0x10/0x10 [ 117.319926][ T9855] ? __pfx_hfs_find_rec_by_key+0x10/0x10 [ 117.319933][ T9855] ? __pfx___hfsplus_brec_find+0x10/0x10 [ 117.319942][ T9855] hfsplus_brec_find+0x28f/0x510 [ 117.319949][ T9855] ? __pfx_hfs_find_rec_by_key+0x10/0x10 [ 117.319956][ T9855] ? __pfx_hfsplus_brec_find+0x10/0x10 [ 117.319963][ T9855] ? __kmalloc_noprof+0x2a9/0x510 [ 117.319969][ T9855] ? hfsplus_find_init+0x8c/0x1d0 [ 117.319976][ T9855] hfsplus_brec_read+0x2b/0x120 [ 117.319983][ T9855] hfsplus_lookup+0x2aa/0x890 [ 117.319990][ T9855] ? __pfx_hfsplus_lookup+0x10/0x10 [ 117.320003][ T9855] ? d_alloc_parallel+0x2f0/0x15e0 [ 117.320008][ T9855] ? __lock_acquire+0xaec/0xd80 [ 117.320013][ T9855] ? __pfx_d_alloc_parallel+0x10/0x10 [ 117.320019][ T9855] ? __raw_spin_lock_init+0x45/0x100 [ 117.320026][ T9855] ? __init_waitqueue_head+0xa9/0x150 [ 117.320034][ T9855] __lookup_slow+0x297/0x3d0 [ 117.320039][ T9855] ? __pfx___lookup_slow+0x10/0x10 [ 117.320045][ T9855] ? down_read+0x1ad/0x2e0 [ 117.320055][ T9855] lookup_slow+0x53/0x70 [ 117.320065][ T9855] walk_component+0x2f0/0x430 [ 117.320073][ T9855] path_lookupat+0x169/0x440 [ 117.320081][ T9855] filename_lookup+0x212/0x590 [ 117.320089][ T9855] ? __pfx_filename_lookup+0x10/0x10 [ 117.320098][ T9855] ? strncpy_from_user+0x150/0x290 [ 117.320105][ T9855] ? getname_flags+0x1e5/0x540 [ 117.320112][ T9855] user_path_at+0x3a/0x60 [ 117.320117][ T9855] __x64_sys_umount+0xee/0x160 [ 117.320123][ T9855] ? __pfx___x64_sys_umount+0x10/0x10 [ 117.320129][ T9855] ? do_syscall_64+0xb7/0x3a0 [ 117.320135][ T9855] ? entry_SYSCALL_64_after_hwframe+0x77/0x7f [ 117.320141][ T9855] ? entry_SYSCALL_64_after_hwframe+0x77/0x7f [ 117.320145][ T9855] do_syscall_64+0xf3/0x3a0 [ 117.320150][ T9855] ? exc_page_fault+0x9f/0xf0 [ 117.320154][ T9855] entry_SYSCALL_64_after_hwframe+0x77/0x7f [ 117.320158][ T9855] RIP: 0033:0x7f7dd7908b07 [ 117.320163][ T9855] Code: 23 0d 00 f7 d8 64 89 01 48 83 c8 ff c3 66 0f 1f 44 00 00 31 f6 e9 09 00 00 00 66 0f 1f 84 00 00 08 [ 117.320167][ T9855] RSP: 002b:00007ffd5ebd9698 EFLAGS: 00000202 ORIG_RAX: 00000000000000a6 [ 117.320172][ T9855] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f7dd7908b07 [ 117.320176][ T9855] RDX: 0000000000000009 RSI: 0000000000000009 RDI: 00007ffd5ebd9740 [ 117.320179][ T9855] RBP: 00007ffd5ebda780 R08: 0000000000000005 R09: 00007ffd5ebd9530 [ 117.320181][ T9855] R10: 00007f7dd799bfc0 R11: 0000000000000202 R12: 000055e2008b32d0 [ 117.320184][ T9855] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 [ 117.320189][ T9855] </TASK> [ 117.320190][ T9855] [ 117.351311][ T9855] Allocated by task 9855: [ 117.351683][ T9855] kasan_save_track+0x3e/0x80 [ 117.352093][ T9855] __kasan_kmalloc+0x8d/0xa0 [ 117.352490][ T9855] __kmalloc_noprof+0x288/0x510 [ 117.352914][ T9855] hfsplus_find_init+0x8c/0x1d0 [ 117.353342][ T9855] hfsplus_lookup+0x19c/0x890 [ 117.353747][ T9855] __lookup_slow+0x297/0x3d0 [ 117.354148][ T9855] lookup_slow+0x53/0x70 [ 117.354514][ T9855] walk_component+0x2f0/0x430 [ 117.354921][ T9855] path_lookupat+0x169/0x440 [ 117.355325][ T9855] filename_lookup+0x212/0x590 [ 117.355740][ T9855] user_path_at+0x3a/0x60 [ 117.356115][ T9855] __x64_sys_umount+0xee/0x160 [ 117.356529][ T9855] do_syscall_64+0xf3/0x3a0 [ 117.356920][ T9855] entry_SYSCALL_64_after_hwframe+0x77/0x7f [ 117.357429][ T9855] [ 117.357636][ T9855] The buggy address belongs to the object at ffff88802160f000 [ 117.357636][ T9855] which belongs to the cache kmalloc-2k of size 2048 [ 117.358827][ T9855] The buggy address is located 0 bytes to the right of [ 117.358827][ T9855] allocated 1036-byte region [ffff88802160f000, ffff88802160f40c) [ 117.360061][ T9855] [ 117.360266][ T9855] The buggy address belongs to the physical page: [ 117.360813][ T9855] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x21608 [ 117.361562][ T9855] head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0 [ 117.362285][ T9855] flags: 0xfff00000000040(head|node=0|zone=1|lastcpupid=0x7ff) [ 117.362929][ T9855] page_type: f5(slab) [ 117.363282][ T9855] raw: 00fff00000000040 ffff88801a842f00 ffffea0000932000 dead000000000002 [ 117.364015][ T9855] raw: 0000000000000000 0000000080080008 00000000f5000000 0000000000000000 [ 117.364750][ T9855] head: 00fff00000000040 ffff88801a842f00 ffffea0000932000 dead000000000002 [ 117.365491][ T9855] head: 0000000000000000 0000000080080008 00000000f5000000 0000000000000000 [ 117.366232][ T9855] head: 00fff00000000003 ffffea0000858201 00000000ffffffff 00000000ffffffff [ 117.366968][ T9855] head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000008 [ 117.367711][ T9855] page dumped because: kasan: bad access detected [ 117.368259][ T9855] page_owner tracks the page as allocated [ 117.368745][ T9855] page last allocated via order 3, migratetype Unmovable, gfp_mask 0xd20c0(__GFP_IO|__GFP_FS|__GFP_NOWARN1 [ 117.370541][ T9855] post_alloc_hook+0x240/0x2a0 [ 117.370954][ T9855] get_page_from_freelist+0x2101/0x21e0 [ 117.371435][ T9855] __alloc_frozen_pages_noprof+0x274/0x380 [ 117.371935][ T9855] alloc_pages_mpol+0x241/0x4b0 [ 117.372360][ T9855] allocate_slab+0x8d/0x380 [ 117.372752][ T9855] ___slab_alloc+0xbe3/0x1400 [ 117.373159][ T9855] __kmalloc_cache_noprof+0x296/0x3d0 [ 117.373621][ T9855] nexthop_net_init+0x75/0x100 [ 117.374038][ T9855] ops_init+0x35c/0x5c0 [ 117.374400][ T9855] setup_net+0x10c/0x320 [ 117.374768][ T9855] copy_net_ns+0x31b/0x4d0 [ 117.375156][ T9855] create_new_namespaces+0x3f3/0x720 [ 117.375613][ T9855] unshare_nsproxy_namespaces+0x11c/0x170 [ 117.376094][ T9855] ksys_unshare+0x4ca/0x8d0 [ 117.376477][ T9855] __x64_sys_unshare+0x38/0x50 [ 117.376879][ T9855] do_syscall_64+0xf3/0x3a0 [ 117.377265][ T9855] page last free pid 9110 tgid 9110 stack trace: [ 117.377795][ T9855] __free_frozen_pages+0xbeb/0xd50 [ 117.378229][ T9855] __put_partials+0x152/0x1a0 [ 117.378625][ T9855] put_cpu_partial+0x17c/0x250 [ 117.379026][ T9855] __slab_free+0x2d4/0x3c0 [ 117.379404][ T9855] qlist_free_all+0x97/0x140 [ 117.379790][ T9855] kasan_quarantine_reduce+0x148/0x160 [ 117.380250][ T9855] __kasan_slab_alloc+0x22/0x80 [ 117.380662][ T9855] __kmalloc_noprof+0x232/0x510 [ 117.381074][ T9855] tomoyo_supervisor+0xc0a/0x1360 [ 117.381498][ T9855] tomoyo_env_perm+0x149/0x1e0 [ 117.381903][ T9855] tomoyo_find_next_domain+0x15ad/0x1b90 [ 117.382378][ T9855] tomoyo_bprm_check_security+0x11c/0x180 [ 117.382859][ T9855] security_bprm_check+0x89/0x280 [ 117.383289][ T9855] bprm_execve+0x8f1/0x14a0 [ 117.383673][ T9855] do_execveat_common+0x528/0x6b0 [ 117.384103][ T9855] __x64_sys_execve+0x94/0xb0 [ 117.384500][ T9855] [ 117.384706][ T9855] Memory state around the buggy address: [ 117.385179][ T9855] ffff88802160f300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 117.385854][ T9855] ffff88802160f380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 117.386534][ T9855] >ffff88802160f400: 00 04 fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 117.387204][ T9855] ^ [ 117.387566][ T9855] ffff88802160f480: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 117.388243][ T9855] ffff88802160f500: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 117.388918][ T9855] ==================================================================
The issue takes place if the length field of struct hfsplus_unistr is bigger than HFSPLUS_MAX_STRLEN. The patch simply checks the length of comparing strings. And if the strings' length is bigger than HFSPLUS_MAX_STRLEN, then it is corrected to this value.
v2
The string length correction has been added for hfsplus_strcmp().
--- fs/hfsplus/unicode.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
fs/hfsplus/unicode.c +24 -0
@@ -40,6 +40,18 @@ int hfsplus_strcasecmp(const struct hfsp p1 = s1->unicode; p2 = s2->unicode; +if (len1 >HFSPLUS_MAX_STRLEN ) { + len1 =HFSPLUS_MAX_STRLEN ; +pr_err ("invalid length %u has been corrected to %d\n" , +be16_to_cpu (s1->length), len1); + } + +if (len2 >HFSPLUS_MAX_STRLEN ) { + len2 =HFSPLUS_MAX_STRLEN ; +pr_err ("invalid length %u has been corrected to %d\n" , +be16_to_cpu (s2->length), len2); + } +while (1 ) { c1 = c2 =0 ;
@@ -74,6 +86,18 @@ int hfsplus_strcmp(const struct hfsplus_ p1 = s1->unicode; p2 = s2->unicode; +if (len1 >HFSPLUS_MAX_STRLEN ) { + len1 =HFSPLUS_MAX_STRLEN ; +pr_err ("invalid length %u has been corrected to %d\n" , +be16_to_cpu (s1->length), len1); + } + +if (len2 >HFSPLUS_MAX_STRLEN ) { + len2 =HFSPLUS_MAX_STRLEN ; +pr_err ("invalid length %u has been corrected to %d\n" , +be16_to_cpu (s2->length), len2); + } +for (len =min (len1, len2); len >0 ; len--) { c1 =be16_to_cpu (*p1); c2 =be16_to_cpu (*p2);
Greg Kroah-Hartman
maintainerPATCH 95/136 xfs: rename the old_crc variable in xlog_recover_process
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig <[email protected]>
[ Upstream commit 0b737f4ac1d3ec093347241df74bbf5f54a7e16c ]
old_crc is a very misleading name. Rename it to expected_crc as that described the usage much better.
Stable-dep-of: e747883c7d73 ("xfs: fix log CRC mismatches between i386 and other architectures")
--- fs/xfs/xfs_log_recover.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-)
fs/xfs/xfs_log_recover.c +8 -9
@@ -2890,20 +2890,19 @@ xlog_recover_process(int pass, struct list_head *buffer_list) { - __le32 old_crc = rhead->h_crc; -__le32 crc; + __le32 expected_crc = rhead->h_crc, crc; crc =xlog_cksum (log, rhead, dp,be32_to_cpu (rhead->h_len));/* * Nothing else to do if this is a CRC verification pass. Just return * if this a record with a non-zero crc. Unfortunately, mkfs always -* sets old_crc to 0 so we must consider this valid even on v5 supers. -* Otherwise, return EFSBADCRC on failure so the callers up the stack -* know precisely what failed. +* sets expected_crc to 0 so we must consider this valid even on v5 +* supers. Otherwise, return EFSBADCRC on failure so the callers up the +* stack know precisely what failed. */ if (pass ==XLOG_RECOVER_CRCPASS ) { -if (old_crc && crc != old_crc) +if (expected_crc && crc != expected_crc)return -EFSBADCRC ;return 0 ; }
@@ -2914,11 +2913,11 @@ xlog_recover_process(* zero CRC check prevents warnings from being emitted when upgrading * the kernel from one that does not add CRCs by default. */ -if (crc != old_crc) { -if (old_crc ||xfs_has_crc (log->l_mp)) { +if (crc != expected_crc) { +if (expected_crc ||xfs_has_crc (log->l_mp)) {xfs_alert (log->l_mp,"log record CRC mismatch: found 0x%x, expected 0x%x." , -le32_to_cpu (old_crc), +le32_to_cpu (expected_crc),le32_to_cpu (crc));xfs_hex_dump (dp,32 ); }
Greg Kroah-Hartman
maintainerPATCH 96/136 xfs: fix log CRC mismatches between i386 and other architectures
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig <[email protected]>
[ Upstream commit e747883c7d7306acb4d683038d881528fbfbe749 ]
When mounting file systems with a log that was dirtied on i386 on other architectures or vice versa, log recovery is unhappy:
[ 11.068052] XFS (vdb): Torn write (CRC failure) detected at log block 0x2. Truncating head block from 0xc.
This is because the CRCs generated by i386 and other architectures always diff. The reason for that is that sizeof(struct xlog_rec_header) returns different values for i386 vs the rest (324 vs 328), because the struct is not sizeof(uint64_t) aligned, and i386 has odd struct size alignment rules.
This issue goes back to commit 13cdc853c519 ("Add log versioning, and new super block field for the log stripe") in the xfs-import tree, which adds log v2 support and the h_size field that causes the unaligned size. At that time it only mattered for the crude debug only log header checksum, but with commit 0e446be44806 ("xfs: add CRC checks to the log") it became a real issue for v5 file system, because now there is a proper CRC, and regular builds actually expect it match.
Fix this by allowing checksums with and without the padding.
--- fs/xfs/libxfs/xfs_log_format.h | 30 +++++++++++++++++++++++++++++- fs/xfs/libxfs/xfs_ondisk.h | 2 ++ fs/xfs/xfs_log.c | 8 ++++---- fs/xfs/xfs_log_priv.h | 4 ++-- fs/xfs/xfs_log_recover.c | 19 +++++++++++++++++-- 5 files changed, 54 insertions(+), 9 deletions(-)
fs/xfs/libxfs/xfs_log_format.h +29 -1
@@ -174,12 +174,40 @@ typedef struct xlog_rec_header {__be32 h_prev_block;/* block number to previous LR : 4 */ __be32 h_num_logops;/* number of log operations in this LR : 4 */ __be32 h_cycle_data[XLOG_HEADER_CYCLE_SIZE /BBSIZE ]; -/* new fields */ + +/* fields added by the Linux port: */ __be32 h_fmt;/* format of log record : 4 */ uuid_t h_fs_uuid;/* uuid of FS : 16 */ + +/* fields added for log v2: */ __be32 h_size;/* iclog size : 4 */ + +/* +* When h_size added for log v2 support, it caused structure to have +* a different size on i386 vs all other architectures because the +* sum of the size ofthe member is not aligned by that of the largest +* __be64-sized member, and i386 has really odd struct alignment rules. +* +* Due to the way the log headers are placed out on-disk that alone is +* not a problem becaue the xlog_rec_header always sits alone in a +* BBSIZEs area, and the rest of that area is padded with zeroes. +* But xlog_cksum used to calculate the checksum based on the structure +* size, and thus gives different checksums for i386 vs the rest. +* We now do two checksum validation passes for both sizes to allow +* moving v5 file systems with unclean logs between i386 and other +* (little-endian) architectures. +*/ +__u32 h_pad0; } xlog_rec_header_t; +#ifdef __i386__ +#define XLOG_REC_SIZE offsetofend(struct xlog_rec_header, h_size) +#define XLOG_REC_SIZE_OTHER sizeof(struct xlog_rec_header) +#else +#define XLOG_REC_SIZE sizeof(struct xlog_rec_header) +#define XLOG_REC_SIZE_OTHER offsetofend(struct xlog_rec_header, h_size) +#endif /* __i386__ */ + typedef struct xlog_rec_ext_header { __be32 xh_cycle; /* write cycle of log : 4 */ __be32 xh_cycle_data[XLOG_HEADER_CYCLE_SIZE / BBSIZE]; /* : 256 */
fs/xfs/libxfs/xfs_ondisk.h +2 -0
@@ -149,6 +149,8 @@ xfs_check_ondisk_structs(void) XFS_CHECK_STRUCT_SIZE(struct xfs_rud_log_format, 16); XFS_CHECK_STRUCT_SIZE(struct xfs_map_extent, 32); XFS_CHECK_STRUCT_SIZE(struct xfs_phys_extent, 16); + XFS_CHECK_STRUCT_SIZE(struct xlog_rec_header, 328); + XFS_CHECK_STRUCT_SIZE(struct xlog_rec_ext_header, 260); XFS_CHECK_OFFSET(struct xfs_bui_log_format, bui_extents, 16); XFS_CHECK_OFFSET(struct xfs_cui_log_format, cui_extents, 16);
fs/xfs/xfs_log.c +4 -4
@@ -1567,13 +1567,13 @@ xlog_cksum(struct xlog *log, struct xlog_rec_header *rhead, char *dp, - int size) + unsigned int hdrsize, + unsigned int size) { uint32_t crc;/* first generate the crc for the record header ... */ - crc =xfs_start_cksum_update ((char *)rhead, -sizeof (struct xlog_rec_header ), + crc =xfs_start_cksum_update ((char *)rhead, hdrsize, offsetof(struct xlog_rec_header , h_crc));/* ... then for additional cycle data for v2 logs ... */
@@ -1837,7 +1837,7 @@ xlog_sync(/* calculcate the checksum */ iclog->ic_header.h_crc =xlog_cksum (log, &iclog->ic_header, - iclog->ic_datap, size); + iclog->ic_datap,XLOG_REC_SIZE , size);/* * Intentionally corrupt the log record CRC based on the error injection * frequency, if defined. This facilitates testing log recovery in the
fs/xfs/xfs_log_priv.h +2 -2
@@ -498,8 +498,8 @@ xlog_recover_finish(extern void xlog_recover_cancel (struct xlog *); -extern __le32 xlog_cksum (struct xlog *log,struct xlog_rec_header *rhead, -char *dp,int size); +__le32 xlog_cksum (struct xlog *log,struct xlog_rec_header *rhead, +char *dp,unsigned int hdrsize,unsigned int size);extern struct kmem_cache *xfs_log_ticket_cache; struct xlog_ticket *xlog_ticket_alloc(struct xlog *log, int unit_bytes,
fs/xfs/xfs_log_recover.c +17 -2
@@ -2890,9 +2890,24 @@ xlog_recover_process(int pass, struct list_head *buffer_list) { - __le32 expected_crc = rhead->h_crc, crc; + __le32 expected_crc = rhead->h_crc, crc, other_crc; - crc =xlog_cksum (log, rhead, dp,be32_to_cpu (rhead->h_len)); + crc =xlog_cksum (log, rhead, dp,XLOG_REC_SIZE , +be32_to_cpu (rhead->h_len)); + +/* +* Look at the end of the struct xlog_rec_header definition in +* xfs_log_format.h for the glory details. +*/ +if (expected_crc && crc != expected_crc) { + other_crc =xlog_cksum (log, rhead, dp,XLOG_REC_SIZE_OTHER , +be32_to_cpu (rhead->h_len)); +if (other_crc == expected_crc) { +xfs_notice_once (log->l_mp, +"Fixing up incorrect CRC due to padding." ); + crc = other_crc; + } + }/* * Nothing else to do if this is a CRC verification pass. Just return
Greg Kroah-Hartman
maintainerPATCH 97/136 phy: cdns-dphy: Store hs_clk_rate and return it
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tomi Valkeinen <[email protected]>
[ Upstream commit 689a54acb56858c85de8c7285db82b8ae6dbf683 ]
The DPHY driver does not return the actual hs_clk_rate, so the DSI driver has no idea what clock was actually achieved. Set the realized hs_clk_rate to the opts struct, so that the DSI driver gets it back.
Stable-dep-of: 284fb19a3ffb ("phy: cadence: cdns-dphy: Fix PLL lock and O_CMN_READY polling")
--- drivers/phy/cadence/cdns-dphy.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/phy/cadence/cdns-dphy.c +5 -0
@@ -79,6 +79,7 @@ struct cdns_dphy_cfg {u8 pll_ipdiv;u8 pll_opdiv;u16 pll_fbdiv; +u32 hs_clk_rate;unsigned int nlanes; };
@@ -154,6 +155,9 @@ static int cdns_dsi_get_dphy_pll_cfg(str cfg->pll_ipdiv, pll_ref_hz); + cfg->hs_clk_rate =div_u64 ((u64 )pll_ref_hz * cfg->pll_fbdiv, +2 * cfg->pll_opdiv * cfg->pll_ipdiv); +return 0 ; }
@@ -297,6 +301,7 @@ static int cdns_dphy_config_from_opts(stif (ret)return ret; + opts->hs_clk_rate = cfg->hs_clk_rate; opts->wakeup =cdns_dphy_get_wakeup_time_ns (dphy) /1000 ;return 0 ;
Greg Kroah-Hartman
maintainerPATCH 98/136 phy: cadence: cdns-dphy: Fix PLL lock and O_CMN_READY polling
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Devarsh Thakkar <[email protected]>
[ Upstream commit 284fb19a3ffb1083c3ad9c00d29749d09dddb99c ]
PLL lockup and O_CMN_READY assertion can only happen after common state machine gets enabled by programming DPHY_CMN_SSM register, but driver was polling them before the common state machine was enabled which is incorrect. This is as per the DPHY initialization sequence as mentioned in J721E TRM [1] at section "12.7.2.4.1.2.1 Start-up Sequence Timing Diagram". It shows O_CMN_READY polling at the end after common configuration pin setup where the common configuration pin setup step enables state machine as referenced in "Table 12-1533. Common Configuration-Related Setup mentions state machine"
To fix this :
- Add new function callbacks for polling on PLL lock and O_CMN_READY assertion.
- As state machine and clocks get enabled in power_on callback only, move the clock related programming part from configure callback to power_on
callback and poll for the PLL lockup and O_CMN_READY assertion after state machine gets enabled.
- The configure callback only saves the PLL configuration received from the client driver which will be applied later on in power_on callback.
- Add checks to ensure configure is called before power_on and state machine is in disabled state before power_on callback is called.
- Disable state machine in power_off so that client driver can re-configure the PLL by following up a power_off, configure, power_on sequence.
[1]: https://www.ti.com/lit/zip/spruil1
--- drivers/phy/cadence/cdns-dphy.c | 124 +++++++++++++++++++++++++++++----------- 1 file changed, 92 insertions(+), 32 deletions(-)
drivers/phy/cadence/cdns-dphy.c +92 -32
@@ -100,6 +100,8 @@ struct cdns_dphy_ops {void (*set_pll_cfg)(struct cdns_dphy *dphy,const struct cdns_dphy_cfg *cfg);unsigned long (*get_wakeup_time_ns)(struct cdns_dphy *dphy); +int (*wait_for_pll_lock)(struct cdns_dphy *dphy); +int (*wait_for_cmn_ready)(struct cdns_dphy *dphy); };struct cdns_dphy {
@@ -109,6 +111,8 @@ struct cdns_dphy {struct clk *pll_ref_clk;const struct cdns_dphy_ops *ops;struct phy *phy; +bool is_configured; +bool is_powered; };/* Order of bands is important since the index is the band number. */
@@ -195,6 +199,16 @@ static unsigned long cdns_dphy_get_wakeureturn dphy->ops->get_wakeup_time_ns (dphy); } +static int cdns_dphy_wait_for_pll_lock (struct cdns_dphy *dphy) +{ +return dphy->ops->wait_for_pll_lock ? dphy->ops->wait_for_pll_lock (dphy) :0 ; +} + +static int cdns_dphy_wait_for_cmn_ready (struct cdns_dphy *dphy) +{ +return dphy->ops->wait_for_cmn_ready ? dphy->ops->wait_for_cmn_ready (dphy) :0 ; +} +static unsigned long cdns_dphy_ref_get_wakeup_time_ns (struct cdns_dphy *dphy) {/* Default wakeup time is 800 ns (in a simulated environment). */
@@ -236,7 +250,6 @@ static unsigned long cdns_dphy_j721e_getstatic void cdns_dphy_j721e_set_pll_cfg (struct cdns_dphy *dphy,const struct cdns_dphy_cfg *cfg) { -u32 status;/* * set the PWM and PLL Byteclk divider settings to recommended values
@@ -253,13 +266,6 @@ static void cdns_dphy_j721e_set_pll_cfg(writel (DPHY_TX_J721E_WIZ_LANE_RSTB , dphy->regs +DPHY_TX_J721E_WIZ_RST_CTRL ); - -readl_poll_timeout (dphy->regs +DPHY_TX_J721E_WIZ_PLL_CTRL , status, - (status &DPHY_TX_WIZ_PLL_LOCK ),0 ,POLL_TIMEOUT_US ); - -readl_poll_timeout (dphy->regs +DPHY_TX_J721E_WIZ_STATUS , status, - (status &DPHY_TX_WIZ_O_CMN_READY ),0 , -POLL_TIMEOUT_US ); }static void cdns_dphy_j721e_set_psm_div (struct cdns_dphy *dphy,u8 div)
@@ -267,6 +273,23 @@ static void cdns_dphy_j721e_set_psm_div(writel (div, dphy->regs +DPHY_TX_J721E_WIZ_PSM_FREQ ); } +static int cdns_dphy_j721e_wait_for_pll_lock (struct cdns_dphy *dphy) +{ +u32 status; + +return readl_poll_timeout (dphy->regs +DPHY_TX_J721E_WIZ_PLL_CTRL , status, + status &DPHY_TX_WIZ_PLL_LOCK ,0 ,POLL_TIMEOUT_US ); +} + +static int cdns_dphy_j721e_wait_for_cmn_ready (struct cdns_dphy *dphy) +{ +u32 status; + +return readl_poll_timeout (dphy->regs +DPHY_TX_J721E_WIZ_STATUS , status, + status &DPHY_TX_WIZ_O_CMN_READY ,0 , +POLL_TIMEOUT_US ); +} +/* * This is the reference implementation of DPHY hooks. Specific integration of * this IP may have to re-implement some of them depending on how they decided
@@ -282,6 +305,8 @@ static const struct cdns_dphy_ops j721e_ .get_wakeup_time_ns = cdns_dphy_j721e_get_wakeup_time_ns, .set_pll_cfg = cdns_dphy_j721e_set_pll_cfg, .set_psm_div = cdns_dphy_j721e_set_psm_div, + .wait_for_pll_lock = cdns_dphy_j721e_wait_for_pll_lock, + .wait_for_cmn_ready = cdns_dphy_j721e_wait_for_cmn_ready, }; static int cdns_dphy_config_from_opts(struct phy *phy,
@@ -339,21 +364,36 @@ static int cdns_dphy_validate(struct phystatic int cdns_dphy_configure (struct phy *phy,union phy_configure_opts *opts) {struct cdns_dphy *dphy =phy_get_drvdata (phy); -struct cdns_dphy_cfg cfg = {0 }; -int ret, band_ctrl; -unsigned int reg; +int ret; - ret =cdns_dphy_config_from_opts (phy, &opts->mipi_dphy, &cfg); -if (ret) -return ret; + ret =cdns_dphy_config_from_opts (phy, &opts->mipi_dphy, &dphy->cfg); +if (!ret) + dphy->is_configured = true; + +return ret; +} + +static int cdns_dphy_power_on (struct phy *phy) +{ +struct cdns_dphy *dphy =phy_get_drvdata (phy); +int ret; +u32 reg; + +if (!dphy->is_configured || dphy->is_powered) +return -EINVAL ; + +clk_prepare_enable (dphy->psm_clk); +clk_prepare_enable (dphy->pll_ref_clk);/* * Configure the internal PSM clk divider so that the DPHY has a * 1MHz clk (or something close). */ ret =cdns_dphy_setup_psm (dphy); -if (ret) -return ret; +if (ret) { +dev_err (&dphy->phy->dev,"Failed to setup PSM with error %d\n" , ret); + goto err_power_on; + }/* * Configure attach clk lanes to data lanes: the DPHY has 2 clk lanes
@@ -368,40 +408,60 @@ static int cdns_dphy_configure(struct ph* Configure the DPHY PLL that will be used to generate the TX byte * clk. */ -cdns_dphy_set_pll_cfg (dphy, &cfg); +cdns_dphy_set_pll_cfg (dphy, &dphy->cfg); - band_ctrl =cdns_dphy_tx_get_band_ctrl (opts->mipi_dphy.hs_clk_rate); -if (band_ctrl <0 ) -return band_ctrl; + ret =cdns_dphy_tx_get_band_ctrl (dphy->cfg.hs_clk_rate); +if (ret <0 ) { +dev_err (&dphy->phy->dev,"Failed to get band control value with error %d\n" , ret); + goto err_power_on; + } - reg =FIELD_PREP (DPHY_BAND_CFG_LEFT_BAND , band_ctrl) | -FIELD_PREP (DPHY_BAND_CFG_RIGHT_BAND , band_ctrl); + reg =FIELD_PREP (DPHY_BAND_CFG_LEFT_BAND , ret) | +FIELD_PREP (DPHY_BAND_CFG_RIGHT_BAND , ret);writel (reg, dphy->regs +DPHY_BAND_CFG ); -return 0 ; -} - -static int cdns_dphy_power_on (struct phy *phy) -{ -struct cdns_dphy *dphy =phy_get_drvdata (phy); - -clk_prepare_enable (dphy->psm_clk); -clk_prepare_enable (dphy->pll_ref_clk); -/* Start TX state machine. */ writel (DPHY_CMN_SSM_EN |DPHY_CMN_TX_MODE_EN , dphy->regs +DPHY_CMN_SSM ); + ret =cdns_dphy_wait_for_pll_lock (dphy); +if (ret) { +dev_err (&dphy->phy->dev,"Failed to lock PLL with error %d\n" , ret); + goto err_power_on; + } + + ret =cdns_dphy_wait_for_cmn_ready (dphy); +if (ret) { +dev_err (&dphy->phy->dev,"O_CMN_READY signal failed to assert with error %d\n" , + ret); + goto err_power_on; + } + + dphy->is_powered = true; +return 0 ; + +err_power_on: +clk_disable_unprepare (dphy->pll_ref_clk); +clk_disable_unprepare (dphy->psm_clk); + +return ret; }static int cdns_dphy_power_off (struct phy *phy) {struct cdns_dphy *dphy =phy_get_drvdata (phy); +u32 reg;clk_disable_unprepare (dphy->pll_ref_clk);clk_disable_unprepare (dphy->psm_clk); +/* Stop TX state machine. */ + reg =readl (dphy->regs +DPHY_CMN_SSM ); +writel (reg & ~DPHY_CMN_SSM_EN , dphy->regs +DPHY_CMN_SSM ); + + dphy->is_powered = false; +return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 99/136 PM: runtime: Add new devm functions
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bence Csókás <[email protected]>
[ Upstream commit 73db799bf5efc5a04654bb3ff6c9bf63a0dfa473 ]
Add devm_pm_runtime_set_active_enabled() anddevm_pm_runtime_get_noresume() for simplifying
common cases in drivers.
Stable-dep-of: 0792c1984a45 ("iio: imu: inv_icm42600: Simplify pm_runtime setup")
--- drivers/base/power/runtime.c | 44 +++++++++++++++++++++++++++++++++++++++++++ include/linux/pm_runtime.h | 4 +++ 2 files changed, 48 insertions(+)
drivers/base/power/runtime.c +44 -0
@@ -1554,6 +1554,32 @@ out: }EXPORT_SYMBOL_GPL (pm_runtime_enable); +static void pm_runtime_set_suspended_action (void *data) +{ +pm_runtime_set_suspended (data); +} + +/** +* devm_pm_runtime_set_active_enabled - set_active version of devm_pm_runtime_enable. +* +* @dev: Device to handle. +*/ +int devm_pm_runtime_set_active_enabled (struct device *dev) +{ +int err; + + err =pm_runtime_set_active (dev); +if (err) +return err; + + err =devm_add_action_or_reset (dev, pm_runtime_set_suspended_action, dev); +if (err) +return err; + +return devm_pm_runtime_enable (dev); +} +EXPORT_SYMBOL_GPL (devm_pm_runtime_set_active_enabled); +static void pm_runtime_disable_action (void *data) {pm_runtime_dont_use_autosuspend (data);
@@ -1576,6 +1602,24 @@ int devm_pm_runtime_enable(struct device }EXPORT_SYMBOL_GPL (devm_pm_runtime_enable); +static void pm_runtime_put_noidle_action (void *data) +{ +pm_runtime_put_noidle (data); +} + +/** +* devm_pm_runtime_get_noresume - devres-enabled version of pm_runtime_get_noresume. +* +* @dev: Device to handle. +*/ +int devm_pm_runtime_get_noresume (struct device *dev) +{ +pm_runtime_get_noresume (dev); + +return devm_add_action_or_reset (dev, pm_runtime_put_noidle_action, dev); +} +EXPORT_SYMBOL_GPL (devm_pm_runtime_get_noresume); +/** * pm_runtime_forbid - Block runtime PM of a device. * @dev: Device to handle.
include/linux/pm_runtime.h +4 -0
@@ -94,7 +94,9 @@ extern void pm_runtime_new_link(struct dextern void pm_runtime_drop_link (struct device_link *link);extern void pm_runtime_release_supplier (struct device_link *link); +int devm_pm_runtime_set_active_enabled (struct device *dev);extern int devm_pm_runtime_enable (struct device *dev); +int devm_pm_runtime_get_noresume (struct device *dev);/** * pm_suspend_ignore_children - Set runtime PM behavior regarding children.
@@ -278,7 +280,9 @@ static inline void __pm_runtime_disable(static inline void pm_runtime_allow (struct device *dev) {}static inline void pm_runtime_forbid (struct device *dev) {} +static inline int devm_pm_runtime_set_active_enabled (struct device *dev) {return 0 ; }static inline int devm_pm_runtime_enable (struct device *dev) {return 0 ; } +static inline int devm_pm_runtime_get_noresume (struct device *dev) {return 0 ; }static inline void pm_suspend_ignore_children (struct device *dev,bool enable) {}static inline void pm_runtime_get_noresume (struct device *dev) {}
Greg Kroah-Hartman
maintainerPATCH 100/136 iio: imu: inv_icm42600: Simplify pm_runtime setup
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Nyekjaer <[email protected]>
[ Upstream commit 0792c1984a45ccd7a296d6b8cb78088bc99a212e ]
Rework the power management in inv_icm42600_core_probe() to use devm_pm_runtime_set_active_enabled(), which simplifies the runtime PM setup by handling activation and enabling in one step. Remove the separate inv_icm42600_disable_pm callback, as it's no longer needed with the devm-managed approach.
Using devm_pm_runtime_enable() also fixes the missing disable of autosuspend.
Update inv_icm42600_disable_vddio_reg() to only disable the regulator if the device is not suspended i.e. powered-down, preventing unbalanced disables.
Also remove redundant error msg on regulator_disable(), the regulator framework already emits an error message when regulator_disable() fails.
This simplifies the PM setup and avoids manipulating the usage counter unnecessarily.
--- drivers/iio/imu/inv_icm42600/inv_icm42600_core.c | 24 ++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-)
drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +7 -17
@@ -667,20 +667,12 @@ static void inv_icm42600_disable_vdd_regstatic void inv_icm42600_disable_vddio_reg (void *_data) {struct inv_icm42600_state *st = _data; -const struct device *dev =regmap_get_device (st->map); -int ret; - - ret =regulator_disable (st->vddio_supply); -if (ret) -dev_err (dev,"failed to disable vddio error %d\n" , ret); -} +struct device *dev =regmap_get_device (st->map); -static void inv_icm42600_disable_pm (void *_data) -{ -struct device *dev = _data; +if (pm_runtime_status_suspended (dev)) +return ; -pm_runtime_put_sync (dev); -pm_runtime_disable (dev); +regulator_disable (st->vddio_supply); } int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq,
@@ -777,16 +769,14 @@ int inv_icm42600_core_probe(struct regmareturn ret;/* setup runtime power management */ - ret =pm_runtime_set_active (dev); + ret =devm_pm_runtime_set_active_enabled (dev);if (ret)return ret; -pm_runtime_get_noresume (dev); -pm_runtime_enable (dev); +pm_runtime_set_autosuspend_delay (dev,INV_ICM42600_SUSPEND_DELAY_MS );pm_runtime_use_autosuspend (dev); -pm_runtime_put (dev); -return devm_add_action_or_reset (dev, inv_icm42600_disable_pm, dev); +return ret; }EXPORT_SYMBOL_NS_GPL (inv_icm42600_core_probe,IIO_ICM42600 );
Greg Kroah-Hartman
maintainerPATCH 101/136 iio: imu: inv_icm42600: Avoid configuring if already pm_runtime suspended
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Nyekjaer <[email protected]>
[ Upstream commit 466f7a2fef2a4e426f809f79845a1ec1aeb558f4 ]
Do as in suspend, skip resume configuration steps if the device is already pm_runtime suspended. This avoids reconfiguring a device that is already in the correct low-power state and ensures that pm_runtime handles the power state transitions properly.
--- drivers/iio/imu/inv_icm42600/inv_icm42600_core.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +6 -5
@@ -787,17 +787,15 @@ EXPORT_SYMBOL_NS_GPL(inv_icm42600_core_pstatic int inv_icm42600_suspend (struct device *dev) {struct inv_icm42600_state *st =dev_get_drvdata (dev); -int ret; +int ret =0 ;mutex_lock (&st->lock); st->suspended.gyro = st->conf.gyro.mode; st->suspended.accel = st->conf.accel.mode; st->suspended.temp = st->conf.temp_en; -if (pm_runtime_suspended (dev)) { - ret =0 ; +if (pm_runtime_suspended (dev)) goto out_unlock; - }/* disable FIFO data streaming */ if (st->fifo.on) {
@@ -829,10 +827,13 @@ static int inv_icm42600_resume(struct destruct inv_icm42600_state *st =dev_get_drvdata (dev);struct inv_icm42600_sensor_state *gyro_st =iio_priv (st->indio_gyro);struct inv_icm42600_sensor_state *accel_st =iio_priv (st->indio_accel); -int ret; +int ret =0 ;mutex_lock (&st->lock); +if (pm_runtime_suspended (dev)) + goto out_unlock; + ret =inv_icm42600_enable_regulator_vddio (st);if (ret) goto out_unlock;
Greg Kroah-Hartman
maintainerPATCH 102/136 nfsd: Use correct error code when decoding extents
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sergey Bashirov <[email protected]>
[ Upstream commit 26d05e1c37d276905bc921384b5a75158fca284b ]
Update error codes in decoding functions of block and scsi layout drivers to match the core nfsd code. NFS4ERR_EINVAL means that the server was able to decode the request, but the decoded values are invalid. Use NFS4ERR_BADXDR instead to indicate a decoding error. And ENOMEM is changed to nfs code NFS4ERR_DELAY.
Stable-dep-of: d68886bae76a ("NFSD: Fix last write offset handling in layoutcommit")
--- fs/nfsd/blocklayout.c | 20 +++++++------ fs/nfsd/blocklayoutxdr.c | 71 +++++++++++++++++++++++++++++++++++++---------- fs/nfsd/blocklayoutxdr.h | 8 ++--- fs/nfsd/nfsd.h | 1 4 files changed, 73 insertions(+), 27 deletions(-)
fs/nfsd/blocklayout.c +12 -8
@@ -178,11 +178,13 @@ nfsd4_block_proc_layoutcommit(struct ino {struct iomap *iomaps;int nr_iomaps; +__be32 nfserr; - nr_iomaps =nfsd4_block_decode_layoutupdate (lcp->lc_up_layout, - lcp->lc_up_len, &iomaps,i_blocksize (inode)); -if (nr_iomaps <0 ) -return nfserrno (nr_iomaps); + nfserr =nfsd4_block_decode_layoutupdate (lcp->lc_up_layout, + lcp->lc_up_len, &iomaps, &nr_iomaps, +i_blocksize (inode)); +if (nfserr != nfs_ok) +return nfserr;return nfsd4_block_commit_blocks (inode, lcp, iomaps, nr_iomaps); }
@@ -316,11 +318,13 @@ nfsd4_scsi_proc_layoutcommit(struct inod {struct iomap *iomaps;int nr_iomaps; +__be32 nfserr; - nr_iomaps =nfsd4_scsi_decode_layoutupdate (lcp->lc_up_layout, - lcp->lc_up_len, &iomaps,i_blocksize (inode)); -if (nr_iomaps <0 ) -return nfserrno (nr_iomaps); + nfserr =nfsd4_scsi_decode_layoutupdate (lcp->lc_up_layout, + lcp->lc_up_len, &iomaps, &nr_iomaps, +i_blocksize (inode)); +if (nfserr != nfs_ok) +return nfserr;return nfsd4_block_commit_blocks (inode, lcp, iomaps, nr_iomaps); }
fs/nfsd/blocklayoutxdr.c +56 -15
133 lines not on this page · raw message
fs/nfsd/blocklayoutxdr.h +4 -4
@@ -54,9 +54,9 @@ __be32 nfsd4_block_encode_getdeviceinfo( const struct nfsd4_getdeviceinfo *gdp);__be32 nfsd4_block_encode_layoutget (struct xdr_stream *xdr,const struct nfsd4_layoutget *lgp); -int nfsd4_block_decode_layoutupdate (__be32 *p,u32 len,struct iomap **iomapp, -u32 block_size); -int nfsd4_scsi_decode_layoutupdate (__be32 *p,u32 len,struct iomap **iomapp, -u32 block_size); +__be32 nfsd4_block_decode_layoutupdate (__be32 *p,u32 len, +struct iomap **iomapp,int *nr_iomapsp,u32 block_size); +__be32 nfsd4_scsi_decode_layoutupdate (__be32 *p,u32 len, +struct iomap **iomapp,int *nr_iomapsp,u32 block_size);#endif /* _NFSD_BLOCKLAYOUTXDR_H */
fs/nfsd/nfsd.h +1 -0
@@ -286,6 +286,7 @@ void nfsd_lockd_shutdown(void);#define nfserr_cb_path_down cpu_to_be32(NFSERR_CB_PATH_DOWN)#define nfserr_locked cpu_to_be32(NFSERR_LOCKED)#define nfserr_wrongsec cpu_to_be32(NFSERR_WRONGSEC) +#define nfserr_delay cpu_to_be32(NFS4ERR_DELAY)#define nfserr_badiomode cpu_to_be32(NFS4ERR_BADIOMODE)#define nfserr_badlayout cpu_to_be32(NFS4ERR_BADLAYOUT)#define nfserr_bad_session_digest cpu_to_be32(NFS4ERR_BAD_SESSION_DIGEST)
Greg Kroah-Hartman
maintainerPATCH 103/136 nfsd: Drop dprintk in blocklayout xdr functions
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sergey Bashirov <[email protected]>
[ Upstream commit e339967eecf1305557f7c697e1bc10b5cc495454 ]
Minor clean up. Instead of dprintk there are appropriate error codes.
Stable-dep-of: d68886bae76a ("NFSD: Fix last write offset handling in layoutcommit")
--- fs/nfsd/blocklayoutxdr.c | 40 +++++++--------------------------------- 1 file changed, 7 insertions(+), 33 deletions(-)
fs/nfsd/blocklayoutxdr.c +7 -33
@@ -139,28 +139,19 @@ nfsd4_block_decode_layoutupdate(__be32 *struct iomap *iomaps;u32 nr_iomaps, i; -if (len <sizeof (u32)) { -dprintk ("%s: extent array too small: %u\n" , __func__, len); +if (len <sizeof (u32))return nfserr_bad_xdr; - } len -=sizeof (u32); -if (len %PNFS_BLOCK_EXTENT_SIZE ) { -dprintk ("%s: extent array invalid: %u\n" , __func__, len); +if (len %PNFS_BLOCK_EXTENT_SIZE )return nfserr_bad_xdr; - } nr_iomaps =be32_to_cpup (p++); -if (nr_iomaps != len /PNFS_BLOCK_EXTENT_SIZE ) { -dprintk ("%s: extent array size mismatch: %u/%u\n" , - __func__, len, nr_iomaps); +if (nr_iomaps != len /PNFS_BLOCK_EXTENT_SIZE )return nfserr_bad_xdr; - } iomaps =kcalloc (nr_iomaps,sizeof (*iomaps),GFP_KERNEL ); -if (!iomaps) { -dprintk ("%s: failed to allocate extent array\n" , __func__); +if (!iomaps)return nfserr_delay; - }for (i =0 ; i < nr_iomaps; i++) {struct pnfs_block_extent bex;
@@ -170,26 +161,18 @@ nfsd4_block_decode_layoutupdate(__be32 * p =xdr_decode_hyper (p, &bex.foff);if (bex.foff & (block_size -1 )) { -dprintk ("%s: unaligned offset 0x%llx\n" , - __func__, bex.foff); goto fail; } p =xdr_decode_hyper (p, &bex.len);if (bex.len & (block_size -1 )) { -dprintk ("%s: unaligned length 0x%llx\n" , - __func__, bex.foff); goto fail; } p =xdr_decode_hyper (p, &bex.soff);if (bex.soff & (block_size -1 )) { -dprintk ("%s: unaligned disk offset 0x%llx\n" , - __func__, bex.soff); goto fail; } bex.es =be32_to_cpup (p++);if (bex.es !=PNFS_BLOCK_READWRITE_DATA ) { -dprintk ("%s: incorrect extent state %d\n" , - __func__, bex.es); goto fail; }
@@ -231,38 +214,29 @@ nfsd4_scsi_decode_layoutupdate(__be32 *pstruct iomap *iomaps;u32 nr_iomaps, expected, i; -if (len <sizeof (u32)) { -dprintk ("%s: extent array too small: %u\n" , __func__, len); +if (len <sizeof (u32))return nfserr_bad_xdr; - } nr_iomaps =be32_to_cpup (p++); expected =sizeof (__be32) + nr_iomaps *PNFS_SCSI_RANGE_SIZE ; -if (len != expected) { -dprintk ("%s: extent array size mismatch: %u/%u\n" , - __func__, len, expected); +if (len != expected)return nfserr_bad_xdr; - } iomaps =kcalloc (nr_iomaps,sizeof (*iomaps),GFP_KERNEL ); -if (!iomaps) { -dprintk ("%s: failed to allocate extent array\n" , __func__); +if (!iomaps)return nfserr_delay; - }for (i =0 ; i < nr_iomaps; i++) {u64 val; p =xdr_decode_hyper (p, &val);if (val & (block_size -1 )) { -dprintk ("%s: unaligned offset 0x%llx\n" , __func__, val); goto fail; } iomaps[i].offset = val; p =xdr_decode_hyper (p, &val);if (val & (block_size -1 )) { -dprintk ("%s: unaligned length 0x%llx\n" , __func__, val); goto fail; } iomaps[i].length = val;
Greg Kroah-Hartman
maintainerPATCH 104/136 NFSD: Rework encoding and decoding of nfsd4_deviceid
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sergey Bashirov <[email protected]>
[ Upstream commit 832738e4b325b742940761e10487403f9aad13e8 ]
Compilers may optimize the layout of C structures, so we should not rely on sizeof struct and memcpy to encode and decode XDR structures. The byte order of the fields should also be taken into account.
This patch adds the correct functions to handle the deviceid4 structure and removes the pad field, which is currently not used by NFSD, from the runtime state. The server's byte order is preserved because the deviceid4 blob on the wire is only used as a cookie by the client.
Stable-dep-of: d68886bae76a ("NFSD: Fix last write offset handling in layoutcommit")
--- fs/nfsd/blocklayoutxdr.c | 7 ++----- fs/nfsd/flexfilelayoutxdr.c | 3 +-- fs/nfsd/nfs4layouts.c | 1 - fs/nfsd/nfs4xdr.c | 14 +------------- fs/nfsd/xdr4.h | 36 +++++++++++++++++++++++++++++++++++- 5 files changed, 39 insertions(+), 22 deletions(-)
fs/nfsd/blocklayoutxdr.c +2 -5
@@ -29,8 +29,7 @@ nfsd4_block_encode_layoutget(struct xdr_ *p++ =cpu_to_be32 (len); *p++ =cpu_to_be32 (1 );/* we always return a single extent */ - p =xdr_encode_opaque_fixed (p, &b->vol_id, -sizeof (struct nfsd4_deviceid )); + p =svcxdr_encode_deviceid4 (p, &b->vol_id); p =xdr_encode_hyper (p, b->foff); p =xdr_encode_hyper (p, b->len); p =xdr_encode_hyper (p, b->soff);
@@ -156,9 +155,7 @@ nfsd4_block_decode_layoutupdate(__be32 *for (i =0 ; i < nr_iomaps; i++) {struct pnfs_block_extent bex; -memcpy (&bex.vol_id, p,sizeof (struct nfsd4_deviceid )); - p +=XDR_QUADLEN (sizeof (struct nfsd4_deviceid )); - + p =svcxdr_decode_deviceid4 (p, &bex.vol_id); p =xdr_decode_hyper (p, &bex.foff);if (bex.foff & (block_size -1 )) { goto fail;
fs/nfsd/flexfilelayoutxdr.c +1 -2
@@ -54,8 +54,7 @@ nfsd4_ff_encode_layoutget(struct xdr_str *p++ =cpu_to_be32 (1 );/* single mirror */ *p++ =cpu_to_be32 (1 );/* single data server */ - p =xdr_encode_opaque_fixed (p, &fl->deviceid, -sizeof (struct nfsd4_deviceid )); + p =svcxdr_encode_deviceid4 (p, &fl->deviceid); *p++ =cpu_to_be32 (1 );/* efficiency */
fs/nfsd/nfs4layouts.c +0 -1
@@ -120,7 +120,6 @@ nfsd4_set_deviceid(struct nfsd4_deviceid id->fsid_idx = fhp->fh_export->ex_devid_map->idx; id->generation = device_generation; - id->pad =0 ;return 0 ; }
fs/nfsd/nfs4xdr.c +1 -13
@@ -566,18 +566,6 @@ nfsd4_decode_state_owner4(struct nfsd4_c }#ifdef CONFIG_NFSD_PNFS -static __be32 -nfsd4_decode_deviceid4 (struct nfsd4_compoundargs *argp, -struct nfsd4_deviceid *devid) -{ -__be32 *p; - - p =xdr_inline_decode (argp->xdr,NFS4_DEVICEID4_SIZE ); -if (!p) -return nfserr_bad_xdr; -memcpy (devid, p,sizeof (*devid)); -return nfs_ok; -} static __be32 nfsd4_decode_layoutupdate4(struct nfsd4_compoundargs *argp,
@@ -1762,7 +1750,7 @@ nfsd4_decode_getdeviceinfo(struct nfsd4___be32 status;memset (gdev,0 ,sizeof (*gdev)); - status =nfsd4_decode_deviceid4 (argp, &gdev->gd_devid); + status =nfsd4_decode_deviceid4 (argp->xdr, &gdev->gd_devid);if (status)return status;if (xdr_stream_decode_u32 (argp->xdr, &gdev->gd_layout_type) <0 )
fs/nfsd/xdr4.h +35 -1
@@ -596,9 +596,43 @@ struct nfsd4_reclaim_complete {struct nfsd4_deviceid {u64 fsid_idx;u32 generation; -u32 pad; }; +static inline __be32 * +svcxdr_encode_deviceid4 (__be32 *p,const struct nfsd4_deviceid *devid) +{ +__be64 *q = (__be64 *)p; + + *q = (__force __be64 )devid->fsid_idx; + p +=2 ; + *p++ = (__force __be32 )devid->generation; + *p++ = xdr_zero; +return p; +} + +static inline __be32 * +svcxdr_decode_deviceid4 (__be32 *p,struct nfsd4_deviceid *devid) +{ +__be64 *q = (__be64 *)p; + + devid->fsid_idx = (__force u64)(*q); + p +=2 ; + devid->generation = (__force u32)(*p++); + p++;/* NFSD does not use the remaining octets */ +return p; +} + +static inline __be32 +nfsd4_decode_deviceid4 (struct xdr_stream *xdr,struct nfsd4_deviceid *devid) +{ +__be32 *p =xdr_inline_decode (xdr,NFS4_DEVICEID4_SIZE ); + +if (unlikely (!p)) +return nfserr_bad_xdr; +svcxdr_decode_deviceid4 (p, devid); +return nfs_ok; +} +struct nfsd4_layout_seg {u32 iomode;u64 offset;
Greg Kroah-Hartman
maintainerPATCH 105/136 NFSD: Minor cleanup in layoutcommit processing
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sergey Bashirov <[email protected]>
[ Upstream commit 274365a51d88658fb51cca637ba579034e90a799 ]
Remove dprintk in nfsd4_layoutcommit. These are not needed in day to day usage, and the information is also available in Wireshark when capturing NFS traffic.
Stable-dep-of: d68886bae76a ("NFSD: Fix last write offset handling in layoutcommit")
--- fs/nfsd/nfs4proc.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-)
fs/nfsd/nfs4proc.c +3 -9
@@ -2379,18 +2379,12 @@ nfsd4_layoutcommit(struct svc_rqst *rqst inode =d_inode (current_fh->fh_dentry); nfserr = nfserr_inval; -if (new_size <= seg->offset) { -dprintk ("pnfsd: last write before layout segment\n" ); +if (new_size <= seg->offset) goto out; - } -if (new_size > seg->offset + seg->length) { -dprintk ("pnfsd: last write beyond layout segment\n" ); +if (new_size > seg->offset + seg->length) goto out; - } -if (!lcp->lc_newoffset && new_size >i_size_read (inode)) { -dprintk ("pnfsd: layoutcommit beyond EOF\n" ); +if (!lcp->lc_newoffset && new_size >i_size_read (inode)) goto out; - } nfserr = nfsd4_preprocess_layout_stateid(rqstp, cstate, &lcp->lc_sid, false, lcp->lc_layout_type,
Greg Kroah-Hartman
maintainerPATCH 106/136 NFSD: Implement large extent array support in pNFS
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sergey Bashirov <[email protected]>
[ Upstream commit f963cf2b91a30b5614c514f3ad53ca124cb65280 ]
When pNFS client in the block or scsi layout mode sends layoutcommit to MDS, a variable length array of modified extents is supplied within the request. This patch allows the server to accept such extent arrays if they do not fit within single memory page.
The issue can be reproduced when writing to a 1GB file using FIO with O_DIRECT, 4K block and large I/O depth without preallocation of the file. In this case, the server returns NFSERR_BADXDR to the client.
Stable-dep-of: d68886bae76a ("NFSD: Fix last write offset handling in layoutcommit")
--- fs/nfsd/blocklayout.c | 20 ++++++----- fs/nfsd/blocklayoutxdr.c | 83 +++++++++++++++++++++++++++++++---------------- fs/nfsd/blocklayoutxdr.h | 4 +- fs/nfsd/nfs4proc.c | 2 - fs/nfsd/nfs4xdr.c | 11 ++---- fs/nfsd/pnfs.h | 1 fs/nfsd/xdr4.h | 3 - 7 files changed, 78 insertions(+), 46 deletions(-)
fs/nfsd/blocklayout.c +12 -8
@@ -173,16 +173,18 @@ nfsd4_block_proc_getdeviceinfo(struct su }static __be32 -nfsd4_block_proc_layoutcommit (struct inode *inode, +nfsd4_block_proc_layoutcommit (struct inode *inode,struct svc_rqst *rqstp,struct nfsd4_layoutcommit *lcp) {struct iomap *iomaps;int nr_iomaps;__be32 nfserr; - nfserr =nfsd4_block_decode_layoutupdate (lcp->lc_up_layout, - lcp->lc_up_len, &iomaps, &nr_iomaps, -i_blocksize (inode)); + rqstp->rq_arg = lcp->lc_up_layout; +svcxdr_init_decode (rqstp); + + nfserr =nfsd4_block_decode_layoutupdate (&rqstp->rq_arg_stream, + &iomaps, &nr_iomaps,i_blocksize (inode));if (nfserr != nfs_ok)return nfserr;
@@ -313,16 +315,18 @@ nfsd4_scsi_proc_getdeviceinfo(struct supreturn nfserrno (nfsd4_block_get_device_info_scsi (sb, clp, gdp)); }static __be32 -nfsd4_scsi_proc_layoutcommit (struct inode *inode, +nfsd4_scsi_proc_layoutcommit (struct inode *inode,struct svc_rqst *rqstp,struct nfsd4_layoutcommit *lcp) {struct iomap *iomaps;int nr_iomaps;__be32 nfserr; - nfserr =nfsd4_scsi_decode_layoutupdate (lcp->lc_up_layout, - lcp->lc_up_len, &iomaps, &nr_iomaps, -i_blocksize (inode)); + rqstp->rq_arg = lcp->lc_up_layout; +svcxdr_init_decode (rqstp); + + nfserr =nfsd4_scsi_decode_layoutupdate (&rqstp->rq_arg_stream, + &iomaps, &nr_iomaps,i_blocksize (inode));if (nfserr != nfs_ok)return nfserr;
fs/nfsd/blocklayoutxdr.c +56 -27
163 lines not on this page · raw message
fs/nfsd/blocklayoutxdr.h +2 -2
@@ -54,9 +54,9 @@ __be32 nfsd4_block_encode_getdeviceinfo( const struct nfsd4_getdeviceinfo *gdp);__be32 nfsd4_block_encode_layoutget (struct xdr_stream *xdr,const struct nfsd4_layoutget *lgp); -__be32 nfsd4_block_decode_layoutupdate (__be32 *p,u32 len, +__be32 nfsd4_block_decode_layoutupdate (struct xdr_stream *xdr,struct iomap **iomapp,int *nr_iomapsp,u32 block_size); -__be32 nfsd4_scsi_decode_layoutupdate (__be32 *p,u32 len, +__be32 nfsd4_scsi_decode_layoutupdate (struct xdr_stream *xdr,struct iomap **iomapp,int *nr_iomapsp,u32 block_size);#endif /* _NFSD_BLOCKLAYOUTXDR_H */
fs/nfsd/nfs4proc.c +1 -1
@@ -2407,7 +2407,7 @@ nfsd4_layoutcommit(struct svc_rqst *rqst lcp->lc_size_chg = false; } - nfserr = ops->proc_layoutcommit (inode, lcp); + nfserr = ops->proc_layoutcommit (inode, rqstp, lcp);nfs4_put_stid (&ls->ls_stid); out:return nfserr;
fs/nfsd/nfs4xdr.c +5 -6
@@ -571,6 +571,8 @@ static __be32 nfsd4_decode_layoutupdate4(struct nfsd4_compoundargs *argp, struct nfsd4_layoutcommit *lcp) { + u32 len; +if (xdr_stream_decode_u32 (argp->xdr, &lcp->lc_layout_type) <0 )return nfserr_bad_xdr;if (lcp->lc_layout_type <LAYOUT_NFSV4_1_FILES )
@@ -578,13 +580,10 @@ nfsd4_decode_layoutupdate4(struct nfsd4_if (lcp->lc_layout_type >=LAYOUT_TYPE_MAX )return nfserr_bad_xdr; -if (xdr_stream_decode_u32 (argp->xdr, &lcp->lc_up_len) <0 ) +if (xdr_stream_decode_u32 (argp->xdr, &len) <0 ) +return nfserr_bad_xdr; +if (!xdr_stream_subsegment (argp->xdr, &lcp->lc_up_layout, len))return nfserr_bad_xdr; -if (lcp->lc_up_len >0 ) { - lcp->lc_up_layout =xdr_inline_decode (argp->xdr, lcp->lc_up_len); -if (!lcp->lc_up_layout) -return nfserr_bad_xdr; - }return nfs_ok; }
fs/nfsd/pnfs.h +1 -0
@@ -35,6 +35,7 @@ struct nfsd4_layout_ops { const struct nfsd4_layoutget *lgp);__be32 (*proc_layoutcommit)(struct inode *inode, +struct svc_rqst *rqstp,struct nfsd4_layoutcommit *lcp); void (*fence_client)(struct nfs4_layout_stateid *ls,
fs/nfsd/xdr4.h +1 -2
@@ -665,8 +665,7 @@ struct nfsd4_layoutcommit {u64 lc_last_wr;/* request */ struct timespec64 lc_mtime;/* request */ u32 lc_layout_type;/* request */ -u32 lc_up_len;/* layout length */ -void *lc_up_layout;/* decoded by callback */ +struct xdr_buf lc_up_layout;/* decoded by callback */ bool lc_size_chg;/* response */ u64 lc_newsize;/* response */ };
Greg Kroah-Hartman
maintainerPATCH 107/136 NFSD: Fix last write offset handling in layoutcommit
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sergey Bashirov <[email protected]>
[ Upstream commit d68886bae76a4b9b3484d23e5b7df086f940fa38 ]
The data type of loca_last_write_offset is newoffset4 and is switched on a boolean value, no_newoffset, that indicates if a previous write occurred or not. If no_newoffset is FALSE, an offset is not given. This means that client does not try to update the file size. Thus, server should not try to calculate new file size and check if it fits into the segment range. See RFC 8881, section 12.5.4.2.
Sometimes the current incorrect logic may cause clients to hang when trying to sync an inode. If layoutcommit fails, the client marks the inode as dirty again.
--- fs/nfsd/blocklayout.c | 5 ++--- fs/nfsd/nfs4proc.c | 30 +++++++++++++++--------------- 2 files changed, 17 insertions(+), 18 deletions(-)
fs/nfsd/blocklayout.c +2 -3
@@ -118,7 +118,6 @@ nfsd4_block_commit_blocks(struct inode * struct iomap *iomaps, int nr_iomaps) {struct timespec64 mtime =inode_get_mtime (inode); -loff_t new_size = lcp->lc_last_wr +1 ;struct iattr iattr = { .ia_valid =0 };int error;
@@ -128,9 +127,9 @@ nfsd4_block_commit_blocks(struct inode * iattr.ia_valid |=ATTR_ATIME |ATTR_CTIME |ATTR_MTIME ; iattr.ia_atime = iattr.ia_ctime = iattr.ia_mtime = lcp->lc_mtime; -if (new_size >i_size_read (inode)) { +if (lcp->lc_size_chg) { iattr.ia_valid |=ATTR_SIZE ; - iattr.ia_size = new_size; + iattr.ia_size = lcp->lc_newsize; } error = inode->i_sb->s_export_op->commit_blocks(inode, iomaps,
fs/nfsd/nfs4proc.c +15 -15
@@ -2362,7 +2362,6 @@ nfsd4_layoutcommit(struct svc_rqst *rqstconst struct nfsd4_layout_seg *seg = &lcp->lc_seg;struct svc_fh *current_fh = &cstate->current_fh;const struct nfsd4_layout_ops *ops; -loff_t new_size = lcp->lc_last_wr +1 ;struct inode *inode;struct nfs4_layout_stateid *ls;__be32 nfserr;
@@ -2378,13 +2377,21 @@ nfsd4_layoutcommit(struct svc_rqst *rqst goto out; inode =d_inode (current_fh->fh_dentry); - nfserr = nfserr_inval; -if (new_size <= seg->offset) - goto out; -if (new_size > seg->offset + seg->length) - goto out; -if (!lcp->lc_newoffset && new_size >i_size_read (inode)) - goto out; + lcp->lc_size_chg = false; +if (lcp->lc_newoffset) { +loff_t new_size = lcp->lc_last_wr +1 ; + + nfserr = nfserr_inval; +if (new_size <= seg->offset) + goto out; +if (new_size > seg->offset + seg->length) + goto out; + +if (new_size >i_size_read (inode)) { + lcp->lc_size_chg = true; + lcp->lc_newsize = new_size; + } + } nfserr = nfsd4_preprocess_layout_stateid(rqstp, cstate, &lcp->lc_sid, false, lcp->lc_layout_type,
@@ -2400,13 +2407,6 @@ nfsd4_layoutcommit(struct svc_rqst *rqst/* LAYOUTCOMMIT does not require any serialization */ mutex_unlock (&ls->ls_mutex); -if (new_size >i_size_read (inode)) { - lcp->lc_size_chg = true; - lcp->lc_newsize = new_size; - }else { - lcp->lc_size_chg = false; - } - nfserr = ops->proc_layoutcommit (inode, rqstp, lcp);nfs4_put_stid (&ls->ls_stid); out:
Greg Kroah-Hartman
maintainerPATCH 108/136 wifi: rtw89: avoid possible TX wait initialization race
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fedor Pchelkin <[email protected]>
[ Upstream commit c24248ed78f33ea299ea61d105355ba47157d49f ]
The value of skb_data->wait indicates whether skb is passed on to the core mac80211 stack or released by the driver itself. Make sure that by the time skb is added to txwd queue and becomes visible to the completing side, it has already allocated and initialized TX wait related data (in case it's needed).
This is found by code review and addresses a possible race scenario described below:
Waiting thread Completing thread
rtw89_core_send_nullfunc()
rtw89_core_tx_write_link()
...
rtw89_pci_txwd_submit()
skb_data->wait = NULL
/* add skb to the queue */
skb_queue_tail(&txwd->queue, skb) /* another thread (e.g. rtw89_ops_tx) performs TX kick off for the same queue */
rtw89_pci_napi_poll()
...
rtw89_pci_release_txwd_skb()
/* get skb from the queue */
skb_unlink(skb, &txwd->queue)
rtw89_pci_tx_status()
rtw89_core_tx_wait_complete()
/* use incorrect skb_data->wait */ rtw89_core_tx_kick_off_and_wait()
/* assign skb_data->wait but too late */
Found by Linux Verification Center (linuxtesting.org).
--- drivers/net/wireless/realtek/rtw89/core.c | 39 ++++++++++++++------------ drivers/net/wireless/realtek/rtw89/core.h | 6 ++-- drivers/net/wireless/realtek/rtw89/mac80211.c | 2 - drivers/net/wireless/realtek/rtw89/pci.c | 2 - 4 files changed, 26 insertions(+), 23 deletions(-)
drivers/net/wireless/realtek/rtw89/core.c +21 -18
@@ -978,25 +978,14 @@ void rtw89_core_tx_kick_off(struct rtw89 }int rtw89_core_tx_kick_off_and_wait (struct rtw89_dev *rtwdev,struct sk_buff *skb, -int qsel,unsigned int timeout) +struct rtw89_tx_wait_info *wait,int qsel, +unsigned int timeout) { -struct rtw89_tx_skb_data *skb_data =RTW89_TX_SKB_CB (skb); -struct rtw89_tx_wait_info *wait;unsigned long time_left;int ret =0 ;lockdep_assert_wiphy (rtwdev->hw->wiphy); - wait =kzalloc (sizeof (*wait),GFP_KERNEL ); -if (!wait) { -rtw89_core_tx_kick_off (rtwdev, qsel); -return 0 ; - } - -init_completion (&wait->completion); - wait->skb = skb; -rcu_assign_pointer (skb_data->wait, wait); -rtw89_core_tx_kick_off (rtwdev, qsel); time_left =wait_for_completion_timeout (&wait->completion,msecs_to_jiffies (timeout));
@@ -1057,10 +1046,12 @@ int rtw89_h2c_tx(struct rtw89_dev *rtwde }int rtw89_core_tx_write (struct rtw89_dev *rtwdev,struct ieee80211_vif *vif, -struct ieee80211_sta *sta,struct sk_buff *skb,int *qsel) +struct ieee80211_sta *sta,struct sk_buff *skb,int *qsel, +struct rtw89_tx_wait_info *wait) {struct rtw89_sta *rtwsta =sta_to_rtwsta_safe (sta);struct rtw89_vif *rtwvif =vif_to_rtwvif (vif); +struct rtw89_tx_skb_data *skb_data =RTW89_TX_SKB_CB (skb);struct rtw89_core_tx_request tx_req = {0 };struct rtw89_sta_link *rtwsta_link =NULL ;struct rtw89_vif_link *rtwvif_link;
@@ -1093,6 +1084,8 @@ int rtw89_core_tx_write(struct rtw89_devrtw89_core_tx_update_desc_info (rtwdev, &tx_req);rtw89_core_tx_wake (rtwdev, &tx_req); +rcu_assign_pointer (skb_data->wait, wait); + ret =rtw89_hci_tx_write (rtwdev, &tx_req);if (ret) {rtw89_err (rtwdev,"failed to transmit skb to HCI\n" );
@@ -2908,7 +2901,7 @@ static void rtw89_core_txq_push(struct r goto out; }rtw89_core_txq_check_agg (rtwdev, rtwtxq, skb); - ret =rtw89_core_tx_write (rtwdev, vif, sta, skb,NULL ); + ret =rtw89_core_tx_write (rtwdev, vif, sta, skb,NULL ,NULL );if (ret) {rtw89_err (rtwdev,"failed to push txq: %d\n" , ret);ieee80211_free_txskb (rtwdev->hw, skb);
@@ -3084,7 +3077,7 @@ bottom: skb_queue_walk_safe(&rtwsta->roc_queue, skb, tmp) {skb_unlink (skb, &rtwsta->roc_queue); - ret =rtw89_core_tx_write (rtwdev, vif, sta, skb, &qsel); + ret =rtw89_core_tx_write (rtwdev, vif, sta, skb, &qsel,NULL );if (ret) {rtw89_warn (rtwdev,"pending tx failed with %d\n" , ret);dev_kfree_skb_any (skb);
@@ -3106,6 +3099,7 @@ static int rtw89_core_send_nullfunc(stru struct rtw89_vif_link *rtwvif_link, bool qos, bool ps) { struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); +struct rtw89_tx_wait_info *wait;struct ieee80211_sta *sta;struct ieee80211_hdr *hdr;struct sk_buff *skb;
@@ -3114,6 +3108,12 @@ static int rtw89_core_send_nullfunc(struif (vif->type !=NL80211_IFTYPE_STATION || !vif->cfg.assoc)return 0 ; + wait =kzalloc (sizeof (*wait),GFP_KERNEL ); +if (!wait) +return -ENOMEM ; + +init_completion (&wait->completion); +rcu_read_lock (); sta =ieee80211_find_sta (vif, vif->cfg.ap_addr);if (!sta) {
@@ -3127,11 +3127,13 @@ static int rtw89_core_send_nullfunc(stru goto out; } + wait->skb = skb; + hdr = (struct ieee80211_hdr *)skb->data;if (ps) hdr->frame_control |=cpu_to_le16 (IEEE80211_FCTL_PM ); - ret =rtw89_core_tx_write (rtwdev, vif, sta, skb, &qsel); + ret =rtw89_core_tx_write (rtwdev, vif, sta, skb, &qsel, wait);if (ret) {rtw89_warn (rtwdev,"nullfunc transmit failed: %d\n" , ret);dev_kfree_skb_any (skb);
@@ -3140,10 +3142,11 @@ static int rtw89_core_send_nullfunc(strurcu_read_unlock (); -return rtw89_core_tx_kick_off_and_wait (rtwdev, skb, qsel, +return rtw89_core_tx_kick_off_and_wait (rtwdev, skb, wait, qsel,RTW89_ROC_TX_TIMEOUT ); out:rcu_read_unlock (); +kfree (wait);return ret; }
drivers/net/wireless/realtek/rtw89/core.h +4 -2
@@ -6818,12 +6818,14 @@ static inline bool rtw89_is_rtl885xb(str }int rtw89_core_tx_write (struct rtw89_dev *rtwdev,struct ieee80211_vif *vif, -struct ieee80211_sta *sta,struct sk_buff *skb,int *qsel); +struct ieee80211_sta *sta,struct sk_buff *skb,int *qsel, +struct rtw89_tx_wait_info *wait);int rtw89_h2c_tx (struct rtw89_dev *rtwdev,struct sk_buff *skb,bool fwdl);void rtw89_core_tx_kick_off (struct rtw89_dev *rtwdev,u8 qsel);int rtw89_core_tx_kick_off_and_wait (struct rtw89_dev *rtwdev,struct sk_buff *skb, -int qsel,unsigned int timeout); +struct rtw89_tx_wait_info *wait,int qsel, +unsigned int timeout);void rtw89_core_fill_txdesc (struct rtw89_dev *rtwdev,struct rtw89_tx_desc_info *desc_info,void *txdesc);
drivers/net/wireless/realtek/rtw89/mac80211.c +1 -1
@@ -36,7 +36,7 @@ static void rtw89_ops_tx(struct ieee8021return ; } - ret =rtw89_core_tx_write (rtwdev, vif, sta, skb, &qsel); + ret =rtw89_core_tx_write (rtwdev, vif, sta, skb, &qsel,NULL );if (ret) {rtw89_err (rtwdev,"failed to transmit skb: %d\n" , ret);ieee80211_free_txskb (hw, skb);
drivers/net/wireless/realtek/rtw89/pci.c +0 -2
@@ -1366,7 +1366,6 @@ static int rtw89_pci_txwd_submit(structstruct pci_dev *pdev = rtwpci->pdev;struct sk_buff *skb = tx_req->skb;struct rtw89_pci_tx_data *tx_data =RTW89_PCI_TX_SKB_CB (skb); -struct rtw89_tx_skb_data *skb_data =RTW89_TX_SKB_CB (skb);bool en_wd_info = desc_info->en_wd_info;u32 txwd_len;u32 txwp_len;
@@ -1382,7 +1381,6 @@ static int rtw89_pci_txwd_submit(struct } tx_data->dma = dma; -rcu_assign_pointer (skb_data->wait,NULL ); txwp_len =sizeof (*txwp_info); txwd_len = chip->txwd_body_size;
Greg Kroah-Hartman
maintainerPATCH 109/136 xfs: use deferred intent items for reaping crosslinked blocks
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Darrick J. Wong" <[email protected]>
[ Upstream commit cd32a0c0dcdf634f2e0e71f41c272e19dece6264 ]
When we're removing rmap records for crosslinked blocks, use deferred intent items so that we can try to free/unmap as many of the old data structure's blocks as we can in the same transaction as the commit.
--- fs/xfs/scrub/reap.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
fs/xfs/scrub/reap.c +5 -4
@@ -409,8 +409,6 @@ xreap_agextent_iter(if (crosslinked) {trace_xreap_dispose_unmap_extent (sc->sa.pag, agbno, *aglenp); - rs->force_roll = true; -if (rs->oinfo == &XFS_RMAP_OINFO_COW ) {/* * If we're unmapping CoW staging extents, remove the
@@ -418,11 +416,14 @@ xreap_agextent_iter(* rmap record as well. */ xfs_refcount_free_cow_extent (sc->tp, fsbno, *aglenp); + rs->force_roll = true;return 0 ; } -return xfs_rmap_free (sc->tp, sc->sa.agf_bp, sc->sa.pag, agbno, - *aglenp, rs->oinfo); +xfs_rmap_free_extent (sc->tp, sc->sa.pag->pag_agno, agbno, + *aglenp, rs->oinfo->oi_owner); + rs->deferred++; +return 0 ; }trace_xreap_dispose_free_extent (sc->sa.pag, agbno, *aglenp);
Greg Kroah-Hartman
maintainerPATCH 110/136 padata: Reset next CPU when reorder sequence wraps around
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiao Liang <[email protected]>
[ Upstream commit 501302d5cee0d8e8ec2c4a5919c37e0df9abc99b ]
When seq_nr wraps around, the next reorder job with seq 0 is hashed to the first CPU in padata_do_serial(). Correspondingly, need reset pd->cpu to the first one when pd->processed wraps around. Otherwise, if the number of used CPUs is not a power of 2, padata_find_next() will be checking a wrong list, hence deadlock.
--- kernel/padata.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
kernel/padata.c +5 -1
@@ -290,7 +290,11 @@ static struct padata_priv *padata_find_nif (remove_object) {list_del_init (&padata->list); ++pd->processed; - pd->cpu =cpumask_next_wrap (cpu, pd->cpumask.pcpu,-1 , false); +/* When sequence wraps around, reset to the first CPU. */ +if (unlikely (pd->processed ==0 )) + pd->cpu =cpumask_first (pd->cpumask.pcpu); +else + pd->cpu =cpumask_next_wrap (cpu, pd->cpumask.pcpu,-1 , false); }spin_unlock (&reorder->lock);
Greg Kroah-Hartman
maintainerPATCH 111/136 md/raid0: Handle bio_split() errors
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Garry <[email protected]>
[ Upstream commit 74538fdac3e85aae55eb4ed786478ed2384cb85d ]
Add proper bio_split() error handling. For any error, set bi_status, end the bio, and return.
Stable-dep-of: 22f166218f73 ("md: fix mssing blktrace bio split events")
--- drivers/md/raid0.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
drivers/md/raid0.c +12 -0
@@ -464,6 +464,12 @@ static void raid0_handle_discard(structstruct bio *split =bio_split (bio, zone->zone_end - bio->bi_iter.bi_sector,GFP_NOIO , &mddev->bio_set); + +if (IS_ERR (split)) { + bio->bi_status =errno_to_blk_status (PTR_ERR (split)); +bio_endio (bio); +return ; + }bio_chain (split, bio);submit_bio_noacct (bio); bio = split;
@@ -606,6 +612,12 @@ static bool raid0_make_request(struct mdif (sectors <bio_sectors (bio)) {struct bio *split =bio_split (bio, sectors,GFP_NOIO , &mddev->bio_set); + +if (IS_ERR (split)) { + bio->bi_status =errno_to_blk_status (PTR_ERR (split)); +bio_endio (bio); +return true; + }bio_chain (split, bio);raid0_map_submit_bio (mddev, bio); bio = split;
Greg KH
maintainerRe: [PATCH 6.12 111/136] md/raid0: Handle bio_split() errors
Quoted 34 lines · Jack Wang
From: Greg Kroah-Hartman <[email protected]>
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Garry <[email protected]>
[ Upstream commit
74538fdac3e85aae55eb4ed786478ed2384cb85d]Add proper
bio_split()error handling. For any error, setbi_status, end the bio, and return.Reviewed-by Yu Kuai <[email protected]>Reviewed-by Hannes Reinecke <[email protected]>Signed-off-by John Garry <[email protected]>Signed-off-by Jens Axboe <[email protected]>Stable-dep-of:
22f166218f73("md: fix mssing blktrace bio split events")Signed-off-by Sasha Levin <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>drivers/md/raid0.c +6
-0@@ -464,6 +464,12 @@ static void raid0_handle_discard(structstruct bio *split =bio_split (bio, zone->zone_end - bio->bi_iter.bi_sector,GFP_NOIO , &mddev->bio_set); + +if (IS_ERR (split)) { + bio->bi_status =errno_to_blk_status (PTR_ERR (split)); +bio_endio (bio); +return ; + }
Quoted 4 lines
The version of
bio_splitreturn NULL or valid pointer, so we need adapt the check to if (IS_ERR_OR_NULL(split)) for all the 3 commits about Handlebio_split()errors for md/raidx.
Sorry, I do not understand the request here, is this not ok as-is?
Re: [PATCH 6.12 111/136] md/raid0: Handle bio_split() errors
Quoted 36 lines · Greg KH
Quoted 34 lines · Jack Wang
From: Greg Kroah-Hartman <[email protected]>
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Garry <[email protected]>
[ Upstream commit
74538fdac3e85aae55eb4ed786478ed2384cb85d]Add proper
bio_split()error handling. For any error, setbi_status, end the bio, and return.Reviewed-by Yu Kuai <[email protected]>Reviewed-by Hannes Reinecke <[email protected]>Signed-off-by John Garry <[email protected]>Signed-off-by Jens Axboe <[email protected]>Stable-dep-of:
22f166218f73("md: fix mssing blktrace bio split events")Signed-off-by Sasha Levin <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>drivers/md/raid0.c +6
-0@@ -464,6 +464,12 @@ static void raid0_handle_discard(structstruct bio *split =bio_split (bio, zone->zone_end - bio->bi_iter.bi_sector,GFP_NOIO , &mddev->bio_set); + +if (IS_ERR (split)) { + bio->bi_status =errno_to_blk_status (PTR_ERR (split)); +bio_endio (bio); +return ; + }
Quoted 6 lines
Quoted 4 lines
The version of
bio_splitreturn NULL or valid pointer, so we need adapt the check to if (IS_ERR_OR_NULL(split)) for all the 3 commits about Handlebio_split()errors for md/raidx.Sorry, I do not understand the request here, is this not ok as-is?
godd question, if keep as-is, it doesn't improve anything, the check doesn't catch the error condition, only add extra code. it doesn't make the situation worse.
Greg Kroah-Hartman
maintainerPATCH 112/136 md/raid1: Handle bio_split() errors
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Garry <[email protected]>
[ Upstream commit b1a7ad8b5c4fa28325ee7b369a2d545d3e16ccde ]
Add proper bio_split() error handling. For any error, call raid_end_bio_io() and return.
For the case of an in the write path, we need to undo the increment in the rdev pending count and NULLify the r1_bio->bios[] pointers.
For read path failure, we need to undo rdev pending count increment from the earlier read_balance() call.
Stable-dep-of: 22f166218f73 ("md: fix mssing blktrace bio split events")
--- drivers/md/raid1.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-)
drivers/md/raid1.c +31 -2
@@ -1317,7 +1317,7 @@ static void raid1_read_request(struct mdstruct raid1_info *mirror;struct bio *read_bio;int max_sectors; -int rdisk; +int rdisk, error;bool r1bio_existed = !!r1_bio;/*
@@ -1378,6 +1378,11 @@ static void raid1_read_request(struct mdif (max_sectors <bio_sectors (bio)) {struct bio *split =bio_split (bio, max_sectors, gfp, &conf->bio_split); + +if (IS_ERR (split)) { + error =PTR_ERR (split); + goto err_handle; + }bio_chain (split, bio);submit_bio_noacct (bio); bio = split;
@@ -1404,6 +1409,13 @@ static void raid1_read_request(struct md read_bio->bi_private = r1_bio;mddev_trace_remap (mddev, read_bio, r1_bio->sector);submit_bio_noacct (read_bio); +return ; + +err_handle: +atomic_dec (&mirror->rdev->nr_pending); + bio->bi_status =errno_to_blk_status (error); +set_bit (R1BIO_Uptodate, &r1_bio->state); +raid_end_bio_io (r1_bio); } static void raid1_write_request(struct mddev *mddev, struct bio *bio,
@@ -1411,7 +1423,7 @@ static void raid1_write_request(struct m {struct r1conf *conf = mddev->private;struct r1bio *r1_bio; -int i, disks; +int i, disks, k, error;unsigned long flags;struct md_rdev *blocked_rdev;int first_clone;
@@ -1557,6 +1569,11 @@ static void raid1_write_request(struct mif (max_sectors <bio_sectors (bio)) {struct bio *split =bio_split (bio, max_sectors,GFP_NOIO , &conf->bio_split); + +if (IS_ERR (split)) { + error =PTR_ERR (split); + goto err_handle; + }bio_chain (split, bio);submit_bio_noacct (bio); bio = split;
@@ -1640,6 +1657,18 @@ static void raid1_write_request(struct m/* In case raid1d snuck in to freeze_array */ wake_up_barrier (conf); +return ; +err_handle: +for (k =0 ; k < i; k++) { +if (r1_bio->bios[k]) { +rdev_dec_pending (conf->mirrors[k].rdev, mddev); + r1_bio->bios[k] =NULL ; + } + } + + bio->bi_status =errno_to_blk_status (error); +set_bit (R1BIO_Uptodate, &r1_bio->state); +raid_end_bio_io (r1_bio); }static bool raid1_make_request (struct mddev *mddev,struct bio *bio)
Greg Kroah-Hartman
maintainerPATCH 113/136 md/raid10: Handle bio_split() errors
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Garry <[email protected]>
[ Upstream commit 4cf58d9529097328b669e3c8693ed21e3a041903 ]
Add proper bio_split() error handling. For any error, call raid_end_bio_io() and return. Except for discard, where we end the bio directly.
Stable-dep-of: 22f166218f73 ("md: fix mssing blktrace bio split events")
--- drivers/md/raid10.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-)
drivers/md/raid10.c +46 -1
@@ -1153,6 +1153,7 @@ static void raid10_read_request(struct mint slot = r10_bio->read_slot;struct md_rdev *err_rdev =NULL ;gfp_t gfp =GFP_NOIO ; +int error;if (slot >=0 && r10_bio->devs[slot].rdev) {/*
@@ -1203,6 +1204,10 @@ static void raid10_read_request(struct mif (max_sectors <bio_sectors (bio)) {struct bio *split =bio_split (bio, max_sectors, gfp, &conf->bio_split); +if (IS_ERR (split)) { + error =PTR_ERR (split); + goto err_handle; + }bio_chain (split, bio);allow_barrier (conf);submit_bio_noacct (bio);
@@ -1233,6 +1238,11 @@ static void raid10_read_request(struct mmddev_trace_remap (mddev, read_bio, r10_bio->sector);submit_bio_noacct (read_bio);return ; +err_handle: +atomic_dec (&rdev->nr_pending); + bio->bi_status =errno_to_blk_status (error); +set_bit (R10BIO_Uptodate, &r10_bio->state); +raid_end_bio_io (r10_bio); } static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio,
@@ -1341,9 +1351,10 @@ static void raid10_write_request(struct struct r10bio *r10_bio) { struct r10conf *conf = mddev->private; - int i; + int i, k; sector_t sectors; int max_sectors; + int error; if ((mddev_is_clustered(mddev) && md_cluster_ops->area_resyncing(mddev, WRITE,
@@ -1469,6 +1480,10 @@ static void raid10_write_request(structif (r10_bio->sectors <bio_sectors (bio)) {struct bio *split =bio_split (bio, r10_bio->sectors,GFP_NOIO , &conf->bio_split); +if (IS_ERR (split)) { + error =PTR_ERR (split); + goto err_handle; + }bio_chain (split, bio);allow_barrier (conf);submit_bio_noacct (bio);
@@ -1488,6 +1503,26 @@ static void raid10_write_request(structraid10_write_one_disk (mddev, r10_bio, bio, true, i); }one_write_done (r10_bio); +return ; +err_handle: +for (k =0 ; k < i; k++) { +int d = r10_bio->devs[k].devnum; +struct md_rdev *rdev = conf->mirrors[d].rdev; +struct md_rdev *rrdev = conf->mirrors[d].replacement; + +if (r10_bio->devs[k].bio) { +rdev_dec_pending (rdev, mddev); + r10_bio->devs[k].bio =NULL ; + } +if (r10_bio->devs[k].repl_bio) { +rdev_dec_pending (rrdev, mddev); + r10_bio->devs[k].repl_bio =NULL ; + } + } + + bio->bi_status =errno_to_blk_status (error); +set_bit (R10BIO_Uptodate, &r10_bio->state); +raid_end_bio_io (r10_bio); }static void __make_request (struct mddev *mddev,struct bio *bio,int sectors)
@@ -1629,6 +1664,11 @@ static int raid10_handle_discard(structif (remainder) { split_size = stripe_size - remainder; split =bio_split (bio, split_size,GFP_NOIO , &conf->bio_split); +if (IS_ERR (split)) { + bio->bi_status =errno_to_blk_status (PTR_ERR (split)); +bio_endio (bio); +return 0 ; + }bio_chain (split, bio);allow_barrier (conf);/* Resend the fist split part */
@@ -1639,6 +1679,11 @@ static int raid10_handle_discard(structif (remainder) { split_size =bio_sectors (bio) - remainder; split =bio_split (bio, split_size,GFP_NOIO , &conf->bio_split); +if (IS_ERR (split)) { + bio->bi_status =errno_to_blk_status (PTR_ERR (split)); +bio_endio (bio); +return 0 ; + }bio_chain (split, bio);allow_barrier (conf);/* Resend the second split part */
Greg Kroah-Hartman
maintainerPATCH 114/136 md: fix mssing blktrace bio split events
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yu Kuai <[email protected]>
[ Upstream commit 22f166218f7313e8fe2d19213b5f4b3265f8c39e ]
If bio is split by internal handling like chunksize or badblocks, the corresponding trace_block_split() is missing, resulting in blktrace inability to catch BIO split events and making it harder to analyze the BIO sequence.
--- drivers/md/md-linear.c | 1 + drivers/md/raid0.c | 4 ++++ drivers/md/raid1.c | 4 ++++ drivers/md/raid10.c | 8 ++++++++ drivers/md/raid5.c | 2 ++ 5 files changed, 19 insertions(+)
drivers/md/md-linear.c +1 -0
@@ -267,6 +267,7 @@ static bool linear_make_request(struct m }bio_chain (split, bio); +trace_block_split (split, bio->bi_iter.bi_sector);submit_bio_noacct (bio); bio = split; }
drivers/md/raid0.c +4 -0
@@ -470,7 +470,9 @@ static void raid0_handle_discard(structbio_endio (bio);return ; } +bio_chain (split, bio); +trace_block_split (split, bio->bi_iter.bi_sector);submit_bio_noacct (bio); bio = split; end = zone->zone_end;
@@ -618,7 +620,9 @@ static bool raid0_make_request(struct mdbio_endio (bio);return true; } +bio_chain (split, bio); +trace_block_split (split, bio->bi_iter.bi_sector);raid0_map_submit_bio (mddev, bio); bio = split; }
drivers/md/raid1.c +4 -0
@@ -1383,7 +1383,9 @@ static void raid1_read_request(struct md error =PTR_ERR (split); goto err_handle; } +bio_chain (split, bio); +trace_block_split (split, bio->bi_iter.bi_sector);submit_bio_noacct (bio); bio = split; r1_bio->master_bio = bio;
@@ -1574,7 +1576,9 @@ static void raid1_write_request(struct m error =PTR_ERR (split); goto err_handle; } +bio_chain (split, bio); +trace_block_split (split, bio->bi_iter.bi_sector);submit_bio_noacct (bio); bio = split; r1_bio->master_bio = bio;
drivers/md/raid10.c +8 -0
@@ -1208,7 +1208,9 @@ static void raid10_read_request(struct m error =PTR_ERR (split); goto err_handle; } +bio_chain (split, bio); +trace_block_split (split, bio->bi_iter.bi_sector);allow_barrier (conf);submit_bio_noacct (bio);wait_barrier (conf, false);
@@ -1484,7 +1486,9 @@ static void raid10_write_request(struct error =PTR_ERR (split); goto err_handle; } +bio_chain (split, bio); +trace_block_split (split, bio->bi_iter.bi_sector);allow_barrier (conf);submit_bio_noacct (bio);wait_barrier (conf, false);
@@ -1669,7 +1673,9 @@ static int raid10_handle_discard(structbio_endio (bio);return 0 ; } +bio_chain (split, bio); +trace_block_split (split, bio->bi_iter.bi_sector);allow_barrier (conf);/* Resend the fist split part */ submit_bio_noacct (split);
@@ -1684,7 +1690,9 @@ static int raid10_handle_discard(structbio_endio (bio);return 0 ; } +bio_chain (split, bio); +trace_block_split (split, bio->bi_iter.bi_sector);allow_barrier (conf);/* Resend the second split part */ submit_bio_noacct (bio);
drivers/md/raid5.c +2 -0
@@ -5484,8 +5484,10 @@ static struct bio *chunk_aligned_read(stif (sectors <bio_sectors (raid_bio)) {struct r5conf *conf = mddev->private; + split =bio_split (raid_bio, sectors,GFP_NOIO , &conf->bio_split);bio_chain (split, raid_bio); +trace_block_split (split, raid_bio->bi_iter.bi_sector);submit_bio_noacct (raid_bio); raid_bio = split; }
Greg Kroah-Hartman
maintainerPATCH 115/136 x86/resctrl: Refactor resctrl_arch_rmid_read()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Babu Moger <[email protected]>
[ Upstream commit 7c9ac605e202c4668e441fc8146a993577131ca1 ]
resctrl_arch_rmid_read() adjusts the value obtained from MSR_IA32_QM_CTR to account for the overflow for MBM events and apply counter scaling for all the events. This logic is common to both reading an RMID and reading a hardware counter directly.
Refactor the hardware value adjustment logic into get_corrected_val() to prepare for support of reading a hardware counter.
Stable-dep-of: 15292f1b4c55 ("x86/resctrl: Fix miscount of bandwidth event when reactivating previously unavailable RMID")
--- arch/x86/kernel/cpu/resctrl/monitor.c | 38 ++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 15 deletions(-)
arch/x86/kernel/cpu/resctrl/monitor.c +23 -15
@@ -312,24 +312,13 @@ static u64 mbm_overflow_count(u64 prev_mreturn chunks >> shift; } -int resctrl_arch_rmid_read (struct rdt_resource *r,struct rdt_mon_domain *d, -u32 unused,u32 rmid,enum resctrl_event_id eventid, -u64 *val,void *ignored) +static u64 get_corrected_val (struct rdt_resource *r,struct rdt_mon_domain *d, +u32 rmid,enum resctrl_event_id eventid,u64 msr_val) {struct rdt_hw_mon_domain *hw_dom =resctrl_to_arch_mon_dom (d);struct rdt_hw_resource *hw_res =resctrl_to_arch_res (r); -int cpu =cpumask_any (&d->hdr.cpu_mask);struct arch_mbm_state *am; -u64 msr_val, chunks; -u32 prmid; -int ret; - -resctrl_arch_rmid_read_context_check (); - - prmid =logical_rmid_to_physical_rmid (cpu, rmid); - ret =__rmid_read_phys (prmid, eventid, &msr_val); -if (ret) -return ret; +u64 chunks; am =get_arch_mbm_state (hw_dom, rmid, eventid);if (am) {
@@ -341,7 +330,26 @@ int resctrl_arch_rmid_read(struct rdt_re chunks = msr_val; } - *val = chunks * hw_res->mon_scale; +return chunks * hw_res->mon_scale; +} + +int resctrl_arch_rmid_read (struct rdt_resource *r,struct rdt_mon_domain *d, +u32 unused,u32 rmid,enum resctrl_event_id eventid, +u64 *val,void *ignored) +{ +int cpu =cpumask_any (&d->hdr.cpu_mask); +u64 msr_val; +u32 prmid; +int ret; + +resctrl_arch_rmid_read_context_check (); + + prmid =logical_rmid_to_physical_rmid (cpu, rmid); + ret =__rmid_read_phys (prmid, eventid, &msr_val); +if (ret) +return ret; + + *val =get_corrected_val (r, d, rmid, eventid, msr_val);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 116/136 x86/resctrl: Fix miscount of bandwidth event when reactivating previously unavailable RMID
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Babu Moger <[email protected]>
[ Upstream commit 15292f1b4c55a3a7c940dbcb6cb8793871ed3d92 ]
Users can create as many monitoring groups as the number of RMIDs supported by the hardware. However, on AMD systems, only a limited number of RMIDs are guaranteed to be actively tracked by the hardware. RMIDs that exceed this limit are placed in an "Unavailable" state.
When a bandwidth counter is read for such an RMID, the hardware sets MSR_IA32_QM_CTR.Unavailable (bit 62). When such an RMID starts being tracked again the hardware counter is reset to zero. MSR_IA32_QM_CTR.Unavailable remains set on first read after tracking re-starts and is clear on all subsequent reads as long as the RMID is tracked.
resctrl miscounts the bandwidth events after an RMID transitions from the "Unavailable" state back to being tracked. This happens because when the hardware starts counting again after resetting the counter to zero, resctrl in turn compares the new count against the counter value stored from the previous time the RMID was tracked.
This results in resctrl computing an event value that is either undercounting (when new counter is more than stored counter) or a mistaken overflow (when new counter is less than stored counter).
Reset the stored value (arch_mbm_state::prev_msr) of MSR_IA32_QM_CTR to zero whenever the RMID is in the "Unavailable" state to ensure accurate counting after the RMID resets to zero when it starts to be tracked again.
Example scenario that results in mistaken overflow
==================================================
1. The resctrl filesystem is mounted, and a task is assigned to a monitoring group.
$mount -t resctrl resctrl /sys/fs/resctrl $mkdir /sys/fs/resctrl/mon_groups/test1/ $echo 1234 > /sys/fs/resctrl/mon_groups/test1/tasks
$cat /sys/fs/resctrl/mon_groups/test1/mon_data/mon_L3_*/mbm_total_bytes
21323 <- Total bytes on domain 0
"Unavailable" <- Total bytes on domain 1
Task is running on domain 0. Counter on domain 1 is "Unavailable".
2. The task runs on domain 0 for a while and then moves to domain 1. The counter starts incrementing on domain 1.
$cat /sys/fs/resctrl/mon_groups/test1/mon_data/mon_L3_*/mbm_total_bytes
7345357 <- Total bytes on domain 0
4545 <- Total bytes on domain 1
3. At some point, the RMID in domain 0 transitions to the "Unavailable" state because the task is no longer executing in that domain.
$cat /sys/fs/resctrl/mon_groups/test1/mon_data/mon_L3_*/mbm_total_bytes
"Unavailable" <- Total bytes on domain 0
434341 <- Total bytes on domain 1
4. Since the task continues to migrate between domains, it may eventually return to domain 0.
$cat /sys/fs/resctrl/mon_groups/test1/mon_data/mon_L3_*/mbm_total_bytes 17592178699059 <- Overflow on domain 0
3232332 <- Total bytes on domain 1
In this case, the RMID on domain 0 transitions from "Unavailable" state to active state. The hardware sets MSR_IA32_QM_CTR.Unavailable (bit 62) when the counter is read and begins tracking the RMID counting from 0.
Subsequent reads succeed but return a value smaller than the previously saved MSR value (7345357). Consequently, the resctrl's overflow logic is triggered, it compares the previous value (7345357) with the new, smaller value and incorrectly interprets this as a counter overflow, adding a large delta.
In reality, this is a false positive: the counter did not overflow but was simply reset when the RMID transitioned from "Unavailable" back to active state.
Here is the text from APM [1] available from [2].
"In PQOS Version 2.0 or higher, the MBM hardware will set the U bit on the first QM_CTR read when it begins tracking an RMID that it was not previously tracking. The U bit will be zero for all subsequent reads from that RMID while it is still tracked by the hardware. Therefore, a QM_CTR read with the U bit set when that RMID is in use by a processor can be considered 0 when calculating the difference with a subsequent read."
[1] AMD64 Architecture Programmer's Manual Volume 2: System Programming Publication # 24593 Revision 3.41 section 19.3.3 Monitoring L3 Memory Bandwidth (MBM).
[ bp: Split commit message into smaller paragraph chunks for better
consumption. ]
--- arch/x86/kernel/cpu/resctrl/monitor.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
arch/x86/kernel/cpu/resctrl/monitor.c +10 -4
@@ -337,7 +337,9 @@ int resctrl_arch_rmid_read(struct rdt_re u32 unused, u32 rmid, enum resctrl_event_id eventid, u64 *val, void *ignored) { + struct rdt_hw_mon_domain *hw_dom = resctrl_to_arch_mon_dom(d);int cpu =cpumask_any (&d->hdr.cpu_mask); +struct arch_mbm_state *am;u64 msr_val;u32 prmid;int ret;
@@ -346,12 +348,16 @@ int resctrl_arch_rmid_read(struct rdt_re prmid =logical_rmid_to_physical_rmid (cpu, rmid); ret =__rmid_read_phys (prmid, eventid, &msr_val); -if (ret) -return ret; - *val =get_corrected_val (r, d, rmid, eventid, msr_val); +if (!ret) { + *val =get_corrected_val (r, d, rmid, eventid, msr_val); + }else if (ret == -EINVAL ) { + am =get_arch_mbm_state (hw_dom, rmid, eventid); +if (am) + am->prev_msr =0 ; + } -return 0 ; +return ret; }static void limbo_release_entry (struct rmid_entry *entry)
Greg Kroah-Hartman
maintainerPATCH 117/136 d_alloc_parallel(): set DCACHE_PAR_LOOKUP earlier
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
[ Upstream commit e95db51c81f54dd12ea465b5127e4786f62a1095 ]
Do that before new dentry is visible anywhere. It does create a new possible state for dentries present in ->d_children/->d_sib - DCACHE_PAR_LOOKUP present, negative, unhashed, not in in-lookup hash chains, refcount positive. Those are going to be skipped by all tree-walkers (both d_walk() callbacks in fs/dcache.c and explicit loops over children/sibling lists elsewhere) and dput() is fine with those.
NOTE: dropping the final reference to a "normal" in-lookup dentry (in in-lookup hash) is a bug - somebody must've forgotten to call d_lookup_done() on it and bad things will happen. With those it's OK; if/when we get around to making __dentry_kill() complain about such breakage, remember that predicate to check should *not* be just d_in_lookup(victim) but rather a combination of that with !hlist_bl_unhashed(&victim->d_u.d_in_lookup_hash). Might be worth considering later...
Stable-dep-of: 56094ad3eaa2 ("vfs: Don't leak disconnected dentries on umount")
--- fs/dcache.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
fs/dcache.c +7 -3
@@ -2475,13 +2475,19 @@ struct dentry *d_alloc_parallel(struct dunsigned int hash = name->hash;struct hlist_bl_head *b =in_lookup_hash (parent, hash);struct hlist_bl_node *node; -struct dentry *new =d_alloc (parent, name); +struct dentry *new =__d_alloc (parent->d_sb, name);struct dentry *dentry;unsigned seq, r_seq, d_seq;if (unlikely (!new))return ERR_PTR (-ENOMEM ); + new->d_flags |=DCACHE_PAR_LOOKUP ; +spin_lock (&parent->d_lock); + new->d_parent =dget_dlock (parent); +hlist_add_head (&new->d_sib, &parent->d_children); +spin_unlock (&parent->d_lock); + retry:rcu_read_lock (); seq =smp_load_acquire (&parent->d_inode->i_dir_seq);
@@ -2565,8 +2571,6 @@ retry:return dentry; }rcu_read_unlock (); -/* we can't take ->d_lock here; it's OK, though. */ - new->d_flags |=DCACHE_PAR_LOOKUP ; new->d_wait = wq;hlist_bl_add_head (&new->d_u.d_in_lookup_hash, b);hlist_bl_unlock (b);
Greg Kroah-Hartman
maintainerPATCH 118/136 vfs: Dont leak disconnected dentries on umount
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
[ Upstream commit 56094ad3eaa21e6621396cc33811d8f72847a834 ]
When user calls open_by_handle_at() on some inode that is not cached, we will create disconnected dentry for it. If such dentry is a directory, exportfs_decode_fh_raw() will then try to connect this dentry to the dentry tree through reconnect_path(). It may happen for various reasons (such as corrupted fs or race with rename) that the call to lookup_one_unlocked() in reconnect_one() will fail to find the dentry we are trying to reconnect and instead create a new dentry under the parent. Now this dentry will not be marked as disconnected although the parent still may well be disconnected (at least in case this inconsistency happened because the fs is corrupted and .. doesn't point to the real parent directory). This creates inconsistency in disconnected flags but AFAICS it was mostly harmless. At least until commit f1ee616214cb ("VFS: don't keep disconnected dentries on d_anon") which removed adding of most disconnected dentries to sb->s_anon list. Thus after this commit cleanup of disconnected dentries implicitely relies on the fact that dput() will immediately reclaim such dentries. However when some leaf dentry isn't marked as disconnected, as in the scenario described above, the reclaim doesn't happen and the dentries are "leaked". Memory reclaim can eventually reclaim them but otherwise they stay in memory and if umount comes first, we hit infamous "Busy inodes after unmount" bug. Make sure all dentries created under a disconnected parent are marked as disconnected as well.
--- fs/dcache.c | 2 ++ 1 file changed, 2 insertions(+)
fs/dcache.c +2 -0
@@ -2486,6 +2486,8 @@ struct dentry *d_alloc_parallel(struct dspin_lock (&parent->d_lock); new->d_parent =dget_dlock (parent);hlist_add_head (&new->d_sib, &parent->d_children); +if (parent->d_flags &DCACHE_DISCONNECTED ) + new->d_flags |=DCACHE_DISCONNECTED ;spin_unlock (&parent->d_lock); retry:
Greg Kroah-Hartman
maintainerPATCH 119/136 PCI: Add PCI_VDEVICE_SUB helper macro
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Piotr Kwapulinski <[email protected]>
[ Upstream commit 208fff3f567e2a3c3e7e4788845e90245c3891b4 ]
PCI_VDEVICE_SUB generates the pci_device_id struct layout for the specific PCI device/subdevice. Private data may follow the output.
Stable-dep-of: a7075f501bd3 ("ixgbevf: fix mailbox API compatibility by negotiating supported features")
--- include/linux/pci.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
include/linux/pci.h +14 -0
@@ -1067,6 +1067,20 @@ struct pci_driver { .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, 0, 0/** +* PCI_VDEVICE_SUB - describe a specific PCI device/subdevice in a short form +* @vend: the vendor name +* @dev: the 16 bit PCI Device ID +* @subvend: the 16 bit PCI Subvendor ID +* @subdev: the 16 bit PCI Subdevice ID +* +* Generate the pci_device_id struct layout for the specific PCI +* device/subdevice. Private data may follow the output. + */ +#define PCI_VDEVICE_SUB (vend, dev, subvend, subdev) \ + .vendor = PCI_VENDOR_ID_##vend, .device = (dev), \ + .subvendor = (subvend), .subdevice = (subdev), 0, 0 + +/** * PCI_DEVICE_DATA - macro used to describe a specific PCI device in very short form * @vend: the vendor name (without PCI_VENDOR_ID_ prefix) * @dev: the device name (without PCI_DEVICE_ID_<vend>_ prefix)
Greg Kroah-Hartman
maintainerPATCH 120/136 ixgbevf: Add support for Intel(R) E610 device
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Piotr Kwapulinski <[email protected]>
[ Upstream commit 4c44b450c69b676955c2790dcf467c1f969d80f1 ]
Add support for Intel(R) E610 Series of network devices. The E610 is based on X550 but adds firmware managed link, enhanced security capabilities and support for updated server manageability
Stable-dep-of: a7075f501bd3 ("ixgbevf: fix mailbox API compatibility by negotiating supported features")
--- drivers/net/ethernet/intel/ixgbevf/defines.h | 5 ++++- drivers/net/ethernet/intel/ixgbevf/ixgbevf.h | 6 +++++- drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 12 ++++++++++-- drivers/net/ethernet/intel/ixgbevf/vf.c | 12 +++++++++++- drivers/net/ethernet/intel/ixgbevf/vf.h | 4 +++- 5 files changed, 33 insertions(+), 6 deletions(-)
drivers/net/ethernet/intel/ixgbevf/defines.h +4 -1
@@ -1,5 +1,5 @@/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 1999 - 2018 Intel Corporation. */ +/* Copyright(c) 1999 - 2024 Intel Corporation. */ #ifndef _IXGBEVF_DEFINES_H_#define _IXGBEVF_DEFINES_H_
@@ -16,6 +16,9 @@#define IXGBE_DEV_ID_X550_VF_HV 0x1564#define IXGBE_DEV_ID_X550EM_X_VF_HV 0x15A9 +#define IXGBE_DEV_ID_E610_VF 0x57AD +#define IXGBE_SUBDEV_ID_E610_VF_HV 0x00FF +#define IXGBE_VF_IRQ_CLEAR_MASK 7#define IXGBE_VF_MAX_TX_QUEUES 8#define IXGBE_VF_MAX_RX_QUEUES 8
drivers/net/ethernet/intel/ixgbevf/ixgbevf.h +5 -1
@@ -1,5 +1,5 @@/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 1999 - 2018 Intel Corporation. */ +/* Copyright(c) 1999 - 2024 Intel Corporation. */ #ifndef _IXGBEVF_H_#define _IXGBEVF_H_
@@ -418,6 +418,8 @@ enum ixgbevf_boards { board_X550EM_x_vf, board_X550EM_x_vf_hv, board_x550em_a_vf, + board_e610_vf, + board_e610_vf_hv, }; enum ixgbevf_xcast_modes {
@@ -434,11 +436,13 @@ extern const struct ixgbevf_info ixgbevfextern const struct ixgbe_mbx_operations ixgbevf_mbx_ops;extern const struct ixgbe_mbx_operations ixgbevf_mbx_ops_legacy;extern const struct ixgbevf_info ixgbevf_x550em_a_vf_info; +extern const struct ixgbevf_info ixgbevf_e610_vf_info;extern const struct ixgbevf_info ixgbevf_82599_vf_hv_info;extern const struct ixgbevf_info ixgbevf_X540_vf_hv_info;extern const struct ixgbevf_info ixgbevf_X550_vf_hv_info;extern const struct ixgbevf_info ixgbevf_X550EM_x_vf_hv_info; +extern const struct ixgbevf_info ixgbevf_e610_vf_hv_info;extern const struct ixgbe_mbx_operations ixgbevf_hv_mbx_ops;/* needed by ethtool.c */
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +10 -2
@@ -1,5 +1,5 @@// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 1999 - 2018 Intel Corporation. */ +/* Copyright(c) 1999 - 2024 Intel Corporation. */ /****************************************************************************** Copyright (c)2006 - 2007 Myricom, Inc. for some LRO specific code
@@ -39,7 +39,7 @@ static const char ixgbevf_driver_string["Intel(R) 10 Gigabit PCI Express Virtual Function Network Driver" ;static char ixgbevf_copyright[] = -"Copyright (c) 2009 - 2018 Intel Corporation." ; +"Copyright (c) 2009 - 2024 Intel Corporation." ;static const struct ixgbevf_info *ixgbevf_info_tbl[] = { [board_82599_vf] = &ixgbevf_82599_vf_info,
@@ -51,6 +51,8 @@ static const struct ixgbevf_info *ixgbev [board_X550EM_x_vf] = &ixgbevf_X550EM_x_vf_info, [board_X550EM_x_vf_hv] = &ixgbevf_X550EM_x_vf_hv_info, [board_x550em_a_vf] = &ixgbevf_x550em_a_vf_info, + [board_e610_vf] = &ixgbevf_e610_vf_info, + [board_e610_vf_hv] = &ixgbevf_e610_vf_hv_info, };/* ixgbevf_pci_tbl - PCI Device ID Table
@@ -71,6 +73,9 @@ static const struct pci_device_id ixgbev {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_VF), board_X550EM_x_vf }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_VF_HV), board_X550EM_x_vf_hv}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_VF), board_x550em_a_vf }, + {PCI_VDEVICE_SUB(INTEL, IXGBE_DEV_ID_E610_VF, PCI_ANY_ID, + IXGBE_SUBDEV_ID_E610_VF_HV), board_e610_vf_hv}, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_E610_VF), board_e610_vf},/* required last entry */ {0, } };
@@ -4693,6 +4698,9 @@ static int ixgbevf_probe(struct pci_devcase ixgbe_mac_X540_vf:dev_info (&pdev->dev,"Intel(R) X540 Virtual Function\n" );break ; +case ixgbe_mac_e610_vf: +dev_info (&pdev->dev,"Intel(R) E610 Virtual Function\n" ); +break ;case ixgbe_mac_82599_vf:default :dev_info (&pdev->dev,"Intel(R) 82599 Virtual Function\n" );
drivers/net/ethernet/intel/ixgbevf/vf.c +11 -1
@@ -1,5 +1,5 @@// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 1999 - 2018 Intel Corporation. */ +/* Copyright(c) 1999 - 2024 Intel Corporation. */ #include "vf.h" #include "ixgbevf.h"
@@ -1076,3 +1076,13 @@ const struct ixgbevf_info ixgbevf_x550em .mac = ixgbe_mac_x550em_a_vf, .mac_ops = &ixgbevf_mac_ops, }; + +const struct ixgbevf_info ixgbevf_e610_vf_info = { + .mac = ixgbe_mac_e610_vf, + .mac_ops = &ixgbevf_mac_ops, +}; + +const struct ixgbevf_info ixgbevf_e610_vf_hv_info = { + .mac = ixgbe_mac_e610_vf, + .mac_ops = &ixgbevf_hv_mac_ops, +};
drivers/net/ethernet/intel/ixgbevf/vf.h +3 -1
@@ -1,5 +1,5 @@/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 1999 - 2018 Intel Corporation. */ +/* Copyright(c) 1999 - 2024 Intel Corporation. */ #ifndef __IXGBE_VF_H__#define __IXGBE_VF_H__
@@ -54,6 +54,8 @@ enum ixgbe_mac_type { ixgbe_mac_X550_vf, ixgbe_mac_X550EM_x_vf, ixgbe_mac_x550em_a_vf, + ixgbe_mac_e610, + ixgbe_mac_e610_vf, ixgbe_num_macs };
Greg Kroah-Hartman
maintainerPATCH 121/136 ixgbevf: fix getting link speed data for E610 devices
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jedrzej Jagielski <[email protected]>
[ Upstream commit 53f0eb62b4d23d40686f2dd51776b8220f2887bb ]
E610 adapters no longer use the VFLINKS register to read PF's link speed and linkup state. As a result VF driver cannot get actual link state and it incorrectly reports 10G which is the default option. It leads to a situation where even 1G adapters print 10G as actual link speed. The same happens when PF driver set speed different than 10G.
Add new mailbox operation to let the VF driver request a PF driver to provide actual link data. Update the mailbox api to v1.6.
Incorporate both ways of getting link status within the legacy ixgbe_check_mac_link_vf() function.
Stable-dep-of: a7075f501bd3 ("ixgbevf: fix mailbox API compatibility by negotiating supported features")
--- drivers/net/ethernet/intel/ixgbevf/defines.h | 1 drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 6 drivers/net/ethernet/intel/ixgbevf/mbx.h | 4 drivers/net/ethernet/intel/ixgbevf/vf.c | 137 +++++++++++++++++----- 4 files changed, 116 insertions(+), 32 deletions(-)
drivers/net/ethernet/intel/ixgbevf/defines.h +1 -0
@@ -28,6 +28,7 @@/* Link speed */ typedef u32 ixgbe_link_speed ; +#define IXGBE_LINK_SPEED_UNKNOWN 0#define IXGBE_LINK_SPEED_1GB_FULL 0x0020#define IXGBE_LINK_SPEED_10GB_FULL 0x0080#define IXGBE_LINK_SPEED_100_FULL 0x0008
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +5 -1
@@ -2278,6 +2278,7 @@ static void ixgbevf_negotiate_api(struct {struct ixgbe_hw *hw = &adapter->hw;static const int api[] = { + ixgbe_mbox_api_16, ixgbe_mbox_api_15, ixgbe_mbox_api_14, ixgbe_mbox_api_13,
@@ -2297,7 +2298,8 @@ static void ixgbevf_negotiate_api(struct idx++; } -if (hw->api_version >= ixgbe_mbox_api_15) { +/* Following is not supported by API 1.6, it is specific for 1.5 */ +if (hw->api_version == ixgbe_mbox_api_15) { hw->mbx.ops.init_params (hw);memcpy (&hw->mbx.ops, &ixgbevf_mbx_ops,sizeof (struct ixgbe_mbx_operations ));
@@ -2654,6 +2656,7 @@ static void ixgbevf_set_num_queues(struccase ixgbe_mbox_api_13:case ixgbe_mbox_api_14:case ixgbe_mbox_api_15: +case ixgbe_mbox_api_16:if (adapter->xdp_prog && hw->mac.max_tx_queues == rss) rss = rss >3 ?2 :1 ;
@@ -4648,6 +4651,7 @@ static int ixgbevf_probe(struct pci_devcase ixgbe_mbox_api_13:case ixgbe_mbox_api_14:case ixgbe_mbox_api_15: +case ixgbe_mbox_api_16: netdev->max_mtu =IXGBE_MAX_JUMBO_FRAME_SIZE - (ETH_HLEN +ETH_FCS_LEN );break ;
drivers/net/ethernet/intel/ixgbevf/mbx.h +4 -0
@@ -66,6 +66,7 @@ enum ixgbe_pfvf_api_rev { ixgbe_mbox_api_13,/* API version 1.3, linux/freebsd VF driver */ ixgbe_mbox_api_14,/* API version 1.4, linux/freebsd VF driver */ ixgbe_mbox_api_15,/* API version 1.5, linux/freebsd VF driver */ + ixgbe_mbox_api_16,/* API version 1.6, linux/freebsd VF driver */ /* This value should always be last */ ixgbe_mbox_api_unknown, /* indicates that API version is not known */ };
@@ -102,6 +103,9 @@ enum ixgbe_pfvf_api_rev {#define IXGBE_VF_GET_LINK_STATE 0x10/* get vf link state */ +/* mailbox API, version 1.6 VF requests */ +#define IXGBE_VF_GET_PF_LINK_STATE 0x11/* request PF to send link info */ +/* length of permanent address message returned from PF */ #define IXGBE_VF_PERMADDR_MSG_LEN 4/* word in permanent address message with the current multicast type */
drivers/net/ethernet/intel/ixgbevf/vf.c +106 -31
185 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 122/136 ixgbevf: fix mailbox API compatibility by negotiating supported features
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jedrzej Jagielski <[email protected]>
[ Upstream commit a7075f501bd33c93570af759b6f4302ef0175168 ]
There was backward compatibility in the terms of mailbox API. Various drivers from various OSes supporting 10G adapters from Intel portfolio could easily negotiate mailbox API.
This convention has been broken since introducing API 1.4. Commit 0062e7cc955e ("ixgbevf: add VF IPsec offload code") added support for IPSec which is specific only for the kernel ixgbe driver. None of the rest of the Intel 10G PF/VF drivers supports it. And actually lack of support was not included in the IPSec implementation - there were no such code paths. No possibility to negotiate support for the feature was introduced along with introduction of the feature itself.
Commit 339f28964147 ("ixgbevf: Add support for new mailbox communication between PF and VF") increasing API version to 1.5 did the same - it introduced code supported specifically by the PF ESX driver. It altered API version for the VF driver in the same time not touching the version defined for the PF ixgbe driver. It led to additional discrepancies, as the code provided within API 1.6 cannot be supported for Linux ixgbe driver as it causes crashes.
The issue was noticed some time ago and mitigated by Jake within the commit d0725312adf5 ("ixgbevf: stop attempting IPSEC offload on Mailbox API 1.5"). As a result we have regression for IPsec support and after increasing API to version 1.6 ixgbevf driver stopped to support ESX MBX.
To fix this mess add new mailbox op asking PF driver about supported features. Basing on a response determine whether to set support for IPSec and ESX-specific enhanced mailbox.
New mailbox op, for compatibility purposes, must be added within new API revision, as API version of OOT PF & VF drivers is already increased to 1.6 and doesn't incorporate features negotiate op.
Features negotiation mechanism gives possibility to be extended with new features when needed in the future.
--- drivers/net/ethernet/intel/ixgbevf/ipsec.c | 10 ++++ drivers/net/ethernet/intel/ixgbevf/ixgbevf.h | 7 +++ drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 32 ++++++++++++++- drivers/net/ethernet/intel/ixgbevf/mbx.h | 4 + drivers/net/ethernet/intel/ixgbevf/vf.c | 45 +++++++++++++++++++++- drivers/net/ethernet/intel/ixgbevf/vf.h | 1 6 files changed, 96 insertions(+), 3 deletions(-)
drivers/net/ethernet/intel/ixgbevf/ipsec.c +10 -0
@@ -271,6 +271,9 @@ static int ixgbevf_ipsec_add_sa(struct x adapter =netdev_priv (dev); ipsec = adapter->ipsec; +if (!(adapter->pf_features &IXGBEVF_PF_SUP_IPSEC )) +return -EOPNOTSUPP ; +if (xs->id.proto !=IPPROTO_ESP && xs->id.proto !=IPPROTO_AH ) {NL_SET_ERR_MSG_MOD (extack,"Unsupported protocol for IPsec offload" );return -EINVAL ;
@@ -400,6 +403,9 @@ static void ixgbevf_ipsec_del_sa(struct adapter =netdev_priv (dev); ipsec = adapter->ipsec; +if (!(adapter->pf_features &IXGBEVF_PF_SUP_IPSEC )) +return ; +if (xs->xso.dir ==XFRM_DEV_OFFLOAD_IN ) { sa_idx = xs->xso.offload_handle -IXGBE_IPSEC_BASE_RX_INDEX ;
@@ -628,6 +634,10 @@ void ixgbevf_init_ipsec_offload(struct isize_t size;switch (adapter->hw.api_version) { +case ixgbe_mbox_api_17: +if (!(adapter->pf_features &IXGBEVF_PF_SUP_IPSEC )) +return ; +break ;case ixgbe_mbox_api_14:break ;default :
drivers/net/ethernet/intel/ixgbevf/ixgbevf.h +7 -0
@@ -366,6 +366,13 @@ struct ixgbevf_adapter {/* Interrupt Throttle Rate */ u32 eitr_param; +u32 pf_features; +#define IXGBEVF_PF_SUP_IPSEC BIT(0) +#define IXGBEVF_PF_SUP_ESX_MBX BIT(1) + +#define IXGBEVF_SUPPORTED_FEATURES (IXGBEVF_PF_SUP_IPSEC | \ + IXGBEVF_PF_SUP_ESX_MBX) +struct ixgbevf_hw_stats stats;unsigned long state;
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +30 -2
@@ -2274,10 +2274,35 @@ static void ixgbevf_init_last_counter_st adapter->stats.base_vfmprc = adapter->stats.last_vfmprc; } +/** +* ixgbevf_set_features - Set features supported by PF +* @adapter: pointer to the adapter struct +* +* Negotiate with PF supported features and then set pf_features accordingly. +*/ +static void ixgbevf_set_features (struct ixgbevf_adapter *adapter) +{ +u32 *pf_features = &adapter->pf_features; +struct ixgbe_hw *hw = &adapter->hw; +int err; + + err = hw->mac.ops.negotiate_features (hw, pf_features); +if (err && err != -EOPNOTSUPP ) +netdev_dbg (adapter->netdev, +"PF feature negotiation failed.\n" ); + +/* Address also pre API 1.7 cases */ +if (hw->api_version == ixgbe_mbox_api_14) + *pf_features |=IXGBEVF_PF_SUP_IPSEC ; +else if (hw->api_version == ixgbe_mbox_api_15) + *pf_features |=IXGBEVF_PF_SUP_ESX_MBX ; +} +static void ixgbevf_negotiate_api (struct ixgbevf_adapter *adapter) {struct ixgbe_hw *hw = &adapter->hw;static const int api[] = { + ixgbe_mbox_api_17, ixgbe_mbox_api_16, ixgbe_mbox_api_15, ixgbe_mbox_api_14,
@@ -2298,8 +2323,9 @@ static void ixgbevf_negotiate_api(struct idx++; } -/* Following is not supported by API 1.6, it is specific for 1.5 */ -if (hw->api_version == ixgbe_mbox_api_15) { +ixgbevf_set_features (adapter); + +if (adapter->pf_features &IXGBEVF_PF_SUP_ESX_MBX ) { hw->mbx.ops.init_params (hw);memcpy (&hw->mbx.ops, &ixgbevf_mbx_ops,sizeof (struct ixgbe_mbx_operations ));
@@ -2657,6 +2683,7 @@ static void ixgbevf_set_num_queues(struccase ixgbe_mbox_api_14:case ixgbe_mbox_api_15:case ixgbe_mbox_api_16: +case ixgbe_mbox_api_17:if (adapter->xdp_prog && hw->mac.max_tx_queues == rss) rss = rss >3 ?2 :1 ;
@@ -4652,6 +4679,7 @@ static int ixgbevf_probe(struct pci_devcase ixgbe_mbox_api_14:case ixgbe_mbox_api_15:case ixgbe_mbox_api_16: +case ixgbe_mbox_api_17: netdev->max_mtu =IXGBE_MAX_JUMBO_FRAME_SIZE - (ETH_HLEN +ETH_FCS_LEN );break ;
drivers/net/ethernet/intel/ixgbevf/mbx.h +4 -0
@@ -67,6 +67,7 @@ enum ixgbe_pfvf_api_rev { ixgbe_mbox_api_14,/* API version 1.4, linux/freebsd VF driver */ ixgbe_mbox_api_15,/* API version 1.5, linux/freebsd VF driver */ ixgbe_mbox_api_16,/* API version 1.6, linux/freebsd VF driver */ + ixgbe_mbox_api_17,/* API version 1.7, linux/freebsd VF driver */ /* This value should always be last */ ixgbe_mbox_api_unknown, /* indicates that API version is not known */ };
@@ -106,6 +107,9 @@ enum ixgbe_pfvf_api_rev {/* mailbox API, version 1.6 VF requests */ #define IXGBE_VF_GET_PF_LINK_STATE 0x11/* request PF to send link info */ +/* mailbox API, version 1.7 VF requests */ +#define IXGBE_VF_FEATURES_NEGOTIATE 0x12/* get features supported by PF*/ +/* length of permanent address message returned from PF */ #define IXGBE_VF_PERMADDR_MSG_LEN 4/* word in permanent address message with the current multicast type */
drivers/net/ethernet/intel/ixgbevf/vf.c +44 -1
99 lines not on this page · raw message
drivers/net/ethernet/intel/ixgbevf/vf.h +1 -0
@@ -26,6 +26,7 @@ struct ixgbe_mac_operations {s32 (*stop_adapter)(struct ixgbe_hw *);s32 (*get_bus_info)(struct ixgbe_hw *);s32 (*negotiate_api_version)(struct ixgbe_hw *hw,int api); +int (*negotiate_features)(struct ixgbe_hw *hw,u32 *pf_features);/* Link */ s32 (*setup_link)(struct ixgbe_hw *,ixgbe_link_speed ,bool ,bool );
Greg Kroah-Hartman
maintainerPATCH 123/136 tcp: convert to dev_net_rcu()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit e7b9ecce562ca6a1de32c56c597fa45e08c44ec0 ]
TCP uses of dev_net() are under RCU protection, change them to dev_net_rcu() to get LOCKDEP support.
Stable-dep-of: 833d4313bc1e ("mptcp: reset blackhole on success with non-loopback ifaces")
--- include/net/inet6_hashtables.h | 2 +- include/net/inet_hashtables.h | 2 +- net/ipv4/tcp_ipv4.c | 12 ++++++------ net/ipv4/tcp_metrics.c | 6 +++--- net/ipv6/tcp_ipv6.c | 22 +++++++++++----------- 5 files changed, 22 insertions(+), 22 deletions(-)
include/net/inet6_hashtables.h +1 -1
@@ -150,7 +150,7 @@ static inline struct sock *__inet6_looku int iif, int sdif, bool *refcounted) { - struct net *net = dev_net(skb_dst(skb)->dev); + struct net *net = dev_net_rcu(skb_dst(skb)->dev);const struct ipv6hdr *ip6h =ipv6_hdr (skb);struct sock *sk;
include/net/inet_hashtables.h +1 -1
@@ -492,7 +492,7 @@ static inline struct sock *__inet_lookupconst int sdif, bool *refcounted) { - struct net *net = dev_net(skb_dst(skb)->dev); + struct net *net = dev_net_rcu(skb_dst(skb)->dev);const struct iphdr *iph =ip_hdr (skb);struct sock *sk;
net/ipv4/tcp_ipv4.c +6 -6
@@ -494,14 +494,14 @@ int tcp_v4_err(struct sk_buff *skb, u32 {const struct iphdr *iph = (const struct iphdr *)skb->data;struct tcphdr *th = (struct tcphdr *)(skb->data + (iph->ihl <<2 )); -struct tcp_sock *tp; +struct net *net =dev_net_rcu (skb->dev);const int type =icmp_hdr (skb)->type;const int code =icmp_hdr (skb)->code; -struct sock *sk;struct request_sock *fastopen; +struct tcp_sock *tp;u32 seq, snd_una; +struct sock *sk;int err; -struct net *net =dev_net (skb->dev); sk = __inet_lookup_established(net, net->ipv4.tcp_death_row.hashinfo, iph->daddr, th->dest, iph->saddr,
@@ -786,7 +786,7 @@ static void tcp_v4_send_reset(const stru arg.iov[0 ].iov_base = (unsigned char *)&rep; arg.iov[0 ].iov_len =sizeof (rep.th); - net = sk ?sock_net (sk) :dev_net (skb_dst (skb)->dev); + net = sk ?sock_net (sk) :dev_net_rcu (skb_dst (skb)->dev);/* Invalid TCP option size or twice included auth */ if (tcp_parse_auth_options (tcp_hdr (skb), &md5_hash_location, &aoh))
@@ -1965,7 +1965,7 @@ EXPORT_SYMBOL(tcp_v4_do_rcv);int tcp_v4_early_demux (struct sk_buff *skb) { -struct net *net =dev_net (skb->dev); +struct net *net =dev_net_rcu (skb->dev);const struct iphdr *iph;const struct tcphdr *th;struct sock *sk;
@@ -2176,7 +2176,7 @@ static void tcp_v4_fill_cb(struct sk_bufint tcp_v4_rcv (struct sk_buff *skb) { -struct net *net =dev_net (skb->dev); +struct net *net =dev_net_rcu (skb->dev);enum skb_drop_reason drop_reason;int sdif =inet_sdif (skb);int dif =inet_iif (skb);
net/ipv4/tcp_metrics.c +3 -3
@@ -170,7 +170,7 @@ static struct tcp_metrics_block *tcpm_nebool reclaim = false;spin_lock_bh (&tcp_metrics_lock); - net =dev_net (dst->dev); + net =dev_net_rcu (dst->dev);/* While waiting for the spin-lock the cache might have been populated * with this entry and so we have to check again.
@@ -273,7 +273,7 @@ static struct tcp_metrics_block *__tcp_greturn NULL ; } - net =dev_net (dst->dev); + net =dev_net_rcu (dst->dev); hash ^=net_hash_mix (net); hash =hash_32 (hash, tcp_metrics_hash_log);
@@ -318,7 +318,7 @@ static struct tcp_metrics_block *tcp_getelse return NULL ; - net =dev_net (dst->dev); + net =dev_net_rcu (dst->dev); hash ^=net_hash_mix (net); hash =hash_32 (hash, tcp_metrics_hash_log);
net/ipv6/tcp_ipv6.c +11 -11
@@ -376,7 +376,7 @@ static int tcp_v6_err(struct sk_buff *sk {const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data;const struct tcphdr *th = (struct tcphdr *)(skb->data+offset); -struct net *net =dev_net (skb->dev); +struct net *net =dev_net_rcu (skb->dev);struct request_sock *fastopen;struct ipv6_pinfo *np;struct tcp_sock *tp;
@@ -864,16 +864,16 @@ static void tcp_v6_send_response(const s int oif, int rst, u8 tclass, __be32 label, u32 priority, u32 txhash, struct tcp_key *key) { - const struct tcphdr *th = tcp_hdr(skb); -struct tcphdr *t1; -struct sk_buff *buff; -struct flowi6 fl6; -struct net *net = sk ?sock_net (sk) :dev_net (skb_dst (skb)->dev); -struct sock *ctl_sk = net->ipv6.tcp_sk; + struct net *net = sk ? sock_net(sk) : dev_net_rcu(skb_dst(skb)->dev);unsigned int tot_len =sizeof (struct tcphdr ); +struct sock *ctl_sk = net->ipv6.tcp_sk; +const struct tcphdr *th =tcp_hdr (skb);__be32 mrst =0 , *topt;struct dst_entry *dst; -__u32 mark =0 ; +struct sk_buff *buff; +struct tcphdr *t1; +struct flowi6 fl6; +u32 mark =0 ;if (tsecr) tot_len +=TCPOLEN_TSTAMP_ALIGNED ;
@@ -1036,7 +1036,7 @@ static void tcp_v6_send_reset(const struif (!sk && !ipv6_unicast_destination (skb))return ; - net = sk ?sock_net (sk) :dev_net (skb_dst (skb)->dev); + net = sk ?sock_net (sk) :dev_net_rcu (skb_dst (skb)->dev);/* Invalid TCP option size or twice included auth */ if (tcp_parse_auth_options (th, &md5_hash_location, &aoh))return ;
@@ -1739,6 +1739,7 @@ static void tcp_v6_fill_cb(struct sk_buf INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb) { +struct net *net =dev_net_rcu (skb->dev);enum skb_drop_reason drop_reason;int sdif =inet6_sdif (skb);int dif =inet6_iif (skb);
@@ -1748,7 +1749,6 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(sbool refcounted;int ret;u32 isn; -struct net *net =dev_net (skb->dev); drop_reason =SKB_DROP_REASON_NOT_SPECIFIED ;if (skb->pkt_type !=PACKET_HOST )
@@ -1999,7 +1999,7 @@ do_time_wait:void tcp_v6_early_demux (struct sk_buff *skb) { -struct net *net =dev_net (skb->dev); +struct net *net =dev_net_rcu (skb->dev);const struct ipv6hdr *hdr;const struct tcphdr *th;struct sock *sk;
Greg Kroah-Hartman
maintainerPATCH 124/136 tcp: cache RTAX_QUICKACK metric in a hot cache line
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 15492700ac41459b54a6683490adcee350ab11e3 ]
tcp_in_quickack_mode() is called from input path for small packets.
It calls __sk_dst_get() which reads sk->sk_dst_cache which has been put in sock_read_tx group (for good reasons).
Then dst_metric(dst, RTAX_QUICKACK) also needs extra cache line misses.
Cache RTAX_QUICKACK in icsk->icsk_ack.dst_quick_ack to no longer pull these cache lines for the cases a delayed ACK is scheduled.
After this patch TCP receive path does not longer access sock_read_tx group.
Stable-dep-of: 833d4313bc1e ("mptcp: reset blackhole on success with non-loopback ifaces")
--- include/net/inet_connection_sock.h | 3 ++- net/core/sock.c | 6 +++++- net/ipv4/tcp_input.c | 3 +-- 3 files changed, 8 insertions(+), 4 deletions(-)
include/net/inet_connection_sock.h +2 -1
@@ -116,7 +116,8 @@ struct inet_connection_sock {#define ATO_BITS 8 __u32 ato:ATO_BITS, /* Predicted tick of soft clock */ lrcv_flowlabel:20, /* last received ipv6 flowlabel */ - unused:4; + dst_quick_ack:1, /* cache dst RTAX_QUICKACK */ + unused:3;unsigned long timeout;/* Currently scheduled timeout */ __u32 lrcvtime;/* timestamp of last received data packet */ __u16 last_seg_size;/* Size of last incoming segment */
net/core/sock.c +5 -1
@@ -2547,8 +2547,12 @@ void sk_setup_caps(struct sock *sk, struu32 max_segs =1 ; sk->sk_route_caps = dst->dev->features; -if (sk_is_tcp (sk)) +if (sk_is_tcp (sk)) { +struct inet_connection_sock *icsk =inet_csk (sk); + sk->sk_route_caps |=NETIF_F_GSO ; + icsk->icsk_ack.dst_quick_ack =dst_metric (dst,RTAX_QUICKACK ); + }if (sk->sk_route_caps &NETIF_F_GSO ) sk->sk_route_caps |=NETIF_F_GSO_SOFTWARE ;if (unlikely (sk->sk_gso_disabled))
net/ipv4/tcp_input.c +1 -2
@@ -331,9 +331,8 @@ static void tcp_enter_quickack_mode(strustatic bool tcp_in_quickack_mode (struct sock *sk) {const struct inet_connection_sock *icsk =inet_csk (sk); -const struct dst_entry *dst =__sk_dst_get (sk); -return (dst &&dst_metric (dst,RTAX_QUICKACK )) || +return icsk->icsk_ack.dst_quick_ack || (icsk->icsk_ack.quick && !inet_csk_in_pingpong_mode (sk)); }
Greg Kroah-Hartman
maintainerPATCH 125/136 net: dst: add four helpers to annotate data-races around dst->dev
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 88fe14253e181878c2ddb51a298ae8c468a63010 ]
dst->dev is read locklessly in many contexts,
and written in dst_dev_put().
Fixing all the races is going to need many changes.
We probably will have to add full RCU protection.
Add three helpers to ease this painful process.
static inline struct net_device *dst_dev(const struct dst_entry *dst)
{
return READ_ONCE(dst->dev);
}static inline struct net_device *skb_dst_dev(const struct sk_buff *skb)
{
return dst_dev(skb_dst(skb));
}static inline struct net *skb_dst_dev_net(const struct sk_buff *skb)
{
return dev_net(skb_dst_dev(skb));
}static inline struct net *skb_dst_dev_net_rcu(const struct sk_buff *skb)
{
return dev_net_rcu(skb_dst_dev(skb));
}Stable-dep-of: 833d4313bc1e ("mptcp: reset blackhole on success with non-loopback ifaces")
--- include/net/dst.h | 20 ++++++++++++++++++++ net/core/dst.c | 4 ++-- net/core/sock.c | 8 ++++---- 3 files changed, 26 insertions(+), 6 deletions(-)
include/net/dst.h +20 -0
@@ -561,6 +561,26 @@ static inline void skb_dst_update_pmtu_n dst->ops->update_pmtu (dst,NULL , skb, mtu, false); } +static inline struct net_device *dst_dev (const struct dst_entry *dst) +{ +return READ_ONCE (dst->dev); +} + +static inline struct net_device *skb_dst_dev (const struct sk_buff *skb) +{ +return dst_dev (skb_dst (skb)); +} + +static inline struct net *skb_dst_dev_net (const struct sk_buff *skb) +{ +return dev_net (skb_dst_dev (skb)); +} + +static inline struct net *skb_dst_dev_net_rcu (const struct sk_buff *skb) +{ +return dev_net_rcu (skb_dst_dev (skb)); +} +struct dst_entry *dst_blackhole_check (struct dst_entry *dst,u32 cookie);void dst_blackhole_update_pmtu (struct dst_entry *dst,struct sock *sk,struct sk_buff *skb,u32 mtu,bool confirm_neigh);
net/core/dst.c +2 -2
@@ -150,7 +150,7 @@ void dst_dev_put(struct dst_entry *dst) dst->ops->ifdown (dst, dev);WRITE_ONCE (dst->input, dst_discard);WRITE_ONCE (dst->output, dst_discard_out); - dst->dev = blackhole_netdev; +WRITE_ONCE (dst->dev, blackhole_netdev);netdev_ref_replace (dev, blackhole_netdev, &dst->dev_tracker,GFP_ATOMIC ); }
@@ -263,7 +263,7 @@ unsigned int dst_blackhole_mtu(const str {unsigned int mtu =dst_metric_raw (dst,RTAX_MTU ); -return mtu ? : dst->dev->mtu; +return mtu ? :dst_dev (dst)->mtu; }EXPORT_SYMBOL_GPL (dst_blackhole_mtu);
net/core/sock.c +4 -4
@@ -2534,8 +2534,8 @@ static u32 sk_dst_gso_max_size(struct so !ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr));#endif /* pairs with the WRITE_ONCE() in netif_set_gso(_ipv4)_max_size() */ - max_size = is_ipv6 ?READ_ONCE (dst->dev->gso_max_size) : -READ_ONCE (dst->dev->gso_ipv4_max_size); + max_size = is_ipv6 ?READ_ONCE (dst_dev (dst)->gso_max_size) : +READ_ONCE (dst_dev (dst)->gso_ipv4_max_size);if (max_size >GSO_LEGACY_MAX_SIZE && !sk_is_tcp (sk)) max_size =GSO_LEGACY_MAX_SIZE ;
@@ -2546,7 +2546,7 @@ void sk_setup_caps(struct sock *sk, stru {u32 max_segs =1 ; - sk->sk_route_caps = dst->dev->features; + sk->sk_route_caps =dst_dev (dst)->features;if (sk_is_tcp (sk)) {struct inet_connection_sock *icsk =inet_csk (sk);
@@ -2564,7 +2564,7 @@ void sk_setup_caps(struct sock *sk, stru sk->sk_route_caps |=NETIF_F_SG |NETIF_F_HW_CSUM ; sk->sk_gso_max_size =sk_dst_gso_max_size (sk, dst);/* pairs with the WRITE_ONCE() in netif_set_gso_max_segs() */ - max_segs =max_t (u32,READ_ONCE (dst->dev->gso_max_segs),1 ); + max_segs =max_t (u32,READ_ONCE (dst_dev (dst)->gso_max_segs),1 ); } } sk->sk_gso_max_segs = max_segs;
Greg Kroah-Hartman
maintainerPATCH 126/136 ipv4: adopt dst_dev, skb_dst_dev and skb_dst_dev_net[_rcu]
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit a74fc62eec155ca5a6da8ff3856f3dc87fe24558 ]
Use the new helpers as a first step to deal with
potential dst->dev races.
Stable-dep-of: 833d4313bc1e ("mptcp: reset blackhole on success with non-loopback ifaces")
--- include/net/inet_hashtables.h | 2 +- include/net/ip.h | 11 ++++++----- include/net/route.h | 2 +- net/ipv4/icmp.c | 24 +++++++++++++----------- net/ipv4/igmp.c | 2 +- net/ipv4/ip_fragment.c | 2 +- net/ipv4/ip_output.c | 6 +++--- net/ipv4/ip_vti.c | 4 ++-- net/ipv4/netfilter.c | 4 ++-- net/ipv4/route.c | 8 ++++---- net/ipv4/tcp_fastopen.c | 4 +++- net/ipv4/tcp_ipv4.c | 2 +- net/ipv4/tcp_metrics.c | 8 ++++---- net/ipv4/xfrm4_output.c | 2 +- 14 files changed, 43 insertions(+), 38 deletions(-)
include/net/inet_hashtables.h +1 -1
@@ -492,7 +492,7 @@ static inline struct sock *__inet_lookupconst int sdif, bool *refcounted) { - struct net *net = dev_net_rcu(skb_dst(skb)->dev); + struct net *net = skb_dst_dev_net_rcu(skb);const struct iphdr *iph =ip_hdr (skb);struct sock *sk;
include/net/ip.h +6 -5
@@ -475,7 +475,7 @@ static inline unsigned int ip_dst_mtu_marcu_read_lock (); - net =dev_net_rcu (dst->dev); + net =dev_net_rcu (dst_dev (dst));if (READ_ONCE (net->ipv4.sysctl_ip_fwd_use_pmtu) ||ip_mtu_locked (dst) || !forwarding) {
@@ -489,7 +489,7 @@ static inline unsigned int ip_dst_mtu_maif (mtu) goto out; - mtu =READ_ONCE (dst->dev->mtu); + mtu =READ_ONCE (dst_dev (dst)->mtu);if (unlikely (ip_mtu_locked (dst))) {if (rt->rt_uses_gateway && mtu >576 )
@@ -509,16 +509,17 @@ out:static inline unsigned int ip_skb_dst_mtu (struct sock *sk,const struct sk_buff *skb) { +const struct dst_entry *dst =skb_dst (skb);unsigned int mtu;if (!sk || !sk_fullsock (sk) ||ip_sk_use_pmtu (sk)) {bool forwarding =IPCB (skb)->flags &IPSKB_FORWARDED ; -return ip_dst_mtu_maybe_forward (skb_dst (skb), forwarding); +return ip_dst_mtu_maybe_forward (dst, forwarding); } - mtu =min (READ_ONCE (skb_dst (skb)->dev->mtu),IP_MAX_MTU ); -return mtu -lwtunnel_headroom (skb_dst (skb)->lwtstate, mtu); + mtu =min (READ_ONCE (dst_dev (dst)->mtu),IP_MAX_MTU ); +return mtu -lwtunnel_headroom (dst->lwtstate, mtu); } struct dst_metrics *ip_fib_metrics_init(struct nlattr *fc_mx, int fc_mx_len,
include/net/route.h +1 -1
@@ -369,7 +369,7 @@ static inline int ip4_dst_hoplimit(constconst struct net *net;rcu_read_lock (); - net =dev_net_rcu (dst->dev); + net =dev_net_rcu (dst_dev (dst)); hoplimit =READ_ONCE (net->ipv4.sysctl_ip_default_ttl);rcu_read_unlock (); }
net/ipv4/icmp.c +13 -11
@@ -311,18 +311,20 @@ static bool icmpv4_xrlim_allow(struct ne {struct dst_entry *dst = &rt->dst;struct inet_peer *peer; +struct net_device *dev;bool rc = true;if (!apply_ratelimit)return true;/* No rate limit on loopback */ -if (dst->dev && (dst->dev->flags&IFF_LOOPBACK )) + dev =dst_dev (dst); +if (dev && (dev->flags &IFF_LOOPBACK )) goto out;rcu_read_lock (); peer =inet_getpeer_v4 (net->ipv4.peers, fl4->daddr, -l3mdev_master_ifindex_rcu (dst->dev)); +l3mdev_master_ifindex_rcu (dev)); rc =inet_peer_xrlim_allow (peer,READ_ONCE (net->ipv4.sysctl_icmp_ratelimit));rcu_read_unlock ();
@@ -468,13 +470,13 @@ out_bh_enable:*/ static struct net_device *icmp_get_route_lookup_dev (struct sk_buff *skb) { -struct net_device *route_lookup_dev =NULL ; +struct net_device *dev = skb->dev; +const struct dst_entry *dst; -if (skb->dev) - route_lookup_dev = skb->dev; -else if (skb_dst (skb)) - route_lookup_dev =skb_dst (skb)->dev; -return route_lookup_dev; +if (dev) +return dev; + dst =skb_dst (skb); +return dst ?dst_dev (dst) :NULL ; } static struct rtable *icmp_route_lookup(struct net *net, struct flowi4 *fl4,
@@ -873,7 +875,7 @@ static enum skb_drop_reason icmp_unreachstruct net *net;u32 info =0 ; - net =dev_net_rcu (skb_dst (skb)->dev); + net =skb_dst_dev_net_rcu (skb);/* * Incomplete header ?
@@ -1016,7 +1018,7 @@ static enum skb_drop_reason icmp_echo(ststruct icmp_bxm icmp_param;struct net *net; - net =dev_net_rcu (skb_dst (skb)->dev); + net =skb_dst_dev_net_rcu (skb);/* should there be an ICMP stat for ignored echos? */ if (READ_ONCE (net->ipv4.sysctl_icmp_echo_ignore_all))return SKB_NOT_DROPPED_YET ;
@@ -1186,7 +1188,7 @@ static enum skb_drop_reason icmp_timestareturn SKB_NOT_DROPPED_YET ; out_err: -__ICMP_INC_STATS (dev_net_rcu (skb_dst (skb)->dev),ICMP_MIB_INERRORS ); +__ICMP_INC_STATS (skb_dst_dev_net_rcu (skb),ICMP_MIB_INERRORS );return SKB_DROP_REASON_PKT_TOO_SMALL ; }
net/ipv4/igmp.c +1 -1
@@ -424,7 +424,7 @@ static int igmpv3_sendpack(struct sk_buf pig->csum =ip_compute_csum (igmp_hdr (skb), igmplen); -return ip_local_out (dev_net (skb_dst (skb)->dev), skb->sk, skb); +return ip_local_out (skb_dst_dev_net (skb), skb->sk, skb); }static int grec_size (struct ip_mc_list *pmc,int type,int gdel,int sdel)
net/ipv4/ip_fragment.c +1 -1
@@ -488,7 +488,7 @@ out_fail:/* Process an incoming IP datagram fragment. */ int ip_defrag (struct net *net,struct sk_buff *skb,u32 user) { -struct net_device *dev = skb->dev ? :skb_dst (skb)->dev; +struct net_device *dev = skb->dev ? :skb_dst_dev (skb);int vif =l3mdev_master_ifindex_rcu (dev);struct ipq *qp;
net/ipv4/ip_output.c +3 -3
@@ -117,7 +117,7 @@ int __ip_local_out(struct net *net, stru skb->protocol =htons (ETH_P_IP );return nf_hook (NFPROTO_IPV4 ,NF_INET_LOCAL_OUT , - net, sk, skb,NULL ,skb_dst (skb)->dev, + net, sk, skb,NULL ,skb_dst_dev (skb), dst_output); }
@@ -200,7 +200,7 @@ static int ip_finish_output2(struct net {struct dst_entry *dst =skb_dst (skb);struct rtable *rt =dst_rtable (dst); -struct net_device *dev = dst->dev; +struct net_device *dev =dst_dev (dst);unsigned int hh_len =LL_RESERVED_SPACE (dev);struct neighbour *neigh;bool is_v6gw = false;
@@ -426,7 +426,7 @@ int ip_mc_output(struct net *net, structint ip_output (struct net *net,struct sock *sk,struct sk_buff *skb) { -struct net_device *dev =skb_dst (skb)->dev, *indev = skb->dev; +struct net_device *dev =skb_dst_dev (skb), *indev = skb->dev; skb->dev = dev; skb->protocol =htons (ETH_P_IP );
net/ipv4/ip_vti.c +2 -2
@@ -229,7 +229,7 @@ static netdev_tx_t vti_xmit(struct sk_bu goto tx_error_icmp; } - tdev = dst->dev; + tdev =dst_dev (dst);if (tdev == dev) {dst_release (dst);
@@ -259,7 +259,7 @@ static netdev_tx_t vti_xmit(struct sk_bu xmit:skb_scrub_packet (skb, !net_eq (tunnel->net,dev_net (dev)));skb_dst_set (skb, dst); - skb->dev =skb_dst (skb)->dev; + skb->dev =skb_dst_dev (skb); err =dst_output (tunnel->net, skb->sk, skb);if (net_xmit_eval (err) ==0 )
net/ipv4/netfilter.c +2 -2
@@ -20,12 +20,12 @@/* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */ int ip_route_me_harder (struct net *net,struct sock *sk,struct sk_buff *skb,unsigned int addr_type) { +struct net_device *dev =skb_dst_dev (skb);const struct iphdr *iph =ip_hdr (skb);struct rtable *rt;struct flowi4 fl4 = {};__be32 saddr = iph->saddr;__u8 flags; -struct net_device *dev =skb_dst (skb)->dev;struct flow_keys flkeys;unsigned int hh_len;
@@ -74,7 +74,7 @@ int ip_route_me_harder(struct net *net,#endif /* Change in oif may mean change in hh_len. */ - hh_len =skb_dst (skb)->dev->hard_header_len; + hh_len =skb_dst_dev (skb)->hard_header_len;if (skb_headroom (skb) < hh_len &&pskb_expand_head (skb,HH_DATA_ALIGN (hh_len -skb_headroom (skb)),0 ,GFP_ATOMIC ))
net/ipv4/route.c +4 -4
@@ -413,7 +413,7 @@ static struct neighbour *ipv4_neigh_look const void *daddr) { const struct rtable *rt = container_of(dst, struct rtable, dst); -struct net_device *dev = dst->dev; +struct net_device *dev =dst_dev (dst);struct neighbour *n;rcu_read_lock ();
@@ -440,7 +440,7 @@ static struct neighbour *ipv4_neigh_lookstatic void ipv4_confirm_neigh (const struct dst_entry *dst,const void *daddr) { const struct rtable *rt = container_of(dst, struct rtable, dst); -struct net_device *dev = dst->dev; +struct net_device *dev =dst_dev (dst);const __be32 *pkey = daddr;if (rt->rt_gw_family ==AF_INET ) {
@@ -1025,7 +1025,7 @@ static void __ip_rt_update_pmtu(struct rreturn ;rcu_read_lock (); - net =dev_net_rcu (dst->dev); + net =dev_net_rcu (dst_dev (dst));if (mtu < net->ipv4.ip_rt_min_pmtu) { lock = true; mtu =min (old_mtu, net->ipv4.ip_rt_min_pmtu);
@@ -1323,7 +1323,7 @@ static unsigned int ipv4_default_advmss(struct net *net;rcu_read_lock (); - net =dev_net_rcu (dst->dev); + net =dev_net_rcu (dst_dev (dst)); advmss = max_t(unsigned int, ipv4_mtu(dst) - header_size, net->ipv4.ip_rt_min_advmss);rcu_read_unlock ();
net/ipv4/tcp_fastopen.c +3 -1
@@ -558,6 +558,7 @@ bool tcp_fastopen_active_should_disable(void tcp_fastopen_active_disable_ofo_check (struct sock *sk) {struct tcp_sock *tp =tcp_sk (sk); +struct net_device *dev;struct dst_entry *dst;struct sk_buff *skb;
@@ -575,7 +576,8 @@ void tcp_fastopen_active_disable_ofo_che }else if (tp->syn_fastopen_ch &&atomic_read (&sock_net (sk)->ipv4.tfo_active_disable_times)) { dst =sk_dst_get (sk); -if (!(dst && dst->dev && (dst->dev->flags &IFF_LOOPBACK ))) + dev = dst ?dst_dev (dst) :NULL ; +if (!(dev && (dev->flags &IFF_LOOPBACK )))atomic_set (&sock_net (sk)->ipv4.tfo_active_disable_times,0 );dst_release (dst); }
net/ipv4/tcp_ipv4.c +1 -1
@@ -786,7 +786,7 @@ static void tcp_v4_send_reset(const stru arg.iov[0 ].iov_base = (unsigned char *)&rep; arg.iov[0 ].iov_len =sizeof (rep.th); - net = sk ?sock_net (sk) :dev_net_rcu (skb_dst (skb)->dev); + net = sk ?sock_net (sk) :skb_dst_dev_net_rcu (skb);/* Invalid TCP option size or twice included auth */ if (tcp_parse_auth_options (tcp_hdr (skb), &md5_hash_location, &aoh))
net/ipv4/tcp_metrics.c +4 -4
@@ -166,11 +166,11 @@ static struct tcp_metrics_block *tcpm_ne unsigned int hash) {struct tcp_metrics_block *tm; -struct net *net;bool reclaim = false; +struct net *net;spin_lock_bh (&tcp_metrics_lock); - net =dev_net_rcu (dst->dev); + net =dev_net_rcu (dst_dev (dst));/* While waiting for the spin-lock the cache might have been populated * with this entry and so we have to check again.
@@ -273,7 +273,7 @@ static struct tcp_metrics_block *__tcp_greturn NULL ; } - net =dev_net_rcu (dst->dev); + net =dev_net_rcu (dst_dev (dst)); hash ^=net_hash_mix (net); hash =hash_32 (hash, tcp_metrics_hash_log);
@@ -318,7 +318,7 @@ static struct tcp_metrics_block *tcp_getelse return NULL ; - net =dev_net_rcu (dst->dev); + net =dev_net_rcu (dst_dev (dst)); hash ^=net_hash_mix (net); hash =hash_32 (hash, tcp_metrics_hash_log);
net/ipv4/xfrm4_output.c +1 -1
@@ -31,7 +31,7 @@ static int __xfrm4_output(struct net *neint xfrm4_output (struct net *net,struct sock *sk,struct sk_buff *skb) {return NF_HOOK_COND (NFPROTO_IPV4 ,NF_INET_POST_ROUTING , - net, sk, skb, skb->dev,skb_dst (skb)->dev, + net, sk, skb, skb->dev,skb_dst_dev (skb), __xfrm4_output, !(IPCB (skb)->flags &IPSKB_REROUTED )); }
Greg Kroah-Hartman
maintainerPATCH 127/136 net: Add locking to protect skb->dev access in ip_output
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sharath Chandra Vurukala <[email protected]>
[ Upstream commit 1dbf1d590d10a6d1978e8184f8dfe20af22d680a ]
In ip_output() skb->dev is updated from the skb_dst(skb)->dev this can become invalid when the interface is unregistered and freed,
Introduced new skb_dst_dev_rcu() function to be used instead of skb_dst_dev() within rcu_locks in ip_output.This will ensure that all the skb's associated with the dev being deregistered will be transnmitted out first, before freeing the dev.
Given that ip_output() is called within an rcu_read_lock() critical section or from a bottom-half context, it is safe to introduce an RCU read-side critical section within it.
Multiple panic call stacks were observed when UL traffic was run in concurrency with device deregistration from different functions, pasting one sample for reference.
[496733.627565][T13385] Call trace: [496733.627570][T13385] bpf_prog_ce7c9180c3b128ea_cgroupskb_egres+0x24c/0x7f0 [496733.627581][T13385] __cgroup_bpf_run_filter_skb+0x128/0x498 [496733.627595][T13385] ip_finish_output+0xa4/0xf4 [496733.627605][T13385] ip_output+0x100/0x1a0 [496733.627613][T13385] ip_send_skb+0x68/0x100 [496733.627618][T13385] udp_send_skb+0x1c4/0x384 [496733.627625][T13385] udp_sendmsg+0x7b0/0x898 [496733.627631][T13385] inet_sendmsg+0x5c/0x7c [496733.627639][T13385] __sys_sendto+0x174/0x1e4 [496733.627647][T13385] __arm64_sys_sendto+0x28/0x3c [496733.627653][T13385] invoke_syscall+0x58/0x11c [496733.627662][T13385] el0_svc_common+0x88/0xf4 [496733.627669][T13385] do_el0_svc+0x2c/0xb0 [496733.627676][T13385] el0_svc+0x2c/0xa4 [496733.627683][T13385] el0t_64_sync_handler+0x68/0xb4 [496733.627689][T13385] el0t_64_sync+0x1a4/0x1a8
Changes in v3:
- Replaced WARN_ON() with WARN_ON_ONCE(), as suggested by Willem de Bruijn.
- Dropped legacy lines mistakenly pulled in from an outdated branch.
Changes in v2:
- Addressed review comments from Eric Dumazet
- Used READ_ONCE() to prevent potential load/store tearing
- Added skb_dst_dev_rcu() and used along with rcu_read_lock() in ip_output
Stable-dep-of: 833d4313bc1e ("mptcp: reset blackhole on success with non-loopback ifaces")
--- include/net/dst.h | 12 ++++++++++++ net/ipv4/ip_output.c | 15 ++++++++++----- 2 files changed, 22 insertions(+), 5 deletions(-)
include/net/dst.h +12 -0
@@ -566,11 +566,23 @@ static inline struct net_device *dst_devreturn READ_ONCE (dst->dev); } +static inline struct net_device *dst_dev_rcu (const struct dst_entry *dst) +{ +/* In the future, use rcu_dereference(dst->dev) */ +WARN_ON_ONCE (!rcu_read_lock_held ()); +return READ_ONCE (dst->dev); +} +static inline struct net_device *skb_dst_dev (const struct sk_buff *skb) {return dst_dev (skb_dst (skb)); } +static inline struct net_device *skb_dst_dev_rcu (const struct sk_buff *skb) +{ +return dst_dev_rcu (skb_dst (skb)); +} +static inline struct net *skb_dst_dev_net (const struct sk_buff *skb) {return dev_net (skb_dst_dev (skb));
net/ipv4/ip_output.c +10 -5
@@ -426,15 +426,20 @@ int ip_mc_output(struct net *net, structint ip_output (struct net *net,struct sock *sk,struct sk_buff *skb) { -struct net_device *dev =skb_dst_dev (skb), *indev = skb->dev; +struct net_device *dev, *indev = skb->dev; +int ret_val; +rcu_read_lock (); + dev =skb_dst_dev_rcu (skb); skb->dev = dev; skb->protocol =htons (ETH_P_IP ); -return NF_HOOK_COND (NFPROTO_IPV4 ,NF_INET_POST_ROUTING , - net, sk, skb, indev, dev, - ip_finish_output, - !(IPCB (skb)->flags &IPSKB_REROUTED )); + ret_val =NF_HOOK_COND (NFPROTO_IPV4 ,NF_INET_POST_ROUTING , + net, sk, skb, indev, dev, + ip_finish_output, + !(IPCB (skb)->flags &IPSKB_REROUTED )); +rcu_read_unlock (); +return ret_val; }EXPORT_SYMBOL (ip_output);