5.10.175-rc1 review
Subsystems (2)
Greg Kroah-Hartman
maintainercover 5.10.175-rc1 review
This is the start of the stable review cycle for the 5.10.175 release. There are 104 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 Fri, 17 Mar 2023 11:57:10 +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/v5.x/stable-review/patch-5.10.175-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-5.10.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 5.10.175-rc1
Stefan Haberland <[email protected]>
s390/dasd: add missing discipline function
Alexandru Matei <[email protected]>
KVM: VMX: Fix crash due to uninitialized current_vmcs
Vitaly Kuznetsov <[email protected]>
KVM: VMX: Introduce vmx_msr_bitmap_l01_changed() helper
Vitaly Kuznetsov <[email protected]>
KVM: nVMX: Don't use Enlightened MSR Bitmap for L3
Masahiro Yamada <[email protected]>
UML: define RUNTIME_DISCARD_EXIT
Tom Saeger <[email protected]>
sh: define RUNTIME_DISCARD_EXIT
Masahiro Yamada <[email protected]>
s390: define RUNTIME_DISCARD_EXIT to fix link error with GNU ld < 2.36
Michael Ellerman <[email protected]>
powerpc/vmlinux.lds: Don't discard .rela* for relocatable builds
Michael Ellerman <[email protected]>
powerpc/vmlinux.lds: Define RUNTIME_DISCARD_EXIT
Masahiro Yamada <[email protected]>
arch: fix broken BuildID for arm64 and riscv
Lukas Czerner <[email protected]>
ext4: block range must be validated before use in ext4_mb_clear_bb()
Ritesh Harjani <[email protected]>
ext4: add strict range checks while freeing blocks
Ritesh Harjani <[email protected]>
ext4: add ext4_sb_block_valid() refactored out of ext4_inode_block_valid()
Ritesh Harjani <[email protected]>
ext4: refactor ext4_free_blocks() to pull out ext4_mb_clear_bb()
Qais Yousef <[email protected]>
sched/fair: Fixes for capacity inversion detection
Qais Yousef <[email protected]>
sched/uclamp: Fix a uninitialized variable warnings
Qais Yousef <[email protected]>
sched/fair: Consider capacity inversion in util_fits_cpu()
Qais Yousef <[email protected]>
sched/fair: Detect capacity inversion
Qais Yousef <[email protected]>
sched/uclamp: Cater for uclamp in find_energy_efficient_cpu()'s early exit condition
Qais Yousef <[email protected]>
sched/uclamp: Make cpu_overutilized() use util_fits_cpu()
Qais Yousef <[email protected]>
sched/uclamp: Make asym_fits_capacity() use util_fits_cpu()
Qais Yousef <[email protected]>
sched/uclamp: Make select_idle_capacity() use util_fits_cpu()
Qais Yousef <[email protected]>
sched/uclamp: Fix fits_capacity() check in feec()
Qais Yousef <[email protected]>
sched/uclamp: Make task_fits_capacity() use util_fits_cpu()
John Harrison <[email protected]>
drm/i915: Don't use BAR mappings for ring buffers with LLC
Tao Liu <[email protected]>
skbuff: Fix nfct leak on napi stolen
Corey Minyard <[email protected]>
ipmi:watchdog: Set panic count to proper value on a panic
Yejune Deng <[email protected]>
ipmi/watchdog: replace atomic_add() and atomic_sub()
Li Jun <[email protected]>
media: rc: gpio-ir-recv: add remove function
Paul Elder <[email protected]>
media: ov5640: Fix analogue gain control
Masahiro Yamada <[email protected]>
scripts: handle BrokenPipeError for python scripts
Alvaro Karsz <[email protected]>
PCI: Avoid FLR for SolidRun SNET DPU rev 1
Alvaro Karsz <[email protected]>
PCI: Add SolidRun vendor ID
Nathan Chancellor <[email protected]>
macintosh: windfarm: Use unsigned type for 1-bit bitfields
Edward Humes <[email protected]>
alpha: fix R_ALPHA_LITERAL reloc for large modules
Rohan McLure <[email protected]>
powerpc/kcsan: Exclude udelay to prevent recursive instrumentation
Christophe Leroy <[email protected]>
powerpc: Check !irq instead of irq == NO_IRQ and remove NO_IRQ
xurui <[email protected]>
MIPS: Fix a compilation issue
Dmitry Baryshkov <[email protected]>
clk: qcom: mmcc-apq8084: remove spdm clocks
Yu Kuai <[email protected]>
block, bfq: fix uaf for bfqq in bic_set_bfqq()
Yu Kuai <[email protected]>
block, bfq: replace 0/1 with false/true in bic apis
NeilBrown <[email protected]>
block/bfq-iosched.c: use "false" rather than "BLK_RW_ASYNC"
Yu Kuai <[email protected]>
block, bfq: fix uaf for bfqq in bfq_exit_icq_bfqq
Yu Kuai <[email protected]>
block, bfq: fix possible uaf for 'bfqq->bic'
Morten Linderud <[email protected]>
tpm/eventlog: Don't abort tpm_read_log on faulty ACPI address
David Disseldorp <[email protected]>
watch_queue: fix IOC_WATCH_QUEUE_SET_SIZE alloc error paths
Krzysztof Kozlowski <[email protected]>
PCI/PM: Define pci_restore_standard_config() only for CONFIG_PM_SLEEP
Gavrilov Ilia <[email protected]>
iommu/amd: Add a length limitation for the ivrs_acpihid command-line parameter
Jan Kara <[email protected]>
ext4: Fix deadlock during directory rename
Conor Dooley <[email protected]>
RISC-V: Don't check text_mutex during stop_machine
Alexandre Ghiti <[email protected]>
riscv: Use READ_ONCE_NOCHECK in imprecise unwinding stack mode
Benjamin Coddington <[email protected]>
SUNRPC: Fix a server shutdown leak
D. Wythe <[email protected]>
net/smc: fix fallback failed while sendmsg with fastopen
Randy Dunlap <[email protected]>
platform: x86: MLX_PLATFORM: select REGMAP instead of depending on it
Chandrakanth Patil <[email protected]>
scsi: megaraid_sas: Update max supported LD IDs to 240
Daniel Golle <[email protected]>
net: ethernet: mtk_eth_soc: fix RX data corruption issue
Lorenz Bauer <[email protected]>
btf: fix resolving BTF_KIND_VAR after ARRAY, STRUCT, UNION, PTR
Florian Westphal <[email protected]>
netfilter: tproxy: fix deadlock due to missing BH disable
Ivan Delalande <[email protected]>
netfilter: ctnetlink: revert to dumping mark regardless of event type
Michael Chan <[email protected]>
bnxt_en: Avoid order-5 memory allocation for TPA data
Russell King (Oracle) <[email protected]>
net: phylib: get rid of unnecessary locking
Rongguang Wei <[email protected]>
net: stmmac: add to set device wake up flag when stmmac init phy
Shigeru Yoshida <[email protected]>
net: caif: Fix use-after-free in cfusbl_device_notify()
Yuiko Oshino <[email protected]>
net: lan78xx: fix accessing the LAN7800's internal phy specific registers from the MAC driver
Lee Jones <[email protected]>
net: usb: lan78xx: Remove lots of set but unused 'ret' variables
Hangbin Liu <[email protected]>
selftests: nft_nat: ensuring the listening side is up before starting the client
Eric Dumazet <[email protected]>
ila: do not generate empty messages in ila_xlat_nl_cmd_get_mapping()
Vladimir Oltean <[email protected]>
powerpc: dts: t1040rdb: fix compatible string for Rev A boards
Kang Chen <[email protected]>
nfc: fdp: add null check of devm_kmalloc_array in fdp_nci_i2c_read_device_properties
Rafał Miłecki <[email protected]>
bgmac: fix *initial* chip reset to support BCM5358
Dmitry Baryshkov <[email protected]>
drm/msm/a5xx: fix context faults during ring switch
Dmitry Baryshkov <[email protected]>
drm/msm/a5xx: fix the emptyness check in the preempt code
Rob Clark <[email protected]>
drm/msm: Document and rename preempt_lock
Dmitry Baryshkov <[email protected]>
drm/msm/a5xx: fix setting of the CP_PREEMPT_ENABLE_LOCAL register
Rob Clark <[email protected]>
drm/msm: Fix potential invalid ptr free
Jiri Slaby (SUSE) <[email protected]>
drm/nouveau/kms/nv50: fix nv50_wndw_new_ prototype
Ben Skeggs <[email protected]>
drm/nouveau/kms/nv50-: remove unused functions
Jan Kara <[email protected]>
ext4: Fix possible corruption when moving a directory
Bart Van Assche <[email protected]>
scsi: core: Remove the /proc/scsi/${proc_name} directory earlierLiao Chang <[email protected]>
riscv: Add header include guards to insn.h
Mattias Nissler <[email protected]>
riscv: Avoid enabling interrupts in die()
Palmer Dabbelt <[email protected]>
RISC-V: Avoid dereferening NULL regs in die()
Pierre Gondois <[email protected]>
arm64: efi: Make efi_rt_lock a raw_spinlock
Jacob Pan <[email protected]>
iommu/vt-d: Fix PASID directory pointer coherency
Lu Baolu <[email protected]>
iommu/vt-d: Fix lockdep splat in intel_pasid_get_entry()
Marc Zyngier <[email protected]>
irqdomain: Fix domain registration race
Bixuan Cui <[email protected]>
irqdomain: Change the type of 'size' in __irq_domain_add() to be consistent
Johan Hovold <[email protected]>
irqdomain: Fix mapping-creation race
Johan Hovold <[email protected]>
irqdomain: Refactor __irq_domain_alloc_irqs()
Johan Hovold <[email protected]>
irqdomain: Look for existing mapping only once
Ingo Molnar <[email protected]>
irq: Fix typos in comments
Jan Kara <[email protected]>
udf: Fix off-by-one error when discarding preallocation
Fedor Pchelkin <[email protected]>
nfc: change order inside nfc_se_io error path
Zhihao Cheng <[email protected]>
ext4: zero i_disksize when initializing the bootloader inode
Ye Bin <[email protected]>
ext4: fix WARNING in ext4_update_inline_data
Ye Bin <[email protected]>
ext4: move where set the MAY_INLINE_DATA flag is set
Darrick J. Wong <[email protected]>
ext4: fix another off-by-one fsmap error on 1k block filesystems
Eric Whitney <[email protected]>
ext4: fix RENAME_WHITEOUT handling for inline directories
Eric Biggers <[email protected]>
ext4: fix cgroup writeback accounting with fs-layer encryption
Harry Wentland <[email protected]>
drm/connector: print max_requested_bpc in state debugfs
Alex Deucher <[email protected]>
drm/amdgpu: fix error checking in amdgpu_read_mm_registers for soc15
Andrew Cooper <[email protected]>
x86/CPU/AMD: Disable XSAVES on AMD family 0x17
Tobias Klauser <[email protected]>
fork: allow CLONE_NEWTIME in clone3 flags
Theodore Ts'o <[email protected]>
fs: prevent out-of-bounds array speculation when closing a file descriptor
-------------
Diffstat:
Makefile | 4 +- arch/alpha/kernel/module.c | 4 +- arch/arm64/include/asm/efi.h | 6 +- arch/arm64/kernel/efi.c | 2 +- arch/mips/include/asm/mach-rc32434/pci.h | 2 +- arch/powerpc/boot/dts/fsl/t1040rdb-rev-a.dts | 1 - arch/powerpc/include/asm/irq.h | 3 - arch/powerpc/kernel/time.c | 4 +- arch/powerpc/kernel/vmlinux.lds.S | 6 +- arch/powerpc/platforms/44x/fsp2.c | 2 +- arch/riscv/include/asm/ftrace.h | 2 +- arch/riscv/include/asm/parse_asm.h | 5 + arch/riscv/include/asm/patch.h | 2 + arch/riscv/kernel/ftrace.c | 14 +- arch/riscv/kernel/patch.c | 28 ++- arch/riscv/kernel/stacktrace.c | 2 +- arch/riscv/kernel/traps.c | 14 +- arch/s390/kernel/vmlinux.lds.S | 2 + arch/sh/kernel/vmlinux.lds.S | 1 + arch/um/kernel/vmlinux.lds.S | 2 +- arch/x86/kernel/cpu/amd.c | 9 + arch/x86/kvm/vmx/evmcs.h | 11 - arch/x86/kvm/vmx/vmx.c | 44 ++-- block/bfq-cgroup.c | 8 +- block/bfq-iosched.c | 19 +- drivers/char/ipmi/ipmi_watchdog.c | 8 +- drivers/char/tpm/eventlog/acpi.c | 6 +- drivers/clk/qcom/mmcc-apq8084.c | 271 ---------------------- drivers/gpu/drm/amd/amdgpu/soc15.c | 5 +- drivers/gpu/drm/drm_atomic.c | 1 + drivers/gpu/drm/i915/gt/intel_ring.c | 4 +- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 8 +- drivers/gpu/drm/msm/adreno/a5xx_preempt.c | 16 +- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 4 +- drivers/gpu/drm/msm/msm_gem_submit.c | 5 +- drivers/gpu/drm/msm/msm_ringbuffer.c | 2 +- drivers/gpu/drm/msm/msm_ringbuffer.h | 7 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 16 -- drivers/gpu/drm/nouveau/dispnv50/wndw.c | 12 - drivers/gpu/drm/nouveau/dispnv50/wndw.h | 7 +- drivers/iommu/amd/init.c | 16 +- drivers/iommu/intel/pasid.c | 28 ++- drivers/irqchip/irq-aspeed-vic.c | 4 +- drivers/irqchip/irq-bcm7120-l2.c | 2 +- drivers/irqchip/irq-csky-apb-intc.c | 2 +- drivers/irqchip/irq-gic-v2m.c | 2 +- drivers/irqchip/irq-gic-v3-its.c | 10 +- drivers/irqchip/irq-gic-v3.c | 2 +- drivers/irqchip/irq-loongson-pch-pic.c | 2 +- drivers/irqchip/irq-meson-gpio.c | 2 +- drivers/irqchip/irq-mtk-cirq.c | 2 +- drivers/irqchip/irq-mxs.c | 4 +- drivers/irqchip/irq-sun4i.c | 2 +- drivers/irqchip/irq-ti-sci-inta.c | 2 +- drivers/irqchip/irq-vic.c | 4 +- drivers/irqchip/irq-xilinx-intc.c | 2 +- drivers/macintosh/windfarm_lm75_sensor.c | 4 +- drivers/macintosh/windfarm_smu_sensors.c | 4 +- drivers/media/i2c/ov5640.c | 2 +- drivers/media/rc/gpio-ir-recv.c | 18 ++ drivers/net/ethernet/broadcom/bgmac.c | 8 +- drivers/net/ethernet/broadcom/bgmac.h | 2 + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 23 +- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3 +- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 1 + drivers/net/phy/microchip.c | 32 +++ drivers/net/phy/phy_device.c | 8 +- drivers/net/usb/lan78xx.c | 189 ++++++--------- drivers/nfc/fdp/i2c.c | 4 + drivers/pci/pci-driver.c | 17 +- drivers/pci/quirks.c | 8 + drivers/platform/x86/Kconfig | 3 +- drivers/s390/block/dasd_diag.c | 7 +- drivers/s390/block/dasd_fba.c | 7 +- drivers/s390/block/dasd_int.h | 1 - drivers/scsi/hosts.c | 2 + drivers/scsi/megaraid/megaraid_sas.h | 2 + drivers/scsi/megaraid/megaraid_sas_fp.c | 2 +- fs/ext4/block_validity.c | 26 ++- fs/ext4/ext4.h | 3 + fs/ext4/fsmap.c | 2 + fs/ext4/inline.c | 1 - fs/ext4/inode.c | 7 +- fs/ext4/ioctl.c | 1 + fs/ext4/mballoc.c | 205 +++++++++------- fs/ext4/namei.c | 36 ++- fs/ext4/page-io.c | 11 +- fs/ext4/xattr.c | 3 + fs/file.c | 1 + fs/udf/inode.c | 2 +- include/asm-generic/vmlinux.lds.h | 5 + include/linux/irq.h | 4 +- include/linux/irqdesc.h | 2 +- include/linux/irqdomain.h | 2 +- include/linux/pci_ids.h | 2 + include/net/netfilter/nf_tproxy.h | 7 + kernel/bpf/btf.c | 1 + kernel/fork.c | 2 +- kernel/irq/chip.c | 2 +- kernel/irq/dummychip.c | 2 +- kernel/irq/irqdesc.c | 2 +- kernel/irq/irqdomain.c | 262 +++++++++++++-------- kernel/irq/manage.c | 6 +- kernel/irq/msi.c | 2 +- kernel/irq/timings.c | 2 +- kernel/sched/core.c | 10 +- kernel/sched/fair.c | 183 ++++++++++++--- kernel/sched/sched.h | 70 +++++- kernel/watch_queue.c | 1 + net/caif/caif_usb.c | 3 + net/core/dev.c | 1 + net/core/skbuff.c | 1 - net/ipv4/netfilter/nf_tproxy_ipv4.c | 2 +- net/ipv6/ila/ila_xlat.c | 1 + net/ipv6/netfilter/nf_tproxy_ipv6.c | 2 +- net/netfilter/nf_conntrack_netlink.c | 14 +- net/nfc/netlink.c | 2 +- net/smc/af_smc.c | 13 +- net/sunrpc/svc.c | 6 +- scripts/checkkconfigsymbols.py | 13 +- scripts/clang-tools/run-clang-tools.py | 21 +- scripts/diffconfig | 16 +- tools/testing/selftests/netfilter/nft_nat.sh | 2 + 124 files changed, 1093 insertions(+), 872 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/104 fs: prevent out-of-bounds array speculation when closing a file descriptor
From: Theodore Ts'o <[email protected]>
commit 609d54441493c99f21c1823dfd66fa7f4c512ff4 upstream.
Google-Bug-Id: 114199369
--- fs/file.c | 1 + 1 file changed, 1 insertion(+)
fs/file.c +1 -0
@@ -677,6 +677,7 @@ static struct file *pick_file(struct fil fdt =files_fdtable (files);if (fd >= fdt->max_fds) goto out_unlock; + fd =array_index_nospec (fd, fdt->max_fds); file = fdt->fd[fd];if (!file) goto out_unlock;
Greg Kroah-Hartman
maintainerPATCH 2/104 fork: allow CLONE_NEWTIME in clone3 flags
In reply to Greg Kroah-HartmanFrom: Tobias Klauser <[email protected]>
commit a402f1e35313fc7ce2ca60f543c4402c2c7c3544 upstream.
Currently, calling clone3() with CLONE_NEWTIME in clone_args->flags fails with -EINVAL. This is because CLONE_NEWTIME intersects with CSIGNAL. However, CSIGNAL was deprecated when clone3 was introduced in commit 7f192e3cd316 ("fork: add clone3"), allowing re-use of that part of clone flags.
Fix this by explicitly allowing CLONE_NEWTIME in clone3_args_valid. This is also in line with the respective check in check_unshare_flags which allow CLONE_NEWTIME for unshare().
--- kernel/fork.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/fork.c +1 -1
@@ -2726,7 +2726,7 @@ static bool clone3_args_valid(struct ker* - make the CLONE_DETACHED bit reuseable for clone3 * - make the CSIGNAL bits reuseable for clone3 */ -if (kargs->flags & (CLONE_DETACHED |CSIGNAL )) +if (kargs->flags & (CLONE_DETACHED | (CSIGNAL & (~CLONE_NEWTIME ))))return false; if ((kargs->flags & (CLONE_SIGHAND | CLONE_CLEAR_SIGHAND)) ==
Greg Kroah-Hartman
maintainerPATCH 3/104 x86/CPU/AMD: Disable XSAVES on AMD family 0x17
In reply to Greg Kroah-HartmanFrom: Andrew Cooper <[email protected]>
commit b0563468eeac88ebc70559d52a0b66efc37e4e9d upstream.
AMD Erratum 1386 is summarised as:
XSAVES Instruction May Fail to Save XMM Registers to the Provided State Save Area
This piece of accidental chronomancy causes the %xmm registers to occasionally reset back to an older value.
Ignore the XSAVES feature on all AMD Zen1/2 hardware. The XSAVEC instruction (which works fine) is equivalent on affected parts.
[ bp: Typos, move it into the F17h-specific function. ]
--- arch/x86/kernel/cpu/amd.c | 9 +++++++++ 1 file changed, 9 insertions(+)
arch/x86/kernel/cpu/amd.c +9 -0
@@ -932,6 +932,15 @@ void init_spectral_chicken(struct cpuinf } }#endif +/* +* Work around Erratum 1386. The XSAVES instruction malfunctions in +* certain circumstances on Zen1/2 uarch, and not all parts have had +* updated microcode at the time of writing (March 2023). +* +* Affected parts all have no supervisor XSAVE states, meaning that +* the XSAVEC instruction (which works fine) is equivalent. +*/ +clear_cpu_cap (c,X86_FEATURE_XSAVES ); }static void init_amd_zn (struct cpuinfo_x86 *c)
Greg Kroah-Hartman
maintainerPATCH 4/104 drm/amdgpu: fix error checking in amdgpu_read_mm_registers for soc15
In reply to Greg Kroah-HartmanFrom: Alex Deucher <[email protected]>
commit 0dcdf8498eae2727bb33cef3576991dc841d4343 upstream.
Properly skip non-existent registers as well.
--- drivers/gpu/drm/amd/amdgpu/soc15.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/amdgpu/soc15.c +3 -2
@@ -382,8 +382,9 @@ static int soc15_read_register(struct am *value =0 ;for (i =0 ; i <ARRAY_SIZE (soc15_allowed_read_registers); i++) { en = &soc15_allowed_read_registers[i]; -if (adev->reg_offset[en->hwip][en->inst] && - reg_offset != (adev->reg_offset[en->hwip][en->inst][en->seg] +if (!adev->reg_offset[en->hwip][en->inst]) +continue ; +else if (reg_offset != (adev->reg_offset[en->hwip][en->inst][en->seg] + en->reg_offset))continue ;
Greg Kroah-Hartman
maintainerPATCH 5/104 drm/connector: print max_requested_bpc in state debugfs
In reply to Greg Kroah-HartmanFrom: Harry Wentland <[email protected]>
commit 7d386975f6a495902e679a3a250a7456d7e54765 upstream.
This is useful to understand the bpc defaults and
support of a driver.
--- drivers/gpu/drm/drm_atomic.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/drm_atomic.c +1 -0
@@ -1010,6 +1010,7 @@ static void drm_atomic_connector_print_sdrm_printf (p,"connector[%u]: %s\n" , connector->base.id, connector->name);drm_printf (p,"\tcrtc=%s\n" , state->crtc ? state->crtc->name :"(null)" );drm_printf (p,"\tself_refresh_aware=%d\n" , state->self_refresh_aware); +drm_printf (p,"\tmax_requested_bpc=%d\n" , state->max_requested_bpc);if (connector->connector_type ==DRM_MODE_CONNECTOR_WRITEBACK )if (state->writeback_job && state->writeback_job->fb)
Greg Kroah-Hartman
maintainerPATCH 6/104 ext4: fix cgroup writeback accounting with fs-layer encryption
In reply to Greg Kroah-HartmanFrom: Eric Biggers <[email protected]>
commit ffec85d53d0f39ee4680a2cf0795255e000e1feb upstream.
When writing a page from an encrypted file that is using filesystem-layer encryption (not inline encryption), ext4 encrypts the pagecache page into a bounce page, then writes the bounce page.
It also passes the bounce page to wbc_account_cgroup_owner(). That's incorrect, because the bounce page is a newly allocated temporary page that doesn't have the memory cgroup of the original pagecache page. This makes wbc_account_cgroup_owner() not account the I/O to the owner of the pagecache page as it should.
Fix this by always passing the pagecache page towbc_account_cgroup_owner().
--- fs/ext4/page-io.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
fs/ext4/page-io.c +6 -5
@@ -416,7 +416,8 @@ static void io_submit_init_bio(struct exstatic void io_submit_add_bh (struct ext4_io_submit *io,struct inode *inode, -struct page *page, +struct page *pagecache_page, +struct page *bounce_page,struct buffer_head *bh) {int ret;
@@ -430,10 +431,11 @@ submit_and_retry:io_submit_init_bio (io, bh); io->io_bio->bi_write_hint = inode->i_write_hint; } - ret =bio_add_page (io->io_bio, page, bh->b_size,bh_offset (bh)); + ret =bio_add_page (io->io_bio, bounce_page ?: pagecache_page, + bh->b_size,bh_offset (bh));if (ret != bh->b_size) goto submit_and_retry; -wbc_account_cgroup_owner (io->io_wbc, page, bh->b_size); +wbc_account_cgroup_owner (io->io_wbc, pagecache_page, bh->b_size); io->io_next_block++; }
@@ -551,8 +553,7 @@ int ext4_bio_write_page(struct ext4_io_sdo {if (!buffer_async_write (bh))continue ; -io_submit_add_bh (io, inode, - bounce_page ? bounce_page : page, bh); +io_submit_add_bh (io, inode, page, bounce_page, bh); nr_submitted++;clear_buffer_dirty (bh); }while ((bh = bh->b_this_page) != head);
Greg Kroah-Hartman
maintainerPATCH 7/104 ext4: fix RENAME_WHITEOUT handling for inline directories
In reply to Greg Kroah-HartmanFrom: Eric Whitney <[email protected]>
commit c9f62c8b2dbf7240536c0cc9a4529397bb8bf38e upstream.
A significant number of xfstests can cause ext4 to log one or more warning messages when they are run on a test file system where the inline_data feature has been enabled. An example:
"EXT4-fs warning (device vdc): ext4_dirblock_csum_set:425: inode
#16385: comm fsstress: No space for directory leaf checksum. Please
run e2fsck -D."
The xfstests include: ext4/057, 058, and 307; generic/013, 051, 068, 070, 076, 078, 083, 232, 269, 270, 390, 461, 475, 476, 482, 579, 585, 589, 626, 631, and 650.
In this situation, the warning message indicates a bug in the code that performs the RENAME_WHITEOUT operation on a directory entry that has been stored inline. It doesn't detect that the directory is stored inline, and incorrectly attempts to compute a dirent block checksum on the whiteout inode when creating it. This attempt fails as a result of the integrity checking in get_dirent_tail (usually due to a failure to match the EXT4_FT_DIR_CSUM magic cookie), and the warning message is then emitted.
Fix this by simply collecting the inlined data state at the time the search for the source directory entry is performed. Existing code handles the rest, and this is sufficient to eliminate all spurious warning messages produced by the tests above. Go one step further and do the same in the code that resets the source directory entry in the event of failure. The inlined state should be present in the "old" struct, but given the possibility of a race there's no harm in taking a conservative approach and getting that information again since the directory entry is being reread anyway.
--- fs/ext4/namei.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
fs/ext4/namei.c +7 -6
@@ -1512,11 +1512,10 @@ static struct buffer_head *__ext4_find_eint has_inline_data =1 ; ret =ext4_find_inline_entry (dir, fname, res_dir, &has_inline_data); -if (has_inline_data) { -if (inlined) - *inlined =1 ; +if (inlined) + *inlined = has_inline_data; +if (has_inline_data) goto cleanup_and_exit; - } } if ((namelen <= 2) && (name[0] == '.') &&
@@ -3698,7 +3697,8 @@ static void ext4_resetent(handle_t *hand* so the old->de may no longer valid and need to find it again * before reset old inode info. */ - old.bh =ext4_find_entry (old.dir, &old.dentry->d_name, &old.de,NULL ); + old.bh =ext4_find_entry (old.dir, &old.dentry->d_name, &old.de, + &old.inlined);if (IS_ERR (old.bh)) retval =PTR_ERR (old.bh);if (!old.bh)
@@ -3863,7 +3863,8 @@ static int ext4_rename(struct inode *oldreturn retval; } - old.bh =ext4_find_entry (old.dir, &old.dentry->d_name, &old.de,NULL ); + old.bh =ext4_find_entry (old.dir, &old.dentry->d_name, &old.de, + &old.inlined);if (IS_ERR (old.bh))return PTR_ERR (old.bh);/*
Greg Kroah-Hartman
maintainerPATCH 8/104 ext4: fix another off-by-one fsmap error on 1k block filesystems
In reply to Greg Kroah-HartmanFrom: Darrick J. Wong <[email protected]>
commit c993799baf9c5861f8df91beb80e1611b12efcbd upstream.
Apparently syzbot figured out that issuing this FSMAP call:
struct fsmap_head cmd = {
.fmh_count = ...;
.fmh_keys = {
{ .fmr_device = /* ext4 dev */, .fmr_physical = 0, },
{ .fmr_device = /* ext4 dev */, .fmr_physical = 0, },
},...
};
ret = ioctl(fd, FS_IOC_GETFSMAP, &cmd);
Produces this crash if the underlying filesystem is a 1k-block ext4 filesystem:
kernel BUG at fs/ext4/ext4.h:3331!
invalid opcode: 0000 [#1] PREEMPT SMP
CPU: 3 PID: 3227965 Comm: xfs_io Tainted: G W O 6.2.0-rc8-achx Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.15.0-1 04/01/2014 RIP: 0010:ext4_mb_load_buddy_gfp+0x47c/0x570 [ext4] RSP: 0018:ffffc90007c03998 EFLAGS: 00010246 RAX: ffff888004978000 RBX: ffffc90007c03a20 RCX: ffff888041618000 RDX: 0000000000000000 RSI: 00000000000005a4 RDI: ffffffffa0c99b11 RBP: ffff888012330000 R08: ffffffffa0c2b7d0 R09: 0000000000000400 R10: ffffc90007c03950 R11: 0000000000000000 R12: 0000000000000001 R13: 00000000ffffffff R14: 0000000000000c40 R15: ffff88802678c398 FS: 00007fdf2020c880(0000) GS:ffff88807e100000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007ffd318a5fe8 CR3: 000000007f80f001 CR4: 00000000001706e0 Call Trace: <TASK> ext4_mballoc_query_range+0x4b/0x210 [ext4 dfa189daddffe8fecd3cdfd00564e0f265a8ab80] ext4_getfsmap_datadev+0x713/0x890 [ext4 dfa189daddffe8fecd3cdfd00564e0f265a8ab80] ext4_getfsmap+0x2b7/0x330 [ext4 dfa189daddffe8fecd3cdfd00564e0f265a8ab80] ext4_ioc_getfsmap+0x153/0x2b0 [ext4 dfa189daddffe8fecd3cdfd00564e0f265a8ab80] __ext4_ioctl+0x2a7/0x17e0 [ext4 dfa189daddffe8fecd3cdfd00564e0f265a8ab80] __x64_sys_ioctl+0x82/0xa0 do_syscall_64+0x2b/0x80 entry_SYSCALL_64_after_hwframe+0x46/0xb0 RIP: 0033:0x7fdf20558aff RSP: 002b:00007ffd318a9e30 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 RAX: ffffffffffffffda RBX: 00000000000200c0 RCX: 00007fdf20558aff RDX: 00007fdf1feb2010 RSI: 00000000c0c0583b RDI: 0000000000000003 RBP: 00005625c0634be0 R08: 00005625c0634c40 R09: 0000000000000001 R10: 0000000000000000 R11: 0000000000000246 R12: 00007fdf1feb2010 R13: 00005625be70d994 R14: 0000000000000800 R15: 0000000000000000
For GETFSMAP calls, the caller selects a physical block device by writing its block number into fsmap_head.fmh_keys[01].fmr_device. To query mappings for a subrange of the device, the starting byte of the range is written to fsmap_head.fmh_keys[0].fmr_physical and the last byte of the range goes in fsmap_head.fmh_keys[1].fmr_physical.
IOWs, to query what mappings overlap with bytes 3-14 of /dev/sda, you'd set the inputs as follows:
fmh_keys[0] = { .fmr_device = major(8, 0), .fmr_physical = 3},
fmh_keys[1] = { .fmr_device = major(8, 0), .fmr_physical = 14},Which would return you whatever is mapped in the 12 bytes starting at physical offset 3.
The crash is due to insufficient range validation of keys[1] in ext4_getfsmap_datadev. On 1k-block filesystems, block 0 is not part of the filesystem, which means that s_first_data_block is nonzero. ext4_get_group_no_and_offset subtracts this quantity from the blocknr argument before cracking it into a group number and a block number within a group. IOWs, block group 0 spans blocks 1-8192 (1-based) instead of 0-8191 (0-based) like what happens with larger blocksizes.
The net result of this encoding is that blocknr < s_first_data_block is not a valid input to this function. The end_fsb variable is set from the keys that are copied from userspace, which means that in the above example, its value is zero. That leads to an underflow here:
blocknr = blocknr - le32_to_cpu(es->s_first_data_block);
The division then operates on -1:
offset = do_div(blocknr, EXT4_BLOCKS_PER_GROUP(sb)) >> EXT4_SB(sb)->s_cluster_bits;
Leaving an impossibly large group number (2^32-1) in blocknr. ext4_getfsmap_check_keys checked that keys[0].fmr_physical and keys[1].fmr_physical are in increasing order, but ext4_getfsmap_datadev adjusts keys[0].fmr_physical to be at least s_first_data_block. This implies that we have to check it again after the adjustment, which is the piece that I forgot.
--- fs/ext4/fsmap.c | 2 ++ 1 file changed, 2 insertions(+)
fs/ext4/fsmap.c +2 -0
@@ -486,6 +486,8 @@ static int ext4_getfsmap_datadev(struct keys[0 ].fmr_physical = bofs;if (keys[1 ].fmr_physical >= eofs) keys[1 ].fmr_physical = eofs -1 ; +if (keys[1 ].fmr_physical < keys[0 ].fmr_physical) +return 0 ; start_fsb = keys[0 ].fmr_physical; end_fsb = keys[1 ].fmr_physical;
Greg Kroah-Hartman
maintainerPATCH 9/104 ext4: move where set the MAY_INLINE_DATA flag is set
In reply to Greg Kroah-HartmanFrom: Ye Bin <[email protected]>
commit 1dcdce5919115a471bf4921a57f20050c545a236 upstream.
The only caller of ext4_find_inline_data_nolock() that needs setting of EXT4_STATE_MAY_INLINE_DATA flag is ext4_iget_extra_inode(). In ext4_write_inline_data_end() we just need to update inode->i_inline_off. Since we are going to add one more caller that does not need to set EXT4_STATE_MAY_INLINE_DATA, just move setting of EXT4_STATE_MAY_INLINE_DATA out to ext4_iget_extra_inode().
--- fs/ext4/inline.c | 1 - fs/ext4/inode.c | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-)
fs/ext4/inline.c +0 -1
@@ -157,7 +157,6 @@ int ext4_find_inline_data_nolock(struct (void *)ext4_raw_inode(&is.iloc));EXT4_I (inode)->i_inline_size =EXT4_MIN_INLINE_DATA_SIZE +le32_to_cpu (is.s.here->e_value_size); -ext4_set_inode_state (inode,EXT4_STATE_MAY_INLINE_DATA ); } out:brelse (is.iloc.bh);
fs/ext4/inode.c +6 -1
@@ -4639,8 +4639,13 @@ static inline int ext4_iget_extra_inode(if (EXT4_INODE_HAS_XATTR_SPACE (inode) && *magic ==cpu_to_le32 (EXT4_XATTR_MAGIC )) { +int err; +ext4_set_inode_state (inode,EXT4_STATE_XATTR ); -return ext4_find_inline_data_nolock (inode); + err =ext4_find_inline_data_nolock (inode); +if (!err &&ext4_has_inline_data (inode)) +ext4_set_inode_state (inode,EXT4_STATE_MAY_INLINE_DATA ); +return err; }else EXT4_I (inode)->i_inline_off =0 ;return 0 ;
Greg Kroah-Hartman
maintainerPATCH 10/104 ext4: fix WARNING in ext4_update_inline_data
In reply to Greg Kroah-HartmanFrom: Ye Bin <[email protected]>
commit 2b96b4a5d9443ca4cad58b0040be455803c05a42 upstream.
Syzbot found the following issue:
EXT4-fs (loop0): mounted filesystem 00000000-0000-0000-0000-000000000000 without journal. Quota mode: none.
fscrypt: AES-256-CTS-CBC using implementation "cts-cbc-aes-aesni"
fscrypt: AES-256-XTS using implementation "xts-aes-aesni"
------------[ cut here ]------------ WARNING: CPU: 0 PID: 5071 at mm/page_alloc.c:5525 __alloc_pages+0x30a/0x560 mm/page_alloc.c:5525 Modules linked in: CPU: 1 PID: 5071 Comm: syz-executor263 Not tainted 6.2.0-rc1-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022 RIP: 0010:__alloc_pages+0x30a/0x560 mm/page_alloc.c:5525 RSP: 0018:ffffc90003c2f1c0 EFLAGS: 00010246 RAX: ffffc90003c2f220 RBX: 0000000000000014 RCX: 0000000000000000 RDX: 0000000000000028 RSI: 0000000000000000 RDI: ffffc90003c2f248 RBP: ffffc90003c2f2d8 R08: dffffc0000000000 R09: ffffc90003c2f220 R10: fffff52000785e49 R11: 1ffff92000785e44 R12: 0000000000040d40 R13: 1ffff92000785e40 R14: dffffc0000000000 R15: 1ffff92000785e3c FS: 0000555556c0d300(0000) GS:ffff8880b9800000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f95d5e04138 CR3: 00000000793aa000 CR4: 00000000003506f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: <TASK> __alloc_pages_node include/linux/gfp.h:237 [inline] alloc_pages_node include/linux/gfp.h:260 [inline] __kmalloc_large_node+0x95/0x1e0 mm/slab_common.c:1113 __do_kmalloc_node mm/slab_common.c:956 [inline] __kmalloc+0xfe/0x190 mm/slab_common.c:981 kmalloc include/linux/slab.h:584 [inline] kzalloc include/linux/slab.h:720 [inline] ext4_update_inline_data+0x236/0x6b0 fs/ext4/inline.c:346 ext4_update_inline_dir fs/ext4/inline.c:1115 [inline] ext4_try_add_inline_entry+0x328/0x990 fs/ext4/inline.c:1307 ext4_add_entry+0x5a4/0xeb0 fs/ext4/namei.c:2385 ext4_add_nondir+0x96/0x260 fs/ext4/namei.c:2772 ext4_create+0x36c/0x560 fs/ext4/namei.c:2817 lookup_open fs/namei.c:3413 [inline] open_last_lookups fs/namei.c:3481 [inline] path_openat+0x12ac/0x2dd0 fs/namei.c:3711 do_filp_open+0x264/0x4f0 fs/namei.c:3741 do_sys_openat2+0x124/0x4e0 fs/open.c:1310 do_sys_open fs/open.c:1326 [inline] __do_sys_openat fs/open.c:1342 [inline] __se_sys_openat fs/open.c:1337 [inline] __x64_sys_openat+0x243/0x290 fs/open.c:1337 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x3d/0xb0 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x63/0xcd
Above issue happens as follows:ext4_iget
ext4_find_inline_data_nolock ->i_inline_off=164 i_inline_size=60ext4_try_add_inline_entry
__ext4_mark_inode_dirty
ext4_expand_extra_isize_ea ->i_extra_isize=32 s_want_extra_isize=44
ext4_xattr_shift_entries
->after shift i_inline_off is incorrect, actually is change to 176
ext4_try_add_inline_entry
ext4_update_inline_dir
get_max_inline_xattr_value_size
if (EXT4_I(inode)->i_inline_off)
entry = (struct ext4_xattr_entry *)((void *)raw_inode +
EXT4_I(inode)->i_inline_off);
free += EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size));
->As entry is incorrect, then 'free' may be negative
ext4_update_inline_data
value = kzalloc(len, GFP_NOFS);
-> len is unsigned int, maybe very large, then trigger warning when
'kzalloc()'To resolve the above issue we need to update 'i_inline_off' after 'ext4_xattr_shift_entries()'. We do not need to set EXT4_STATE_MAY_INLINE_DATA flag here, since ext4_mark_inode_dirty() already sets this flag if needed. Setting EXT4_STATE_MAY_INLINE_DATA when it is needed may trigger a BUG_ON in ext4_writepages().
--- fs/ext4/xattr.c | 3 +++ 1 file changed, 3 insertions(+)
fs/ext4/xattr.c +3 -0
@@ -2804,6 +2804,9 @@ shift: (void *)header, total_ino);EXT4_I (inode)->i_extra_isize = new_extra_isize; +if (ext4_has_inline_data (inode)) + error =ext4_find_inline_data_nolock (inode); + cleanup:if (error && (mnt_count !=le16_to_cpu (sbi->s_es->s_mnt_count))) { ext4_warning(inode->i_sb, "Unable to expand inode %lu. Delete some EAs or run e2fsck.",
Greg Kroah-Hartman
maintainerPATCH 11/104 ext4: zero i_disksize when initializing the bootloader inode
In reply to Greg Kroah-HartmanFrom: Zhihao Cheng <[email protected]>
commit f5361da1e60d54ec81346aee8e3d8baf1be0b762 upstream.
If the boot loader inode has never been used before, the EXT4_IOC_SWAP_BOOT inode will initialize it, including setting the i_size to 0. However, if the "never before used" boot loader has a non-zero i_size, then i_disksize will be non-zero, and the inconsistency between i_size and i_disksize can trigger a kernel warning:
WARNING: CPU: 0 PID: 2580 at fs/ext4/file.c:319 CPU: 0 PID: 2580 Comm: bb Not tainted 6.3.0-rc1-00004-g703695902cfa RIP: 0010:ext4_file_write_iter+0xbc7/0xd10 Call Trace: vfs_write+0x3b1/0x5c0 ksys_write+0x77/0x160 __x64_sys_write+0x22/0x30 do_syscall_64+0x39/0x80
Reproducer:
1. create corrupted image and mount it:
mke2fs -t ext4 /tmp/foo.img 200
debugfs -wR "sif <5> size 25700" /tmp/foo.img
mount -t ext4 /tmp/foo.img /mnt
cd /mnt
echo 123 > file
2. Run the reproducer program:
posix_memalign(&buf, 1024, 1024)
fd = open("file", O_RDWR | O_DIRECT);
ioctl(fd, EXT4_IOC_SWAP_BOOT);
write(fd, buf, 1024);Fix this by setting i_disksize as well as i_size to zero when initiaizing the boot loader inode.
--- fs/ext4/ioctl.c | 1 + 1 file changed, 1 insertion(+)
fs/ext4/ioctl.c +1 -0
@@ -180,6 +180,7 @@ static long swap_inode_boot_loader(struc ei_bl->i_flags =0 ;inode_set_iversion (inode_bl,1 );i_size_write (inode_bl,0 ); +EXT4_I (inode_bl)->i_disksize = inode_bl->i_size; inode_bl->i_mode =S_IFREG ;if (ext4_has_feature_extents (sb)) {ext4_set_inode_flag (inode_bl,EXT4_INODE_EXTENTS );
Greg Kroah-Hartman
maintainerPATCH 12/104 nfc: change order inside nfc_se_io error path
In reply to Greg Kroah-HartmanFrom: Fedor Pchelkin <[email protected]>
commit 7d834b4d1ab66c48e8c0810fdeadaabb80fa2c81 upstream.
cb_context should be freed on the error path in nfc_se_io as stated by commit 25ff6f8a5a3b ("nfc: fix memory leak of se_io context in nfc_genl_se_io").
Make the error path in nfc_se_io unwind everything in reverse order, i.e. free the cb_context after unlocking the device.
--- net/nfc/netlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/nfc/netlink.c +1 -1
@@ -1446,8 +1446,8 @@ static int nfc_se_io(struct nfc_dev *devreturn rc; error: -kfree (cb_context);device_unlock (&dev->dev); +kfree (cb_context);return rc; }
Greg Kroah-Hartman
maintainerPATCH 13/104 udf: Fix off-by-one error when discarding preallocation
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
[ Upstream commit f54aa97fb7e5329a373f9df4e5e213ced4fc8759 ]
The condition determining whether the preallocation can be used had an off-by-one error so we didn't discard preallocation when new allocation was just following it. This can then confuse code in inode_getblk().
--- fs/udf/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/udf/inode.c +1 -1
@@ -442,7 +442,7 @@ static int udf_get_block(struct inode *inode, sector_t block,* Block beyond EOF and prealloc extents? Just discard preallocation * as it is not useful and complicates things. */ -if (((loff_t )block) << inode->i_blkbits > iinfo->i_lenExtents) +if (((loff_t )block) << inode->i_blkbits >= iinfo->i_lenExtents)udf_discard_prealloc (inode);udf_clear_extent_cache (inode); phys =inode_getblk (inode, block, &err, &new);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 14/104 irq: Fix typos in comments
In reply to Greg Kroah-HartmanFrom: Ingo Molnar <[email protected]>
[ Upstream commit a359f757965aafd0f58570de95dc6bc06cf12a9c ]
Fix ~36 single-word typos in the IRQ, irqchip and irqdomain code comments.
Stable-dep-of: 6e6f75c9c98d ("irqdomain: Look for existing mapping only once")
--- drivers/irqchip/irq-aspeed-vic.c | 4 ++-- drivers/irqchip/irq-bcm7120-l2.c | 2 +- drivers/irqchip/irq-csky-apb-intc.c | 2 +- drivers/irqchip/irq-gic-v2m.c | 2 +- drivers/irqchip/irq-gic-v3-its.c | 10 +++++----- drivers/irqchip/irq-gic-v3.c | 2 +- drivers/irqchip/irq-loongson-pch-pic.c | 2 +- drivers/irqchip/irq-meson-gpio.c | 2 +- drivers/irqchip/irq-mtk-cirq.c | 2 +- drivers/irqchip/irq-mxs.c | 4 ++-- drivers/irqchip/irq-sun4i.c | 2 +- drivers/irqchip/irq-ti-sci-inta.c | 2 +- drivers/irqchip/irq-vic.c | 4 ++-- drivers/irqchip/irq-xilinx-intc.c | 2 +- include/linux/irq.h | 4 ++-- include/linux/irqdesc.h | 2 +- kernel/irq/chip.c | 2 +- kernel/irq/dummychip.c | 2 +- kernel/irq/irqdesc.c | 2 +- kernel/irq/irqdomain.c | 8 ++++---- kernel/irq/manage.c | 6 +++--- kernel/irq/msi.c | 2 +- kernel/irq/timings.c | 2 +- 23 files changed, 36 insertions(+), 36 deletions(-)
drivers/irqchip/irq-aspeed-vic.c +2 -2
@@ -71,7 +71,7 @@ static void vic_init_hw(struct aspeed_vic *vic)writel (0 , vic->base +AVIC_INT_SELECT );writel (0 , vic->base +AVIC_INT_SELECT +4 ); -/* Some interrupts have a programable high/low level trigger +/* Some interrupts have a programmable high/low level trigger * (4 GPIO direct inputs), for now we assume this was configured * by firmware. We read which ones are edge now. */
@@ -203,7 +203,7 @@ static int __init avic_of_init(struct device_node *node, } vic->base = regs; -/* Initialize soures, all masked */ +/* Initialize sources, all masked */ vic_init_hw (vic);/* Ready to receive interrupts */
drivers/irqchip/irq-bcm7120-l2.c +1 -1
@@ -310,7 +310,7 @@ static int __init bcm7120_l2_intc_probe(struct device_node *dn,if (data->can_wake) {/* This IRQ chip can wake the system, set all -* relevant child interupts in wake_enabled mask +* relevant child interrupts in wake_enabled mask */ gc->wake_enabled =0xffffffff ; gc->wake_enabled &= ~gc->unused;
drivers/irqchip/irq-csky-apb-intc.c +1 -1
@@ -176,7 +176,7 @@ gx_intc_init(struct device_node *node, struct device_node *parent)writel (0x0 , reg_base +GX_INTC_NEN63_32 );/* -* Initial mask reg with all unmasked, because we only use enalbe reg +* Initial mask reg with all unmasked, because we only use enable reg */ writel (0x0 , reg_base +GX_INTC_NMASK31_00 );writel (0x0 , reg_base +GX_INTC_NMASK63_32 );
drivers/irqchip/irq-gic-v2m.c +1 -1
@@ -371,7 +371,7 @@ static int __init gicv2m_init_one(struct fwnode_handle *fwnode,* the MSI data is the absolute value within the range from * spi_start to (spi_start + num_spis). * -* Broadom NS2 GICv2m implementation has an erratum where the MSI data +* Broadcom NS2 GICv2m implementation has an erratum where the MSI data * is 'spi_number - 32' * * Reading that register fails on the Graviton implementation
drivers/irqchip/irq-gic-v3-its.c +5 -5
@@ -1492,7 +1492,7 @@ static void its_vlpi_set_doorbell(struct irq_data *d, bool enable)* * Ideally, we'd issue a VMAPTI to set the doorbell to its LPI * value or to 1023, depending on the enable bit. But that -* would be issueing a mapping for an /existing/ DevID+EventID +* would be issuing a mapping for an /existing/ DevID+EventID * pair, which is UNPREDICTABLE. Instead, let's issue a VMOVI * to the /same/ vPE, using this opportunity to adjust the * doorbell. Mouahahahaha. We loves it, Precious.
@@ -3122,7 +3122,7 @@ static void its_cpu_init_lpis(void)/* * It's possible for CPU to receive VLPIs before it is -* sheduled as a vPE, especially for the first CPU, and the +* scheduled as a vPE, especially for the first CPU, and the * VLPI with INTID larger than 2^(IDbits+1) will be considered * as out of range and dropped by GIC. * So we initialize IDbits to known value to avoid VLPI drop.
@@ -3613,7 +3613,7 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,/* * If all interrupts have been freed, start mopping the -* floor. This is conditionned on the device not being shared. +* floor. This is conditioned on the device not being shared. */ if (!its_dev->shared && bitmap_empty(its_dev->event_map.lpi_map,
@@ -4187,7 +4187,7 @@ static int its_sgi_set_affinity(struct irq_data *d, {/* * There is no notion of affinity for virtual SGIs, at least -* not on the host (since they can only be targetting a vPE). +* not on the host (since they can only be targeting a vPE). * Tell the kernel we've done whatever it asked for. */ irq_data_update_effective_affinity (d, mask_val);
@@ -4232,7 +4232,7 @@ static int its_sgi_get_irqchip_state(struct irq_data *d,/* * Locking galore! We can race against two different events: * -* - Concurent vPE affinity change: we must make sure it cannot +* - Concurrent vPE affinity change: we must make sure it cannot * happen, or we'll talk to the wrong redistributor. This is * identical to what happens with vLPIs. *
drivers/irqchip/irq-gic-v3.c +1 -1
@@ -1456,7 +1456,7 @@ static int gic_irq_domain_translate(struct irq_domain *d,/* * Make it clear that broken DTs are... broken. -* Partitionned PPIs are an unfortunate exception. +* Partitioned PPIs are an unfortunate exception. */ WARN_ON (*type ==IRQ_TYPE_NONE && fwspec->param[0 ] !=GIC_IRQ_TYPE_PARTITION );
drivers/irqchip/irq-loongson-pch-pic.c +1 -1
@@ -180,7 +180,7 @@ static void pch_pic_reset(struct pch_pic *priv)int i;for (i =0 ; i <PIC_COUNT ; i++) { -/* Write vectore ID */ +/* Write vectored ID */ writeb (priv->ht_vec_base + i, priv->base +PCH_INT_HTVEC (i));/* Hardcode route to HT0 Lo */ writeb (1 , priv->base +PCH_INT_ROUTE (i));
drivers/irqchip/irq-meson-gpio.c +1 -1
@@ -227,7 +227,7 @@ meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl,/* * Get the hwirq number assigned to this channel through -* a pointer the channel_irq table. The added benifit of this +* a pointer the channel_irq table. The added benefit of this * method is that we can also retrieve the channel index with * it, using the table base. */
drivers/irqchip/irq-mtk-cirq.c +1 -1
@@ -217,7 +217,7 @@ static void mtk_cirq_resume(void) {u32 value; -/* flush recored interrupts, will send signals to parent controller */ +/* flush recorded interrupts, will send signals to parent controller */ value =readl_relaxed (cirq_data->base +CIRQ_CONTROL );writel_relaxed (value |CIRQ_FLUSH , cirq_data->base +CIRQ_CONTROL );
drivers/irqchip/irq-mxs.c +2 -2
@@ -58,7 +58,7 @@ struct icoll_priv {static struct icoll_priv icoll_priv;static struct irq_domain *icoll_domain; -/* calculate bit offset depending on number of intterupt per register */ +/* calculate bit offset depending on number of interrupt per register */ static u32 icoll_intr_bitshift (struct irq_data *d,u32 bit) {/*
@@ -68,7 +68,7 @@ static u32 icoll_intr_bitshift(struct irq_data *d, u32 bit)return bit << ((d->hwirq &3 ) <<3 ); } -/* calculate mem offset depending on number of intterupt per register */ +/* calculate mem offset depending on number of interrupt per register */ static void __iomem *icoll_intr_reg (struct irq_data *d) {/* offset = hwirq / intr_per_reg * 0x10 */
drivers/irqchip/irq-sun4i.c +1 -1
@@ -189,7 +189,7 @@ static void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs)* 3) spurious irq * So if we immediately get a reading of 0, check the irq-pending reg * to differentiate between 2 and 3. We only do this once to avoid -* the extra check in the common case of 1 hapening after having +* the extra check in the common case of 1 happening after having * read the vector-reg once. */ hwirq =readl (irq_ic_data->irq_base +SUN4I_IRQ_VECTOR_REG ) >>2 ;
drivers/irqchip/irq-ti-sci-inta.c +1 -1
@@ -78,7 +78,7 @@ struct ti_sci_inta_vint_desc {* struct ti_sci_inta_irq_domain - Structure representing a TISCI based * Interrupt Aggregator IRQ domain. * @sci: Pointer to TISCI handle -* @vint: TISCI resource pointer representing IA inerrupts. +* @vint: TISCI resource pointer representing IA interrupts. * @global_event: TISCI resource pointer representing global events. * @vint_list: List of the vints active in the system * @vint_mutex: Mutex to protect vint_list
drivers/irqchip/irq-vic.c +2 -2
@@ -163,7 +163,7 @@ static struct syscore_ops vic_syscore_ops = { };/** -* vic_pm_init - initicall to register VIC pm +* vic_pm_init - initcall to register VIC pm * * This is called via late_initcall() to register * the resources for the VICs due to the early
@@ -397,7 +397,7 @@ static void __init vic_clear_interrupts(void __iomem *base)/* * The PL190 cell from ARM has been modified by ST to handle 64 interrupts. * The original cell has 32 interrupts, while the modified one has 64, -* replocating two blocks 0x00..0x1f in 0x20..0x3f. In that case +* replicating two blocks 0x00..0x1f in 0x20..0x3f. In that case * the probe function is called twice, with base set to offset 000 * and 020 within the page. We call this "second block". */
drivers/irqchip/irq-xilinx-intc.c +1 -1
@@ -210,7 +210,7 @@ static int __init xilinx_intc_of_init(struct device_node *intc,/* * Disable all external interrupts until they are -* explicity requested. +* explicitly requested. */ xintc_write (irqc,IER ,0 );
include/linux/irq.h +2 -2
@@ -116,7 +116,7 @@ enum {* IRQ_SET_MASK_NOCPY - OK, chip did update irq_common_data.affinity * IRQ_SET_MASK_OK_DONE - Same as IRQ_SET_MASK_OK for core. Special code to * support stacked irqchips, which indicates skipping -* all descendent irqchips. +* all descendant irqchips. */ enum {IRQ_SET_MASK_OK =0 ,
@@ -302,7 +302,7 @@ static inline bool irqd_is_level_type(struct irq_data *d)/* * Must only be called of irqchip.irq_set_affinity() or low level -* hieararchy domain allocation functions. +* hierarchy domain allocation functions. */ static inline void irqd_set_single_target (struct irq_data *d) {
include/linux/irqdesc.h +1 -1
@@ -32,7 +32,7 @@ struct pt_regs;* @last_unhandled: aging timer for unhandled count * @irqs_unhandled: stats field for spurious unhandled interrupts * @threads_handled: stats field for deferred spurious detection of threaded handlers -* @threads_handled_last: comparator field for deferred spurious detection of theraded handlers +* @threads_handled_last: comparator field for deferred spurious detection of threaded handlers * @lock: locking for SMP * @affinity_hint: hint to user space for preferred irq affinity * @affinity_notify: context for notification of affinity changes
kernel/irq/chip.c +1 -1
@@ -811,7 +811,7 @@ void handle_edge_irq(struct irq_desc *desc)/* * When another irq arrived while we were handling * one, we could have masked the irq. -* Renable it, if it was not disabled in meantime. +* Reenable it, if it was not disabled in meantime. */ if (unlikely (desc->istate &IRQS_PENDING )) { if (!irqd_irq_disabled(&desc->irq_data) &&
kernel/irq/dummychip.c +1 -1
@@ -13,7 +13,7 @@/* * What should we do if we get a hw irq event on an illegal vector? -* Each architecture has to answer this themself. +* Each architecture has to answer this themselves. */ static void ack_bad (struct irq_data *data) {
kernel/irq/irqdesc.c +1 -1
@@ -31,7 +31,7 @@ static int __init irq_affinity_setup(char *str)cpulist_parse (str, irq_default_affinity);/* * Set at least the boot cpu. We don't want to end up with -* bugreports caused by random comandline masks +* bugreports caused by random commandline masks */ cpumask_set_cpu (smp_processor_id (), irq_default_affinity);return 1 ;
kernel/irq/irqdomain.c +4 -4
@@ -53,7 +53,7 @@ EXPORT_SYMBOL_GPL(irqchip_fwnode_ops);* @name: Optional user provided domain name * @pa: Optional user-provided physical address * -* Allocate a struct irqchip_fwid, and return a poiner to the embedded +* Allocate a struct irqchip_fwid, and return a pointer to the embedded * fwnode_handle (or NULL on failure). * * Note: The types IRQCHIP_FWNODE_NAMED and IRQCHIP_FWNODE_NAMED_ID are
@@ -657,7 +657,7 @@ unsigned int irq_create_mapping_affinity(struct irq_domain *domain,pr_debug ("irq_create_mapping(0x%p, 0x%lx)\n" , domain, hwirq); -/* Look for default domain if nececssary */ +/* Look for default domain if necessary */ if (domain ==NULL ) domain = irq_default_domain;if (domain ==NULL ) {
@@ -893,7 +893,7 @@ unsigned int irq_find_mapping(struct irq_domain *domain, {struct irq_data *data; -/* Look for default domain if nececssary */ +/* Look for default domain if necessary */ if (domain ==NULL ) domain = irq_default_domain;if (domain ==NULL )
@@ -1423,7 +1423,7 @@ int irq_domain_alloc_irqs_hierarchy(struct irq_domain *domain,* The whole process to setup an IRQ has been split into two steps. * The first step, __irq_domain_alloc_irqs(), is to allocate IRQ * descriptor and required hardware resources. The second step, -* irq_domain_activate_irq(), is to program hardwares with preallocated +* irq_domain_activate_irq(), is to program the hardware with preallocated * resources. In this way, it's easier to rollback when failing to * allocate resources. */
kernel/irq/manage.c +3 -3
@@ -341,7 +341,7 @@ static bool irq_set_affinity_deactivated(struct irq_data *data,* If the interrupt is not yet activated, just store the affinity * mask and do not call the chip driver at all. On activation the * driver has to make sure anyway that the interrupt is in a -* useable state so startup works. +* usable state so startup works. */ if (!IS_ENABLED (CONFIG_IRQ_DOMAIN_HIERARCHY ) ||irqd_is_activated (data) || !irqd_affinity_on_activate (data))
@@ -999,7 +999,7 @@ static void irq_finalize_oneshot(struct irq_desc *desc,* to IRQS_INPROGRESS and the irq line is masked forever. * * This also serializes the state of shared oneshot handlers -* versus "desc->threads_onehsot |= action->thread_mask;" in +* versus "desc->threads_oneshot |= action->thread_mask;" in * irq_wake_thread(). See the comment there which explains the * serialization. */
@@ -1877,7 +1877,7 @@ static struct irqaction *__free_irq(struct irq_desc *desc, void *dev_id)/* Last action releases resources */ if (!desc->action) {/* -* Reaquire bus lock as irq_release_resources() might +* Reacquire bus lock as irq_release_resources() might * require it to deallocate resources over the slow bus. */ chip_bus_lock (desc);
kernel/irq/msi.c +1 -1
@@ -5,7 +5,7 @@* * This file is licensed under GPLv2. * -* This file contains common code to support Message Signalled Interrupt for +* This file contains common code to support Message Signaled Interrupts for * PCI compatible and non PCI compatible devices. */ #include <linux/types.h>
kernel/irq/timings.c +1 -1
@@ -490,7 +490,7 @@ static inline void irq_timings_store(int irq, struct irqt_stat *irqs, u64 ts)/* * The interrupt triggered more than one second apart, that -* ends the sequence as predictible for our purpose. In this +* ends the sequence as predictable for our purpose. In this * case, assume we have the beginning of a sequence and the * timestamp is the first value. As it is impossible to * predict anything at this point, return.
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 15/104 irqdomain: Look for existing mapping only once
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
[ Upstream commit 6e6f75c9c98d2d246d90411ff2b6f0cd271f4cba ]
Avoid looking for an existing mapping twice when creating a new mapping using irq_create_fwspec_mapping() by factoring out the actual allocation which is shared with irq_create_mapping_affinity().
The new helper function will also be used to fix a shared-interrupt mapping race, hence the Fixes tag.
--- kernel/irq/irqdomain.c | 60 +++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 27 deletions(-)
kernel/irq/irqdomain.c +33 -27
@@ -637,6 +637,34 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain) }EXPORT_SYMBOL_GPL (irq_create_direct_mapping); +static unsigned int __irq_create_mapping_affinity (struct irq_domain *domain, +irq_hw_number_t hwirq, +const struct irq_affinity_desc *affinity) +{ +struct device_node *of_node =irq_domain_get_of_node (domain); +int virq; + +pr_debug ("irq_create_mapping(0x%p, 0x%lx)\n" , domain, hwirq); + +/* Allocate a virtual interrupt number */ + virq =irq_domain_alloc_descs (-1 ,1 , hwirq,of_node_to_nid (of_node), + affinity); +if (virq <=0 ) { +pr_debug ("-> virq allocation failed\n" ); +return 0 ; + } + +if (irq_domain_associate (domain, virq, hwirq)) { +irq_free_desc (virq); +return 0 ; + } + +pr_debug ("irq %lu on domain %s mapped to virtual irq %u\n" , + hwirq,of_node_full_name (of_node), virq); + +return virq; +} +/** * irq_create_mapping_affinity() - Map a hardware interrupt into linux irq space * @domain: domain owning this hardware interrupt or NULL for default domain
@@ -649,14 +677,11 @@ EXPORT_SYMBOL_GPL(irq_create_direct_mapping);* on the number returned from that call. */ unsigned int irq_create_mapping_affinity (struct irq_domain *domain, -irq_hw_number_t hwirq, -const struct irq_affinity_desc *affinity) +irq_hw_number_t hwirq, +const struct irq_affinity_desc *affinity) { -struct device_node *of_node;int virq; -pr_debug ("irq_create_mapping(0x%p, 0x%lx)\n" , domain, hwirq); -/* Look for default domain if necessary */ if (domain ==NULL ) domain = irq_default_domain;
@@ -664,34 +689,15 @@ unsigned int irq_create_mapping_affinity(struct irq_domain *domain,WARN (1 ,"%s(, %lx) called with NULL domain\n" , __func__, hwirq);return 0 ; } -pr_debug ("-> using domain @%p\n" , domain); - - of_node =irq_domain_get_of_node (domain);/* Check if mapping already exists */ virq =irq_find_mapping (domain, hwirq);if (virq) { -pr_debug ("-> existing mapping on virq %d\n" , virq); +pr_debug ("existing mapping on virq %d\n" , virq);return virq; } -/* Allocate a virtual interrupt number */ - virq =irq_domain_alloc_descs (-1 ,1 , hwirq,of_node_to_nid (of_node), - affinity); -if (virq <=0 ) { -pr_debug ("-> virq allocation failed\n" ); -return 0 ; - } - -if (irq_domain_associate (domain, virq, hwirq)) { -irq_free_desc (virq); -return 0 ; - } - -pr_debug ("irq %lu on domain %s mapped to virtual irq %u\n" , - hwirq,of_node_full_name (of_node), virq); - -return virq; +return __irq_create_mapping_affinity (domain, hwirq, affinity); }EXPORT_SYMBOL_GPL (irq_create_mapping_affinity);
@@ -831,7 +837,7 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)return 0 ; }else {/* Create mapping */ - virq =irq_create_mapping (domain, hwirq); + virq =__irq_create_mapping_affinity (domain, hwirq,NULL );if (!virq)return virq; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 16/104 irqdomain: Refactor __irq_domain_alloc_irqs()
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
[ Upstream commit d55f7f4c58c07beb5050a834bf57ae2ede599c7e ]
Refactor __irq_domain_alloc_irqs() so that it can be called internally while holding the irq_domain_mutex.
This will be used to fix a shared-interrupt mapping race, hence the Fixes tag.
--- kernel/irq/irqdomain.c | 88 +++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 40 deletions(-)
kernel/irq/irqdomain.c +48 -40
@@ -1411,40 +1411,12 @@ int irq_domain_alloc_irqs_hierarchy(struct irq_domain *domain,return domain->ops->alloc (domain, irq_base, nr_irqs, arg); } -/** -* __irq_domain_alloc_irqs - Allocate IRQs from domain -* @domain: domain to allocate from -* @irq_base: allocate specified IRQ number if irq_base >= 0 -* @nr_irqs: number of IRQs to allocate -* @node: NUMA node id for memory allocation -* @arg: domain specific argument -* @realloc: IRQ descriptors have already been allocated if true -* @affinity: Optional irq affinity mask for multiqueue devices -* -* Allocate IRQ numbers and initialized all data structures to support -* hierarchy IRQ domains. -* Parameter @realloc is mainly to support legacy IRQs. -* Returns error code or allocated IRQ number -* -* The whole process to setup an IRQ has been split into two steps. -* The first step, __irq_domain_alloc_irqs(), is to allocate IRQ -* descriptor and required hardware resources. The second step, -* irq_domain_activate_irq(), is to program the hardware with preallocated -* resources. In this way, it's easier to rollback when failing to -* allocate resources. -*/ -int __irq_domain_alloc_irqs (struct irq_domain *domain,int irq_base, -unsigned int nr_irqs,int node,void *arg, -bool realloc,const struct irq_affinity_desc *affinity) +static int irq_domain_alloc_irqs_locked (struct irq_domain *domain,int irq_base, +unsigned int nr_irqs,int node,void *arg, +bool realloc,const struct irq_affinity_desc *affinity) {int i, ret, virq; -if (domain ==NULL ) { - domain = irq_default_domain; -if (WARN (!domain,"domain is NULL; cannot allocate IRQ\n" )) -return -EINVAL ; - } -if (realloc && irq_base >=0 ) { virq = irq_base; }else {
@@ -1463,24 +1435,18 @@ int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base, goto out_free_desc; } -mutex_lock (&irq_domain_mutex); ret =irq_domain_alloc_irqs_hierarchy (domain, virq, nr_irqs, arg); -if (ret <0 ) { -mutex_unlock (&irq_domain_mutex); +if (ret <0 ) goto out_free_irq_data; - }for (i =0 ; i < nr_irqs; i++) { ret =irq_domain_trim_hierarchy (virq + i); -if (ret) { -mutex_unlock (&irq_domain_mutex); +if (ret) goto out_free_irq_data; - } } - +for (i =0 ; i < nr_irqs; i++)irq_domain_insert_irq (virq + i); -mutex_unlock (&irq_domain_mutex);return virq;
@@ -1491,6 +1457,48 @@ int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,return ret; } +/** +* __irq_domain_alloc_irqs - Allocate IRQs from domain +* @domain: domain to allocate from +* @irq_base: allocate specified IRQ number if irq_base >= 0 +* @nr_irqs: number of IRQs to allocate +* @node: NUMA node id for memory allocation +* @arg: domain specific argument +* @realloc: IRQ descriptors have already been allocated if true +* @affinity: Optional irq affinity mask for multiqueue devices +* +* Allocate IRQ numbers and initialized all data structures to support +* hierarchy IRQ domains. +* Parameter @realloc is mainly to support legacy IRQs. +* Returns error code or allocated IRQ number +* +* The whole process to setup an IRQ has been split into two steps. +* The first step, __irq_domain_alloc_irqs(), is to allocate IRQ +* descriptor and required hardware resources. The second step, +* irq_domain_activate_irq(), is to program the hardware with preallocated +* resources. In this way, it's easier to rollback when failing to +* allocate resources. +*/ +int __irq_domain_alloc_irqs (struct irq_domain *domain,int irq_base, +unsigned int nr_irqs,int node,void *arg, +bool realloc,const struct irq_affinity_desc *affinity) +{ +int ret; + +if (domain ==NULL ) { + domain = irq_default_domain; +if (WARN (!domain,"domain is NULL; cannot allocate IRQ\n" )) +return -EINVAL ; + } + +mutex_lock (&irq_domain_mutex); + ret =irq_domain_alloc_irqs_locked (domain, irq_base, nr_irqs, node, arg, + realloc, affinity); +mutex_unlock (&irq_domain_mutex); + +return ret; +} +/* The irq_data was moved, fix the revmap to refer to the new location */ static void irq_domain_fix_revmap (struct irq_data *d) {
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 17/104 irqdomain: Fix mapping-creation race
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
[ Upstream commit 601363cc08da25747feb87c55573dd54de91d66a ]
Parallel probing of devices that share interrupts (e.g. when a driver uses asynchronous probing) can currently result in two mappings for the same hardware interrupt to be created due to missing serialisation.
Make sure to hold the irq_domain_mutex when creating mappings so that looking for an existing mapping before creating a new one is done atomically.
--- kernel/irq/irqdomain.c | 64 ++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 18 deletions(-)
kernel/irq/irqdomain.c +46 -18
@@ -25,6 +25,9 @@ static DEFINE_MUTEX(irq_domain_mutex);static struct irq_domain *irq_default_domain; +static int irq_domain_alloc_irqs_locked (struct irq_domain *domain,int irq_base, +unsigned int nr_irqs,int node,void *arg, +bool realloc,const struct irq_affinity_desc *affinity);static void irq_domain_check_hierarchy (struct irq_domain *domain);struct irqchip_fwid {
@@ -637,9 +640,9 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain) }EXPORT_SYMBOL_GPL (irq_create_direct_mapping); -static unsigned int __irq_create_mapping_affinity (struct irq_domain *domain, -irq_hw_number_t hwirq, -const struct irq_affinity_desc *affinity) +static unsigned int irq_create_mapping_affinity_locked (struct irq_domain *domain, +irq_hw_number_t hwirq, +const struct irq_affinity_desc *affinity) {struct device_node *of_node =irq_domain_get_of_node (domain);int virq;
@@ -654,7 +657,7 @@ static unsigned int __irq_create_mapping_affinity(struct irq_domain *domain,return 0 ; } -if (irq_domain_associate (domain, virq, hwirq)) { +if (irq_domain_associate_locked (domain, virq, hwirq)) {irq_free_desc (virq);return 0 ; }
@@ -690,14 +693,20 @@ unsigned int irq_create_mapping_affinity(struct irq_domain *domain,return 0 ; } +mutex_lock (&irq_domain_mutex); +/* Check if mapping already exists */ virq =irq_find_mapping (domain, hwirq);if (virq) {pr_debug ("existing mapping on virq %d\n" , virq); -return virq; + goto out; } -return __irq_create_mapping_affinity (domain, hwirq, affinity); + virq =irq_create_mapping_affinity_locked (domain, hwirq, affinity); +out: +mutex_unlock (&irq_domain_mutex); + +return virq; }EXPORT_SYMBOL_GPL (irq_create_mapping_affinity);
@@ -799,6 +808,8 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)if (WARN_ON (type & ~IRQ_TYPE_SENSE_MASK )) type &=IRQ_TYPE_SENSE_MASK ; +mutex_lock (&irq_domain_mutex); +/* * If we've already configured this interrupt, * don't do it again, or hell will break loose.
@@ -811,7 +822,7 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)* interrupt number. */ if (type ==IRQ_TYPE_NONE || type ==irq_get_trigger_type (virq)) -return virq; + goto out;/* * If the trigger type has not been set yet, then set
@@ -819,35 +830,45 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)*/ if (irq_get_trigger_type (virq) ==IRQ_TYPE_NONE ) { irq_data =irq_get_irq_data (virq); -if (!irq_data) -return 0 ; +if (!irq_data) { + virq =0 ; + goto out; + }irqd_set_trigger_type (irq_data, type); -return virq; + goto out; }pr_warn ("type mismatch, failed to map hwirq-%lu for %s!\n" , hwirq,of_node_full_name (to_of_node (fwspec->fwnode))); -return 0 ; + virq =0 ; + goto out; }if (irq_domain_is_hierarchy (domain)) { - virq =irq_domain_alloc_irqs (domain,1 ,NUMA_NO_NODE , fwspec); -if (virq <=0 ) -return 0 ; + virq =irq_domain_alloc_irqs_locked (domain,-1 ,1 ,NUMA_NO_NODE , + fwspec, false,NULL ); +if (virq <=0 ) { + virq =0 ; + goto out; + } }else {/* Create mapping */ - virq =__irq_create_mapping_affinity (domain, hwirq,NULL ); + virq =irq_create_mapping_affinity_locked (domain, hwirq,NULL );if (!virq) -return virq; + goto out; } irq_data =irq_get_irq_data (virq); -if (WARN_ON (!irq_data)) -return 0 ; +if (WARN_ON (!irq_data)) { + virq =0 ; + goto out; + }/* Store trigger type */ irqd_set_trigger_type (irq_data, type); +out: +mutex_unlock (&irq_domain_mutex);return virq; }
@@ -1856,6 +1877,13 @@ void irq_domain_set_info(struct irq_domain *domain, unsigned int virq,irq_set_handler_data (virq, handler_data); } +static int irq_domain_alloc_irqs_locked (struct irq_domain *domain,int irq_base, +unsigned int nr_irqs,int node,void *arg, +bool realloc,const struct irq_affinity_desc *affinity) +{ +return -EINVAL ; +} +static void irq_domain_check_hierarchy (struct irq_domain *domain) { }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 18/104 irqdomain: Change the type of size in __irq_domain_add() to be consistent
In reply to Greg Kroah-HartmanFrom: Bixuan Cui <[email protected]>
[ Upstream commit 20c36ce2164f1774b487d443ece99b754bc6ad43 ]
The 'size' is used in struct_size(domain, revmap, size) and its input parameter type is 'size_t'(unsigned int).
Changing the size to 'unsigned int' to make the type consistent.
Stable-dep-of: 8932c32c3053 ("irqdomain: Fix domain registration race")
--- include/linux/irqdomain.h | 2 +- kernel/irq/irqdomain.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
include/linux/irqdomain.h +1 -1
@@ -256,7 +256,7 @@ static inline struct fwnode_handle *irq_domain_alloc_fwnode(phys_addr_t *pa) }void irq_domain_free_fwnode (struct fwnode_handle *fwnode); -struct irq_domain *__irq_domain_add (struct fwnode_handle *fwnode,int size, +struct irq_domain *__irq_domain_add (struct fwnode_handle *fwnode,unsigned int size,irq_hw_number_t hwirq_max,int direct_max,const struct irq_domain_ops *ops,void *host_data);
kernel/irq/irqdomain.c +1 -1
@@ -130,7 +130,7 @@ EXPORT_SYMBOL_GPL(irq_domain_free_fwnode);* Allocates and initializes an irq_domain structure. * Returns pointer to IRQ domain, or NULL on failure. */ -struct irq_domain *__irq_domain_add (struct fwnode_handle *fwnode,int size, +struct irq_domain *__irq_domain_add (struct fwnode_handle *fwnode,unsigned int size,irq_hw_number_t hwirq_max,int direct_max,const struct irq_domain_ops *ops,void *host_data)
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 19/104 irqdomain: Fix domain registration race
In reply to Greg Kroah-HartmanFrom: Marc Zyngier <[email protected]>
[ Upstream commit 8932c32c3053accd50702b36e944ac2016cd103c ]
Hierarchical domains created using irq_domain_create_hierarchy() are currently added to the domain list before having been fully initialised.
This specifically means that a racing allocation request might fail to allocate irq data for the inner domains of a hierarchy in case the parent domain pointer has not yet been set up.
Note that this is not really any issue for irqchip drivers that are registered early (e.g. via IRQCHIP_DECLARE() or IRQCHIP_ACPI_DECLARE()) but could potentially cause trouble with drivers that are registered later (e.g. modular drivers using IRQCHIP_PLATFORM_DRIVER_BEGIN(), gpiochip drivers, etc.).
--- kernel/irq/irqdomain.c | 62 +++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 19 deletions(-)
kernel/irq/irqdomain.c +43 -19
@@ -117,23 +117,12 @@ void irq_domain_free_fwnode(struct fwnode_handle *fwnode) }EXPORT_SYMBOL_GPL (irq_domain_free_fwnode); -/** -* __irq_domain_add() - Allocate a new irq_domain data structure -* @fwnode: firmware node for the interrupt controller -* @size: Size of linear map; 0 for radix mapping only -* @hwirq_max: Maximum number of interrupts supported by controller -* @direct_max: Maximum value of direct maps; Use ~0 for no limit; 0 for no -* direct mapping -* @ops: domain callbacks -* @host_data: Controller private data pointer -* -* Allocates and initializes an irq_domain structure. -* Returns pointer to IRQ domain, or NULL on failure. -*/ -struct irq_domain *__irq_domain_add (struct fwnode_handle *fwnode,unsigned int size, -irq_hw_number_t hwirq_max,int direct_max, -const struct irq_domain_ops *ops, -void *host_data) +static struct irq_domain *__irq_domain_create (struct fwnode_handle *fwnode, +unsigned int size, +irq_hw_number_t hwirq_max, +int direct_max, +const struct irq_domain_ops *ops, +void *host_data) {struct irqchip_fwid *fwid;struct irq_domain *domain;
@@ -210,12 +199,44 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, unsigned int s domain->revmap_direct_max_irq = direct_max;irq_domain_check_hierarchy (domain); +return domain; +} + +static void __irq_domain_publish (struct irq_domain *domain) +{mutex_lock (&irq_domain_mutex);debugfs_add_domain_dir (domain);list_add (&domain->link, &irq_domain_list);mutex_unlock (&irq_domain_mutex);pr_debug ("Added domain %s\n" , domain->name); +} + +/** +* __irq_domain_add() - Allocate a new irq_domain data structure +* @fwnode: firmware node for the interrupt controller +* @size: Size of linear map; 0 for radix mapping only +* @hwirq_max: Maximum number of interrupts supported by controller +* @direct_max: Maximum value of direct maps; Use ~0 for no limit; 0 for no +* direct mapping +* @ops: domain callbacks +* @host_data: Controller private data pointer +* +* Allocates and initializes an irq_domain structure. +* Returns pointer to IRQ domain, or NULL on failure. +*/ +struct irq_domain *__irq_domain_add (struct fwnode_handle *fwnode,unsigned int size, +irq_hw_number_t hwirq_max,int direct_max, +const struct irq_domain_ops *ops, +void *host_data) +{ +struct irq_domain *domain; + + domain =__irq_domain_create (fwnode, size, hwirq_max, direct_max, + ops, host_data); +if (domain) +__irq_domain_publish (domain); +return domain; }EXPORT_SYMBOL_GPL (__irq_domain_add);
@@ -1110,12 +1131,15 @@ struct irq_domain *irq_domain_create_hierarchy(struct irq_domain *parent,struct irq_domain *domain;if (size) - domain =irq_domain_create_linear (fwnode, size, ops, host_data); + domain =__irq_domain_create (fwnode, size, size,0 , ops, host_data);else - domain =irq_domain_create_tree (fwnode, ops, host_data); + domain =__irq_domain_create (fwnode,0 , ~0 ,0 , ops, host_data); +if (domain) { domain->parent = parent; domain->flags |= flags; + +__irq_domain_publish (domain); }return domain;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 20/104 iommu/vt-d: Fix lockdep splat in intel_pasid_get_entry()
In reply to Greg Kroah-HartmanFrom: Lu Baolu <[email protected]>
[ Upstream commit 803766cbf85fb8edbf896729bbefc2d38dcf1e0a ]
The pasid_lock is used to synchronize different threads from modifying a same pasid directory entry at the same time. It causes below lockdep splat.
[ 83.296538] ========================================================
[ 83.296538] WARNING: possible irq lock inversion dependency detected
[ 83.296539] 5.12.0-rc3+ #25 Tainted: G W
[ 83.296539] --------------------------------------------------------
[ 83.296540] bash/780 just changed the state of lock:
[ 83.296540] ffffffff82b29c98 (device_domain_lock){..-.}-{2:2}, at:
iommu_flush_dev_iotlb.part.0+0x32/0x110
[ 83.296547] but this lock took another, SOFTIRQ-unsafe lock in the past:
[ 83.296547] (pasid_lock){+.+.}-{2:2}
[ 83.296548]and interrupts could create inverse lock ordering between them.
[ 83.296549] other info that might help us debug this:
[ 83.296549] Chain exists of:
device_domain_lock --> &iommu->lock --> pasid_lock
[ 83.296551] Possible interrupt unsafe locking scenario:[ 83.296551] CPU0 CPU1
[ 83.296552] ---- ----
[ 83.296552] lock(pasid_lock);
[ 83.296553] local_irq_disable();
[ 83.296553] lock(device_domain_lock);
[ 83.296554] lock(&iommu->lock);
[ 83.296554] <Interrupt>
[ 83.296554] lock(device_domain_lock);
[ 83.296555]
*** DEADLOCK ***Fix it by replacing the pasid_lock with an atomic exchange operation.
Stable-dep-of: 194b3348bdbb ("iommu/vt-d: Fix PASID directory pointer coherency")
--- drivers/iommu/intel/pasid.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-)
drivers/iommu/intel/pasid.c +13 -8
@@ -24,7 +24,6 @@/* * Intel IOMMU system wide PASID name space: */ -static DEFINE_SPINLOCK (pasid_lock);u32 intel_pasid_max_id =PASID_MAX ;int vcmd_alloc_pasid (struct intel_iommu *iommu,u32 *pasid)
@@ -259,19 +258,25 @@ struct pasid_entry *intel_pasid_get_entry(struct device *dev, u32 pasid) dir_index = pasid >>PASID_PDE_SHIFT ; index = pasid &PASID_PTE_MASK ; -spin_lock (&pasid_lock); +retry: entries =get_pasid_table_from_pde (&dir[dir_index]);if (!entries) { entries =alloc_pgtable_page (info->iommu->node); -if (!entries) { -spin_unlock (&pasid_lock); +if (!entries)return NULL ; - } -WRITE_ONCE (dir[dir_index].val, - (u64 )virt_to_phys (entries) |PASID_PTE_PRESENT ); +/* +* The pasid directory table entry won't be freed after +* allocation. No worry about the race with free and +* clear. However, this entry might be populated by others +* while we are preparing it. Use theirs with a retry. +*/ +if (cmpxchg64 (&dir[dir_index].val,0ULL , + (u64 )virt_to_phys (entries) |PASID_PTE_PRESENT )) { +free_pgtable_page (entries); + goto retry; + } } -spin_unlock (&pasid_lock);return &entries[index]; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 21/104 iommu/vt-d: Fix PASID directory pointer coherency
In reply to Greg Kroah-HartmanFrom: Jacob Pan <[email protected]>
[ Upstream commit 194b3348bdbb7db65375c72f3f774aee4cc6614e ]
On platforms that do not support IOMMU Extended capability bit 0 Page-walk Coherency, CPU caches are not snooped when IOMMU is accessing any translation structures. IOMMU access goes only directly to memory. Intel IOMMU code was missing a flush for the PASID table directory that resulted in the unrecoverable fault as shown below.
This patch adds clflush calls whenever allocating and updating a PASID table directory to ensure cache coherency.
On the reverse direction, there's no need to clflush the PASID directory pointer when we deactivate a context entry in that IOMMU hardware will not see the old PASID directory pointer after we clear the context entry. PASID directory entries are also never freed once allocated.
DMAR: DRHD: handling fault status reg 3
DMAR: [DMA Read NO_PASID] Request device [00:0d.2] fault addr 0x1026a4000
[fault reason 0x51] SM: Present bit in Directory Entry is clear
DMAR: Dump dmar1 table entries for IOVA 0x1026a4000
DMAR: scalable mode root entry: hi 0x0000000102448001, low 0x0000000101b3e001
DMAR: context entry: hi 0x0000000000000000, low 0x0000000101b4d401
DMAR: pasid dir entry: 0x0000000101b4e001
DMAR: pasid table entry[0]: 0x0000000000000109
DMAR: pasid table entry[1]: 0x0000000000000001
DMAR: pasid table entry[2]: 0x0000000000000000
DMAR: pasid table entry[3]: 0x0000000000000000
DMAR: pasid table entry[4]: 0x0000000000000000
DMAR: pasid table entry[5]: 0x0000000000000000
DMAR: pasid table entry[6]: 0x0000000000000000
DMAR: pasid table entry[7]: 0x0000000000000000
DMAR: PTE not present at level 4
--- drivers/iommu/intel/pasid.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/iommu/intel/pasid.c +7 -0
@@ -186,6 +186,9 @@ int intel_pasid_alloc_table(struct device *dev) attach_out:device_attach_pasid_table (info, pasid_table); +if (!ecap_coherent (info->iommu->ecap)) +clflush_cache_range (pasid_table->table, size); +return 0 ; }
@@ -276,6 +279,10 @@ struct pasid_entry *intel_pasid_get_entry(struct device *dev, u32 pasid)free_pgtable_page (entries); goto retry; } +if (!ecap_coherent (info->iommu->ecap)) { +clflush_cache_range (entries,VTD_PAGE_SIZE ); +clflush_cache_range (&dir[dir_index].val,sizeof (*dir)); + } }return &entries[index];
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 22/104 arm64: efi: Make efi_rt_lock a raw_spinlock
In reply to Greg Kroah-HartmanFrom: Pierre Gondois <[email protected]>
[ Upstream commit 0e68b5517d3767562889f1d83fdb828c26adb24f ]
Running a rt-kernel base on 6.2.0-rc3-rt1 on an Ampere Altra outputs the following:
BUG: sleeping function called from invalid context at kernel/locking/spinlock_rt.c:46
in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 9, name: kworker/u320:0
preempt_count: 2, expected: 0
RCU nest depth: 0, expected: 0
3 locks held by kworker/u320:0/9:
#0: ffff3fff8c27d128 ((wq_completion)efi_rts_wq){+.+.}-{0:0}, at: process_one_work (./include/linux/atomic/atomic-long.h:41)
#1: ffff80000861bdd0 ((work_completion)(&efi_rts_work.work)){+.+.}-{0:0}, at: process_one_work (./include/linux/atomic/atomic-long.h:41)
#2: ffffdf7e1ed3e460 (efi_rt_lock){+.+.}-{3:3}, at: efi_call_rts (drivers/firmware/efi/runtime-wrappers.c:101)
Preemption disabled at:
efi_virtmap_load (./arch/arm64/include/asm/mmu_context.h:248)
CPU: 0 PID: 9 Comm: kworker/u320:0 Tainted: G W 6.2.0-rc3-rt1
Hardware name: WIWYNN Mt.Jade Server System B81.03001.0005/Mt.Jade Motherboard, BIOS 1.08.20220218 (SCP: 1.08.20220218) 2022/02/18
Workqueue: efi_rts_wq efi_call_rts
Call trace:
dump_backtrace (arch/arm64/kernel/stacktrace.c:158)
show_stack (arch/arm64/kernel/stacktrace.c:165)
dump_stack_lvl (lib/dump_stack.c:107 (discriminator 4))
dump_stack (lib/dump_stack.c:114)
__might_resched (kernel/sched/core.c:10134)
rt_spin_lock (kernel/locking/rtmutex.c:1769 (discriminator 4))
efi_call_rts (drivers/firmware/efi/runtime-wrappers.c:101)
[...]This seems to come from commit ff7a167961d1 ("arm64: efi: Execute runtime services from a dedicated stack") which adds a spinlock. This spinlock is taken through:efi_call_rts()
\-efi_call_virt()
\-efi_call_virt_pointer()
\-arch_efi_call_virt_setup()
Make 'efi_rt_lock' a raw_spinlock to avoid being preempted.
[ardb: The EFI runtime services are called with a different set of
translation tables, and are permitted to use the SIMD registers. The context switch code preserves/restores neither, and so EFI calls must be made with preemption disabled, rather than only disabling migration.]
--- arch/arm64/include/asm/efi.h | 6 +++--- arch/arm64/kernel/efi.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-)
arch/arm64/include/asm/efi.h +3 -3
@@ -25,7 +25,7 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); ({ \efi_virtmap_load (); \__efi_fpsimd_begin (); \ -spin_lock (&efi_rt_lock); \ +raw_spin_lock (&efi_rt_lock); \ }) #define arch_efi_call_virt(p, f, args...) \
@@ -37,12 +37,12 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);#define arch_efi_call_virt_teardown () \ ({ \ - spin_unlock(&efi_rt_lock); \ + raw_spin_unlock(&efi_rt_lock); \ __efi_fpsimd_end(); \ efi_virtmap_unload(); \ }) -extern spinlock_t efi_rt_lock; +extern raw_spinlock_t efi_rt_lock;efi_status_t __efi_rt_asm_wrapper (void *,const char *, ...);#define ARCH_EFI_IRQ_FLAGS_MASK (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT)
arch/arm64/kernel/efi.c +1 -1
@@ -144,7 +144,7 @@ asmlinkage efi_status_t efi_handle_corrupted_x18(efi_status_t s, const char *f)return s; } -DEFINE_SPINLOCK (efi_rt_lock); +DEFINE_RAW_SPINLOCK (efi_rt_lock); asmlinkage u64 *efi_rt_stack_top __ro_after_init;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 23/104 RISC-V: Avoid dereferening NULL regs in die()
In reply to Greg Kroah-HartmanFrom: Palmer Dabbelt <[email protected]>
[ Upstream commit f2913d006fcdb61719635e093d1b5dd0dafecac7 ]
I don't think we can actually die() without a regs pointer, but the compiler was warning about a NULL check after a dereference. It seems prudent to just avoid the possibly-NULL dereference, given that when die()ing the system is already toast so who knows how we got there.
Stable-dep-of: 130aee3fd998 ("riscv: Avoid enabling interrupts in die()")
--- arch/riscv/kernel/traps.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
arch/riscv/kernel/traps.c +6 -3
@@ -31,6 +31,7 @@ void die(struct pt_regs *regs, const char *str) {static int die_counter;int ret; +long cause;oops_enter ();
@@ -40,11 +41,13 @@ void die(struct pt_regs *regs, const char *str)pr_emerg ("%s [#%d]\n" , str, ++die_counter);print_modules (); -show_regs (regs); +if (regs) +show_regs (regs); - ret =notify_die (DIE_OOPS , str, regs,0 , regs->cause,SIGSEGV ); + cause = regs ? regs->cause :-1 ; + ret =notify_die (DIE_OOPS , str, regs,0 , cause,SIGSEGV ); -if (regs &&kexec_should_crash (current)) +if (kexec_should_crash (current))crash_kexec (regs);bust_spinlocks (0 );
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 24/104 riscv: Avoid enabling interrupts in die()
In reply to Greg Kroah-HartmanFrom: Mattias Nissler <[email protected]>
[ Upstream commit 130aee3fd9981297ff9354e5d5609cd59aafbbea ]
While working on something else, I noticed that the kernel would start accepting interrupts again after crashing in an interrupt handler. Since the kernel is already in inconsistent state, enabling interrupts is dangerous and opens up risk of kernel state deteriorating further. Interrupts do get enabled via what looks like an unintended side effect of spin_unlock_irq, so switch to the more cautious spin_lock_irqsave/spin_unlock_irqrestore instead.
--- arch/riscv/kernel/traps.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
arch/riscv/kernel/traps.c +3 -2
@@ -32,10 +32,11 @@ void die(struct pt_regs *regs, const char *str)static int die_counter;int ret;long cause; +unsigned long flags;oops_enter (); -spin_lock_irq (&die_lock); +spin_lock_irqsave (&die_lock, flags);console_verbose ();bust_spinlocks (1 );
@@ -52,7 +53,7 @@ void die(struct pt_regs *regs, const char *str)bust_spinlocks (0 );add_taint (TAINT_DIE ,LOCKDEP_NOW_UNRELIABLE ); -spin_unlock_irq (&die_lock); +spin_unlock_irqrestore (&die_lock, flags);oops_exit ();if (in_interrupt ())
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 25/104 riscv: Add header include guards to insn.h
In reply to Greg Kroah-HartmanFrom: Liao Chang <[email protected]>
[ Upstream commit 8ac6e619d9d51b3eb5bae817db8aa94e780a0db4 ]
Add header include guards to insn.h to prevent repeating declaration of any identifiers in insn.h.
--- arch/riscv/include/asm/parse_asm.h | 5 +++++ 1 file changed, 5 insertions(+)
arch/riscv/include/asm/parse_asm.h +5 -0
@@ -3,6 +3,9 @@* Copyright (C) 2020 SiFive */ +#ifndef _ASM_RISCV_INSN_H +#define _ASM_RISCV_INSN_H +#include <linux/bits.h> /* The bit field of immediate value in I-type instruction */
@@ -217,3 +220,5 @@ static inline bool is_ ## INSN_NAME ## _insn(long insn) \ (RVC_X (x_,RVC_B_IMM_5_OPOFF ,RVC_B_IMM_5_MASK ) <<RVC_B_IMM_5_OFF ) | \ (RVC_X (x_,RVC_B_IMM_7_6_OPOFF ,RVC_B_IMM_7_6_MASK ) <<RVC_B_IMM_7_6_OFF ) | \ (RVC_IMM_SIGN(x_) << RVC_B_IMM_SIGN_OFF); }) + +#endif /* _ASM_RISCV_INSN_H */
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 26/104 scsi: core: Remove the /proc/scsi/${proc_name} directory earlier
In reply to Greg Kroah-HartmanFrom: Bart Van Assche <[email protected]>
[ Upstream commit fc663711b94468f4e1427ebe289c9f05669699c9 ]
Remove the /proc/scsi/${proc_name} directory earlier to fix a race condition between unloading and reloading kernel modules. This fixes a bug introduced in 2009 by commit 77c019768f06 ("[SCSI] fix /proc memory leak in the SCSI core").
Fix the following kernel warning:
proc_dir_entry 'scsi/scsi_debug' already registered
WARNING: CPU: 19 PID: 27986 at fs/proc/generic.c:376 proc_register+0x27d/0x2e0 Call Trace: proc_mkdir+0xb5/0xe0 scsi_proc_hostdir_add+0xb5/0x170 scsi_host_alloc+0x683/0x6c0 sdebug_driver_probe+0x6b/0x2d0 [scsi_debug] really_probe+0x159/0x540 __driver_probe_device+0xdc/0x230 driver_probe_device+0x4f/0x120 __device_attach_driver+0xef/0x180 bus_for_each_drv+0xe5/0x130 __device_attach+0x127/0x290 device_initial_probe+0x17/0x20 bus_probe_device+0x110/0x130 device_add+0x673/0xc80 device_register+0x1e/0x30 sdebug_add_host_helper+0x1a7/0x3b0 [scsi_debug] scsi_debug_init+0x64f/0x1000 [scsi_debug] do_one_initcall+0xd7/0x470 do_init_module+0xe7/0x330 load_module+0x122a/0x12c0 __do_sys_finit_module+0x124/0x1a0 __x64_sys_finit_module+0x46/0x50 do_syscall_64+0x38/0x80 entry_SYSCALL_64_after_hwframe+0x46/0xb0
--- drivers/scsi/hosts.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/scsi/hosts.c +2 -0
@@ -180,6 +180,7 @@ void scsi_remove_host(struct Scsi_Host *shost)scsi_forget_host (shost);mutex_unlock (&shost->scan_mutex);scsi_proc_host_rm (shost); +scsi_proc_hostdir_rm (shost->hostt);spin_lock_irqsave (shost->host_lock, flags);if (scsi_host_set_state (shost,SHOST_DEL ))
@@ -321,6 +322,7 @@ static void scsi_host_dev_release(struct device *dev)struct Scsi_Host *shost =dev_to_shost (dev);struct device *parent = dev->parent; +/* In case scsi_remove_host() has not been called. */ scsi_proc_hostdir_rm (shost->hostt);/* Wait for functions invoked through call_rcu(&shost->rcu, ...) */
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 27/104 ext4: Fix possible corruption when moving a directory
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
[ Upstream commit 0813299c586b175d7edb25f56412c54b812d0379 ]
When we are renaming a directory to a different directory, we need to update '..' entry in the moved directory. However nothing prevents moved directory from being modified and even converted from the inline format to the normal format. When such race happens the rename code gets confused and we crash. Fix the problem by locking the moved directory.
--- fs/ext4/namei.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
fs/ext4/namei.c +10 -1
@@ -3923,9 +3923,16 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,if (new.dir != old.dir &&EXT4_DIR_LINK_MAX (new.dir)) goto end_rename; } +/* +* We need to protect against old.inode directory getting +* converted from inline directory format into a normal one. +*/ +inode_lock_nested (old.inode,I_MUTEX_NONDIR2 ); retval =ext4_rename_dir_prepare (handle, &old); -if (retval) +if (retval) { +inode_unlock (old.inode); goto end_rename; + } }/* * If we're renaming a file within an inline_data dir and adding or
@@ -4050,6 +4057,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, }else {ext4_journal_stop (handle); } +if (old.dir_bh) +inode_unlock (old.inode); release_bh:brelse (old.dir_bh);brelse (old.bh);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 28/104 drm/nouveau/kms/nv50-: remove unused functions
In reply to Greg Kroah-HartmanFrom: Ben Skeggs <[email protected]>
[ Upstream commit 89ed996b888faaf11c69bb4cbc19f21475c9050e ]
Stable-dep-of: 3638a820c5c3 ("drm/nouveau/kms/nv50: fix nv50_wndw_new_ prototype")
--- drivers/gpu/drm/nouveau/dispnv50/disp.c | 16 ---------------- drivers/gpu/drm/nouveau/dispnv50/wndw.c | 12 ------------ drivers/gpu/drm/nouveau/dispnv50/wndw.h | 2 -- 3 files changed, 30 deletions(-)
drivers/gpu/drm/nouveau/dispnv50/disp.c +0 -16
@@ -2555,14 +2555,6 @@ nv50_display_fini(struct drm_device *dev, bool runtime, bool suspend) {struct nouveau_drm *drm =nouveau_drm (dev);struct drm_encoder *encoder; -struct drm_plane *plane; - -drm_for_each_plane (plane, dev) { -struct nv50_wndw *wndw =nv50_wndw (plane); -if (plane->funcs != &nv50_wndw) -continue ; -nv50_wndw_fini (wndw); - }list_for_each_entry (encoder, &dev->mode_config.encoder_list, head) {if (encoder->encoder_type !=DRM_MODE_ENCODER_DPMST )
@@ -2578,7 +2570,6 @@ nv50_display_init(struct drm_device *dev, bool resume, bool runtime) {struct nv50_core *core =nv50_disp (dev)->core;struct drm_encoder *encoder; -struct drm_plane *plane;if (resume || runtime) core->func->init (core);
@@ -2591,13 +2582,6 @@ nv50_display_init(struct drm_device *dev, bool resume, bool runtime) } } -drm_for_each_plane (plane, dev) { -struct nv50_wndw *wndw =nv50_wndw (plane); -if (plane->funcs != &nv50_wndw) -continue ; -nv50_wndw_init (wndw); - } -return 0 ; }
drivers/gpu/drm/nouveau/dispnv50/wndw.c +0 -12
@@ -690,18 +690,6 @@ nv50_wndw_notify(struct nvif_notify *notify)return NVIF_NOTIFY_KEEP ; } -void -nv50_wndw_fini (struct nv50_wndw *wndw) -{ -nvif_notify_put (&wndw->notify); -} - -void -nv50_wndw_init (struct nv50_wndw *wndw) -{ -nvif_notify_get (&wndw->notify); -} -static const u64 nv50_cursor_format_modifiers[] = {DRM_FORMAT_MOD_LINEAR ,DRM_FORMAT_MOD_INVALID ,
drivers/gpu/drm/nouveau/dispnv50/wndw.h +0 -2
@@ -40,8 +40,6 @@ int nv50_wndw_new_(const struct nv50_wndw_func *, struct drm_device *, enum drm_plane_type, const char *name, int index, const u32 *format, enum nv50_disp_interlock_type, u32 interlock_data, u32 heads, struct nv50_wndw **); -void nv50_wndw_init(struct nv50_wndw *); -void nv50_wndw_fini (struct nv50_wndw *); void nv50_wndw_flush_set(struct nv50_wndw *, u32 *interlock,struct nv50_wndw_atom *); void nv50_wndw_flush_clr(struct nv50_wndw *, u32 *interlock, bool flush,
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 29/104 drm/nouveau/kms/nv50: fix nv50_wndw_new_ prototype
In reply to Greg Kroah-HartmanFrom: Jiri Slaby (SUSE) <[email protected]>
[ Upstream commit 3638a820c5c3b52f327cebb174fd4274bee08aa7 ]
gcc-13 warns about mismatching types for enums. That revealed switched
arguments of nv50_wndw_new_():
drivers/gpu/drm/nouveau/dispnv50/wndw.c:696:1: error: conflicting types for 'nv50_wndw_new_' due to enum/integer mismatch; have 'int(const struct nv50_wndw_func *, struct drm_device *, enum drm_plane_type, const char *, int, const u32 *, u32, enum nv50_disp_interlock_type, u32, struct nv50_wndw **)' drivers/gpu/drm/nouveau/dispnv50/wndw.h:36:5: note: previous declaration of 'nv50_wndw_new_' with type 'int(const struct nv50_wndw_func *, struct drm_device *, enum drm_plane_type, const char *, int, const u32 *, enum nv50_disp_interlock_type, u32, u32, struct nv50_wndw **)'
It can be barely visible, but the declaration says about the parameters in the middle:
enum nv50_disp_interlock_type,
u32 interlock_data,
u32 heads,
While the definition states differently:
u32 heads,
enum nv50_disp_interlock_type interlock_type,
u32 interlock_data,
Unify/fix the declaration to match the definition.
--- drivers/gpu/drm/nouveau/dispnv50/wndw.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/gpu/drm/nouveau/dispnv50/wndw.h +3 -2
@@ -38,8 +38,9 @@ struct nv50_wndw {int nv50_wndw_new_ (const struct nv50_wndw_func *,struct drm_device *,enum drm_plane_type ,const char *name,int index, -const u32 *format,enum nv50_disp_interlock_type , -u32 interlock_data,u32 heads,struct nv50_wndw **); +const u32 *format,u32 heads, +enum nv50_disp_interlock_type ,u32 interlock_data, +struct nv50_wndw **);void nv50_wndw_flush_set (struct nv50_wndw *,u32 *interlock,struct nv50_wndw_atom *); void nv50_wndw_flush_clr(struct nv50_wndw *, u32 *interlock, bool flush,
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 30/104 drm/msm: Fix potential invalid ptr free
In reply to Greg Kroah-HartmanFrom: Rob Clark <[email protected]>
[ Upstream commit 8a86f213f4426f19511a16d886871805b35c3acf ]
The error path cleanup expects that chain and syncobj are either NULL or valid pointers. But post_deps was not allocated with __GFP_ZERO.
Patchwork: https://patchwork.freedesktop.org/patch/523051/
--- drivers/gpu/drm/msm/msm_gem_submit.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/gpu/drm/msm/msm_gem_submit.c +2 -3
@@ -494,8 +494,8 @@ static struct msm_submit_post_dep *msm_parse_post_deps(struct drm_device *dev,int ret =0 ;uint32_t i, j; - post_deps =kmalloc_array (nr_syncobjs,sizeof (*post_deps), -GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); + post_deps =kcalloc (nr_syncobjs,sizeof (*post_deps), +GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);if (!post_deps)return ERR_PTR (-ENOMEM );
@@ -510,7 +510,6 @@ static struct msm_submit_post_dep *msm_parse_post_deps(struct drm_device *dev, } post_deps[i].point = syncobj_desc.point; - post_deps[i].chain =NULL ;if (syncobj_desc.flags) { ret = -EINVAL ;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 31/104 drm/msm/a5xx: fix setting of the CP_PREEMPT_ENABLE_LOCAL register
In reply to Greg Kroah-HartmanFrom: Dmitry Baryshkov <[email protected]>
[ Upstream commit a7a4c19c36de1e4b99b06e4060ccc8ab837725bc ]
Rather than writing CP_PREEMPT_ENABLE_GLOBAL twice, follow the vendor kernel and set CP_PREEMPT_ENABLE_LOCAL register instead. a5xx_submit() will override it during submission, but let's get the sequence correct.
Patchwork: https://patchwork.freedesktop.org/patch/522638/
--- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/msm/adreno/a5xx_gpu.c +2 -2
@@ -144,8 +144,8 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)OUT_RING (ring,1 );/* Enable local preemption for finegrain preemption */ -OUT_PKT7 (ring,CP_PREEMPT_ENABLE_GLOBAL ,1 ); -OUT_RING (ring,0x02 ); +OUT_PKT7 (ring,CP_PREEMPT_ENABLE_LOCAL ,1 ); +OUT_RING (ring,0x1 );/* Allow CP_CONTEXT_SWITCH_YIELD packets in the IB2 */ OUT_PKT7 (ring,CP_YIELD_ENABLE ,1 );
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 32/104 drm/msm: Document and rename preempt_lock
In reply to Greg Kroah-HartmanFrom: Rob Clark <[email protected]>
[ Upstream commit 77c406038e830a4b6219b14a116cd2a6ac9f4908 ]
Before adding another lock, give ring->lock a more descriptive name.
Stable-dep-of: b4fb748f0b73 ("drm/msm/a5xx: fix the emptyness check in the preempt code")
--- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 4 ++-- drivers/gpu/drm/msm/adreno/a5xx_preempt.c | 12 ++++++------ drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 4 ++-- drivers/gpu/drm/msm/msm_ringbuffer.c | 2 +- drivers/gpu/drm/msm/msm_ringbuffer.h | 7 ++++++- 5 files changed, 17 insertions(+), 12 deletions(-)
drivers/gpu/drm/msm/adreno/a5xx_gpu.c +2 -2
@@ -36,7 +36,7 @@ void a5xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring,OUT_RING (ring,upper_32_bits (shadowptr (a5xx_gpu, ring))); } -spin_lock_irqsave (&ring->lock, flags); +spin_lock_irqsave (&ring->preempt_lock, flags);/* Copy the shadow to the actual register */ ring->cur = ring->next;
@@ -44,7 +44,7 @@ void a5xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring,/* Make sure to wrap wptr if we need to */ wptr =get_wptr (ring); -spin_unlock_irqrestore (&ring->lock, flags); +spin_unlock_irqrestore (&ring->preempt_lock, flags);/* Make sure everything is posted before making a decision */ mb ();
drivers/gpu/drm/msm/adreno/a5xx_preempt.c +6 -6
@@ -45,9 +45,9 @@ static inline void update_wptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)if (!ring)return ; -spin_lock_irqsave (&ring->lock, flags); +spin_lock_irqsave (&ring->preempt_lock, flags); wptr =get_wptr (ring); -spin_unlock_irqrestore (&ring->lock, flags); +spin_unlock_irqrestore (&ring->preempt_lock, flags);gpu_write (gpu,REG_A5XX_CP_RB_WPTR , wptr); }
@@ -62,9 +62,9 @@ static struct msm_ringbuffer *get_next_ring(struct msm_gpu *gpu)bool empty;struct msm_ringbuffer *ring = gpu->rb[i]; -spin_lock_irqsave (&ring->lock, flags); +spin_lock_irqsave (&ring->preempt_lock, flags); empty = (get_wptr (ring) == ring->memptrs->rptr); -spin_unlock_irqrestore (&ring->lock, flags); +spin_unlock_irqrestore (&ring->preempt_lock, flags);if (!empty)return ring;
@@ -132,9 +132,9 @@ void a5xx_preempt_trigger(struct msm_gpu *gpu) }/* Make sure the wptr doesn't update while we're in motion */ -spin_lock_irqsave (&ring->lock, flags); +spin_lock_irqsave (&ring->preempt_lock, flags); a5xx_gpu->preempt[ring->id]->wptr =get_wptr (ring); -spin_unlock_irqrestore (&ring->lock, flags); +spin_unlock_irqrestore (&ring->preempt_lock, flags);/* Set the address of the incoming preemption record */ gpu_write64(gpu, REG_A5XX_CP_CONTEXT_SWITCH_RESTORE_ADDR_LO,
drivers/gpu/drm/msm/adreno/a6xx_gpu.c +2 -2
@@ -65,7 +65,7 @@ static void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)OUT_RING (ring,upper_32_bits (shadowptr (a6xx_gpu, ring))); } -spin_lock_irqsave (&ring->lock, flags); +spin_lock_irqsave (&ring->preempt_lock, flags);/* Copy the shadow to the actual register */ ring->cur = ring->next;
@@ -73,7 +73,7 @@ static void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)/* Make sure to wrap wptr if we need to */ wptr =get_wptr (ring); -spin_unlock_irqrestore (&ring->lock, flags); +spin_unlock_irqrestore (&ring->preempt_lock, flags);/* Make sure everything is posted before making a decision */ mb ();
drivers/gpu/drm/msm/msm_ringbuffer.c +1 -1
@@ -46,7 +46,7 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id, ring->memptrs_iova = memptrs_iova;INIT_LIST_HEAD (&ring->submits); -spin_lock_init (&ring->lock); +spin_lock_init (&ring->preempt_lock);snprintf (name,sizeof (name),"gpu-ring-%d" , ring->id);
drivers/gpu/drm/msm/msm_ringbuffer.h +6 -1
@@ -46,7 +46,12 @@ struct msm_ringbuffer {struct msm_rbmemptrs *memptrs;uint64_t memptrs_iova;struct msm_fence_context *fctx; -spinlock_t lock; + +/* +* preempt_lock protects preemption and serializes wptr updates against +* preemption. Can be aquired from irq context. +*/ +spinlock_t preempt_lock; }; struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id,
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 33/104 drm/msm/a5xx: fix the emptyness check in the preempt code
In reply to Greg Kroah-HartmanFrom: Dmitry Baryshkov <[email protected]>
[ Upstream commit b4fb748f0b734ce1d2e7834998cc599fcbd25d67 ]
Quoting Yassine: ring->memptrs->rptr is never updated and stays 0, so the comparison always evaluates to false and get_next_ring always returns ring 0 thinking it isn't empty.
Fix this by calling get_rptr() instead of reading rptr directly.
Patchwork: https://patchwork.freedesktop.org/patch/522642/
--- drivers/gpu/drm/msm/adreno/a5xx_preempt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/msm/adreno/a5xx_preempt.c +1 -1
@@ -63,7 +63,7 @@ static struct msm_ringbuffer *get_next_ring(struct msm_gpu *gpu)struct msm_ringbuffer *ring = gpu->rb[i];spin_lock_irqsave (&ring->preempt_lock, flags); - empty = (get_wptr (ring) == ring->memptrs->rptr); + empty = (get_wptr (ring) == gpu->funcs->get_rptr (gpu, ring));spin_unlock_irqrestore (&ring->preempt_lock, flags);if (!empty)
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 34/104 drm/msm/a5xx: fix context faults during ring switch
In reply to Greg Kroah-HartmanFrom: Dmitry Baryshkov <[email protected]>
[ Upstream commit 32e7083429d46f29080626fe387ff90c086b1fbe ]
The rptr_addr is set in the preempt_init_ring(), which is called from a5xx_gpu_init(). It uses shadowptr() to set the address, however the shadow_iova is not yet initialized at that time. Move the rptr_addr setting to the a5xx_preempt_hw_init() which is called after setting the shadow_iova, getting the correct value for the address.
Patchwork: https://patchwork.freedesktop.org/patch/522640/
--- drivers/gpu/drm/msm/adreno/a5xx_preempt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/msm/adreno/a5xx_preempt.c +1 -1
@@ -210,6 +210,7 @@ void a5xx_preempt_hw_init(struct msm_gpu *gpu) a5xx_gpu->preempt[i]->wptr =0 ; a5xx_gpu->preempt[i]->rptr =0 ; a5xx_gpu->preempt[i]->rbase = gpu->rb[i]->iova; + a5xx_gpu->preempt[i]->rptr_addr =shadowptr (a5xx_gpu, gpu->rb[i]); }/* Write a 0 to signal that we aren't switching pagetables */
@@ -261,7 +262,6 @@ static int preempt_init_ring(struct a5xx_gpu *a5xx_gpu, ptr->data =0 ; ptr->cntl =MSM_GPU_RB_CNTL_DEFAULT |AXXX_CP_RB_CNTL_NO_UPDATE ; - ptr->rptr_addr =shadowptr (a5xx_gpu, ring); ptr->counter = counters_iova;return 0 ;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 35/104 bgmac: fix *initial* chip reset to support BCM5358
In reply to Greg Kroah-HartmanFrom: Rafał Miłecki <[email protected]>
[ Upstream commit f99e6d7c4ed3be2531bd576425a5bd07fb133bd7 ]
While bringing hardware up we should perform a full reset including the switch bit (BGMAC_BCMA_IOCTL_SW_RESET aka SICF_SWRST). It's what specification says and what reference driver does.
This seems to be critical for the BCM5358. Without this hardware doesn't get initialized properly and doesn't seem to transmit or receive any packets.
Originally bgmac was calling bgmac_chip_reset() before setting "has_robosw" property which resulted in expected behaviour. That has changed as a side effect of adding platform device support which regressed BCM5358 support.
--- drivers/net/ethernet/broadcom/bgmac.c | 8 ++++++-- drivers/net/ethernet/broadcom/bgmac.h | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-)
drivers/net/ethernet/broadcom/bgmac.c +6 -2
@@ -890,13 +890,13 @@ static void bgmac_chip_reset_idm_config(struct bgmac *bgmac)if (iost &BGMAC_BCMA_IOST_ATTACHED ) { flags =BGMAC_BCMA_IOCTL_SW_CLKEN ; -if (!bgmac->has_robosw) +if (bgmac->in_init || !bgmac->has_robosw) flags |=BGMAC_BCMA_IOCTL_SW_RESET ; }bgmac_clk_enable (bgmac, flags); } -if (iost &BGMAC_BCMA_IOST_ATTACHED && !bgmac->has_robosw) +if (iost &BGMAC_BCMA_IOST_ATTACHED && (bgmac->in_init || !bgmac->has_robosw))bgmac_idm_write (bgmac,BCMA_IOCTL ,bgmac_idm_read (bgmac,BCMA_IOCTL ) & ~BGMAC_BCMA_IOCTL_SW_RESET );
@@ -1490,6 +1490,8 @@ int bgmac_enet_probe(struct bgmac *bgmac)struct net_device *net_dev = bgmac->net_dev;int err; + bgmac->in_init = true; +bgmac_chip_intrs_off (bgmac); net_dev->irq = bgmac->irq;
@@ -1542,6 +1544,8 @@ int bgmac_enet_probe(struct bgmac *bgmac)/* Omit FCS from max MTU size */ net_dev->max_mtu =BGMAC_RX_MAX_FRAME_SIZE -ETH_FCS_LEN ; + bgmac->in_init = false; + err =register_netdev (bgmac->net_dev);if (err) {dev_err (bgmac->dev,"Cannot register net device\n" );
drivers/net/ethernet/broadcom/bgmac.h +2 -0
@@ -512,6 +512,8 @@ struct bgmac {int irq;u32 int_mask; +bool in_init; +/* Current MAC state */ int mac_speed;int mac_duplex;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 36/104 nfc: fdp: add null check of devm_kmalloc_array in fdp_nci_i2c_read_device_properties
In reply to Greg Kroah-HartmanFrom: Kang Chen <[email protected]>
[ Upstream commit 11f180a5d62a51b484e9648f9b310e1bd50b1a57 ]
devm_kmalloc_array may fails, *fw_vsc_cfg might be null and cause out-of-bounds write in device_property_read_u8_array later.
--- drivers/nfc/fdp/i2c.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/nfc/fdp/i2c.c +4 -0
@@ -249,6 +249,9 @@ static void fdp_nci_i2c_read_device_properties(struct device *dev, len,sizeof (**fw_vsc_cfg), GFP_KERNEL); +if (!*fw_vsc_cfg) + goto alloc_err; + r =device_property_read_u8_array (dev,FDP_DP_FW_VSC_CFG_NAME , *fw_vsc_cfg, len);
@@ -262,6 +265,7 @@ static void fdp_nci_i2c_read_device_properties(struct device *dev, *fw_vsc_cfg =NULL ; } +alloc_err:dev_dbg (dev,"Clock type: %d, clock frequency: %d, VSC: %s" , *clock_type, *clock_freq, *fw_vsc_cfg !=NULL ?"yes" :"no" ); }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 37/104 powerpc: dts: t1040rdb: fix compatible string for Rev A boards
In reply to Greg Kroah-HartmanFrom: Vladimir Oltean <[email protected]>
[ Upstream commit ae44f1c9d1fc54aeceb335fedb1e73b2c3ee4561 ]
It looks like U-Boot fails to start the kernel properly when the compatible string of the board isn't fsl,T1040RDB, so stop overriding it from the rev-a.dts.
--- arch/powerpc/boot/dts/fsl/t1040rdb-rev-a.dts | 1 - 1 file changed, 1 deletion(-)
arch/powerpc/boot/dts/fsl/t1040rdb-rev-a.dts +0 -1
@@ -10,7 +10,6 @@ / { model = "fsl,T1040RDB-REV-A"; - compatible = "fsl,T1040RDB-REV-A"; }; &seville_port0 {
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 38/104 ila: do not generate empty messages in ila_xlat_nl_cmd_get_mapping()
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
[ Upstream commit 693aa2c0d9b6d5b1f2745d31b6e70d09dbbaf06e ]
ila_xlat_nl_cmd_get_mapping() generates an empty skb, triggerring a recent sanity check [1].
Instead, return an error code, so that user space
can get it.
[1]skb_assert_len
WARNING: CPU: 0 PID: 5923 at include/linux/skbuff.h:2527 skb_assert_len include/linux/skbuff.h:2527 [inline] WARNING: CPU: 0 PID: 5923 at include/linux/skbuff.h:2527 __dev_queue_xmit+0x1bc0/0x3488 net/core/dev.c:4156 Modules linked in: CPU: 0 PID: 5923 Comm: syz-executor269 Not tainted 6.2.0-syzkaller-18300-g2ebd1fbb946d #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/21/2023 pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : skb_assert_len include/linux/skbuff.h:2527 [inline] pc : __dev_queue_xmit+0x1bc0/0x3488 net/core/dev.c:4156 lr : skb_assert_len include/linux/skbuff.h:2527 [inline] lr : __dev_queue_xmit+0x1bc0/0x3488 net/core/dev.c:4156
sp : ffff80001e0d6c40
x29: ffff80001e0d6e60 x28: dfff800000000000 x27: ffff0000c86328c0
x26: dfff800000000000 x25: ffff0000c8632990 x24: ffff0000c8632a00
x23: 0000000000000000 x22: 1fffe000190c6542 x21: ffff0000c8632a10
x20: ffff0000c8632a00 x19: ffff80001856e000 x18: ffff80001e0d5fc0
x17: 0000000000000000 x16: ffff80001235d16c x15: 0000000000000000
x14: 0000000000000000 x13: 0000000000000001 x12: 0000000000000001
x11: ff80800008353a30 x10: 0000000000000000 x9 : 21567eaf25bfb600 x8 : 21567eaf25bfb600 x7 : 0000000000000001 x6 : 0000000000000001 x5 : ffff80001e0d6558 x4 : ffff800015c74760 x3 : ffff800008596744 x2 : 0000000000000001 x1 : 0000000100000000 x0 : 000000000000000e
Call trace: skb_assert_len include/linux/skbuff.h:2527 [inline] __dev_queue_xmit+0x1bc0/0x3488 net/core/dev.c:4156 dev_queue_xmit include/linux/netdevice.h:3033 [inline] __netlink_deliver_tap_skb net/netlink/af_netlink.c:307 [inline] __netlink_deliver_tap+0x45c/0x6f8 net/netlink/af_netlink.c:325 netlink_deliver_tap+0xf4/0x174 net/netlink/af_netlink.c:338 __netlink_sendskb net/netlink/af_netlink.c:1283 [inline] netlink_sendskb+0x6c/0x154 net/netlink/af_netlink.c:1292 netlink_unicast+0x334/0x8d4 net/netlink/af_netlink.c:1380 nlmsg_unicast include/net/netlink.h:1099 [inline] genlmsg_unicast include/net/genetlink.h:433 [inline] genlmsg_reply include/net/genetlink.h:443 [inline] ila_xlat_nl_cmd_get_mapping+0x620/0x7d0 net/ipv6/ila/ila_xlat.c:493 genl_family_rcv_msg_doit net/netlink/genetlink.c:968 [inline] genl_family_rcv_msg net/netlink/genetlink.c:1048 [inline] genl_rcv_msg+0x938/0xc1c net/netlink/genetlink.c:1065 netlink_rcv_skb+0x214/0x3c4 net/netlink/af_netlink.c:2574 genl_rcv+0x38/0x50 net/netlink/genetlink.c:1076 netlink_unicast_kernel net/netlink/af_netlink.c:1339 [inline] netlink_unicast+0x660/0x8d4 net/netlink/af_netlink.c:1365 netlink_sendmsg+0x800/0xae0 net/netlink/af_netlink.c:1942 sock_sendmsg_nosec net/socket.c:714 [inline] sock_sendmsg net/socket.c:734 [inline] ____sys_sendmsg+0x558/0x844 net/socket.c:2479 ___sys_sendmsg net/socket.c:2533 [inline] __sys_sendmsg+0x26c/0x33c net/socket.c:2562 __do_sys_sendmsg net/socket.c:2571 [inline] __se_sys_sendmsg net/socket.c:2569 [inline] __arm64_sys_sendmsg+0x80/0x94 net/socket.c:2569 __invoke_syscall arch/arm64/kernel/syscall.c:38 [inline] invoke_syscall+0x98/0x2c0 arch/arm64/kernel/syscall.c:52 el0_svc_common+0x138/0x258 arch/arm64/kernel/syscall.c:142 do_el0_svc+0x64/0x198 arch/arm64/kernel/syscall.c:193 el0_svc+0x58/0x168 arch/arm64/kernel/entry-common.c:637 el0t_64_sync_handler+0x84/0xf0 arch/arm64/kernel/entry-common.c:655 el0t_64_sync+0x190/0x194 arch/arm64/kernel/entry.S:591 irq event stamp: 136484 hardirqs last enabled at (136483): [<ffff800008350244>] __up_console_sem+0x60/0xb4 kernel/printk/printk.c:345 hardirqs last disabled at (136484): [<ffff800012358d60>] el1_dbg+0x24/0x80 arch/arm64/kernel/entry-common.c:405 softirqs last enabled at (136418): [<ffff800008020ea8>] softirq_handle_end kernel/softirq.c:414 [inline] softirqs last enabled at (136418): [<ffff800008020ea8>] __do_softirq+0xd4c/0xfa4 kernel/softirq.c:600 softirqs last disabled at (136371): [<ffff80000802b4a4>] ____do_softirq+0x14/0x20 arch/arm64/kernel/irq.c:80 ---[ end trace 0000000000000000 ]---
skb len=0 headroom=0 headlen=0 tailroom=192 mac=(0,0) net=(0,-1) trans=-1 shinfo(txflags=0 nr_frags=0 gso(size=0 type=0 segs=0)) csum(0x0 ip_summed=0 complete_sw=0 valid=0 level=0) hash(0x0 sw=0 l4=0) proto=0x0010 pkttype=6 iif=0 dev name=nlmon0 feat=0x0000000000005861
--- net/ipv6/ila/ila_xlat.c | 1 + 1 file changed, 1 insertion(+)
net/ipv6/ila/ila_xlat.c +1 -0
@@ -477,6 +477,7 @@ int ila_xlat_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info)rcu_read_lock (); + ret = -ESRCH ; ila =ila_lookup_by_params (&xp, ilan);if (ila) { ret = ila_dump_info(ila,
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 39/104 selftests: nft_nat: ensuring the listening side is up before starting the client
In reply to Greg Kroah-HartmanFrom: Hangbin Liu <[email protected]>
[ Upstream commit 2067e7a00aa604b94de31d64f29b8893b1696f26 ]
The test_local_dnat_portonly() function initiates the client-side as soon as it sets the listening side to the background. This could lead to a race condition where the server may not be ready to listen. To ensure that the server-side is up and running before initiating the client-side, a delay is introduced to the test_local_dnat_portonly() function.
Before the fix:
# ./nft_nat.sh PASS: netns routing/connectivity: ns0-rthlYrBU can reach ns1-rthlYrBU and ns2-rthlYrBU PASS: ping to ns1-rthlYrBU was ip NATted to ns2-rthlYrBU PASS: ping to ns1-rthlYrBU OK after ip nat output chain flush PASS: ipv6 ping to ns1-rthlYrBU was ip6 NATted to ns2-rthlYrBU 2023/02/27 04:11:03 socat[6055] E connect(5, AF=2 10.0.1.99:2000, 16): Connection refused ERROR: inet port rewrite
After the fix:
# ./nft_nat.sh PASS: netns routing/connectivity: ns0-9sPJV6JJ can reach ns1-9sPJV6JJ and ns2-9sPJV6JJ PASS: ping to ns1-9sPJV6JJ was ip NATted to ns2-9sPJV6JJ PASS: ping to ns1-9sPJV6JJ OK after ip nat output chain flush PASS: ipv6 ping to ns1-9sPJV6JJ was ip6 NATted to ns2-9sPJV6JJ PASS: inet port rewrite without l3 address
--- tools/testing/selftests/netfilter/nft_nat.sh | 2 ++ 1 file changed, 2 insertions(+)
tools/testing/selftests/netfilter/nft_nat.sh +2 -0
@@ -404,6 +404,8 @@ EOF echo SERVER-$family | ip netns exec "$ns1" timeout 5 socat -u STDIN TCP-LISTEN:2000 & sc_s=$! + sleep 1 + result=$(ip netns exec "$ns0" timeout 1 socat TCP:$daddr:2000 STDOUT) if [ "$result" = "SERVER-inet" ];then
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 40/104 net: usb: lan78xx: Remove lots of set but unused ret variables
In reply to Greg Kroah-HartmanFrom: Lee Jones <[email protected]>
[ Upstream commit 06cd7c46b3ab3f2252c61bf85b191236cf0254e1 ]
Fixes the following W=1 kernel build warning(s):
drivers/net/usb/lan78xx.c: In function ‘lan78xx_read_raw_otp’:
drivers/net/usb/lan78xx.c:825:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] drivers/net/usb/lan78xx.c: In function ‘lan78xx_write_raw_otp’:
drivers/net/usb/lan78xx.c:879:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] drivers/net/usb/lan78xx.c: In function ‘lan78xx_deferred_multicast_write’:
drivers/net/usb/lan78xx.c:1041:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] drivers/net/usb/lan78xx.c: In function ‘lan78xx_update_flowcontrol’:
drivers/net/usb/lan78xx.c:1127:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] drivers/net/usb/lan78xx.c: In function ‘lan78xx_init_mac_address’:
drivers/net/usb/lan78xx.c:1666:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] drivers/net/usb/lan78xx.c: In function ‘lan78xx_link_status_change’:
drivers/net/usb/lan78xx.c:1841:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] drivers/net/usb/lan78xx.c: In function ‘lan78xx_irq_bus_sync_unlock’:
drivers/net/usb/lan78xx.c:1920:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] drivers/net/usb/lan78xx.c: In function ‘lan8835_fixup’:
drivers/net/usb/lan78xx.c:1994:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] drivers/net/usb/lan78xx.c: In function ‘lan78xx_set_rx_max_frame_length’:
drivers/net/usb/lan78xx.c:2192:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] drivers/net/usb/lan78xx.c: In function ‘lan78xx_change_mtu’:
drivers/net/usb/lan78xx.c:2270:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] drivers/net/usb/lan78xx.c: In function ‘lan78xx_set_mac_addr’:
drivers/net/usb/lan78xx.c:2299:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] drivers/net/usb/lan78xx.c: In function ‘lan78xx_set_features’:
drivers/net/usb/lan78xx.c:2333:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] drivers/net/usb/lan78xx.c: In function ‘lan78xx_set_suspend’:
drivers/net/usb/lan78xx.c:3807:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable]
Stable-dep-of: e57cf3639c32 ("net: lan78xx: fix accessing the LAN7800's internal phy specific registers from the MAC driver")
--- drivers/net/usb/lan78xx.c | 168 ++++++++++++++++++-------------------- 1 file changed, 78 insertions(+), 90 deletions(-)
drivers/net/usb/lan78xx.c +78 -90
@@ -824,20 +824,19 @@ static int lan78xx_read_raw_otp(struct lan78xx_net *dev, u32 offset, u32 length, u8 *data) { int i; -int ret;u32 buf;unsigned long timeout; - ret =lan78xx_read_reg (dev,OTP_PWR_DN , &buf); +lan78xx_read_reg (dev,OTP_PWR_DN , &buf);if (buf &OTP_PWR_DN_PWRDN_N_ ) {/* clear it and wait to be cleared */ - ret =lan78xx_write_reg (dev,OTP_PWR_DN ,0 ); +lan78xx_write_reg (dev,OTP_PWR_DN ,0 ); timeout = jiffies +HZ ; do { usleep_range(1, 10); - ret = lan78xx_read_reg(dev, OTP_PWR_DN, &buf); + lan78xx_read_reg(dev, OTP_PWR_DN, &buf); if (time_after(jiffies, timeout)) { netdev_warn(dev->net, "timeout on OTP_PWR_DN");
@@ -847,18 +846,18 @@ static int lan78xx_read_raw_otp(struct lan78xx_net *dev, u32 offset, }for (i =0 ; i < length; i++) { - ret =lan78xx_write_reg (dev,OTP_ADDR1 , +lan78xx_write_reg (dev,OTP_ADDR1 , ((offset + i) >>8 ) &OTP_ADDR1_15_11 ); - ret =lan78xx_write_reg (dev,OTP_ADDR2 , +lan78xx_write_reg (dev,OTP_ADDR2 , ((offset + i) &OTP_ADDR2_10_3 )); - ret =lan78xx_write_reg (dev,OTP_FUNC_CMD ,OTP_FUNC_CMD_READ_ ); - ret =lan78xx_write_reg (dev,OTP_CMD_GO ,OTP_CMD_GO_GO_ ); +lan78xx_write_reg (dev,OTP_FUNC_CMD ,OTP_FUNC_CMD_READ_ ); +lan78xx_write_reg (dev,OTP_CMD_GO ,OTP_CMD_GO_GO_ ); timeout = jiffies +HZ ; do { udelay(1); - ret = lan78xx_read_reg(dev, OTP_STATUS, &buf); + lan78xx_read_reg(dev, OTP_STATUS, &buf); if (time_after(jiffies, timeout)) { netdev_warn(dev->net, "timeout on OTP_STATUS");
@@ -866,7 +865,7 @@ static int lan78xx_read_raw_otp(struct lan78xx_net *dev, u32 offset, } }while (buf &OTP_STATUS_BUSY_ ); - ret =lan78xx_read_reg (dev,OTP_RD_DATA , &buf); +lan78xx_read_reg (dev,OTP_RD_DATA , &buf); data[i] = (u8)(buf &0xFF ); }
@@ -878,20 +877,19 @@ static int lan78xx_write_raw_otp(struct lan78xx_net *dev, u32 offset, u32 length, u8 *data) { int i; -int ret;u32 buf;unsigned long timeout; - ret =lan78xx_read_reg (dev,OTP_PWR_DN , &buf); +lan78xx_read_reg (dev,OTP_PWR_DN , &buf);if (buf &OTP_PWR_DN_PWRDN_N_ ) {/* clear it and wait to be cleared */ - ret =lan78xx_write_reg (dev,OTP_PWR_DN ,0 ); +lan78xx_write_reg (dev,OTP_PWR_DN ,0 ); timeout = jiffies +HZ ; do { udelay(1); - ret = lan78xx_read_reg(dev, OTP_PWR_DN, &buf); + lan78xx_read_reg(dev, OTP_PWR_DN, &buf); if (time_after(jiffies, timeout)) { netdev_warn(dev->net, "timeout on OTP_PWR_DN completion");
@@ -901,21 +899,21 @@ static int lan78xx_write_raw_otp(struct lan78xx_net *dev, u32 offset, }/* set to BYTE program mode */ - ret =lan78xx_write_reg (dev,OTP_PRGM_MODE ,OTP_PRGM_MODE_BYTE_ ); +lan78xx_write_reg (dev,OTP_PRGM_MODE ,OTP_PRGM_MODE_BYTE_ );for (i =0 ; i < length; i++) { - ret =lan78xx_write_reg (dev,OTP_ADDR1 , +lan78xx_write_reg (dev,OTP_ADDR1 , ((offset + i) >>8 ) &OTP_ADDR1_15_11 ); - ret =lan78xx_write_reg (dev,OTP_ADDR2 , +lan78xx_write_reg (dev,OTP_ADDR2 , ((offset + i) &OTP_ADDR2_10_3 )); - ret =lan78xx_write_reg (dev,OTP_PRGM_DATA , data[i]); - ret =lan78xx_write_reg (dev,OTP_TST_CMD ,OTP_TST_CMD_PRGVRFY_ ); - ret =lan78xx_write_reg (dev,OTP_CMD_GO ,OTP_CMD_GO_GO_ ); +lan78xx_write_reg (dev,OTP_PRGM_DATA , data[i]); +lan78xx_write_reg (dev,OTP_TST_CMD ,OTP_TST_CMD_PRGVRFY_ ); +lan78xx_write_reg (dev,OTP_CMD_GO ,OTP_CMD_GO_GO_ ); timeout = jiffies +HZ ; do { udelay(1); - ret = lan78xx_read_reg(dev, OTP_STATUS, &buf); + lan78xx_read_reg(dev, OTP_STATUS, &buf); if (time_after(jiffies, timeout)) { netdev_warn(dev->net, "Timeout on OTP_STATUS completion");
@@ -1040,7 +1038,6 @@ static void lan78xx_deferred_multicast_write(struct work_struct *param) container_of(param, struct lan78xx_priv, set_multicast);struct lan78xx_net *dev = pdata->dev;int i; -int ret;netif_dbg (dev, drv, dev->net,"deferred multicast write 0x%08x\n" , pdata->rfe_ctl);
@@ -1049,14 +1046,14 @@ static void lan78xx_deferred_multicast_write(struct work_struct *param) DP_SEL_VHF_HASH_LEN, pdata->mchash_table);for (i =1 ; i <NUM_OF_MAF ; i++) { - ret =lan78xx_write_reg (dev,MAF_HI (i),0 ); - ret =lan78xx_write_reg (dev,MAF_LO (i), +lan78xx_write_reg (dev,MAF_HI (i),0 ); +lan78xx_write_reg (dev,MAF_LO (i), pdata->pfilter_table[i][1 ]); - ret =lan78xx_write_reg (dev,MAF_HI (i), +lan78xx_write_reg (dev,MAF_HI (i), pdata->pfilter_table[i][0 ]); } - ret =lan78xx_write_reg (dev,RFE_CTL , pdata->rfe_ctl); +lan78xx_write_reg (dev,RFE_CTL , pdata->rfe_ctl); }static void lan78xx_set_multicast (struct net_device *netdev)
@@ -1126,7 +1123,6 @@ static int lan78xx_update_flowcontrol(struct lan78xx_net *dev, u8 duplex, u16 lcladv, u16 rmtadv) {u32 flow =0 , fct_flow =0 ; -int ret;u8 cap;if (dev->fc_autoneg)
@@ -1149,10 +1145,10 @@ static int lan78xx_update_flowcontrol(struct lan78xx_net *dev, u8 duplex, (cap &FLOW_CTRL_RX ?"enabled" :"disabled" ), (cap & FLOW_CTRL_TX ? "enabled" : "disabled")); - ret =lan78xx_write_reg (dev,FCT_FLOW , fct_flow); +lan78xx_write_reg (dev,FCT_FLOW , fct_flow);/* threshold value should be set before enabling flow */ - ret =lan78xx_write_reg (dev,FLOW , flow); +lan78xx_write_reg (dev,FLOW , flow);return 0 ; }
@@ -1673,11 +1669,10 @@ static const struct ethtool_ops lan78xx_ethtool_ops = {static void lan78xx_init_mac_address (struct lan78xx_net *dev) {u32 addr_lo, addr_hi; -int ret;u8 addr[6 ]; - ret =lan78xx_read_reg (dev,RX_ADDRL , &addr_lo); - ret =lan78xx_read_reg (dev,RX_ADDRH , &addr_hi); +lan78xx_read_reg (dev,RX_ADDRL , &addr_lo); +lan78xx_read_reg (dev,RX_ADDRH , &addr_hi); addr[0 ] = addr_lo &0xFF ; addr[1 ] = (addr_lo >>8 ) &0xFF ;
@@ -1710,12 +1705,12 @@ static void lan78xx_init_mac_address(struct lan78xx_net *dev) (addr[2 ] <<16 ) | (addr[3 ] <<24 ); addr_hi = addr[4 ] | (addr[5 ] <<8 ); - ret =lan78xx_write_reg (dev,RX_ADDRL , addr_lo); - ret =lan78xx_write_reg (dev,RX_ADDRH , addr_hi); +lan78xx_write_reg (dev,RX_ADDRL , addr_lo); +lan78xx_write_reg (dev,RX_ADDRH , addr_hi); } - ret =lan78xx_write_reg (dev,MAF_LO (0 ), addr_lo); - ret =lan78xx_write_reg (dev,MAF_HI (0 ), addr_hi |MAF_HI_VALID_ ); +lan78xx_write_reg (dev,MAF_LO (0 ), addr_lo); +lan78xx_write_reg (dev,MAF_HI (0 ), addr_hi |MAF_HI_VALID_ );ether_addr_copy (dev->net->dev_addr, addr); }
@@ -1848,7 +1843,7 @@ static void lan78xx_remove_mdio(struct lan78xx_net *dev)static void lan78xx_link_status_change (struct net_device *net) {struct phy_device *phydev = net->phydev; -int ret, temp; +int temp;/* At forced 100 F/H mode, chip may fail to set mode correctly * when cable is switched between long(~50+m) and short one.
@@ -1859,7 +1854,7 @@ static void lan78xx_link_status_change(struct net_device *net)/* disable phy interrupt */ temp =phy_read (phydev,LAN88XX_INT_MASK ); temp &= ~LAN88XX_INT_MASK_MDINTPIN_EN_ ; - ret =phy_write (phydev,LAN88XX_INT_MASK , temp); +phy_write (phydev,LAN88XX_INT_MASK , temp); temp =phy_read (phydev,MII_BMCR ); temp &= ~(BMCR_SPEED100 |BMCR_SPEED1000 );
@@ -1873,7 +1868,7 @@ static void lan78xx_link_status_change(struct net_device *net)/* enable phy interrupt back */ temp =phy_read (phydev,LAN88XX_INT_MASK ); temp |=LAN88XX_INT_MASK_MDINTPIN_EN_ ; - ret =phy_write (phydev,LAN88XX_INT_MASK , temp); +phy_write (phydev,LAN88XX_INT_MASK , temp); } }
@@ -1927,14 +1922,13 @@ static void lan78xx_irq_bus_sync_unlock(struct irq_data *irqd)struct lan78xx_net *dev = container_of(data, struct lan78xx_net, domain_data);u32 buf; -int ret;/* call register access here because irq_bus_lock & irq_bus_sync_unlock * are only two callbacks executed in non-atomic contex. */ - ret =lan78xx_read_reg (dev,INT_EP_CTL , &buf); +lan78xx_read_reg (dev,INT_EP_CTL , &buf);if (buf != data->irqenable) - ret =lan78xx_write_reg (dev,INT_EP_CTL , data->irqenable); +lan78xx_write_reg (dev,INT_EP_CTL , data->irqenable);mutex_unlock (&data->irq_lock); }
@@ -2001,7 +1995,6 @@ static void lan78xx_remove_irq_domain(struct lan78xx_net *dev)static int lan8835_fixup (struct phy_device *phydev) {int buf; -int ret;struct lan78xx_net *dev =netdev_priv (phydev->attached_dev);/* LED2/PME_N/IRQ_N/RGMII_ID pin to IRQ_N mode */
@@ -2011,11 +2004,11 @@ static int lan8835_fixup(struct phy_device *phydev)phy_write_mmd (phydev,MDIO_MMD_PCS ,0x8010 , buf);/* RGMII MAC TXC Delay Enable */ - ret =lan78xx_write_reg (dev,MAC_RGMII_ID , +lan78xx_write_reg (dev,MAC_RGMII_ID ,MAC_RGMII_ID_TXC_DELAY_EN_ );/* RGMII TX DLL Tune Adjust */ - ret =lan78xx_write_reg (dev,RGMII_TX_BYP_DLL ,0x3D00 ); +lan78xx_write_reg (dev,RGMII_TX_BYP_DLL ,0x3D00 ); dev->interface =PHY_INTERFACE_MODE_RGMII_TXID ;
@@ -2199,28 +2192,27 @@ static int lan78xx_phy_init(struct lan78xx_net *dev)static int lan78xx_set_rx_max_frame_length (struct lan78xx_net *dev,int size) { -int ret =0 ;u32 buf;bool rxenabled; - ret =lan78xx_read_reg (dev,MAC_RX , &buf); +lan78xx_read_reg (dev,MAC_RX , &buf); rxenabled = ((buf &MAC_RX_RXEN_ ) !=0 );if (rxenabled) { buf &= ~MAC_RX_RXEN_ ; - ret =lan78xx_write_reg (dev,MAC_RX , buf); +lan78xx_write_reg (dev,MAC_RX , buf); }/* add 4 to size for FCS */ buf &= ~MAC_RX_MAX_SIZE_MASK_ ; buf |= (((size +4 ) <<MAC_RX_MAX_SIZE_SHIFT_ ) &MAC_RX_MAX_SIZE_MASK_ ); - ret =lan78xx_write_reg (dev,MAC_RX , buf); +lan78xx_write_reg (dev,MAC_RX , buf);if (rxenabled) { buf |=MAC_RX_RXEN_ ; - ret =lan78xx_write_reg (dev,MAC_RX , buf); +lan78xx_write_reg (dev,MAC_RX , buf); }return 0 ;
@@ -2277,13 +2269,12 @@ static int lan78xx_change_mtu(struct net_device *netdev, int new_mtu)int ll_mtu = new_mtu + netdev->hard_header_len;int old_hard_mtu = dev->hard_mtu;int old_rx_urb_size = dev->rx_urb_size; -int ret;/* no second zero-length packet read wanted after mtu-sized packets */ if ((ll_mtu % dev->maxpacket) ==0 )return -EDOM ; - ret =lan78xx_set_rx_max_frame_length (dev, new_mtu +VLAN_ETH_HLEN ); +lan78xx_set_rx_max_frame_length (dev, new_mtu +VLAN_ETH_HLEN ); netdev->mtu = new_mtu;
@@ -2306,7 +2297,6 @@ static int lan78xx_set_mac_addr(struct net_device *netdev, void *p)struct lan78xx_net *dev =netdev_priv (netdev);struct sockaddr *addr = p;u32 addr_lo, addr_hi; -int ret;if (netif_running (netdev))return -EBUSY ;
@@ -2323,12 +2313,12 @@ static int lan78xx_set_mac_addr(struct net_device *netdev, void *p) addr_hi = netdev->dev_addr[4 ] | netdev->dev_addr[5 ] <<8 ; - ret =lan78xx_write_reg (dev,RX_ADDRL , addr_lo); - ret =lan78xx_write_reg (dev,RX_ADDRH , addr_hi); +lan78xx_write_reg (dev,RX_ADDRL , addr_lo); +lan78xx_write_reg (dev,RX_ADDRH , addr_hi);/* Added to support MAC address changes */ - ret =lan78xx_write_reg (dev,MAF_LO (0 ), addr_lo); - ret =lan78xx_write_reg (dev,MAF_HI (0 ), addr_hi |MAF_HI_VALID_ ); +lan78xx_write_reg (dev,MAF_LO (0 ), addr_lo); +lan78xx_write_reg (dev,MAF_HI (0 ), addr_hi |MAF_HI_VALID_ );return 0 ; }
@@ -2340,7 +2330,6 @@ static int lan78xx_set_features(struct net_device *netdev,struct lan78xx_net *dev =netdev_priv (netdev);struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0 ]);unsigned long flags; -int ret;spin_lock_irqsave (&pdata->rfe_ctl_lock, flags);
@@ -2364,7 +2353,7 @@ static int lan78xx_set_features(struct net_device *netdev,spin_unlock_irqrestore (&pdata->rfe_ctl_lock, flags); - ret =lan78xx_write_reg (dev,RFE_CTL , pdata->rfe_ctl); +lan78xx_write_reg (dev,RFE_CTL , pdata->rfe_ctl);return 0 ; }
@@ -3820,7 +3809,6 @@ static u16 lan78xx_wakeframe_crc16(const u8 *buf, int len)static int lan78xx_set_suspend (struct lan78xx_net *dev,u32 wol) {u32 buf; -int ret;int mask_index;u16 crc;u32 temp_wucsr;
@@ -3829,26 +3817,26 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)const u8 ipv6_multicast[3 ] = {0x33 ,0x33 };const u8 arp_type[2 ] = {0x08 ,0x06 }; - ret =lan78xx_read_reg (dev,MAC_TX , &buf); +lan78xx_read_reg (dev,MAC_TX , &buf); buf &= ~MAC_TX_TXEN_ ; - ret =lan78xx_write_reg (dev,MAC_TX , buf); - ret =lan78xx_read_reg (dev,MAC_RX , &buf); +lan78xx_write_reg (dev,MAC_TX , buf); +lan78xx_read_reg (dev,MAC_RX , &buf); buf &= ~MAC_RX_RXEN_ ; - ret =lan78xx_write_reg (dev,MAC_RX , buf); +lan78xx_write_reg (dev,MAC_RX , buf); - ret =lan78xx_write_reg (dev,WUCSR ,0 ); - ret =lan78xx_write_reg (dev,WUCSR2 ,0 ); - ret =lan78xx_write_reg (dev,WK_SRC ,0xFFF1FF1FUL ); +lan78xx_write_reg (dev,WUCSR ,0 ); +lan78xx_write_reg (dev,WUCSR2 ,0 ); +lan78xx_write_reg (dev,WK_SRC ,0xFFF1FF1FUL ); temp_wucsr =0 ; temp_pmt_ctl =0 ; - ret =lan78xx_read_reg (dev,PMT_CTL , &temp_pmt_ctl); +lan78xx_read_reg (dev,PMT_CTL , &temp_pmt_ctl); temp_pmt_ctl &= ~PMT_CTL_RES_CLR_WKP_EN_ ; temp_pmt_ctl |=PMT_CTL_RES_CLR_WKP_STS_ ;for (mask_index =0 ; mask_index <NUM_OF_WUF_CFG ; mask_index++) - ret =lan78xx_write_reg (dev,WUF_CFG (mask_index),0 ); +lan78xx_write_reg (dev,WUF_CFG (mask_index),0 ); mask_index =0 ;if (wol &WAKE_PHY ) {
@@ -3877,30 +3865,30 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)/* set WUF_CFG & WUF_MASK for IPv4 Multicast */ crc =lan78xx_wakeframe_crc16 (ipv4_multicast,3 ); - ret =lan78xx_write_reg (dev,WUF_CFG (mask_index), +lan78xx_write_reg (dev,WUF_CFG (mask_index),WUF_CFGX_EN_ |WUF_CFGX_TYPE_MCAST_ | (0 <<WUF_CFGX_OFFSET_SHIFT_ ) | (crc &WUF_CFGX_CRC16_MASK_ )); - ret =lan78xx_write_reg (dev,WUF_MASK0 (mask_index),7 ); - ret =lan78xx_write_reg (dev,WUF_MASK1 (mask_index),0 ); - ret =lan78xx_write_reg (dev,WUF_MASK2 (mask_index),0 ); - ret =lan78xx_write_reg (dev,WUF_MASK3 (mask_index),0 ); +lan78xx_write_reg (dev,WUF_MASK0 (mask_index),7 ); +lan78xx_write_reg (dev,WUF_MASK1 (mask_index),0 ); +lan78xx_write_reg (dev,WUF_MASK2 (mask_index),0 ); +lan78xx_write_reg (dev,WUF_MASK3 (mask_index),0 ); mask_index++;/* for IPv6 Multicast */ crc =lan78xx_wakeframe_crc16 (ipv6_multicast,2 ); - ret =lan78xx_write_reg (dev,WUF_CFG (mask_index), +lan78xx_write_reg (dev,WUF_CFG (mask_index),WUF_CFGX_EN_ |WUF_CFGX_TYPE_MCAST_ | (0 <<WUF_CFGX_OFFSET_SHIFT_ ) | (crc &WUF_CFGX_CRC16_MASK_ )); - ret =lan78xx_write_reg (dev,WUF_MASK0 (mask_index),3 ); - ret =lan78xx_write_reg (dev,WUF_MASK1 (mask_index),0 ); - ret =lan78xx_write_reg (dev,WUF_MASK2 (mask_index),0 ); - ret =lan78xx_write_reg (dev,WUF_MASK3 (mask_index),0 ); +lan78xx_write_reg (dev,WUF_MASK0 (mask_index),3 ); +lan78xx_write_reg (dev,WUF_MASK1 (mask_index),0 ); +lan78xx_write_reg (dev,WUF_MASK2 (mask_index),0 ); +lan78xx_write_reg (dev,WUF_MASK3 (mask_index),0 ); mask_index++; temp_pmt_ctl |=PMT_CTL_WOL_EN_ ;
@@ -3921,16 +3909,16 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)* for packettype (offset 12,13) = ARP (0x0806) */ crc =lan78xx_wakeframe_crc16 (arp_type,2 ); - ret =lan78xx_write_reg (dev,WUF_CFG (mask_index), +lan78xx_write_reg (dev,WUF_CFG (mask_index),WUF_CFGX_EN_ |WUF_CFGX_TYPE_ALL_ | (0 <<WUF_CFGX_OFFSET_SHIFT_ ) | (crc &WUF_CFGX_CRC16_MASK_ )); - ret =lan78xx_write_reg (dev,WUF_MASK0 (mask_index),0x3000 ); - ret =lan78xx_write_reg (dev,WUF_MASK1 (mask_index),0 ); - ret =lan78xx_write_reg (dev,WUF_MASK2 (mask_index),0 ); - ret =lan78xx_write_reg (dev,WUF_MASK3 (mask_index),0 ); +lan78xx_write_reg (dev,WUF_MASK0 (mask_index),0x3000 ); +lan78xx_write_reg (dev,WUF_MASK1 (mask_index),0 ); +lan78xx_write_reg (dev,WUF_MASK2 (mask_index),0 ); +lan78xx_write_reg (dev,WUF_MASK3 (mask_index),0 ); mask_index++; temp_pmt_ctl |=PMT_CTL_WOL_EN_ ;
@@ -3938,7 +3926,7 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol) temp_pmt_ctl |=PMT_CTL_SUS_MODE_0_ ; } - ret =lan78xx_write_reg (dev,WUCSR , temp_wucsr); +lan78xx_write_reg (dev,WUCSR , temp_wucsr);/* when multiple WOL bits are set */ if (hweight_long ((unsigned long )wol) >1 ) {
@@ -3946,16 +3934,16 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol) temp_pmt_ctl &= ~PMT_CTL_SUS_MODE_MASK_ ; temp_pmt_ctl |=PMT_CTL_SUS_MODE_0_ ; } - ret =lan78xx_write_reg (dev,PMT_CTL , temp_pmt_ctl); +lan78xx_write_reg (dev,PMT_CTL , temp_pmt_ctl);/* clear WUPS */ - ret =lan78xx_read_reg (dev,PMT_CTL , &buf); +lan78xx_read_reg (dev,PMT_CTL , &buf); buf |=PMT_CTL_WUPS_MASK_ ; - ret =lan78xx_write_reg (dev,PMT_CTL , buf); +lan78xx_write_reg (dev,PMT_CTL , buf); - ret =lan78xx_read_reg (dev,MAC_RX , &buf); +lan78xx_read_reg (dev,MAC_RX , &buf); buf |=MAC_RX_RXEN_ ; - ret =lan78xx_write_reg (dev,MAC_RX , buf); +lan78xx_write_reg (dev,MAC_RX , buf);return 0 ; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 41/104 net: lan78xx: fix accessing the LAN7800s internal phy specific registers from the MAC driver
In reply to Greg Kroah-HartmanFrom: Yuiko Oshino <[email protected]>
[ Upstream commit e57cf3639c323eeed05d3725fd82f91b349adca8 ]
Move the LAN7800 internal phy (phy ID 0x0007c132) specific register accesses to the phy driver (microchip.c).
Fix the error reported by Enguerrand de Ribaucourt in December 2022, "Some operations during the cable switch workaround modify the register LAN88XX_INT_MASK of the PHY. However, this register is specific to the LAN8835 PHY. For instance, if a DP8322I PHY is connected to the LAN7801, that register (0x19), corresponds to the LED and MAC address configuration, resulting in unapropriate behavior."
I did not test with the DP8322I PHY, but I tested with an EVB-LAN7800 with the internal PHY.
--- drivers/net/phy/microchip.c | 32 ++++++++++++++++++++++++++++++++ drivers/net/usb/lan78xx.c | 27 +-------------------------- 2 files changed, 33 insertions(+), 26 deletions(-)
drivers/net/phy/microchip.c +32 -0
@@ -326,6 +326,37 @@ static int lan88xx_config_aneg(struct phy_device *phydev)return genphy_config_aneg (phydev); } +static void lan88xx_link_change_notify (struct phy_device *phydev) +{ +int temp; + +/* At forced 100 F/H mode, chip may fail to set mode correctly +* when cable is switched between long(~50+m) and short one. +* As workaround, set to 10 before setting to 100 +* at forced 100 F/H mode. +*/ +if (!phydev->autoneg && phydev->speed ==100 ) { +/* disable phy interrupt */ + temp =phy_read (phydev,LAN88XX_INT_MASK ); + temp &= ~LAN88XX_INT_MASK_MDINTPIN_EN_ ; +phy_write (phydev,LAN88XX_INT_MASK , temp); + + temp =phy_read (phydev,MII_BMCR ); + temp &= ~(BMCR_SPEED100 |BMCR_SPEED1000 ); +phy_write (phydev,MII_BMCR , temp);/* set to 10 first */ + temp |=BMCR_SPEED100 ; +phy_write (phydev,MII_BMCR , temp);/* set to 100 later */ + +/* clear pending interrupt generated while workaround */ + temp =phy_read (phydev,LAN88XX_INT_STS ); + +/* enable phy interrupt back */ + temp =phy_read (phydev,LAN88XX_INT_MASK ); + temp |=LAN88XX_INT_MASK_MDINTPIN_EN_ ; +phy_write (phydev,LAN88XX_INT_MASK , temp); + } +} +static struct phy_driver microchip_phy_driver[] = { { .phy_id =0x0007c130 ,
@@ -339,6 +370,7 @@ static struct phy_driver microchip_phy_driver[] = { .config_init = lan88xx_config_init, .config_aneg = lan88xx_config_aneg, + .link_change_notify = lan88xx_link_change_notify, .ack_interrupt = lan88xx_phy_ack_interrupt, .config_intr = lan88xx_phy_config_intr,
drivers/net/usb/lan78xx.c +1 -26
@@ -1843,33 +1843,8 @@ static void lan78xx_remove_mdio(struct lan78xx_net *dev)static void lan78xx_link_status_change (struct net_device *net) {struct phy_device *phydev = net->phydev; -int temp; - -/* At forced 100 F/H mode, chip may fail to set mode correctly -* when cable is switched between long(~50+m) and short one. -* As workaround, set to 10 before setting to 100 -* at forced 100 F/H mode. -*/ -if (!phydev->autoneg && (phydev->speed ==100 )) { -/* disable phy interrupt */ - temp =phy_read (phydev,LAN88XX_INT_MASK ); - temp &= ~LAN88XX_INT_MASK_MDINTPIN_EN_ ; -phy_write (phydev,LAN88XX_INT_MASK , temp); - temp =phy_read (phydev,MII_BMCR ); - temp &= ~(BMCR_SPEED100 |BMCR_SPEED1000 ); -phy_write (phydev,MII_BMCR , temp);/* set to 10 first */ - temp |=BMCR_SPEED100 ; -phy_write (phydev,MII_BMCR , temp);/* set to 100 later */ - -/* clear pending interrupt generated while workaround */ - temp =phy_read (phydev,LAN88XX_INT_STS ); - -/* enable phy interrupt back */ - temp =phy_read (phydev,LAN88XX_INT_MASK ); - temp |=LAN88XX_INT_MASK_MDINTPIN_EN_ ; -phy_write (phydev,LAN88XX_INT_MASK , temp); - } +phy_print_status (phydev); } static int irq_map(struct irq_domain *d, unsigned int irq,
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 42/104 net: caif: Fix use-after-free in cfusbl_device_notify()
In reply to Greg Kroah-HartmanFrom: Shigeru Yoshida <[email protected]>
[ Upstream commit 9781e98a97110f5e76999058368b4be76a788484 ]
syzbot reported use-after-free in cfusbl_device_notify() [1]. This causes a stack trace like below:
BUG: KASAN: use-after-free in cfusbl_device_notify+0x7c9/0x870 net/caif/caif_usb.c:138 Read of size 8 at addr ffff88807ac4e6f0 by task kworker/u4:6/1214 CPU: 0 PID: 1214 Comm: kworker/u4:6 Not tainted 5.19.0-rc3-syzkaller-00146-g92f20ff72066 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Workqueue: netns cleanup_net Call Trace: <TASK> __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0xcd/0x134 lib/dump_stack.c:106 print_address_description.constprop.0.cold+0xeb/0x467 mm/kasan/report.c:313 print_report mm/kasan/report.c:429 [inline] kasan_report.cold+0xf4/0x1c6 mm/kasan/report.c:491 cfusbl_device_notify+0x7c9/0x870 net/caif/caif_usb.c:138 notifier_call_chain+0xb5/0x200 kernel/notifier.c:87 call_netdevice_notifiers_info+0xb5/0x130 net/core/dev.c:1945 call_netdevice_notifiers_extack net/core/dev.c:1983 [inline] call_netdevice_notifiers net/core/dev.c:1997 [inline] netdev_wait_allrefs_any net/core/dev.c:10227 [inline] netdev_run_todo+0xbc0/0x10f0 net/core/dev.c:10341 default_device_exit_batch+0x44e/0x590 net/core/dev.c:11334 ops_exit_list+0x125/0x170 net/core/net_namespace.c:167 cleanup_net+0x4ea/0xb00 net/core/net_namespace.c:594 process_one_work+0x996/0x1610 kernel/workqueue.c:2289 worker_thread+0x665/0x1080 kernel/workqueue.c:2436 kthread+0x2e9/0x3a0 kernel/kthread.c:376 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:302 </TASK>
When unregistering a net device, unregister_netdevice_many_notify() sets the device's reg_state to NETREG_UNREGISTERING, calls notifiers with NETDEV_UNREGISTER, and adds the device to the todo list.
Later on, devices in the todo list are processed by netdev_run_todo(). netdev_run_todo() waits devices' reference count become 1 while rebdoadcasting NETDEV_UNREGISTER notification.
When cfusbl_device_notify() is called with NETDEV_UNREGISTER multiple times, the parent device might be freed. This could cause UAF. Processing NETDEV_UNREGISTER multiple times also causes inbalance of reference count for the module.
This patch fixes the issue by accepting only first NETDEV_UNREGISTER notification.
--- net/caif/caif_usb.c | 3 +++ 1 file changed, 3 insertions(+)
net/caif/caif_usb.c +3 -0
@@ -134,6 +134,9 @@ static int cfusbl_device_notify(struct notifier_block *me, unsigned long what,struct usb_device *usbdev;int res; +if (what ==NETDEV_UNREGISTER && dev->reg_state >=NETREG_UNREGISTERED ) +return 0 ; +/* Check whether we have a NCM device, and find its VID/PID. */ if (!(dev->dev.parent && dev->dev.parent->driver &&strcmp (dev->dev.parent->driver->name,"cdc_ncm" ) ==0 ))
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 43/104 net: stmmac: add to set device wake up flag when stmmac init phy
In reply to Greg Kroah-HartmanFrom: Rongguang Wei <[email protected]>
[ Upstream commit a9334b702a03b693f54ebd3b98f67bf722b74870 ]
When MAC is not support PMT, driver will check PHY's WoL capability and set device wakeup capability in stmmac_init_phy(). We can enable the WoL through ethtool, the driver would enable the device wake up flag. Now the device_may_wakeup() return true.
But if there is a way which enable the PHY's WoL capability derectly, like in BIOS. The driver would not know the enable thing and would not set the device wake up flag. The phy_suspend may failed like this:
[ 32.409063] PM: dpm_run_callback(): mdio_bus_phy_suspend+0x0/0x50 returns -16 [ 32.409065] PM: Device stmmac-1:00 failed to suspend: error -16 [ 32.409067] PM: Some devices failed to suspend, or early wake event detected
Add to set the device wakeup enable flag according to the get_wol function result in PHY can fix the error in this scene.
v2: add a Fixes tag.
--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +1 -0
@@ -1145,6 +1145,7 @@ static int stmmac_init_phy(struct net_device *dev)phylink_ethtool_get_wol (priv->phylink, &wol);device_set_wakeup_capable (priv->device, !!wol.supported); +device_set_wakeup_enable (priv->device, !!wol.wolopts); }return ret;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 44/104 net: phylib: get rid of unnecessary locking
In reply to Greg Kroah-HartmanFrom: Russell King (Oracle) <[email protected]>
[ Upstream commit f4b47a2e9463950df3e7c8b70e017877c1d4eb11 ]
The locking in phy_probe() and phy_remove() does very little to prevent any races with e.g. phy_attach_direct(), but instead causes lockdep ABBA warnings. Remove it.
======================================================
WARNING: possible circular locking dependency detected
6.2.0-dirty #1108 Tainted: G W E
------------------------------------------------------
ip/415 is trying to acquire lock:ffff5c268f81ef50 (&dev->lock){+.+.}-{3:3}, at: phy_attach_direct+0x17c/0x3a0 [libphy]
but task is already holding lock:ffffaef6496cb518 (rtnl_mutex){+.+.}-{3:3}, at: rtnetlink_rcv_msg+0x154/0x560
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #1 (rtnl_mutex){+.+.}-{3:3}:
__lock_acquire+0x35c/0x6c0
lock_acquire.part.0+0xcc/0x220
lock_acquire+0x68/0x84
__mutex_lock+0x8c/0x414
mutex_lock_nested+0x34/0x40
rtnl_lock+0x24/0x30
sfp_bus_add_upstream+0x34/0x150
phy_sfp_probe+0x4c/0x94 [libphy]
mv3310_probe+0x148/0x184 [marvell10g]
phy_probe+0x8c/0x200 [libphy]
call_driver_probe+0xbc/0x15c
really_probe+0xc0/0x320
__driver_probe_device+0x84/0x120
driver_probe_device+0x44/0x120
__device_attach_driver+0xc4/0x160
bus_for_each_drv+0x80/0xe0
__device_attach+0xb0/0x1f0
device_initial_probe+0x1c/0x2c
bus_probe_device+0xa4/0xb0
device_add+0x360/0x53c
phy_device_register+0x60/0xa4 [libphy]
fwnode_mdiobus_phy_device_register+0xc0/0x190 [fwnode_mdio]
fwnode_mdiobus_register_phy+0x160/0xd80 [fwnode_mdio]
of_mdiobus_register+0x140/0x340 [of_mdio]
orion_mdio_probe+0x298/0x3c0 [mvmdio]
platform_probe+0x70/0xe0
call_driver_probe+0x34/0x15c
really_probe+0xc0/0x320
__driver_probe_device+0x84/0x120
driver_probe_device+0x44/0x120
__driver_attach+0x104/0x210
bus_for_each_dev+0x78/0xdc
driver_attach+0x2c/0x3c
bus_add_driver+0x184/0x240
driver_register+0x80/0x13c
__platform_driver_register+0x30/0x3c
xt_compat_calc_jump+0x28/0xa4 [x_tables]
do_one_initcall+0x50/0x1b0
do_init_module+0x50/0x1fc
load_module+0x684/0x744
__do_sys_finit_module+0xc4/0x140
__arm64_sys_finit_module+0x28/0x34
invoke_syscall+0x50/0x120
el0_svc_common.constprop.0+0x6c/0x1b0
do_el0_svc+0x34/0x44
el0_svc+0x48/0xf0
el0t_64_sync_handler+0xb8/0xc0
el0t_64_sync+0x1a0/0x1a4-> #0 (&dev->lock){+.+.}-{3:3}:
check_prev_add+0xb4/0xc80
validate_chain+0x414/0x47c
__lock_acquire+0x35c/0x6c0
lock_acquire.part.0+0xcc/0x220
lock_acquire+0x68/0x84
__mutex_lock+0x8c/0x414
mutex_lock_nested+0x34/0x40
phy_attach_direct+0x17c/0x3a0 [libphy]
phylink_fwnode_phy_connect.part.0+0x70/0xe4 [phylink]
phylink_fwnode_phy_connect+0x48/0x60 [phylink]
mvpp2_open+0xec/0x2e0 [mvpp2]
__dev_open+0x104/0x214
__dev_change_flags+0x1d4/0x254
dev_change_flags+0x2c/0x7c
do_setlink+0x254/0xa50
__rtnl_newlink+0x430/0x514
rtnl_newlink+0x58/0x8c
rtnetlink_rcv_msg+0x17c/0x560
netlink_rcv_skb+0x64/0x150
rtnetlink_rcv+0x20/0x30
netlink_unicast+0x1d4/0x2b4
netlink_sendmsg+0x1a4/0x400
____sys_sendmsg+0x228/0x290
___sys_sendmsg+0x88/0xec
__sys_sendmsg+0x70/0xd0
__arm64_sys_sendmsg+0x2c/0x40
invoke_syscall+0x50/0x120
el0_svc_common.constprop.0+0x6c/0x1b0
do_el0_svc+0x34/0x44
el0_svc+0x48/0xf0
el0t_64_sync_handler+0xb8/0xc0
el0t_64_sync+0x1a0/0x1a4other info that might help us debug this:
Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(rtnl_mutex);
lock(&dev->lock);
lock(rtnl_mutex); lock(&dev->lock);
*** DEADLOCK ***
--- drivers/net/phy/phy_device.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-)
drivers/net/phy/phy_device.c +1 -7
@@ -2833,8 +2833,6 @@ static int phy_probe(struct device *dev)if (phydrv->flags &PHY_IS_INTERNAL ) phydev->is_internal = true; -mutex_lock (&phydev->lock); -/* Deassert the reset signal */ phy_device_reset (phydev,0 );
@@ -2903,12 +2901,10 @@ static int phy_probe(struct device *dev) phydev->state =PHY_READY ; out: -/* Assert the reset signal */ +/* Re-assert the reset signal on error */ if (err)phy_device_reset (phydev,1 ); -mutex_unlock (&phydev->lock); -return err; }
@@ -2918,9 +2914,7 @@ static int phy_remove(struct device *dev)cancel_delayed_work_sync (&phydev->state_queue); -mutex_lock (&phydev->lock); phydev->state =PHY_DOWN ; -mutex_unlock (&phydev->lock);sfp_bus_del_upstream (phydev->sfp_bus); phydev->sfp_bus =NULL ;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 45/104 bnxt_en: Avoid order-5 memory allocation for TPA data
In reply to Greg Kroah-HartmanFrom: Michael Chan <[email protected]>
[ Upstream commit accd7e23693aaaa9aa0d3e9eca0ae77d1be80ab3 ]
The driver needs to keep track of all the possible concurrent TPA (GRO/LRO) completions on the aggregation ring. On P5 chips, the maximum number of concurrent TPA is 256 and the amount of memory we allocate is order-5 on systems using 4K pages. Memory allocation failure has been reported:
NetworkManager: page allocation failure: order:5, mode:0x40dc0(GFP_KERNEL|__GFP_COMP|__GFP_ZERO), nodemask=(null),cpuset=/,mems_allowed=0-1
CPU: 15 PID: 2995 Comm: NetworkManager Kdump: loaded Not tainted 5.10.156 #1 Hardware name: Dell Inc. PowerEdge R660/0M1CC5, BIOS 0.2.25 08/12/2022 Call Trace: dump_stack+0x57/0x6e warn_alloc.cold.120+0x7b/0xdd ? _cond_resched+0x15/0x30 ? __alloc_pages_direct_compact+0x15f/0x170 __alloc_pages_slowpath.constprop.108+0xc58/0xc70 __alloc_pages_nodemask+0x2d0/0x300 kmalloc_order+0x24/0xe0 kmalloc_order_trace+0x19/0x80 bnxt_alloc_mem+0x1150/0x15c0 [bnxt_en] ? bnxt_get_func_stat_ctxs+0x13/0x60 [bnxt_en] __bnxt_open_nic+0x12e/0x780 [bnxt_en] bnxt_open+0x10b/0x240 [bnxt_en] __dev_open+0xe9/0x180 __dev_change_flags+0x1af/0x220 dev_change_flags+0x21/0x60 do_setlink+0x35c/0x1100
Instead of allocating this big chunk of memory and dividing it up for the concurrent TPA instances, allocate each small chunk separately for each TPA instance. This will reduce it to order-0 allocations.
--- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-)
drivers/net/ethernet/broadcom/bnxt/bnxt.c +12 -11
@@ -2854,7 +2854,7 @@ static int bnxt_alloc_ring(struct bnxt *bp, struct bnxt_ring_mem_info *rmem)static void bnxt_free_tpa_info (struct bnxt *bp) { -int i; +int i, j;for (i =0 ; i < bp->rx_nr_rings; i++) {struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
@@ -2862,8 +2862,10 @@ static void bnxt_free_tpa_info(struct bnxt *bp)kfree (rxr->rx_tpa_idx_map); rxr->rx_tpa_idx_map =NULL ;if (rxr->rx_tpa) { -kfree (rxr->rx_tpa[0 ].agg_arr); - rxr->rx_tpa[0 ].agg_arr =NULL ; +for (j =0 ; j < bp->max_tpa; j++) { +kfree (rxr->rx_tpa[j].agg_arr); + rxr->rx_tpa[j].agg_arr =NULL ; + } }kfree (rxr->rx_tpa); rxr->rx_tpa =NULL ;
@@ -2872,14 +2874,13 @@ static void bnxt_free_tpa_info(struct bnxt *bp)static int bnxt_alloc_tpa_info (struct bnxt *bp) { -int i, j, total_aggs =0 ; +int i, j; bp->max_tpa =MAX_TPA ;if (bp->flags &BNXT_FLAG_CHIP_P5 ) {if (!bp->max_tpa_v2)return 0 ; bp->max_tpa =max_t (u16, bp->max_tpa_v2,MAX_TPA_P5 ); - total_aggs = bp->max_tpa *MAX_SKB_FRAGS ; }for (i =0 ; i < bp->rx_nr_rings; i++) {
@@ -2893,12 +2894,12 @@ static int bnxt_alloc_tpa_info(struct bnxt *bp)if (!(bp->flags &BNXT_FLAG_CHIP_P5 ))continue ; - agg =kcalloc (total_aggs,sizeof (*agg),GFP_KERNEL ); - rxr->rx_tpa[0 ].agg_arr = agg; -if (!agg) -return -ENOMEM ; -for (j =1 ; j < bp->max_tpa; j++) - rxr->rx_tpa[j].agg_arr = agg + j *MAX_SKB_FRAGS ; +for (j =0 ; j < bp->max_tpa; j++) { + agg =kcalloc (MAX_SKB_FRAGS ,sizeof (*agg),GFP_KERNEL ); +if (!agg) +return -ENOMEM ; + rxr->rx_tpa[j].agg_arr = agg; + } rxr->rx_tpa_idx_map =kzalloc (sizeof (*rxr->rx_tpa_idx_map),GFP_KERNEL );if (!rxr->rx_tpa_idx_map)
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 46/104 netfilter: ctnetlink: revert to dumping mark regardless of event type
In reply to Greg Kroah-HartmanFrom: Ivan Delalande <[email protected]>
[ Upstream commit 9f7dd42f0db1dc6915a52d4a8a96ca18dd8cc34e ]
It seems that change was unintentional, we have userspace code that needs the mark while listening for events like REPLY, DESTROY, etc. Also include 0-marks in requested dumps, as they were before that fix.
--- net/netfilter/nf_conntrack_netlink.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
net/netfilter/nf_conntrack_netlink.c +7 -7
@@ -317,11 +317,12 @@ ctnetlink_dump_timestamp(struct sk_buff *skb, const struct nf_conn *ct) }#ifdef CONFIG_NF_CONNTRACK_MARK -static int ctnetlink_dump_mark (struct sk_buff *skb,const struct nf_conn *ct) +static int ctnetlink_dump_mark (struct sk_buff *skb,const struct nf_conn *ct, +bool dump) {u32 mark =READ_ONCE (ct->mark); -if (!mark) +if (!mark && !dump)return 0 ;if (nla_put_be32 (skb,CTA_MARK ,htonl (mark)))
@@ -332,7 +333,7 @@ static int ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct) return -1; }#else -#define ctnetlink_dump_mark (a, b) (0) +#define ctnetlink_dump_mark (a, b, c) (0)#endif #ifdef CONFIG_NF_CONNTRACK_SECMARK
@@ -537,7 +538,7 @@ static int ctnetlink_dump_extinfo(struct sk_buff *skb,static int ctnetlink_dump_info (struct sk_buff *skb,struct nf_conn *ct) { if (ctnetlink_dump_status(skb, ct) < 0 || - ctnetlink_dump_mark(skb, ct) < 0 || + ctnetlink_dump_mark(skb, ct, true) < 0 || ctnetlink_dump_secctx(skb, ct) < 0 || ctnetlink_dump_id(skb, ct) < 0 || ctnetlink_dump_use(skb, ct) < 0 ||
@@ -816,8 +817,7 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item) }#ifdef CONFIG_NF_CONNTRACK_MARK -if (events & (1 <<IPCT_MARK ) && -ctnetlink_dump_mark (skb, ct) <0 ) +if (ctnetlink_dump_mark (skb, ct, events & (1 <<IPCT_MARK ))) goto nla_put_failure;#endif nlmsg_end (skb, nlh);
@@ -2734,7 +2734,7 @@ static int __ctnetlink_glue_build(struct sk_buff *skb, struct nf_conn *ct) goto nla_put_failure;#ifdef CONFIG_NF_CONNTRACK_MARK -if (ctnetlink_dump_mark (skb, ct) <0 ) +if (ctnetlink_dump_mark (skb, ct, true) <0 ) goto nla_put_failure;#endif if (ctnetlink_dump_labels (skb, ct) <0 )
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 47/104 netfilter: tproxy: fix deadlock due to missing BH disable
In reply to Greg Kroah-HartmanFrom: Florian Westphal <[email protected]>
[ Upstream commit 4a02426787bf024dafdb79b362285ee325de3f5e ]
The xtables packet traverser performs an unconditional local_bh_disable(), but the nf_tables evaluation loop does not.
Functions that are called from either xtables or nftables must assume that they can be called in process context.
inet_twsk_deschedule_put() assumes that no softirq interrupt can occur. If tproxy is used from nf_tables its possible that we'll deadlock trying to aquire a lock already held in process context.
Add a small helper that takes care of this and use it.
--- include/net/netfilter/nf_tproxy.h | 7 +++++++ net/ipv4/netfilter/nf_tproxy_ipv4.c | 2 +- net/ipv6/netfilter/nf_tproxy_ipv6.c | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-)
include/net/netfilter/nf_tproxy.h +7 -0
@@ -17,6 +17,13 @@ static inline bool nf_tproxy_sk_is_transparent(struct sock *sk)return false; } +static inline void nf_tproxy_twsk_deschedule_put (struct inet_timewait_sock *tw) +{ +local_bh_disable (); +inet_twsk_deschedule_put (tw); +local_bh_enable (); +} +/* assign a socket to the skb -- consumes sk */ static inline void nf_tproxy_assign_sock (struct sk_buff *skb,struct sock *sk) {
net/ipv4/netfilter/nf_tproxy_ipv4.c +1 -1
@@ -38,7 +38,7 @@ nf_tproxy_handle_time_wait4(struct net *net, struct sk_buff *skb, hp->source, lport ? lport : hp->dest, skb->dev, NF_TPROXY_LOOKUP_LISTENER);if (sk2) { -inet_twsk_deschedule_put (inet_twsk (sk)); +nf_tproxy_twsk_deschedule_put (inet_twsk (sk)); sk = sk2; } }
net/ipv6/netfilter/nf_tproxy_ipv6.c +1 -1
@@ -63,7 +63,7 @@ nf_tproxy_handle_time_wait6(struct sk_buff *skb, int tproto, int thoff, lport ? lport : hp->dest, skb->dev, NF_TPROXY_LOOKUP_LISTENER);if (sk2) { -inet_twsk_deschedule_put (inet_twsk (sk)); +nf_tproxy_twsk_deschedule_put (inet_twsk (sk)); sk = sk2; } }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 48/104 btf: fix resolving BTF_KIND_VAR after ARRAY, STRUCT, UNION, PTR
In reply to Greg Kroah-HartmanFrom: Lorenz Bauer <[email protected]>
[ Upstream commit 9b459804ff9973e173fabafba2a1319f771e85fa ]
btf_datasec_resolve contains a bug that causes the following BTF to fail loading:
[1] DATASEC a size=2 vlen=2
type_id=4 offset=0 size=1
type_id=7 offset=1 size=1
[2] INT (anon) size=1 bits_offset=0 nr_bits=8 encoding=(none)
[3] PTR (anon) type_id=2
[4] VAR a type_id=3 linkage=0
[5] INT (anon) size=1 bits_offset=0 nr_bits=8 encoding=(none)
[6] TYPEDEF td type_id=5
[7] VAR b type_id=6 linkage=0This error message is printed during btf_check_all_types:
[1] DATASEC a size=2 vlen=2
type_id=7 offset=1 size=1 Invalid type
By tracing btf_*_resolve we can pinpoint the problem:
btf_datasec_resolve(depth: 1, type_id: 1, mode: RESOLVE_TBD) = 0
btf_var_resolve(depth: 2, type_id: 4, mode: RESOLVE_TBD) = 0
btf_ptr_resolve(depth: 3, type_id: 3, mode: RESOLVE_PTR) = 0
btf_var_resolve(depth: 2, type_id: 4, mode: RESOLVE_PTR) = 0
btf_datasec_resolve(depth: 1, type_id: 1, mode: RESOLVE_PTR) = -22
The last invocation of btf_datasec_resolve should invoke btf_var_resolve by means of env_stack_push, instead it returns EINVAL. The reason is that env_stack_push is never executed for the second VAR.
if (!env_type_is_resolve_sink(env, var_type) &&
!env_type_is_resolved(env, var_type_id)) {
env_stack_set_next_member(env, i + 1);
return env_stack_push(env, var_type, var_type_id);
}env_type_is_resolve_sink() changes its behaviour based on resolve_mode. For RESOLVE_PTR, we can simplify the if condition to the following:
(btf_type_is_modifier() || btf_type_is_ptr) && !env_type_is_resolved()
Since we're dealing with a VAR the clause evaluates to false. This is not sufficient to trigger the bug however. The log output and EINVAL are only generated if btf_type_id_size() fails.
if (!btf_type_id_size(btf, &type_id, &type_size)) {
btf_verifier_log_vsi(env, v->t, vsi, "Invalid type");
return -EINVAL;
}Most types are sized, so for example a VAR referring to an INT is not a problem. The bug is only triggered if a VAR points at a modifier. Since we skipped btf_var_resolve that modifier was also never resolved, which means that btf_resolved_type_id returns 0 aka VOID for the modifier. This in turn causes btf_type_id_size to return NULL, triggering EINVAL.
To summarise, the following conditions are necessary:
- VAR pointing at PTR, STRUCT, UNION or ARRAY
- Followed by a VAR pointing at TYPEDEF, VOLATILE, CONST, RESTRICT or TYPE_TAG
The fix is to reset resolve_mode to RESOLVE_TBD before attempting to resolve a VAR from a DATASEC.
--- kernel/bpf/btf.c | 1 + 1 file changed, 1 insertion(+)
kernel/bpf/btf.c +1 -0
@@ -3541,6 +3541,7 @@ static int btf_datasec_resolve(struct btf_verifier_env *env,struct btf *btf = env->btf;u16 i; + env->resolve_mode =RESOLVE_TBD ;for_each_vsi_from (i, v->next_member, v->t, vsi) {u32 var_type_id = vsi->type, type_id, type_size =0 ; const struct btf_type *var_type = btf_type_by_id(env->btf,
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 49/104 net: ethernet: mtk_eth_soc: fix RX data corruption issue
In reply to Greg Kroah-HartmanFrom: Daniel Golle <[email protected]>
[ Upstream commit 193250ace270fecd586dd2d0dfbd9cbd2ade977f ]
Fix data corruption issue with SerDes connected PHYs operating at 1.25 Gbps speed where we could previously observe about 30% packet loss while the bad packet counter was increasing.
As almost all boards with MediaTek MT7622 or MT7986 use either the MT7531 switch IC operating at 3.125Gbps SerDes rate or single-port PHYs using rate-adaptation to 2500Base-X mode, this issue only got exposed now when we started trying to use SFP modules operating with 1.25 Gbps with the BananaPi R3 board.
The fix is to set bit 12 which disables the RX FIFO clear function when setting up MAC MCR, MediaTek SDK did the same change stating:
"If without this patch, kernel might receive invalid packets that are corrupted by GMAC."[1]
--- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3 ++- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-)
drivers/net/ethernet/mediatek/mtk_eth_soc.c +2 -1
@@ -354,7 +354,8 @@ static void mtk_mac_config(struct phylink_config *config, unsigned int mode, mcr_cur =mtk_r32 (mac->hw,MTK_MAC_MCR (mac->id)); mcr_new = mcr_cur; mcr_new |=MAC_MCR_MAX_RX_1536 |MAC_MCR_IPG_CFG |MAC_MCR_FORCE_MODE | -MAC_MCR_BACKOFF_EN |MAC_MCR_BACKPR_EN |MAC_MCR_FORCE_LINK ; +MAC_MCR_BACKOFF_EN |MAC_MCR_BACKPR_EN |MAC_MCR_FORCE_LINK | +MAC_MCR_RX_FIFO_CLR_DIS ;/* Only update control register when needed! */ if (mcr_new != mcr_cur)
drivers/net/ethernet/mediatek/mtk_eth_soc.h +1 -0
@@ -339,6 +339,7 @@#define MAC_MCR_FORCE_MODE BIT(15)#define MAC_MCR_TX_EN BIT(14)#define MAC_MCR_RX_EN BIT(13) +#define MAC_MCR_RX_FIFO_CLR_DIS BIT(12)#define MAC_MCR_BACKOFF_EN BIT(9)#define MAC_MCR_BACKPR_EN BIT(8)#define MAC_MCR_FORCE_RX_FC BIT(5)
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 50/104 scsi: megaraid_sas: Update max supported LD IDs to 240
In reply to Greg Kroah-HartmanFrom: Chandrakanth Patil <[email protected]>
[ Upstream commit bfa659177dcba48cf13f2bd88c1972f12a60bf1c ]
The firmware only supports Logical Disk IDs up to 240 and LD ID 255 (0xFF) is reserved for deleted LDs. However, in some cases, firmware was assigning LD ID 254 (0xFE) to deleted LDs and this was causing the driver to mark the wrong disk as deleted. This in turn caused the wrong disk device to be taken offline by the SCSI midlayer.
To address this issue, limit the LD ID range from 255 to 240. This ensures the deleted LD ID is properly identified and removed by the driver without accidently deleting any valid LDs.
--- drivers/scsi/megaraid/megaraid_sas.h | 2 ++ drivers/scsi/megaraid/megaraid_sas_fp.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-)
drivers/scsi/megaraid/megaraid_sas.h +2 -0
@@ -1517,6 +1517,8 @@ struct megasas_ctrl_info {#define MEGASAS_MAX_LD_IDS (MEGASAS_MAX_LD_CHANNELS * \ MEGASAS_MAX_DEV_PER_CHANNEL) +#define MEGASAS_MAX_SUPPORTED_LD_IDS 240 +#define MEGASAS_MAX_SECTORS (2*1024)#define MEGASAS_MAX_SECTORS_IEEE (2*128)#define MEGASAS_DBG_LVL 1
drivers/scsi/megaraid/megaraid_sas_fp.c +1 -1
@@ -358,7 +358,7 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance, u64 map_id) ld =MR_TargetIdToLdGet (i, drv_map);/* For non existing VDs, iterate to next VD*/ -if (ld >= (MAX_LOGICAL_DRIVES_EXT -1 )) +if (ld >=MEGASAS_MAX_SUPPORTED_LD_IDS )continue ; raid =MR_LdRaidGet (ld, drv_map);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 51/104 platform: x86: MLX_PLATFORM: select REGMAP instead of depending on it
In reply to Greg Kroah-HartmanFrom: Randy Dunlap <[email protected]>
[ Upstream commit 7e7e1541c91615e9950d0b96bcd1806d297e970e ]
REGMAP is a hidden (not user visible) symbol. Users cannot set it directly thru "make *config", so drivers should select it instead of depending on it if they need it.
Consistently using "select" or "depends on" can also help reduce Kconfig circular dependency issues.
Therefore, change the use of "depends on REGMAP" to "select REGMAP".
--- drivers/platform/x86/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/platform/x86/Kconfig +2 -1
@@ -1195,7 +1195,8 @@ config I2C_MULTI_INSTANTIATE config MLX_PLATFORM tristate "Mellanox Technologies platform support" - depends on I2C && REGMAP + depends on I2C + select REGMAP help This option enables system support for the Mellanox Technologies platform. The Mellanox systems provide data center networking
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 52/104 net/smc: fix fallback failed while sendmsg with fastopen
In reply to Greg Kroah-HartmanFrom: D. Wythe <[email protected]>
[ Upstream commit ce7ca794712f186da99719e8b4e97bd5ddbb04c3 ]
Before determining whether the msg has unsupported options, it has been prematurely terminated by the wrong status check.
For the application, the general usages of MSG_FASTOPEN likes
fd = socket(...)
/* rather than connect */sendto(fd, data, len, MSG_FASTOPEN)
Hence, We need to check the flag before state check, because the sock state here is always SMC_INIT when applications tries MSG_FASTOPEN. Once we found unsupported options, fallback it to TCP.
v2 -> v1: Optimize code style
--- net/smc/af_smc.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
net/smc/af_smc.c +8 -5
@@ -1988,16 +1988,14 @@ static int smc_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) {struct sock *sk = sock->sk;struct smc_sock *smc; -int rc = -EPIPE ; +int rc; smc =smc_sk (sk);lock_sock (sk); -if ((sk->sk_state !=SMC_ACTIVE ) && - (sk->sk_state !=SMC_APPCLOSEWAIT1 ) && - (sk->sk_state !=SMC_INIT )) - goto out; +/* SMC does not support connect with fastopen */ if (msg->msg_flags &MSG_FASTOPEN ) { +/* not connected yet, fallback */ if (sk->sk_state ==SMC_INIT && !smc->connect_nonblock) {smc_switch_to_fallback (smc); smc->fallback_rsn =SMC_CLC_DECL_OPTUNSUPP ;
@@ -2005,6 +2003,11 @@ static int smc_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) rc = -EINVAL ; goto out; } + }else if ((sk->sk_state !=SMC_ACTIVE ) && + (sk->sk_state !=SMC_APPCLOSEWAIT1 ) && + (sk->sk_state !=SMC_INIT )) { + rc = -EPIPE ; + goto out; }if (smc->use_fallback)
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 53/104 SUNRPC: Fix a server shutdown leak
In reply to Greg Kroah-HartmanFrom: Benjamin Coddington <[email protected]>
[ Upstream commit 9ca6705d9d609441d34f8b853e1e4a6369b3b171 ]
Fix a race where kthread_stop() may prevent the threadfn from ever getting called. If that happens the svc_rqst will not be cleaned up.
--- net/sunrpc/svc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
net/sunrpc/svc.c +5 -1
@@ -800,6 +800,7 @@ EXPORT_SYMBOL_GPL(svc_set_num_threads);static int svc_stop_kthreads (struct svc_serv *serv,struct svc_pool *pool,int nrservs) { +struct svc_rqst *rqstp;struct task_struct *task;unsigned int state = serv->sv_nrthreads-1 ;
@@ -808,7 +809,10 @@ svc_stop_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs) task =choose_victim (serv, pool, &state);if (task ==NULL )break ; -kthread_stop (task); + rqstp =kthread_data (task); +/* Did we lose a race to svo_function threadfn? */ +if (kthread_stop (task) == -EINTR ) +svc_exit_thread (rqstp); nrservs++; }while (nrservs <0 );return 0 ;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 54/104 riscv: Use READ_ONCE_NOCHECK in imprecise unwinding stack mode
In reply to Greg Kroah-HartmanFrom: Alexandre Ghiti <[email protected]>
[ Upstream commit 76950340cf03b149412fe0d5f0810e52ac1df8cb ]
When CONFIG_FRAME_POINTER is unset, the stack unwinding function walk_stackframe randomly reads the stack and then, when KASAN is enabled, it can lead to the following backtrace:
[ 0.000000] ================================================================== [ 0.000000] BUG: KASAN: stack-out-of-bounds in walk_stackframe+0xa6/0x11a [ 0.000000] Read of size 8 at addr ffffffff81807c40 by task swapper/0 [ 0.000000] [ 0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted 6.2.0-12919-g24203e6db61f #43 [ 0.000000] Hardware name: riscv-virtio,qemu (DT) [ 0.000000] Call Trace: [ 0.000000] [<ffffffff80007ba8>] walk_stackframe+0x0/0x11a [ 0.000000] [<ffffffff80099ecc>] init_param_lock+0x26/0x2a [ 0.000000] [<ffffffff80007c4a>] walk_stackframe+0xa2/0x11a [ 0.000000] [<ffffffff80c49c80>] dump_stack_lvl+0x22/0x36 [ 0.000000] [<ffffffff80c3783e>] print_report+0x198/0x4a8 [ 0.000000] [<ffffffff80099ecc>] init_param_lock+0x26/0x2a [ 0.000000] [<ffffffff80007c4a>] walk_stackframe+0xa2/0x11a [ 0.000000] [<ffffffff8015f68a>] kasan_report+0x9a/0xc8 [ 0.000000] [<ffffffff80007c4a>] walk_stackframe+0xa2/0x11a [ 0.000000] [<ffffffff80007c4a>] walk_stackframe+0xa2/0x11a [ 0.000000] [<ffffffff8006e99c>] desc_make_final+0x80/0x84 [ 0.000000] [<ffffffff8009a04e>] stack_trace_save+0x88/0xa6 [ 0.000000] [<ffffffff80099fc2>] filter_irq_stacks+0x72/0x76 [ 0.000000] [<ffffffff8006b95e>] devkmsg_read+0x32a/0x32e [ 0.000000] [<ffffffff8015ec16>] kasan_save_stack+0x28/0x52 [ 0.000000] [<ffffffff8006e998>] desc_make_final+0x7c/0x84 [ 0.000000] [<ffffffff8009a04a>] stack_trace_save+0x84/0xa6 [ 0.000000] [<ffffffff8015ec52>] kasan_set_track+0x12/0x20 [ 0.000000] [<ffffffff8015f22e>] __kasan_slab_alloc+0x58/0x5e [ 0.000000] [<ffffffff8015e7ea>] __kmem_cache_create+0x21e/0x39a [ 0.000000] [<ffffffff80e133ac>] create_boot_cache+0x70/0x9c [ 0.000000] [<ffffffff80e17ab2>] kmem_cache_init+0x6c/0x11e [ 0.000000] [<ffffffff80e00fd6>] mm_init+0xd8/0xfe [ 0.000000] [<ffffffff80e011d8>] start_kernel+0x190/0x3ca [ 0.000000] [ 0.000000] The buggy address belongs to stack of task swapper/0 [ 0.000000] and is located at offset 0 in frame: [ 0.000000] stack_trace_save+0x0/0xa6 [ 0.000000] [ 0.000000] This frame has 1 object: [ 0.000000] [32, 56) 'c' [ 0.000000] [ 0.000000] The buggy address belongs to the physical page: [ 0.000000] page:(____ptrval____) refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x81a07 [ 0.000000] flags: 0x1000(reserved|zone=0) [ 0.000000] raw: 0000000000001000 ff600003f1e3d150 ff600003f1e3d150 0000000000000000 [ 0.000000] raw: 0000000000000000 0000000000000000 00000001ffffffff [ 0.000000] page dumped because: kasan: bad access detected [ 0.000000] [ 0.000000] Memory state around the buggy address: [ 0.000000] ffffffff81807b00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 0.000000] ffffffff81807b80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 0.000000] >ffffffff81807c00: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00 00 f3 [ 0.000000] ^ [ 0.000000] ffffffff81807c80: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 [ 0.000000] ffffffff81807d00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 0.000000] ==================================================================
Fix that by using READ_ONCE_NOCHECK when reading the stack in imprecise mode.
--- arch/riscv/kernel/stacktrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/riscv/kernel/stacktrace.c +1 -1
@@ -96,7 +96,7 @@ void notrace walk_stackframe(struct task_struct *task,while (!kstack_end (ksp)) {if (__kernel_text_address (pc) &&unlikely (fn (pc, arg)))break ; - pc = (*ksp++) -0x4 ; + pc =READ_ONCE_NOCHECK (*ksp++) -0x4 ; } }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 55/104 RISC-V: Dont check text_mutex during stop_machine
In reply to Greg Kroah-HartmanFrom: Conor Dooley <[email protected]>
[ Upstream commit 2a8db5ec4a28a0fce822d10224db9471a44b6925 ]
We're currently using stop_machine() to update ftrace & kprobes, which means that the thread that takes text_mutex during may not be the same as the thread that eventually patches the code. This isn't actually a race because the lock is still held (preventing any other concurrent accesses) and there is only one thread running during stop_machine(), but it does trigger a lockdep failure.
This patch just elides the lockdep check during stop_machine.
--- arch/riscv/include/asm/ftrace.h | 2 +- arch/riscv/include/asm/patch.h | 2 ++ arch/riscv/kernel/ftrace.c | 14 ++++++++++++-- arch/riscv/kernel/patch.c | 28 +++++++++++++++++++++++++--- 4 files changed, 40 insertions(+), 6 deletions(-)
arch/riscv/include/asm/ftrace.h +1 -1
@@ -83,6 +83,6 @@ int ftrace_init_nop(struct module *mod,#define ftrace_init_nop ftrace_init_nop#endif -#endif +#endif /* CONFIG_DYNAMIC_FTRACE */ #endif /* _ASM_RISCV_FTRACE_H */
arch/riscv/include/asm/patch.h +2 -0
@@ -9,4 +9,6 @@int patch_text_nosync (void *addr,const void *insns,size_t len);int patch_text (void *addr,u32 insn); +extern int riscv_patch_in_stop_machine; +#endif /* _ASM_RISCV_PATCH_H */
arch/riscv/kernel/ftrace.c +12 -2
@@ -15,11 +15,21 @@ int ftrace_arch_code_modify_prepare(void) __acquires(&text_mutex) {mutex_lock (&text_mutex); + +/* +* The code sequences we use for ftrace can't be patched while the +* kernel is running, so we need to use stop_machine() to modify them +* for now. This doesn't play nice with text_mutex, we use this flag +* to elide the check. +*/ + riscv_patch_in_stop_machine = true; +return 0 ; } int ftrace_arch_code_modify_post_process(void) __releases(&text_mutex) { + riscv_patch_in_stop_machine = false;mutex_unlock (&text_mutex);return 0 ; }
@@ -109,9 +119,9 @@ int ftrace_init_nop(struct module *mod, {int out; -ftrace_arch_code_modify_prepare (); +mutex_lock (&text_mutex); out =ftrace_make_nop (mod, rec,MCOUNT_ADDR ); -ftrace_arch_code_modify_post_process (); +mutex_unlock (&text_mutex);return out; }
arch/riscv/kernel/patch.c +25 -3
@@ -11,6 +11,7 @@#include <asm/kprobes.h> #include <asm/cacheflush.h> #include <asm/fixmap.h> +#include <asm/ftrace.h> #include <asm/patch.h> struct patch_insn {
@@ -19,6 +20,8 @@ struct patch_insn {atomic_t cpu_count; }; +int riscv_patch_in_stop_machine = false; +#ifdef CONFIG_MMU static void *patch_map (void *addr,int fixmap) {
@@ -55,8 +58,15 @@ static int patch_insn_write(void *addr,* Before reaching here, it was expected to lock the text_mutex * already, so we don't need to give another lock here and could * ensure that it was safe between each cores. +* +* We're currently using stop_machine() for ftrace & kprobes, and while +* that ensures text_mutex is held before installing the mappings it +* does not ensure text_mutex is held by the calling thread. That's +* safe but triggers a lockdep failure, so just elide it for that +* specific case. */ -lockdep_assert_held (&text_mutex); +if (!riscv_patch_in_stop_machine) +lockdep_assert_held (&text_mutex);if (across_pages)patch_map (addr + len,FIX_TEXT_POKE1 );
@@ -117,13 +127,25 @@ NOKPROBE_SYMBOL(patch_text_cb);int patch_text (void *addr,u32 insn) { +int ret;struct patch_insn patch = { .addr = addr, .insn = insn, .cpu_count =ATOMIC_INIT (0 ), }; -return stop_machine_cpuslocked (patch_text_cb, - &patch, cpu_online_mask); +/* +* kprobes takes text_mutex, before calling patch_text(), but as we call +* calls stop_machine(), the lockdep assertion in patch_insn_write() +* gets confused by the context in which the lock is taken. +* Instead, ensure the lock is held before calling stop_machine(), and +* set riscv_patch_in_stop_machine to skip the check in +* patch_insn_write(). +*/ +lockdep_assert_held (&text_mutex); + riscv_patch_in_stop_machine = true; + ret =stop_machine_cpuslocked (patch_text_cb, &patch, cpu_online_mask); + riscv_patch_in_stop_machine = false; +return ret; }NOKPROBE_SYMBOL (patch_text);
Greg Kroah-Hartman
maintainerPATCH 56/104 ext4: Fix deadlock during directory rename
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
[ Upstream commit 3c92792da8506a295afb6d032b4476e46f979725 ]
As lockdep properly warns, we should not be locking i_rwsem while having transactions started as the proper lock ordering used by all directory handling operations is i_rwsem -> transaction start. Fix the lock ordering by moving the locking of the directory earlier in ext4_rename().
--- fs/ext4/namei.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-)
fs/ext4/namei.c +17 -9
@@ -3863,10 +3863,20 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,return retval; } +/* +* We need to protect against old.inode directory getting converted +* from inline directory format into a normal one. +*/ +if (S_ISDIR (old.inode->i_mode)) +inode_lock_nested (old.inode,I_MUTEX_NONDIR2 ); + old.bh =ext4_find_entry (old.dir, &old.dentry->d_name, &old.de, &old.inlined); -if (IS_ERR (old.bh)) -return PTR_ERR (old.bh); +if (IS_ERR (old.bh)) { + retval =PTR_ERR (old.bh); + goto unlock_moved_dir; + } +/* * Check for inode number is _not_ due to possible IO errors. * We might rmdir the source, keep it as pwd of some process
@@ -3923,11 +3933,6 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,if (new.dir != old.dir &&EXT4_DIR_LINK_MAX (new.dir)) goto end_rename; } -/* -* We need to protect against old.inode directory getting -* converted from inline directory format into a normal one. -*/ -inode_lock_nested (old.inode,I_MUTEX_NONDIR2 ); retval =ext4_rename_dir_prepare (handle, &old);if (retval) {inode_unlock (old.inode);
@@ -4057,12 +4062,15 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, }else {ext4_journal_stop (handle); } -if (old.dir_bh) -inode_unlock (old.inode); release_bh:brelse (old.dir_bh);brelse (old.bh);brelse (new.bh); + +unlock_moved_dir: +if (S_ISDIR (old.inode->i_mode)) +inode_unlock (old.inode); +return retval; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 57/104 iommu/amd: Add a length limitation for the ivrs_acpihid command-line parameter
In reply to Greg Kroah-HartmanFrom: Gavrilov Ilia <[email protected]>
[ Upstream commit b6b26d86c61c441144c72f842f7469bb686e1211 ]
The 'acpiid' buffer in the parse_ivrs_acpihid function may overflow, because the string specifier in the format string sscanf() has no width limitation.
Found by InfoTeCS on behalf of Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/iommu/amd/init.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
drivers/iommu/amd/init.c +15 -1
@@ -3124,15 +3124,26 @@ static int __init parse_ivrs_hpet(char *str)return 1 ; } +#define ACPIID_LEN (ACPIHID_UID_LEN + ACPIHID_HID_LEN) +static int __init parse_ivrs_acpihid (char *str) {u32 seg =0 , bus, dev, fn;char *hid, *uid, *p, *addr; -char acpiid[ACPIHID_UID_LEN +ACPIHID_HID_LEN ] = {0 }; +char acpiid[ACPIID_LEN ] = {0 };int i; addr =strchr (str,'@' );if (!addr) { + addr =strchr (str,'=' ); +if (!addr) + goto not_found; + + ++addr; + +if (strlen (addr) >ACPIID_LEN ) + goto not_found; +if (sscanf (str,"[%x:%x.%x]=%s" , &bus, &dev, &fn, acpiid) ==4 ||sscanf (str,"[%x:%x:%x.%x]=%s" , &seg, &bus, &dev, &fn, acpiid) ==5 ) { pr_warn("ivrs_acpihid%s option format deprecated; use ivrs_acpihid=%s@%04x:%02x:%02x.%d instead\n",
@@ -3145,6 +3156,9 @@ static int __init parse_ivrs_acpihid(char *str)/* We have the '@', make it the terminator to get just the acpiid */ *addr++ =0 ; +if (strlen (str) >ACPIID_LEN +1 ) + goto not_found; +if (sscanf (str,"=%s" , acpiid) !=1 ) goto not_found;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 58/104 PCI/PM: Define pci_restore_standard_config() only for CONFIG_PM_SLEEP
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
[ Upstream commit 18a94192e20de31e7e495d7c805c8930c42e99ef ]
pci_restore_standard_config() was defined under CONFIG_PM but called only by pci_pm_resume() (defined under CONFIG_SUSPEND) and pci_pm_restore() (defined under CONFIG_HIBERNATE_CALLBACKS). A configuration with only CONFIG_PM leads to a warning:
drivers/pci/pci-driver.c:533:12: error: ‘pci_restore_standard_config’ defined but not used [-Werror=unused-function]
CONFIG_PM_SLEEP depends on CONFIG_SUSPEND and CONFIG_HIBERNATE_CALLBACKS, so define pci_restore_standard_config() under that instead.
Stable-dep-of: ac91e6980563 ("PCI: Unify delay handling for reset and resume")
--- drivers/pci/pci-driver.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
drivers/pci/pci-driver.c +11 -6
@@ -499,9 +499,9 @@ static void pci_device_shutdown(struct device *dev)pci_clear_master (pci_dev); } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP -/* Auxiliary functions used for system resume and run-time resume. */ +/* Auxiliary functions used for system resume */ /** * pci_restore_standard_config - restore standard config registers of PCI device
@@ -521,6 +521,11 @@ static int pci_restore_standard_config(struct pci_dev *pci_dev)pci_pme_restore (pci_dev);return 0 ; } +#endif /* CONFIG_PM_SLEEP */ + +#ifdef CONFIG_PM + +/* Auxiliary functions used for system resume and run-time resume */ static void pci_pm_default_resume (struct pci_dev *pci_dev) {
@@ -528,10 +533,6 @@ static void pci_pm_default_resume(struct pci_dev *pci_dev)pci_enable_wake (pci_dev,PCI_D0 , false); } -#endif - -#ifdef CONFIG_PM_SLEEP -static void pci_pm_default_resume_early (struct pci_dev *pci_dev) {pci_power_up (pci_dev);
@@ -540,6 +541,10 @@ static void pci_pm_default_resume_early(struct pci_dev *pci_dev) pci_pme_restore(pci_dev); } +#endif /* CONFIG_PM */ + +#ifdef CONFIG_PM_SLEEP +/* * Default "suspend" method for devices that have no driver provided suspend, * or not even a driver at all (second part).
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 59/104 watch_queue: fix IOC_WATCH_QUEUE_SET_SIZE alloc error paths
In reply to Greg Kroah-HartmanFrom: David Disseldorp <[email protected]>
[ Upstream commit 03e1d60e177eedbd302b77af4ea5e21b5a7ade31 ]
The watch_queue_set_size() allocation error paths return the ret value set via the prior pipe_resize_ring() call, which will always be zero.
As a result, IOC_WATCH_QUEUE_SET_SIZE callers such as "keyctl watch" fail to detect kernel wqueue->notes allocation failures and proceed to KEYCTL_WATCH_KEY, with any notifications subsequently lost.
--- kernel/watch_queue.c | 1 + 1 file changed, 1 insertion(+)
kernel/watch_queue.c +1 -0
@@ -274,6 +274,7 @@ long watch_queue_set_size(struct pipe_inode_info *pipe, unsigned int nr_notes)if (ret <0 ) goto error; + ret = -ENOMEM ; pages =kcalloc (sizeof (struct page *), nr_pages,GFP_KERNEL );if (!pages) goto error;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 60/104 tpm/eventlog: Dont abort tpm_read_log on faulty ACPI address
In reply to Greg Kroah-HartmanFrom: Morten Linderud <[email protected]>
[ Upstream commit 80a6c216b16d7f5c584d2148c2e4345ea4eb06ce ]
tpm_read_log_acpi() should return -ENODEV when no eventlog from the ACPI table is found. If the firmware vendor includes an invalid log address we are unable to map from the ACPI memory and tpm_read_log() returns -EIO which would abort discovery of the eventlog.
Change the return value from -EIO to -ENODEV when acpi_os_map_iomem() fails to map the event log.
The following hardware was used to test this issue:
Framework Laptop (Pre-production)
BIOS: INSYDE Corp, Revision: 3.2
TPM Device: NTC, Firmware Revision: 7.2
Dump of the faulty ACPI TPM2 table:
[000h 0000 4] Signature : "TPM2" [Trusted Platform Module hardware interface Table]
[004h 0004 4] Table Length : 0000004C
[008h 0008 1] Revision : 04
[009h 0009 1] Checksum : 2B
[00Ah 0010 6] Oem ID : "INSYDE"
[010h 0016 8] Oem Table ID : "TGL-ULT"
[018h 0024 4] Oem Revision : 00000002
[01Ch 0028 4] Asl Compiler ID : "ACPI"
[020h 0032 4] Asl Compiler Revision : 00040000 [024h 0036 2] Platform Class : 0000
[026h 0038 2] Reserved : 0000
[028h 0040 8] Control Address : 0000000000000000
[030h 0048 4] Start Method : 06 [Memory Mapped I/O] [034h 0052 12] Method Parameters : 00 00 00 00 00 00 00 00 00 00 00 00
[040h 0064 4] Minimum Log Length : 00010000
[044h 0068 8] Log Address : 000000004053D000--- drivers/char/tpm/eventlog/acpi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/char/tpm/eventlog/acpi.c +5 -1
@@ -143,8 +143,12 @@ int tpm_read_log_acpi(struct tpm_chip *chip) ret = -EIO ; virt =acpi_os_map_iomem (start, len); -if (!virt) +if (!virt) { +dev_warn (&chip->dev,"%s: Failed to map ACPI memory\n" , __func__); +/* try EFI log next */ + ret = -ENODEV ; goto err; + }memcpy_fromio (log->bios_event_log, virt, len);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 61/104 block, bfq: fix possible uaf for bfqq->bic
In reply to Greg Kroah-HartmanFrom: Yu Kuai <[email protected]>
[ Upstream commit 64dc8c732f5c2b406cc752e6aaa1bd5471159cab ]
Our test report a uaf for 'bfqq->bic' in 5.10:
==================================================================
BUG: KASAN: use-after-free in bfq_select_queue+0x378/0xa30 CPU: 6 PID: 2318352 Comm: fsstress Kdump: loaded Not tainted 5.10.0-60.18.0.50.h602.kasan.eulerosv2r11.x86_64 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58-20220320_160524-szxrtosci10000 04/01/2014 Call Trace: bfq_select_queue+0x378/0xa30 bfq_dispatch_request+0xe8/0x130 blk_mq_do_dispatch_sched+0x62/0xb0 __blk_mq_sched_dispatch_requests+0x215/0x2a0 blk_mq_sched_dispatch_requests+0x8f/0xd0 __blk_mq_run_hw_queue+0x98/0x180 __blk_mq_delay_run_hw_queue+0x22b/0x240 blk_mq_run_hw_queue+0xe3/0x190 blk_mq_sched_insert_requests+0x107/0x200 blk_mq_flush_plug_list+0x26e/0x3c0 blk_finish_plug+0x63/0x90 __iomap_dio_rw+0x7b5/0x910 iomap_dio_rw+0x36/0x80 ext4_dio_read_iter+0x146/0x190 [ext4] ext4_file_read_iter+0x1e2/0x230 [ext4] new_sync_read+0x29f/0x400 vfs_read+0x24e/0x2d0 ksys_read+0xd5/0x1b0 do_syscall_64+0x33/0x40 entry_SYSCALL_64_after_hwframe+0x61/0xc6
Commit 3bc5e683c67d ("bfq: Split shared queues on move between cgroups") changes that move process to a new cgroup will allocate a new bfqq to use, however, the old bfqq and new bfqq can point to the same bic:
1) Initial state, two process with io in the same cgroup.
Process 1 Process 2
(BIC1) (BIC2)
| Λ | Λ | | | | V | V | bfqq1 bfqq2
2) bfqq1 is merged to bfqq2.
Process 1 Process 2
(BIC1) (BIC2)
| | \-------------\|
V
bfqq1 bfqq2(coop)
3) Process 1 exit, then issue new io(denoce IOA) from Process 2.
(BIC2)
| Λ | | V |
bfqq2(coop)
4) Before IOA is completed, move Process 2 to another cgroup and issue io.
Process 2
(BIC2)
Λ
|\--------------\
| V
bfqq2 bfqq3
Now that BIC2 points to bfqq3, while bfqq2 and bfqq3 both point to BIC2. If all the requests are completed, and Process 2 exit, BIC2 will be freed while there is no guarantee that bfqq2 will be freed before BIC2.
Fix the problem by clearing bfqq->bic while bfqq is detached from bic.
--- block/bfq-iosched.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
block/bfq-iosched.c +6 -1
@@ -373,6 +373,12 @@ struct bfq_queue *bic_to_bfqq(struct bfq_io_cq *bic, bool is_sync)void bic_set_bfqq (struct bfq_io_cq *bic,struct bfq_queue *bfqq,bool is_sync) { +struct bfq_queue *old_bfqq = bic->bfqq[is_sync]; + +/* Clear bic pointer if bfqq is detached from this bic */ +if (old_bfqq && old_bfqq->bic == bic) + old_bfqq->bic =NULL ; + bic->bfqq[is_sync] = bfqq; }
@@ -4977,7 +4983,6 @@ static void bfq_exit_icq_bfqq(struct bfq_io_cq *bic, bool is_sync)unsigned long flags;spin_lock_irqsave (&bfqd->lock, flags); - bfqq->bic =NULL ;bfq_exit_bfqq (bfqd, bfqq);bic_set_bfqq (bic,NULL , is_sync);spin_unlock_irqrestore (&bfqd->lock, flags);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 62/104 block, bfq: fix uaf for bfqq in bfq_exit_icq_bfqq
In reply to Greg Kroah-HartmanFrom: Yu Kuai <[email protected]>
[ Upstream commit 246cf66e300b76099b5dbd3fdd39e9a5dbc53f02 ]
Commit 64dc8c732f5c ("block, bfq: fix possible uaf for 'bfqq->bic'") will access 'bic->bfqq' in bic_set_bfqq(), however, bfq_exit_icq_bfqq() can free bfqq first, and then call bic_set_bfqq(), which will cause uaf.
Fix the problem by moving bfq_exit_bfqq() behind bic_set_bfqq().
--- block/bfq-iosched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
block/bfq-iosched.c +1 -1
@@ -4983,8 +4983,8 @@ static void bfq_exit_icq_bfqq(struct bfq_io_cq *bic, bool is_sync)unsigned long flags;spin_lock_irqsave (&bfqd->lock, flags); -bfq_exit_bfqq (bfqd, bfqq);bic_set_bfqq (bic,NULL , is_sync); +bfq_exit_bfqq (bfqd, bfqq);spin_unlock_irqrestore (&bfqd->lock, flags); } }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 63/104 block/bfq-iosched.c: use "false" rather than "BLK_RW_ASYNC"
In reply to Greg Kroah-HartmanFrom: NeilBrown <[email protected]>
[ Upstream commit f6bad159f5d5e5b33531aba3d9b860ad8618afe0 ]
bfq_get_queue() expects a "bool" for the third arg, so pass "false" rather than "BLK_RW_ASYNC" which will soon be removed.
Stable-dep-of: b600de2d7d3a ("block, bfq: fix uaf for bfqq in bic_set_bfqq()")
--- block/bfq-iosched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
block/bfq-iosched.c +1 -1
@@ -5071,7 +5071,7 @@ static void bfq_check_ioprio_change(struct bfq_io_cq *bic, struct bio *bio) bfqq =bic_to_bfqq (bic, false);if (bfqq) {bfq_release_process_ref (bfqd, bfqq); - bfqq =bfq_get_queue (bfqd, bio,BLK_RW_ASYNC , bic); + bfqq =bfq_get_queue (bfqd, bio, false, bic);bic_set_bfqq (bic, bfqq, false); }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 64/104 block, bfq: replace 0/1 with false/true in bic apis
In reply to Greg Kroah-HartmanFrom: Yu Kuai <[email protected]>
[ Upstream commit 337366e02b370d2800110fbc99940f6ddddcbdfa ]
Just to make the code a litter cleaner, there are no functional changes.
Stable-dep-of: b600de2d7d3a ("block, bfq: fix uaf for bfqq in bic_set_bfqq()")
--- block/bfq-cgroup.c | 8 ++++---- block/bfq-iosched.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-)
block/bfq-cgroup.c +4 -4
@@ -705,15 +705,15 @@ static void *__bfq_bic_change_cgroup(struct bfq_data *bfqd,struct bfq_io_cq *bic, struct bfq_group *bfqg) { - struct bfq_queue *async_bfqq = bic_to_bfqq(bic, 0); -struct bfq_queue *sync_bfqq =bic_to_bfqq (bic,1 ); + struct bfq_queue *async_bfqq = bic_to_bfqq(bic, false); +struct bfq_queue *sync_bfqq =bic_to_bfqq (bic, true);struct bfq_entity *entity;if (async_bfqq) { entity = &async_bfqq->entity;if (entity->sched_data != &bfqg->sched_data) { -bic_set_bfqq (bic,NULL ,0 ); +bic_set_bfqq (bic,NULL , false);bfq_release_process_ref (bfqd, async_bfqq); } }
@@ -749,7 +749,7 @@ static void *__bfq_bic_change_cgroup(struct bfq_data *bfqd,*/ bfq_put_cooperator (sync_bfqq);bfq_release_process_ref (bfqd, sync_bfqq); -bic_set_bfqq (bic,NULL ,1 ); +bic_set_bfqq (bic,NULL , true); } } }
block/bfq-iosched.c +2 -2
@@ -2816,7 +2816,7 @@ bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic,/* * Merge queues (that is, let bic redirect its requests to new_bfqq) */ -bic_set_bfqq (bic, new_bfqq,1 ); +bic_set_bfqq (bic, new_bfqq, true);bfq_mark_bfqq_coop (new_bfqq);/* * new_bfqq now belongs to at least two bics (it is a shared queue):
@@ -6014,7 +6014,7 @@ bfq_split_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq)return bfqq; } -bic_set_bfqq (bic,NULL ,1 ); +bic_set_bfqq (bic,NULL , true);bfq_put_cooperator (bfqq);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 65/104 block, bfq: fix uaf for bfqq in bic_set_bfqq()
In reply to Greg Kroah-HartmanFrom: Yu Kuai <[email protected]>
[ Upstream commit b600de2d7d3a16f9007fad1bdae82a3951a26af2 ]
After commit 64dc8c732f5c ("block, bfq: fix possible uaf for 'bfqq->bic'"), bic->bfqq will be accessed in bic_set_bfqq(), however, in some context bic->bfqq will be freed, and bic_set_bfqq() is called with the freed bic->bfqq.
Fix the problem by always freeing bfqq after bic_set_bfqq().
--- block/bfq-cgroup.c | 2 +- block/bfq-iosched.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-)
block/bfq-cgroup.c +1 -1
@@ -748,8 +748,8 @@ static void *__bfq_bic_change_cgroup(struct bfq_data *bfqd,* request from the old cgroup. */ bfq_put_cooperator (sync_bfqq); -bfq_release_process_ref (bfqd, sync_bfqq);bic_set_bfqq (bic,NULL , true); +bfq_release_process_ref (bfqd, sync_bfqq); } } }
block/bfq-iosched.c +3 -1
@@ -5070,9 +5070,11 @@ static void bfq_check_ioprio_change(struct bfq_io_cq *bic, struct bio *bio) bfqq =bic_to_bfqq (bic, false);if (bfqq) { -bfq_release_process_ref (bfqd, bfqq); +struct bfq_queue *old_bfqq = bfqq; + bfqq =bfq_get_queue (bfqd, bio, false, bic);bic_set_bfqq (bic, bfqq, false); +bfq_release_process_ref (bfqd, old_bfqq); } bfqq =bic_to_bfqq (bic, true);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 66/104 clk: qcom: mmcc-apq8084: remove spdm clocks
In reply to Greg Kroah-HartmanFrom: Dmitry Baryshkov <[email protected]>
[ Upstream commit 7b347f4b677b6d84687e67d82b6b17c6f55ea2b4 ]
SPDM is used for debug/profiling and does not have any other functionality. These clocks can safely be removed.
--- drivers/clk/qcom/mmcc-apq8084.c | 271 -------------------------------- 1 file changed, 271 deletions(-)
drivers/clk/qcom/mmcc-apq8084.c +0 -271
@@ -2363,262 +2363,6 @@ static struct clk_branch mmss_rbcpr_clk = { }, }; -static struct clk_branch mmss_spdm_ahb_clk = { - .halt_reg =0x0230 , - .clkr = { - .enable_reg =0x0230 , - .enable_mask =BIT (0 ), - .hw.init = &(struct clk_init_data ){ - .name ="mmss_spdm_ahb_clk" , - .parent_names = (const char *[]){ -"mmss_spdm_ahb_div_clk" , - }, - .num_parents =1 , - .flags =CLK_SET_RATE_PARENT , - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch mmss_spdm_axi_clk = { - .halt_reg =0x0210 , - .clkr = { - .enable_reg =0x0210 , - .enable_mask =BIT (0 ), - .hw.init = &(struct clk_init_data ){ - .name ="mmss_spdm_axi_clk" , - .parent_names = (const char *[]){ -"mmss_spdm_axi_div_clk" , - }, - .num_parents =1 , - .flags =CLK_SET_RATE_PARENT , - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch mmss_spdm_csi0_clk = { - .halt_reg =0x023c , - .clkr = { - .enable_reg =0x023c , - .enable_mask =BIT (0 ), - .hw.init = &(struct clk_init_data ){ - .name ="mmss_spdm_csi0_clk" , - .parent_names = (const char *[]){ -"mmss_spdm_csi0_div_clk" , - }, - .num_parents =1 , - .flags =CLK_SET_RATE_PARENT , - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch mmss_spdm_gfx3d_clk = { - .halt_reg =0x022c , - .clkr = { - .enable_reg =0x022c , - .enable_mask =BIT (0 ), - .hw.init = &(struct clk_init_data ){ - .name ="mmss_spdm_gfx3d_clk" , - .parent_names = (const char *[]){ -"mmss_spdm_gfx3d_div_clk" , - }, - .num_parents =1 , - .flags =CLK_SET_RATE_PARENT , - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch mmss_spdm_jpeg0_clk = { - .halt_reg =0x0204 , - .clkr = { - .enable_reg =0x0204 , - .enable_mask =BIT (0 ), - .hw.init = &(struct clk_init_data ){ - .name ="mmss_spdm_jpeg0_clk" , - .parent_names = (const char *[]){ -"mmss_spdm_jpeg0_div_clk" , - }, - .num_parents =1 , - .flags =CLK_SET_RATE_PARENT , - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch mmss_spdm_jpeg1_clk = { - .halt_reg =0x0208 , - .clkr = { - .enable_reg =0x0208 , - .enable_mask =BIT (0 ), - .hw.init = &(struct clk_init_data ){ - .name ="mmss_spdm_jpeg1_clk" , - .parent_names = (const char *[]){ -"mmss_spdm_jpeg1_div_clk" , - }, - .num_parents =1 , - .flags =CLK_SET_RATE_PARENT , - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch mmss_spdm_jpeg2_clk = { - .halt_reg =0x0224 , - .clkr = { - .enable_reg =0x0224 , - .enable_mask =BIT (0 ), - .hw.init = &(struct clk_init_data ){ - .name ="mmss_spdm_jpeg2_clk" , - .parent_names = (const char *[]){ -"mmss_spdm_jpeg2_div_clk" , - }, - .num_parents =1 , - .flags =CLK_SET_RATE_PARENT , - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch mmss_spdm_mdp_clk = { - .halt_reg =0x020c , - .clkr = { - .enable_reg =0x020c , - .enable_mask =BIT (0 ), - .hw.init = &(struct clk_init_data ){ - .name ="mmss_spdm_mdp_clk" , - .parent_names = (const char *[]){ -"mmss_spdm_mdp_div_clk" , - }, - .num_parents =1 , - .flags =CLK_SET_RATE_PARENT , - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch mmss_spdm_pclk0_clk = { - .halt_reg =0x0234 , - .clkr = { - .enable_reg =0x0234 , - .enable_mask =BIT (0 ), - .hw.init = &(struct clk_init_data ){ - .name ="mmss_spdm_pclk0_clk" , - .parent_names = (const char *[]){ -"mmss_spdm_pclk0_div_clk" , - }, - .num_parents =1 , - .flags =CLK_SET_RATE_PARENT , - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch mmss_spdm_pclk1_clk = { - .halt_reg =0x0228 , - .clkr = { - .enable_reg =0x0228 , - .enable_mask =BIT (0 ), - .hw.init = &(struct clk_init_data ){ - .name ="mmss_spdm_pclk1_clk" , - .parent_names = (const char *[]){ -"mmss_spdm_pclk1_div_clk" , - }, - .num_parents =1 , - .flags =CLK_SET_RATE_PARENT , - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch mmss_spdm_vcodec0_clk = { - .halt_reg =0x0214 , - .clkr = { - .enable_reg =0x0214 , - .enable_mask =BIT (0 ), - .hw.init = &(struct clk_init_data ){ - .name ="mmss_spdm_vcodec0_clk" , - .parent_names = (const char *[]){ -"mmss_spdm_vcodec0_div_clk" , - }, - .num_parents =1 , - .flags =CLK_SET_RATE_PARENT , - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch mmss_spdm_vfe0_clk = { - .halt_reg =0x0218 , - .clkr = { - .enable_reg =0x0218 , - .enable_mask =BIT (0 ), - .hw.init = &(struct clk_init_data ){ - .name ="mmss_spdm_vfe0_clk" , - .parent_names = (const char *[]){ -"mmss_spdm_vfe0_div_clk" , - }, - .num_parents =1 , - .flags =CLK_SET_RATE_PARENT , - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch mmss_spdm_vfe1_clk = { - .halt_reg =0x021c , - .clkr = { - .enable_reg =0x021c , - .enable_mask =BIT (0 ), - .hw.init = &(struct clk_init_data ){ - .name ="mmss_spdm_vfe1_clk" , - .parent_names = (const char *[]){ -"mmss_spdm_vfe1_div_clk" , - }, - .num_parents =1 , - .flags =CLK_SET_RATE_PARENT , - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch mmss_spdm_rm_axi_clk = { - .halt_reg =0x0304 , - .clkr = { - .enable_reg =0x0304 , - .enable_mask =BIT (0 ), - .hw.init = &(struct clk_init_data ){ - .name ="mmss_spdm_rm_axi_clk" , - .parent_names = (const char *[]){ -"mmss_axi_clk_src" , - }, - .num_parents =1 , - .flags =CLK_SET_RATE_PARENT , - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch mmss_spdm_rm_ocmemnoc_clk = { - .halt_reg =0x0308 , - .clkr = { - .enable_reg =0x0308 , - .enable_mask =BIT (0 ), - .hw.init = &(struct clk_init_data ){ - .name ="mmss_spdm_rm_ocmemnoc_clk" , - .parent_names = (const char *[]){ -"ocmemnoc_clk_src" , - }, - .num_parents =1 , - .flags =CLK_SET_RATE_PARENT , - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch mmss_misc_ahb_clk = { .halt_reg =0x502c , .clkr = {
@@ -3251,21 +2995,6 @@ static struct clk_regmap *mmcc_apq8084_clocks[] = { [MDSS_VSYNC_CLK] = &mdss_vsync_clk.clkr, [MMSS_RBCPR_AHB_CLK] = &mmss_rbcpr_ahb_clk.clkr, [MMSS_RBCPR_CLK] = &mmss_rbcpr_clk.clkr, - [MMSS_SPDM_AHB_CLK] = &mmss_spdm_ahb_clk.clkr, - [MMSS_SPDM_AXI_CLK] = &mmss_spdm_axi_clk.clkr, - [MMSS_SPDM_CSI0_CLK] = &mmss_spdm_csi0_clk.clkr, - [MMSS_SPDM_GFX3D_CLK] = &mmss_spdm_gfx3d_clk.clkr, - [MMSS_SPDM_JPEG0_CLK] = &mmss_spdm_jpeg0_clk.clkr, - [MMSS_SPDM_JPEG1_CLK] = &mmss_spdm_jpeg1_clk.clkr, - [MMSS_SPDM_JPEG2_CLK] = &mmss_spdm_jpeg2_clk.clkr, - [MMSS_SPDM_MDP_CLK] = &mmss_spdm_mdp_clk.clkr, - [MMSS_SPDM_PCLK0_CLK] = &mmss_spdm_pclk0_clk.clkr, - [MMSS_SPDM_PCLK1_CLK] = &mmss_spdm_pclk1_clk.clkr, - [MMSS_SPDM_VCODEC0_CLK] = &mmss_spdm_vcodec0_clk.clkr, - [MMSS_SPDM_VFE0_CLK] = &mmss_spdm_vfe0_clk.clkr, - [MMSS_SPDM_VFE1_CLK] = &mmss_spdm_vfe1_clk.clkr, - [MMSS_SPDM_RM_AXI_CLK] = &mmss_spdm_rm_axi_clk.clkr, - [MMSS_SPDM_RM_OCMEMNOC_CLK] = &mmss_spdm_rm_ocmemnoc_clk.clkr, [MMSS_MISC_AHB_CLK] = &mmss_misc_ahb_clk.clkr, [MMSS_MMSSNOC_AHB_CLK] = &mmss_mmssnoc_ahb_clk.clkr, [MMSS_MMSSNOC_BTO_AHB_CLK] = &mmss_mmssnoc_bto_ahb_clk.clkr,
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 67/104 MIPS: Fix a compilation issue
In reply to Greg Kroah-HartmanFrom: xurui <[email protected]>
[ Upstream commit 109d587a4b4d7ccca2200ab1f808f43ae23e2585 ]
arch/mips/include/asm/mach-rc32434/pci.h:377:
cc1: error: result of ‘-117440512 << 16’ requires 44 bits to represent, but ‘int’ only has 32 bits [-Werror=shift-overflow=]
All bits in KORINA_STAT are already at the correct position, so there is no addtional shift needed.
--- arch/mips/include/asm/mach-rc32434/pci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/mips/include/asm/mach-rc32434/pci.h +1 -1
@@ -374,7 +374,7 @@ struct pci_msu { PCI_CFG04_STAT_SSE | \ PCI_CFG04_STAT_PE) -#define KORINA_CNFG1 ((KORINA_STAT<<16)|KORINA_CMD) +#define KORINA_CNFG1 (KORINA_STAT | KORINA_CMD)#define KORINA_REVID 0#define KORINA_CLASS_CODE 0
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 68/104 powerpc: Check !irq instead of irq == NO_IRQ and remove NO_IRQ
In reply to Greg Kroah-HartmanFrom: Christophe Leroy <[email protected]>
[ Upstream commit bab537805a10bdbf55b31324ba4a9599e0651e5e ]
NO_IRQ is a relic from the old days. It is not used anymore in core functions. By the way, function irq_of_parse_and_map() returns value 0 on error.
In some drivers, NO_IRQ is erroneously used to check the return of irq_of_parse_and_map().
It is not a real bug today because the only architectures using the drivers being fixed by this patch define NO_IRQ as 0, but there are architectures which define NO_IRQ as -1. If one day those architectures start using the non fixed drivers, there will be a problem.
Long time ago Linus advocated for not using NO_IRQ, see
https://lore.kernel.org/all/[email protected]
He re-iterated the same view recently in
https://lore.kernel.org/all/CAHk-=wg2Pkb9kbfbstbB91AJA2SF6cySbsgHG-iQMq56j3VTcA@mail.gmail.com
So test !irq instead of tesing irq == NO_IRQ.
All other usage of NO_IRQ for powerpc were removed in previous cycles so the time has come to remove NO_IRQ completely for powerpc.
--- arch/powerpc/include/asm/irq.h | 3 --- arch/powerpc/platforms/44x/fsp2.c | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-)
arch/powerpc/include/asm/irq.h +0 -3
@@ -17,9 +17,6 @@extern atomic_t ppc_n_lost_interrupts; -/* This number is used when no interrupt has been assigned */ -#define NO_IRQ (0) -/* Total number of virq in the platform */ #define NR_IRQS CONFIG_NR_IRQS
arch/powerpc/platforms/44x/fsp2.c +1 -1
@@ -205,7 +205,7 @@ static void node_irq_request(const char *compat, irq_handler_t errirq_handler)for_each_compatible_node (np,NULL , compat) { irq =irq_of_parse_and_map (np,0 ); -if (irq ==NO_IRQ ) { +if (!irq) {pr_err ("device tree node %pOFn is missing a interrupt" , np);of_node_put (np);
Signature · 1 line
2.39.2
Re: [PATCH 5.10 068/104] powerpc: Check !irq instead of irq == NO_IRQ and remove NO_IRQ
Le 15/03/2023 à 13:12, Greg Kroah-Hartman a écrit :
Quoted 25 lines
From: Christophe Leroy <[email protected]>
[ Upstream commit
bab537805a10bdbf55b31324ba4a9599e0651e5e]
NO_IRQis a relic from the old days. It is not used anymore in core functions. By the way, functionirq_of_parse_and_map()returns value 0 on error.In some drivers,
NO_IRQis erroneously used to check the return ofirq_of_parse_and_map().It is not a real bug today because the only architectures using the drivers being fixed by this patch define
NO_IRQas 0, but there are architectures which defineNO_IRQas -1. If one day those architectures start using the non fixed drivers, there will be a problem.Long time ago Linus advocated for not using
NO_IRQ, see
https://lore.kernel.org/all/[email protected]He re-iterated the same view recently in
https://lore.kernel.org/all/CAHk-=wg2Pkb9kbfbstbB91AJA2SF6cySbsgHG-iQMq56j3VTcA@mail.gmail.comSo test !irq instead of tesing irq ==
NO_IRQ.
Quoted 7 lines
All other usage of
NO_IRQfor powerpc were removed in previous cycles so the time has come to removeNO_IRQcompletely for powerpc.
You can't remove NO_IRQ macro without first all preparation patches merged during the 6.2 cycle.
Christophe
Quoted 32 lines
--- arch/powerpc/include/asm/irq.h | 3 --- arch/powerpc/platforms/44x/fsp2.c | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-)arch/powerpc/include/asm/irq.h +0
-3@@ -17,9 +17,6 @@extern atomic_t ppc_n_lost_interrupts; -/* This number is used when no interrupt has been assigned */ -#define NO_IRQ (0) -/* Total number of virq in the platform */ #define NR_IRQS CONFIG_NR_IRQSarch/powerpc/platforms/44x/fsp2.c +1
-1@@ -205,7 +205,7 @@ static void node_irq_request(const char *compat, irq_handler_t errirq_handler)for_each_compatible_node (np,NULL , compat) { irq =irq_of_parse_and_map (np,0 ); -if (irq ==NO_IRQ ) { +if (!irq) {pr_err ("device tree node %pOFn is missing a interrupt" , np);of_node_put (np);
Greg Kroah-Hartman
maintainerPATCH 69/104 powerpc/kcsan: Exclude udelay to prevent recursive instrumentation
In reply to Greg Kroah-HartmanFrom: Rohan McLure <[email protected]>
[ Upstream commit 2a7ce82dc46c591c9244057d89a6591c9639b9b9 ]
In order for KCSAN to increase its likelihood of observing a data race, it sets a watchpoint on memory accesses and stalls, allowing for detection of conflicting accesses by other kernel threads or interrupts.
Stalls are implemented by injecting a call to udelay in instrumented code. To prevent recursive instrumentation, exclude udelay from being instrumented.
--- arch/powerpc/kernel/time.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/powerpc/kernel/time.c +2 -2
@@ -436,7 +436,7 @@ void vtime_flush(struct task_struct *tsk)#define calc_cputime_factors ()#endif -void __delay (unsigned long loops) +void __no_kcsan __delay(unsigned long loops) {unsigned long start;
@@ -457,7 +457,7 @@ void __delay(unsigned long loops) }EXPORT_SYMBOL (__delay); -void udelay (unsigned long usecs) +void __no_kcsan udelay(unsigned long usecs) {__delay (tb_ticks_per_usec * usecs); }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 70/104 alpha: fix R_ALPHA_LITERAL reloc for large modules
In reply to Greg Kroah-HartmanFrom: Edward Humes <[email protected]>
[ Upstream commit b6b17a8b3ecd878d98d5472a9023ede9e669ca72 ]
Previously, R_ALPHA_LITERAL relocations would overflow for large kernel modules.
This was because the Alpha's apply_relocate_add was relying on the kernel's module loader to have sorted the GOT towards the very end of the module as it was mapped into memory in order to correctly assign the global pointer. While this behavior would mostly work fine for small kernel modules, this approach would overflow on kernel modules with large GOT's since the global pointer would be very far away from the GOT, and thus, certain entries would be out of range.
This patch fixes this by instead using the Tru64 behavior of assigning the global pointer to be 32KB away from the start of the GOT. The change made in this patch won't work for multi-GOT kernel modules as it makes the assumption the module only has one GOT located at the beginning of .got, although for the vast majority kernel modules, this should be fine. Of the kernel modules that would previously result in a relocation error, none of them, even modules like nouveau, have even come close to filling up a single GOT, and they've all worked fine under this patch.
--- arch/alpha/kernel/module.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
arch/alpha/kernel/module.c +1 -3
@@ -146,10 +146,8 @@ apply_relocate_add(Elf64_Shdr *sechdrs, const char *strtab, base = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr; symtab = (Elf64_Sym *)sechdrs[symindex].sh_addr; -/* The small sections were sorted to the end of the segment. -The following should definitely cover them. */ - gp = (u64 )me->core_layout.base + me->core_layout.size -0x8000 ; got = sechdrs[me->arch.gotsecindex].sh_addr; + gp = got +0x8000 ;for (i =0 ; i < n; i++) {unsigned long r_sym =ELF64_R_SYM (rela[i].r_info);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 71/104 macintosh: windfarm: Use unsigned type for 1-bit bitfields
In reply to Greg Kroah-HartmanFrom: Nathan Chancellor <[email protected]>
[ Upstream commit 748ea32d2dbd813d3bd958117bde5191182f909a ]
Clang warns:
drivers/macintosh/windfarm_lm75_sensor.c:63:14: error: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Werror,-Wsingle-bit-bitfield-constant-conversion]
lm->inited = 1;
^ ~ drivers/macintosh/windfarm_smu_sensors.c:356:19: error: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Werror,-Wsingle-bit-bitfield-constant-conversion]
pow->fake_volts = 1;
^ ~
drivers/macintosh/windfarm_smu_sensors.c:368:18: error: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Werror,-Wsingle-bit-bitfield-constant-conversion]
pow->quadratic = 1;
^ ~There is no bug here since no code checks the actual value of these fields, just whether or not they are zero (boolean context), but this can be easily fixed by switching to an unsigned type.
--- drivers/macintosh/windfarm_lm75_sensor.c | 4 ++-- drivers/macintosh/windfarm_smu_sensors.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
drivers/macintosh/windfarm_lm75_sensor.c +2 -2
@@ -34,8 +34,8 @@#endif struct wf_lm75_sensor { -int ds1775 :1 ; -int inited :1 ; +unsigned int ds1775 :1 ; +unsigned int inited :1 ;struct i2c_client *i2c;struct wf_sensor sens; };
drivers/macintosh/windfarm_smu_sensors.c +2 -2
@@ -273,8 +273,8 @@ struct smu_cpu_power_sensor {struct list_head link;struct wf_sensor *volts;struct wf_sensor *amps; - int fake_volts : 1; - int quadratic : 1; + unsigned int fake_volts : 1; + unsigned int quadratic : 1;struct wf_sensor sens; };#define to_smu_cpu_power (c) container_of(c, struct smu_cpu_power_sensor, sens)
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 72/104 PCI: Add SolidRun vendor ID
In reply to Greg Kroah-HartmanFrom: Alvaro Karsz <[email protected]>
[ Upstream commit db6c4dee4c104f50ed163af71c53bfdb878a8318 ]
Add SolidRun vendor ID to pci_ids.h
The vendor ID is used in 2 different source files, the SNET vDPA driver and PCI quirks.
Message-Id: <[email protected]>
--- include/linux/pci_ids.h | 2 ++ 1 file changed, 2 insertions(+)
include/linux/pci_ids.h +2 -0
@@ -3115,6 +3115,8 @@#define PCI_VENDOR_ID_3COM_2 0xa727 +#define PCI_VENDOR_ID_SOLIDRUN 0xd063 +#define PCI_VENDOR_ID_DIGIUM 0xd161#define PCI_DEVICE_ID_DIGIUM_HFC4S 0xb410
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 73/104 PCI: Avoid FLR for SolidRun SNET DPU rev 1
In reply to Greg Kroah-HartmanFrom: Alvaro Karsz <[email protected]>
[ Upstream commit d089d69cc1f824936eeaa4fa172f8fa1a0949eaa ]
This patch fixes a FLR bug on the SNET DPU rev 1 by setting the PCI_DEV_FLAGS_NO_FLR_RESET flag.
As there is a quirk to avoid FLR (quirk_no_flr), I added a new quirk to check the rev ID before calling to quirk_no_flr.
Without this patch, a SNET DPU rev 1 may hang when FLR is applied.
Message-Id: <[email protected]>
--- drivers/pci/quirks.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/pci/quirks.c +8 -0
@@ -5328,6 +5328,14 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AMD, 0x7901, quirk_no_flr);DECLARE_PCI_FIXUP_EARLY (PCI_VENDOR_ID_INTEL ,0x1502 , quirk_no_flr);DECLARE_PCI_FIXUP_EARLY (PCI_VENDOR_ID_INTEL ,0x1503 , quirk_no_flr); +/* FLR may cause the SolidRun SNET DPU (rev 0x1) to hang */ +static void quirk_no_flr_snet (struct pci_dev *dev) +{ +if (dev->revision ==0x1 ) +quirk_no_flr (dev); +} +DECLARE_PCI_FIXUP_EARLY (PCI_VENDOR_ID_SOLIDRUN ,0x1000 , quirk_no_flr_snet); +static void quirk_no_ext_tags (struct pci_dev *pdev) {struct pci_host_bridge *bridge =pci_find_host_bridge (pdev->bus);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 74/104 scripts: handle BrokenPipeError for python scripts
In reply to Greg Kroah-HartmanFrom: Masahiro Yamada <[email protected]>
[ Upstream commit 87c7ee67deb7fce9951a5f9d80641138694aad17 ]
In the follow-up of commit fb3041d61f68 ("kbuild: fix SIGPIPE error message for AR=gcc-ar and AR=llvm-ar"), Kees Cook pointed out that tools should _not_ catch their own SIGPIPEs [1] [2].
Based on his feedback, LLVM was fixed [3].
However, Python's default behavior is to show noisy bracktrace when SIGPIPE is sent. So, scripts written in Python are basically in the same situation as the buggy llvm tools.
Example:
$ make -s allnoconfig
$ make -s allmodconfig
$ scripts/diffconfig .config.old .config | head -n1
-ALIX n
Traceback (most recent call last):
File "/home/masahiro/linux/scripts/diffconfig", line 132, in <module>
main()
File "/home/masahiro/linux/scripts/diffconfig", line 130, in main
print_config("+", config, None, b[config])
File "/home/masahiro/linux/scripts/diffconfig", line 64, in print_config
print("+%s %s" % (config, new_value))
BrokenPipeError: [Errno 32] Broken pipePython documentation [4] notes how to make scripts die immediately and silently:
"""
Piping output of your program to tools like head(1) will cause a SIGPIPE signal to be sent to your process when the receiver of its standard output closes early. This results in an exception like
BrokenPipeError: [Errno 32] Broken pipe. To handle this case, wrap your entry point to catch this exception as follows:
import os
import sys
def main():
try:
# simulate large output (your code replaces this loop) for x in range(10000):
print("y")
# flush output here to force SIGPIPE to be triggered
# while inside this try block.
sys.stdout.flush()
except BrokenPipeError:
# Python flushes standard streams on exit; redirect remaining output # to devnull to avoid another BrokenPipeError at shutdown devnull = os.open(os.devnull, os.O_WRONLY) os.dup2(devnull, sys.stdout.fileno())
sys.exit(1) # Python exits with error code 1 on EPIPE
if __name__ == '__main__':
main()
Do not set SIGPIPE’s disposition to SIG_DFL in order to avoid BrokenPipeError. Doing that would cause your program to exit unexpectedly whenever any socket connection is interrupted while your program is still writing to it.
"""
Currently, tools/perf/scripts/python/intel-pt-events.py seems to be the only script that fixes the issue that way.
tools/perf/scripts/python/compaction-times.py uses another approach signal.signal(signal.SIGPIPE, signal.SIG_DFL) but the Python documentation clearly says "Don't do it".
I cannot fix all Python scripts since there are so many. I fixed some in the scripts/ directory.
[1]: https://lore.kernel.org/all/202211161056.1B9611A@keescook/
[2]: https://github.com/llvm/llvm-project/issues/59037
[3]: https://github.com/llvm/llvm-project/commit/4787efa38066adb51e2c049499d25b3610c0877b
[4]: https://docs.python.org/3/library/signal.html#note-on-sigpipe
--- scripts/checkkconfigsymbols.py | 13 ++++++++++++- scripts/clang-tools/run-clang-tools.py | 21 ++++++++++++++------- scripts/diffconfig | 16 ++++++++++++++-- 3 files changed, 40 insertions(+), 10 deletions(-)
scripts/checkkconfigsymbols.py +12 -1
@@ -113,7 +113,7 @@ def parse_options(): return args -def main(): +def print_undefined_symbols(): """Main function of this module.""" args = parse_options()
@@ -472,5 +472,16 @@ def parse_kconfig_file(kfile): return defined, references +def main(): + try: + print_undefined_symbols() + except BrokenPipeError: + # Python flushes standard streams on exit; redirect remaining output + # to devnull to avoid another BrokenPipeError at shutdown + devnull = os.open(os.devnull, os.O_WRONLY) + os.dup2(devnull, sys.stdout.fileno()) + sys.exit(1) # Python exits with error code 1 on EPIPE + + if __name__ == "__main__": main()
scripts/clang-tools/run-clang-tools.py +14 -7
@@ -60,14 +60,21 @@ def run_analysis(entry): def main(): - args = parse_arguments() + try: + args = parse_arguments() - lock = multiprocessing.Lock() - pool = multiprocessing.Pool(initializer=init, initargs=(lock, args)) - # Read JSON data into the datastore variable - with open(args.path, "r") as f: - datastore = json.load(f) - pool.map(run_analysis, datastore) + lock = multiprocessing.Lock() + pool = multiprocessing.Pool(initializer=init, initargs=(lock, args)) + # Read JSON data into the datastore variable + with open(args.path, "r") as f: + datastore = json.load(f) + pool.map(run_analysis, datastore) + except BrokenPipeError: + # Python flushes standard streams on exit; redirect remaining output + # to devnull to avoid another BrokenPipeError at shutdown + devnull = os.open(os.devnull, os.O_WRONLY) + os.dup2(devnull, sys.stdout.fileno()) + sys.exit(1) # Python exits with error code 1 on EPIPE if __name__ == "__main__":
scripts/diffconfig +14 -2
@@ -65,7 +65,7 @@ def print_config(op, config, value, new_value): else: print(" %s %s -> %s" % (config, value, new_value)) -def main(): +def show_diff(): global merge_style # parse command line args
@@ -129,4 +129,16 @@ def main(): for config in new: print_config("+", config, None, b[config]) -main() +def main(): + try: + show_diff() + except BrokenPipeError: + # Python flushes standard streams on exit; redirect remaining output + # to devnull to avoid another BrokenPipeError at shutdown + devnull = os.open(os.devnull, os.O_WRONLY) + os.dup2(devnull, sys.stdout.fileno()) + sys.exit(1) # Python exits with error code 1 on EPIPE + + +if __name__ == '__main__': + main()
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 75/104 media: ov5640: Fix analogue gain control
In reply to Greg Kroah-HartmanFrom: Paul Elder <[email protected]>
[ Upstream commit afa4805799c1d332980ad23339fdb07b5e0cf7e0 ]
Gain control is badly documented in publicly available (including leaked) documentation.
There is an AGC pre-gain in register 0x3a13, expressed as a 6-bit value (plus an enable bit in bit 6). The driver hardcodes it to 0x43, which one application note states is equal to x1.047. The documentation also states that 0x40 is equel to x1.000. The pre-gain thus seems to be expressed as in 1/64 increments, and thus ranges from x1.00 to x1.984. What the pre-gain does is however unspecified.
There is then an AGC gain limit, in registers 0x3a18 and 0x3a19, expressed as a 10-bit "real gain format" value. One application note sets it to 0x00f8 and states it is equal to x15.5, so it appears to be expressed in 1/16 increments, up to x63.9375.
The manual gain is stored in registers 0x350a and 0x350b, also as a 10-bit "real gain format" value. It is documented in the application note as a Q6.4 values, up to x63.9375.
One version of the datasheet indicates that the sensor supports a digital gain:
The OV5640 supports 1/2/4 digital gain. Normally, the gain is controlled automatically by the automatic gain control (AGC) block.
It isn't clear how that would be controlled manually.
There appears to be no indication regarding whether the gain controlled through registers 0x350a and 0x350b is an analogue gain only or also includes digital gain. The words "real gain" don't necessarily mean "combined analogue and digital gains". Some OmniVision sensors (such as the OV8858) are documented as supoprting different formats for the gain values, selectable through a register bit, and they are called "real gain format" and "sensor gain format". For that sensor, we have (one of) the gain registers documented as
0x3503[2]=0, gain[7:0] is real gain format, where low 4 bits are fraction bits, for example, 0x10 is 1x gain, 0x28 is 2.5x gain
If 0x3503[2]=1, gain[7:0] is sensor gain format, gain[7:4] is coarse gain, 00000: 1x, 00001: 2x, 00011: 4x, 00111: 8x, gain[7] is 1, gain[3:0] is fine gain. For example, 0x10 is 1x gain, 0x30 is 2x gain, 0x70 is 4x gain
(The second part of the text makes little sense)
"Real gain" may thus refer to the combination of the coarse and fine analogue gains as a single value.
The OV5640 0x350a and 0x350b registers thus appear to control analogue gain. The driver incorrectly uses V4L2_CID_GAIN as V4L2 has a specific control for analogue gain, V4L2_CID_ANALOGUE_GAIN. Use it.
If registers 0x350a and 0x350b are later found to control digital gain as well, the driver could then restrict the range of the analogue gain control value to lower than x64 and add a separate digital gain control.
--- drivers/media/i2c/ov5640.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/i2c/ov5640.c +1 -1
@@ -2748,7 +2748,7 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)/* Auto/manual gain */ ctrls->auto_gain =v4l2_ctrl_new_std (hdl, ops,V4L2_CID_AUTOGAIN ,0 ,1 ,1 ,1 ); - ctrls->gain =v4l2_ctrl_new_std (hdl, ops,V4L2_CID_GAIN , + ctrls->gain =v4l2_ctrl_new_std (hdl, ops,V4L2_CID_ANALOGUE_GAIN ,0 ,1023 ,1 ,0 ); ctrls->saturation = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION,
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 76/104 media: rc: gpio-ir-recv: add remove function
In reply to Greg Kroah-HartmanFrom: Li Jun <[email protected]>
[ Upstream commit 30040818b338b8ebc956ce0ebd198f8d593586a6 ]
In case runtime PM is enabled, do runtime PM clean up to remove cpu latency qos request, otherwise driver removal may have below kernel dump:
[ 19.463299] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000048 [ 19.472161] Mem abort info: [ 19.474985] ESR = 0x0000000096000004 [ 19.478754] EC = 0x25: DABT (current EL), IL = 32 bits [ 19.484081] SET = 0, FnV = 0 [ 19.487149] EA = 0, S1PTW = 0 [ 19.490361] FSC = 0x04: level 0 translation fault [ 19.495256] Data abort info: [ 19.498149] ISV = 0, ISS = 0x00000004 [ 19.501997] CM = 0, WnR = 0 [ 19.504977] user pgtable: 4k pages, 48-bit VAs, pgdp=0000000049f81000 [ 19.511432] [0000000000000048] pgd=0000000000000000, p4d=0000000000000000 [ 19.518245] Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP [ 19.524520] Modules linked in: gpio_ir_recv(+) rc_core [last unloaded: rc_core] [ 19.531845] CPU: 0 PID: 445 Comm: insmod Not tainted 6.2.0-rc1-00028-g2c397a46d47c #72 [ 19.531854] Hardware name: FSL i.MX8MM EVK board (DT) [ 19.531859] pstate: 80000005 (Nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 19.551777] pc : cpu_latency_qos_remove_request+0x20/0x110 [ 19.557277] lr : gpio_ir_recv_runtime_suspend+0x18/0x30 [gpio_ir_recv] [ 19.557294] sp : ffff800008ce3740 [ 19.557297] x29: ffff800008ce3740 x28: 0000000000000000 x27: ffff800008ce3d50 [ 19.574270] x26: ffffc7e3e9cea100 x25: 00000000000f4240 x24: ffffc7e3f9ef0e30 [ 19.574284] x23: 0000000000000000 x22: ffff0061803820f4 x21: 0000000000000008 [ 19.574296] x20: ffffc7e3fa75df30 x19: 0000000000000020 x18: ffffffffffffffff [ 19.588570] x17: 0000000000000000 x16: ffffc7e3f9efab70 x15: ffffffffffffffff [ 19.595712] x14: ffff800008ce37b8 x13: ffff800008ce37aa x12: 0000000000000001 [ 19.602853] x11: 0000000000000001 x10: ffffcbe3ec0dff87 x9 : 0000000000000008 [ 19.609991] x8 : 0101010101010101 x7 : 0000000000000000 x6 : 000000000f0bfe9f [ 19.624261] x5 : 00ffffffffffffff x4 : 0025ab8e00000000 x3 : ffff006180382010 [ 19.631405] x2 : ffffc7e3e9ce8030 x1 : ffffc7e3fc3eb810 x0 : 0000000000000020 [ 19.638548] Call trace: [ 19.640995] cpu_latency_qos_remove_request+0x20/0x110 [ 19.646142] gpio_ir_recv_runtime_suspend+0x18/0x30 [gpio_ir_recv] [ 19.652339] pm_generic_runtime_suspend+0x2c/0x44 [ 19.657055] __rpm_callback+0x48/0x1dc [ 19.660807] rpm_callback+0x6c/0x80 [ 19.664301] rpm_suspend+0x10c/0x640 [ 19.667880] rpm_idle+0x250/0x2d0 [ 19.671198] update_autosuspend+0x38/0xe0 [ 19.675213] pm_runtime_set_autosuspend_delay+0x40/0x60 [ 19.680442] gpio_ir_recv_probe+0x1b4/0x21c [gpio_ir_recv] [ 19.685941] platform_probe+0x68/0xc0 [ 19.689610] really_probe+0xc0/0x3dc [ 19.693189] __driver_probe_device+0x7c/0x190 [ 19.697550] driver_probe_device+0x3c/0x110 [ 19.701739] __driver_attach+0xf4/0x200 [ 19.705578] bus_for_each_dev+0x70/0xd0 [ 19.709417] driver_attach+0x24/0x30 [ 19.712998] bus_add_driver+0x17c/0x240 [ 19.716834] driver_register+0x78/0x130 [ 19.720676] __platform_driver_register+0x28/0x34 [ 19.725386] gpio_ir_recv_driver_init+0x20/0x1000 [gpio_ir_recv] [ 19.731404] do_one_initcall+0x44/0x2ac [ 19.735243] do_init_module+0x48/0x1d0 [ 19.739003] load_module+0x19fc/0x2034 [ 19.742759] __do_sys_finit_module+0xac/0x12c [ 19.747124] __arm64_sys_finit_module+0x20/0x30 [ 19.751664] invoke_syscall+0x48/0x114 [ 19.755420] el0_svc_common.constprop.0+0xcc/0xec [ 19.760132] do_el0_svc+0x38/0xb0 [ 19.763456] el0_svc+0x2c/0x84 [ 19.766516] el0t_64_sync_handler+0xf4/0x120 [ 19.770789] el0t_64_sync+0x190/0x194 [ 19.774460] Code: 910003fd a90153f3 aa0003f3 91204021 (f9401400) [ 19.780556] ---[ end trace 0000000000000000 ]---
--- drivers/media/rc/gpio-ir-recv.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
drivers/media/rc/gpio-ir-recv.c +18 -0
@@ -130,6 +130,23 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) "gpio-ir-recv-irq", gpio_dev); } +static int gpio_ir_recv_remove (struct platform_device *pdev) +{ +struct gpio_rc_dev *gpio_dev =platform_get_drvdata (pdev); +struct device *pmdev = gpio_dev->pmdev; + +if (pmdev) { +pm_runtime_get_sync (pmdev); +cpu_latency_qos_remove_request (&gpio_dev->qos); + +pm_runtime_disable (pmdev); +pm_runtime_put_noidle (pmdev); +pm_runtime_set_suspended (pmdev); + } + +return 0 ; +} +#ifdef CONFIG_PM static int gpio_ir_recv_suspend (struct device *dev) {
@@ -189,6 +206,7 @@ MODULE_DEVICE_TABLE(of, gpio_ir_recv_of_match);static struct platform_driver gpio_ir_recv_driver = { .probe = gpio_ir_recv_probe, + .remove = gpio_ir_recv_remove, .driver = { .name =KBUILD_MODNAME , .of_match_table =of_match_ptr (gpio_ir_recv_of_match),
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 77/104 ipmi/watchdog: replace atomic_add() and atomic_sub()
In reply to Greg Kroah-HartmanFrom: Yejune Deng <[email protected]>
commit a01a89b1db1066a6af23ae08b9a0c345b7966f0b upstream.
atomic_inc() and atomic_dec() looks better
Message-Id: <[email protected]>
--- drivers/char/ipmi/ipmi_watchdog.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/char/ipmi/ipmi_watchdog.c +4 -4
@@ -503,7 +503,7 @@ static void panic_halt_ipmi_heartbeat(vo msg.cmd =IPMI_WDOG_RESET_TIMER ; msg.data =NULL ; msg.data_len =0 ; -atomic_add (1 , &panic_done_count); +atomic_inc (&panic_done_count); rv = ipmi_request_supply_msgs(watchdog_user, (struct ipmi_addr *) &addr, 0,
@@ -513,7 +513,7 @@ static void panic_halt_ipmi_heartbeat(vo &panic_halt_heartbeat_recv_msg, 1);if (rv) -atomic_sub (1 , &panic_done_count); +atomic_dec (&panic_done_count); }static struct ipmi_smi_msg panic_halt_smi_msg = {
@@ -537,12 +537,12 @@ static void panic_halt_ipmi_set_timeout(/* Wait for the messages to be free. */ while (atomic_read (&panic_done_count) !=0 )ipmi_poll_interface (watchdog_user); -atomic_add (1 , &panic_done_count); +atomic_inc (&panic_done_count); rv =__ipmi_set_timeout (&panic_halt_smi_msg, &panic_halt_recv_msg, &send_heartbeat_now);if (rv) { -atomic_sub (1 , &panic_done_count); +atomic_dec (&panic_done_count);pr_warn ("Unable to extend the watchdog timeout\n" ); }else {if (send_heartbeat_now)
Greg Kroah-Hartman
maintainerPATCH 78/104 ipmi:watchdog: Set panic count to proper value on a panic
In reply to Greg Kroah-HartmanFrom: Corey Minyard <[email protected]>
commit db05ddf7f321634c5659a0cf7ea56594e22365f7 upstream.
You will get two decrements when the messages on a panic are sent, not one, since commit 2033f6858970 ("ipmi: Free receive messages when in an oops") was added, but the watchdog code had a bug where it didn't set the value properly.
--- drivers/char/ipmi/ipmi_watchdog.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/char/ipmi/ipmi_watchdog.c +4 -4
@@ -503,7 +503,7 @@ static void panic_halt_ipmi_heartbeat(vo msg.cmd =IPMI_WDOG_RESET_TIMER ; msg.data =NULL ; msg.data_len =0 ; -atomic_inc (&panic_done_count); +atomic_add (2 , &panic_done_count); rv = ipmi_request_supply_msgs(watchdog_user, (struct ipmi_addr *) &addr, 0,
@@ -513,7 +513,7 @@ static void panic_halt_ipmi_heartbeat(vo &panic_halt_heartbeat_recv_msg, 1);if (rv) -atomic_dec (&panic_done_count); +atomic_sub (2 , &panic_done_count); }static struct ipmi_smi_msg panic_halt_smi_msg = {
@@ -537,12 +537,12 @@ static void panic_halt_ipmi_set_timeout(/* Wait for the messages to be free. */ while (atomic_read (&panic_done_count) !=0 )ipmi_poll_interface (watchdog_user); -atomic_inc (&panic_done_count); +atomic_add (2 , &panic_done_count); rv =__ipmi_set_timeout (&panic_halt_smi_msg, &panic_halt_recv_msg, &send_heartbeat_now);if (rv) { -atomic_dec (&panic_done_count); +atomic_sub (2 , &panic_done_count);pr_warn ("Unable to extend the watchdog timeout\n" ); }else {if (send_heartbeat_now)
Greg Kroah-Hartman
maintainerPATCH 79/104 skbuff: Fix nfct leak on napi stolen
In reply to Greg Kroah-HartmanFrom: Tao Liu <[email protected]>
Upstream commit [0] had fixed this issue, and backported to kernel 5.10.54. However, nf_reset_ct() added in skb_release_head_state() instead of napi_skb_free_stolen_head(), which lead to leakage still exist in 5.10.
--- net/core/dev.c | 1 + net/core/skbuff.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-)
net/core/dev.c +1 -0
@@ -6111,6 +6111,7 @@ EXPORT_SYMBOL(gro_find_complete_by_type)static void napi_skb_free_stolen_head (struct sk_buff *skb) { +nf_reset_ct (skb);skb_dst_drop (skb);skb_ext_put (skb);kmem_cache_free (skbuff_head_cache, skb);
net/core/skbuff.c +0 -1
@@ -659,7 +659,6 @@ fastpath:void skb_release_head_state (struct sk_buff *skb) { -nf_reset_ct (skb);skb_dst_drop (skb);if (skb->destructor) {WARN_ON (in_irq ());
Greg Kroah-Hartman
maintainerPATCH 80/104 drm/i915: Dont use BAR mappings for ring buffers with LLC
In reply to Greg Kroah-HartmanFrom: John Harrison <[email protected]>
commit 85636167e3206c3fbd52254fc432991cc4e90194 upstream.
Direction from hardware is that ring buffers should never be mapped via the BAR on systems with LLC. There are too many caching pitfalls due to the way BAR accesses are routed. So it is safest to just not use it.
--- drivers/gpu/drm/i915/gt/intel_ring.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/gt/intel_ring.c +2 -2
@@ -49,7 +49,7 @@ int intel_ring_pin(struct intel_ring *riif (unlikely (ret)) goto err_unpin; -if (i915_vma_is_map_and_fenceable (vma)) +if (i915_vma_is_map_and_fenceable (vma) && !HAS_LLC (vma->vm->i915)) addr = (void __force *)i915_vma_pin_iomap (vma);else addr = i915_gem_object_pin_map(vma->obj,
@@ -91,7 +91,7 @@ void intel_ring_unpin(struct intel_ringreturn ;i915_vma_unset_ggtt_write (vma); -if (i915_vma_is_map_and_fenceable (vma)) +if (i915_vma_is_map_and_fenceable (vma) && !HAS_LLC (vma->vm->i915))i915_vma_unpin_iomap (vma);else i915_gem_object_unpin_map (vma->obj);
Greg Kroah-Hartman
maintainerPATCH 81/104 sched/uclamp: Make task_fits_capacity() use util_fits_cpu()
In reply to Greg Kroah-HartmanFrom: Qais Yousef <[email protected]>
commit b48e16a69792b5dc4a09d6807369d11b2970cc36 upstream.
So that the new uclamp rules in regard to migration margin and capacity pressure are taken into account correctly.
--- kernel/sched/fair.c | 26 ++++++++++++++++---------- kernel/sched/sched.h | 9 +++++++++ 2 files changed, 25 insertions(+), 10 deletions(-)
kernel/sched/fair.c +16 -10
@@ -4197,10 +4197,12 @@ static inline int util_fits_cpu(unsignedreturn fits; } -static inline int task_fits_capacity (struct task_struct *p, -unsigned long capacity) +static inline int task_fits_cpu (struct task_struct *p,int cpu) { -return fits_capacity (uclamp_task_util (p), capacity); +unsigned long uclamp_min =uclamp_eff_value (p,UCLAMP_MIN ); +unsigned long uclamp_max =uclamp_eff_value (p,UCLAMP_MAX ); +unsigned long util =task_util_est (p); +return util_fits_cpu (util, uclamp_min, uclamp_max, cpu); }static inline void update_misfit_status (struct task_struct *p,struct rq *rq)
@@ -4213,7 +4215,7 @@ static inline void update_misfit_status(return ; } -if (task_fits_capacity (p,capacity_of (cpu_of (rq)))) { +if (task_fits_cpu (p,cpu_of (rq))) { rq->misfit_task_load =0 ;return ; }
@@ -7898,7 +7900,7 @@ static int detach_tasks(struct lb_env *ecase migrate_misfit:/* This is not a misfit task */ -if (task_fits_capacity (p,capacity_of (env->src_cpu))) +if (task_fits_cpu (p, env->src_cpu)) goto next; env->imbalance =0 ;
@@ -8840,6 +8842,10 @@ static inline void update_sg_wakeup_statmemset (sgs,0 ,sizeof (*sgs)); +/* Assume that task can't fit any CPU of the group */ +if (sd->flags &SD_ASYM_CPUCAPACITY ) + sgs->group_misfit_task_load =1 ; +for_each_cpu (i,sched_group_span (group)) {struct rq *rq =cpu_rq (i);unsigned int local;
@@ -8859,12 +8865,12 @@ static inline void update_sg_wakeup_statif (!nr_running &&idle_cpu_without (i, p)) sgs->idle_cpus++; - } +/* Check if task fits in the CPU */ +if (sd->flags &SD_ASYM_CPUCAPACITY && + sgs->group_misfit_task_load && +task_fits_cpu (p, i)) + sgs->group_misfit_task_load =0 ; -/* Check if task fits in the group */ -if (sd->flags &SD_ASYM_CPUCAPACITY && - !task_fits_capacity (p, group->sgc->max_capacity)) { - sgs->group_misfit_task_load =1 ; } sgs->group_capacity = group->sgc->capacity;
kernel/sched/sched.h +9 -0
@@ -2468,6 +2468,15 @@ static inline bool uclamp_is_used(void) return static_branch_likely(&sched_uclamp_used); }#else /* CONFIG_UCLAMP_TASK */ +static inline unsigned long uclamp_eff_value (struct task_struct *p, +enum uclamp_id clamp_id) +{ +if (clamp_id ==UCLAMP_MIN ) +return 0 ; + +return SCHED_CAPACITY_SCALE ; +} +static inline unsigned long uclamp_rq_util_with (struct rq *rq,unsigned long util,struct task_struct *p)
Greg Kroah-Hartman
maintainerPATCH 82/104 sched/uclamp: Fix fits_capacity() check in feec()
In reply to Greg Kroah-HartmanFrom: Qais Yousef <[email protected]>
commit 244226035a1f9b2b6c326e55ae5188fab4f428cb upstream.
As reported by Yun Hsiang [1], if a task has its uclamp_min >= 0.8 * 1024, it'll always pick the previous CPU because fits_capacity() will always return false in this case.
The new util_fits_cpu() logic should handle this correctly for us beside more corner cases where similar failures could occur, like when using UCLAMP_MAX.
We open code uclamp_rq_util_with() except for the clamp() part, util_fits_cpu() needs the 'raw' values to be passed to it.
Also introduce uclamp_rq_{set, get}() shorthand accessors to get uclamp value for the rq. Makes the code more readable and ensures the right rules (use READ_ONCE/WRITE_ONCE) are respected transparently.
[1] https://lists.linaro.org/pipermail/eas-dev/2020-July/001488.html
[Fix trivial conflict in kernel/sched/fair.c due to new automatic variables in master vs 5.10]
--- kernel/sched/core.c | 10 +++++----- kernel/sched/fair.c | 26 ++++++++++++++++++++++++-- kernel/sched/sched.h | 42 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 68 insertions(+), 10 deletions(-)
kernel/sched/core.c +5 -5
@@ -980,7 +980,7 @@ static inline void uclamp_idle_reset(strif (!(rq->uclamp_flags &UCLAMP_FLAG_IDLE ))return ; -WRITE_ONCE (rq->uclamp[clamp_id].value, clamp_value); +uclamp_rq_set (rq, clamp_id, clamp_value); } static inline
@@ -1158,8 +1158,8 @@ static inline void uclamp_rq_inc_id(struif (bucket->tasks ==1 || uc_se->value > bucket->value) bucket->value = uc_se->value; -if (uc_se->value >READ_ONCE (uc_rq->value)) -WRITE_ONCE (uc_rq->value, uc_se->value); +if (uc_se->value >uclamp_rq_get (rq, clamp_id)) +uclamp_rq_set (rq, clamp_id, uc_se->value); }/*
@@ -1225,7 +1225,7 @@ static inline void uclamp_rq_dec_id(struif (likely (bucket->tasks))return ; - rq_clamp =READ_ONCE (uc_rq->value); + rq_clamp =uclamp_rq_get (rq, clamp_id);/* * Defensive programming: this should never happen. If it happens, * e.g. due to future modification, warn and fixup the expected value.
@@ -1233,7 +1233,7 @@ static inline void uclamp_rq_dec_id(struSCHED_WARN_ON (bucket->value > rq_clamp);if (bucket->value >= rq_clamp) { bkt_clamp =uclamp_rq_max_value (rq, clamp_id, uc_se->value); -WRITE_ONCE (uc_rq->value, bkt_clamp); +uclamp_rq_set (rq, clamp_id, bkt_clamp); } }
kernel/sched/fair.c +24 -2
@@ -6755,6 +6755,8 @@ compute_energy(struct task_struct *p, instatic int find_energy_efficient_cpu (struct task_struct *p,int prev_cpu) {unsigned long prev_delta =ULONG_MAX , best_delta =ULONG_MAX ; +unsigned long p_util_min =uclamp_is_used () ?uclamp_eff_value (p,UCLAMP_MIN ) :0 ; +unsigned long p_util_max =uclamp_is_used () ?uclamp_eff_value (p,UCLAMP_MAX ) :1024 ;struct root_domain *rd =cpu_rq (smp_processor_id ())->rd;unsigned long cpu_cap, util, base_energy =0 ;int cpu, best_energy_cpu = prev_cpu;
@@ -6782,6 +6784,8 @@ static int find_energy_efficient_cpu(strfor (; pd; pd = pd->next) {unsigned long cur_delta, spare_cap, max_spare_cap =0 ; +unsigned long rq_util_min, rq_util_max; +unsigned long util_min, util_max;unsigned long base_energy_pd;int max_spare_cap_cpu =-1 ;
@@ -6805,8 +6809,26 @@ static int find_energy_efficient_cpu(str* much capacity we can get out of the CPU; this is * aligned with schedutil_cpu_util(). */ - util =uclamp_rq_util_with (cpu_rq (cpu), util, p); -if (!fits_capacity (util, cpu_cap)) +if (uclamp_is_used ()) { +if (uclamp_rq_is_idle (cpu_rq (cpu))) { + util_min = p_util_min; + util_max = p_util_max; + }else { +/* +* Open code uclamp_rq_util_with() except for +* the clamp() part. Ie: apply max aggregation +* only. util_fits_cpu() logic requires to +* operate on non clamped util but must use the +* max-aggregated uclamp_{min, max}. +*/ + rq_util_min =uclamp_rq_get (cpu_rq (cpu),UCLAMP_MIN ); + rq_util_max =uclamp_rq_get (cpu_rq (cpu),UCLAMP_MAX ); + + util_min =max (rq_util_min, p_util_min); + util_max =max (rq_util_max, p_util_max); + } + } +if (!util_fits_cpu (util, util_min, util_max, cpu))continue ;/* Always use prev_cpu as a candidate. */
kernel/sched/sched.h +39 -3
63 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 83/104 sched/uclamp: Make select_idle_capacity() use util_fits_cpu()
In reply to Greg Kroah-HartmanFrom: Qais Yousef <[email protected]>
commit b759caa1d9f667b94727b2ad12589cbc4ce13a82 upstream.
Use the new util_fits_cpu() to ensure migration margin and capacity pressure are taken into account correctly when uclamp is being used otherwise we will fail to consider CPUs as fitting in scenarios where they should.
--- kernel/sched/fair.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
kernel/sched/fair.c +5 -3
@@ -6347,21 +6347,23 @@ static int select_idle_cpu(struct task_sstatic int select_idle_capacity (struct task_struct *p,struct sched_domain *sd,int target) { -unsigned long task_util, best_cap =0 ; +unsigned long task_util, util_min, util_max, best_cap =0 ;int cpu, best_cpu =-1 ;struct cpumask *cpus; cpus =this_cpu_cpumask_var_ptr (select_idle_mask);cpumask_and (cpus,sched_domain_span (sd), p->cpus_ptr); - task_util =uclamp_task_util (p); + task_util =task_util_est (p); + util_min =uclamp_eff_value (p,UCLAMP_MIN ); + util_max =uclamp_eff_value (p,UCLAMP_MAX );for_each_cpu_wrap (cpu, cpus, target) {unsigned long cpu_cap =capacity_of (cpu);if (!available_idle_cpu (cpu) && !sched_idle_cpu (cpu))continue ; -if (fits_capacity (task_util, cpu_cap)) +if (util_fits_cpu (task_util, util_min, util_max, cpu))return cpu;if (cpu_cap > best_cap) {
Greg Kroah-Hartman
maintainerPATCH 84/104 sched/uclamp: Make asym_fits_capacity() use util_fits_cpu()
In reply to Greg Kroah-HartmanFrom: Qais Yousef <[email protected]>
commit a2e7f03ed28fce26c78b985f87913b6ce3accf9d upstream.
Use the new util_fits_cpu() to ensure migration margin and capacity pressure are taken into account correctly when uclamp is being used otherwise we will fail to consider CPUs as fitting in scenarios where they should.
s/asym_fits_capacity/asym_fits_cpu/ to better reflect what it does now.
[Conflict in kernel/sched/fair.c due different name of static key wrapper function and slightly different if condition block in one of the asym_fits_cpu() call sites]
--- kernel/sched/fair.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-)
kernel/sched/fair.c +13 -8
@@ -6375,10 +6375,13 @@ select_idle_capacity(struct task_structreturn best_cpu; } -static inline bool asym_fits_capacity (unsigned long task_util,int cpu) +static inline bool asym_fits_cpu (unsigned long util, +unsigned long util_min, +unsigned long util_max, +int cpu) {if (static_branch_unlikely (&sched_asym_cpucapacity)) -return fits_capacity (task_util,capacity_of (cpu)); +return util_fits_cpu (util, util_min, util_max, cpu);return true; }
@@ -6389,7 +6392,7 @@ static inline bool asym_fits_capacity(unstatic int select_idle_sibling (struct task_struct *p,int prev,int target) {struct sched_domain *sd; -unsigned long task_util; +unsigned long task_util, util_min, util_max;int i, recent_used_cpu;/*
@@ -6398,11 +6401,13 @@ static int select_idle_sibling(struct ta*/ if (static_branch_unlikely (&sched_asym_cpucapacity)) {sync_entity_load_avg (&p->se); - task_util =uclamp_task_util (p); + task_util =task_util_est (p); + util_min =uclamp_eff_value (p,UCLAMP_MIN ); + util_max =uclamp_eff_value (p,UCLAMP_MAX ); }if ((available_idle_cpu (target) ||sched_idle_cpu (target)) && -asym_fits_capacity (task_util, target)) +asym_fits_cpu (task_util, util_min, util_max, target))return target;/*
@@ -6410,7 +6415,7 @@ static int select_idle_sibling(struct ta*/ if (prev != target &&cpus_share_cache (prev, target) && (available_idle_cpu (prev) ||sched_idle_cpu (prev)) && -asym_fits_capacity (task_util, prev)) +asym_fits_cpu (task_util, util_min, util_max, prev))return prev;/*
@@ -6425,7 +6430,7 @@ static int select_idle_sibling(struct ta in_task() && prev == smp_processor_id() && this_rq()->nr_running <= 1 && - asym_fits_capacity(task_util, prev)) { + asym_fits_cpu(task_util, util_min, util_max, prev)) {return prev; }
@@ -6436,7 +6441,7 @@ static int select_idle_sibling(struct tacpus_share_cache (recent_used_cpu, target) && (available_idle_cpu (recent_used_cpu) ||sched_idle_cpu (recent_used_cpu)) &&cpumask_test_cpu (p->recent_used_cpu, p->cpus_ptr) && - asym_fits_capacity(task_util, recent_used_cpu)) { + asym_fits_cpu(task_util, util_min, util_max, recent_used_cpu)) {/* * Replace recent_used_cpu with prev as it is a potential * candidate for the next wake:
Greg Kroah-Hartman
maintainerPATCH 85/104 sched/uclamp: Make cpu_overutilized() use util_fits_cpu()
In reply to Greg Kroah-HartmanFrom: Qais Yousef <[email protected]>
commit c56ab1b3506ba0e7a872509964b100912bde165d upstream.
So that it is now uclamp aware.
This fixes a major problem of busy tasks capped with UCLAMP_MAX keeping the system in overutilized state which disables EAS and leads to wasting energy in the long run.
Without this patch running a busy background activity like JIT compilation on Pixel 6 causes the system to be in overutilized state 74.5% of the time.
With this patch this goes down to 9.79%.
It also fixes another problem when long running tasks that have their UCLAMP_MIN changed while running such that they need to upmigrate to honour the new UCLAMP_MIN value. The upmigration doesn't get triggered because overutilized state never gets set in this state, hence misfit migration never happens at tick in this case until the task wakes up again.
[Conflict in kernel/sched/fair.c: use cpu_util() instead of cpu_util_cfs()]
--- kernel/sched/fair.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
kernel/sched/fair.c +4 -1
@@ -5610,7 +5610,10 @@ static inline unsigned long cpu_util(intstatic inline bool cpu_overutilized (int cpu) { -return !fits_capacity (cpu_util (cpu),capacity_of (cpu)); +unsigned long rq_util_min =uclamp_rq_get (cpu_rq (cpu),UCLAMP_MIN ); +unsigned long rq_util_max =uclamp_rq_get (cpu_rq (cpu),UCLAMP_MAX ); + +return !util_fits_cpu (cpu_util (cpu), rq_util_min, rq_util_max, cpu); }static inline void update_overutilized_status (struct rq *rq)
Greg Kroah-Hartman
maintainerPATCH 86/104 sched/uclamp: Cater for uclamp in find_energy_efficient_cpu()s early exit condition
In reply to Greg Kroah-HartmanFrom: Qais Yousef <[email protected]>
commit d81304bc6193554014d4372a01debdf65e1e9a4d upstream.
If the utilization of the woken up task is 0, we skip the energy calculation because it has no impact.
But if the task is boosted (uclamp_min != 0) will have an impact on task placement and frequency selection. Only skip if the util is truly 0 after applying uclamp values.
Change uclamp_task_cpu() signature to avoid unnecessary additional calls to uclamp_eff_get(). feec() is the only user now.
--- kernel/sched/fair.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
kernel/sched/fair.c +8 -6
@@ -3928,14 +3928,16 @@ static inline unsigned long task_util_es }#ifdef CONFIG_UCLAMP_TASK -static inline unsigned long uclamp_task_util (struct task_struct *p) +static inline unsigned long uclamp_task_util (struct task_struct *p, +unsigned long uclamp_min, +unsigned long uclamp_max) { -return clamp (task_util_est (p), -uclamp_eff_value (p,UCLAMP_MIN ), -uclamp_eff_value (p,UCLAMP_MAX )); +return clamp (task_util_est (p), uclamp_min, uclamp_max); }#else -static inline unsigned long uclamp_task_util (struct task_struct *p) +static inline unsigned long uclamp_task_util (struct task_struct *p, +unsigned long uclamp_min, +unsigned long uclamp_max) {return task_util_est (p); }
@@ -6789,7 +6791,7 @@ static int find_energy_efficient_cpu(str goto fail;sync_entity_load_avg (&p->se); -if (!task_util_est (p)) +if (!uclamp_task_util (p, p_util_min, p_util_max)) goto unlock;for (; pd; pd = pd->next) {
Greg Kroah-Hartman
maintainerPATCH 87/104 sched/fair: Detect capacity inversion
In reply to Greg Kroah-HartmanFrom: Qais Yousef <[email protected]>
commit: 44c7b80bffc3a657a36857098d5d9c49d94e652b upstream.
Check each performance domain to see if thermal pressure is causing its capacity to be lower than another performance domain.
We assume that each performance domain has CPUs with the same capacities, which is similar to an assumption made in energy_model.c
We also assume that thermal pressure impacts all CPUs in a performance domain equally.
If there're multiple performance domains with the same capacity_orig, we will trigger a capacity inversion if the domain is under thermal pressure.
The new cpu_in_capacity_inversion() should help users to know when information about capacity_orig are not reliable and can opt in to use the inverted capacity as the 'actual' capacity_orig.
--- kernel/sched/fair.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++--- kernel/sched/sched.h | 19 +++++++++++++++ 2 files changed, 79 insertions(+), 3 deletions(-)
kernel/sched/fair.c +60 -3
@@ -8332,16 +8332,73 @@ static unsigned long scale_rt_capacity(istatic void update_cpu_capacity (struct sched_domain *sd,int cpu) { +unsigned long capacity_orig =arch_scale_cpu_capacity (cpu);unsigned long capacity =scale_rt_capacity (cpu);struct sched_group *sdg = sd->groups; +struct rq *rq =cpu_rq (cpu); -cpu_rq (cpu)->cpu_capacity_orig =arch_scale_cpu_capacity (cpu); + rq->cpu_capacity_orig = capacity_orig;if (!capacity) capacity =1 ; -cpu_rq (cpu)->cpu_capacity = capacity; -trace_sched_cpu_capacity_tp (cpu_rq (cpu)); + rq->cpu_capacity = capacity; + +/* +* Detect if the performance domain is in capacity inversion state. +* +* Capacity inversion happens when another perf domain with equal or +* lower capacity_orig_of() ends up having higher capacity than this +* domain after subtracting thermal pressure. +* +* We only take into account thermal pressure in this detection as it's +* the only metric that actually results in *real* reduction of +* capacity due to performance points (OPPs) being dropped/become +* unreachable due to thermal throttling. +* +* We assume: +* * That all cpus in a perf domain have the same capacity_orig +* (same uArch). +* * Thermal pressure will impact all cpus in this perf domain +* equally. +*/ +if (static_branch_unlikely (&sched_asym_cpucapacity)) { +unsigned long inv_cap = capacity_orig -thermal_load_avg (rq); +struct perf_domain *pd =rcu_dereference (rq->rd->pd); + + rq->cpu_capacity_inverted =0 ; + +for (; pd; pd = pd->next) { +struct cpumask *pd_span =perf_domain_span (pd); +unsigned long pd_cap_orig, pd_cap; + + cpu =cpumask_any (pd_span); + pd_cap_orig =arch_scale_cpu_capacity (cpu); + +if (capacity_orig < pd_cap_orig) +continue ; + +/* +* handle the case of multiple perf domains have the +* same capacity_orig but one of them is under higher +* thermal pressure. We record it as capacity +* inversion. +*/ +if (capacity_orig == pd_cap_orig) { + pd_cap = pd_cap_orig -thermal_load_avg (cpu_rq (cpu)); + +if (pd_cap > inv_cap) { + rq->cpu_capacity_inverted = inv_cap; +break ; + } + }else if (pd_cap_orig > inv_cap) { + rq->cpu_capacity_inverted = inv_cap; +break ; + } + } + } + +trace_sched_cpu_capacity_tp (rq); sdg->sgc->capacity = capacity; sdg->sgc->min_capacity = capacity;
kernel/sched/sched.h +19 -0
@@ -973,6 +973,7 @@ struct rq {unsigned long cpu_capacity;unsigned long cpu_capacity_orig; +unsigned long cpu_capacity_inverted;struct callback_head *balance_callback;
@@ -2541,6 +2542,24 @@ static inline unsigned long capacity_ori }#endif +/* +* Returns inverted capacity if the CPU is in capacity inversion state. +* 0 otherwise. +* +* Capacity inversion detection only considers thermal impact where actual +* performance points (OPPs) gets dropped. +* +* Capacity inversion state happens when another performance domain that has +* equal or lower capacity_orig_of() becomes effectively larger than the perf +* domain this CPU belongs to due to thermal pressure throttling it hard. +* +* See comment in update_cpu_capacity(). +*/ +static inline unsigned long cpu_in_capacity_inversion (int cpu) +{ +return cpu_rq (cpu)->cpu_capacity_inverted; +} +/** * enum schedutil_type - CPU utilization type * @FREQUENCY_UTIL: Utilization used to select frequency
Greg Kroah-Hartman
maintainerPATCH 88/104 sched/fair: Consider capacity inversion in util_fits_cpu()
In reply to Greg Kroah-HartmanFrom: Qais Yousef <[email protected]>
commit: aa69c36f31aadc1669bfa8a3de6a47b5e6c98ee8 upstream.
We do consider thermal pressure in util_fits_cpu() for uclamp_min only. With the exception of the biggest cores which by definition are the max performance point of the system and all tasks by definition should fit.
Even under thermal pressure, the capacity of the biggest CPU is the highest in the system and should still fit every task. Except when it reaches capacity inversion point, then this is no longer true.
We can handle this by using the inverted capacity as capacity_orig in util_fits_cpu(). Which not only addresses the problem above, but also ensure uclamp_max now considers the inverted capacity. Force fitting a task when a CPU is in this adverse state will contribute to making the thermal throttling last longer.
--- kernel/sched/fair.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
kernel/sched/fair.c +9 -5
@@ -4113,12 +4113,16 @@ static inline int util_fits_cpu(unsigned* For uclamp_max, we can tolerate a drop in performance level as the * goal is to cap the task. So it's okay if it's getting less. * -* In case of capacity inversion, which is not handled yet, we should -* honour the inverted capacity for both uclamp_min and uclamp_max all -* the time. +* In case of capacity inversion we should honour the inverted capacity +* for both uclamp_min and uclamp_max all the time. */ - capacity_orig =capacity_orig_of (cpu); - capacity_orig_thermal = capacity_orig -arch_scale_thermal_pressure (cpu); + capacity_orig =cpu_in_capacity_inversion (cpu); +if (capacity_orig) { + capacity_orig_thermal = capacity_orig; + }else { + capacity_orig =capacity_orig_of (cpu); + capacity_orig_thermal = capacity_orig -arch_scale_thermal_pressure (cpu); + }/* * We want to force a task to fit a cpu as implied by uclamp_max.
Greg Kroah-Hartman
maintainerPATCH 89/104 sched/uclamp: Fix a uninitialized variable warnings
In reply to Greg Kroah-HartmanFrom: Qais Yousef <[email protected]>
commit e26fd28db82899be71b4b949527373d0a6be1e65 upstream.
Addresses the following warnings:
Quoted 6 lines
config: riscv-randconfig-m031-20221111
compiler: riscv64-linux-gcc (GCC) 12.1.0smatch warnings:
kernel/sched/fair.c:7263find_energy_efficient_cpu()error: uninitialized symbol 'util_min'.kernel/sched/fair.c:7263find_energy_efficient_cpu()error: uninitialized symbol 'util_max'.
[Conflict in kernel/sched/fair.c due to new automatic variable in master vs 5.10 and new code around for loop]
--- kernel/sched/fair.c | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-)
kernel/sched/fair.c +16 -19
@@ -6799,9 +6799,9 @@ static int find_energy_efficient_cpu(str goto unlock;for (; pd; pd = pd->next) { +unsigned long util_min = p_util_min, util_max = p_util_max;unsigned long cur_delta, spare_cap, max_spare_cap =0 ;unsigned long rq_util_min, rq_util_max; -unsigned long util_min, util_max;unsigned long base_energy_pd;int max_spare_cap_cpu =-1 ;
@@ -6810,6 +6810,8 @@ static int find_energy_efficient_cpu(str base_energy += base_energy_pd;for_each_cpu_and (cpu,perf_domain_span (pd),sched_domain_span (sd)) { +struct rq *rq =cpu_rq (cpu); +if (!cpumask_test_cpu (cpu, p->cpus_ptr))continue ;
@@ -6825,24 +6827,19 @@ static int find_energy_efficient_cpu(str* much capacity we can get out of the CPU; this is * aligned with schedutil_cpu_util(). */ -if (uclamp_is_used ()) { -if (uclamp_rq_is_idle (cpu_rq (cpu))) { - util_min = p_util_min; - util_max = p_util_max; - }else { -/* -* Open code uclamp_rq_util_with() except for -* the clamp() part. Ie: apply max aggregation -* only. util_fits_cpu() logic requires to -* operate on non clamped util but must use the -* max-aggregated uclamp_{min, max}. -*/ - rq_util_min =uclamp_rq_get (cpu_rq (cpu),UCLAMP_MIN ); - rq_util_max =uclamp_rq_get (cpu_rq (cpu),UCLAMP_MAX ); - - util_min =max (rq_util_min, p_util_min); - util_max =max (rq_util_max, p_util_max); - } +if (uclamp_is_used () && !uclamp_rq_is_idle (rq)) { +/* +* Open code uclamp_rq_util_with() except for +* the clamp() part. Ie: apply max aggregation +* only. util_fits_cpu() logic requires to +* operate on non clamped util but must use the +* max-aggregated uclamp_{min, max}. +*/ + rq_util_min =uclamp_rq_get (rq,UCLAMP_MIN ); + rq_util_max =uclamp_rq_get (rq,UCLAMP_MAX ); + + util_min =max (rq_util_min, p_util_min); + util_max =max (rq_util_max, p_util_max); }if (!util_fits_cpu (util, util_min, util_max, cpu))continue ;
Greg Kroah-Hartman
maintainerPATCH 90/104 sched/fair: Fixes for capacity inversion detection
In reply to Greg Kroah-HartmanFrom: Qais Yousef <[email protected]>
commit da07d2f9c153e457e845d4dcfdd13568d71d18a4 upstream.
Traversing the Perf Domains requires rcu_read_lock() to be held and is conditional on sched_energy_enabled(). Ensure right protections applied.
Also skip capacity inversion detection for our own pd; which was an error.
--- kernel/sched/fair.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
kernel/sched/fair.c +11 -2
@@ -8363,16 +8363,23 @@ static void update_cpu_capacity(struct s* * Thermal pressure will impact all cpus in this perf domain * equally. */ -if (static_branch_unlikely (&sched_asym_cpucapacity)) { +if (sched_energy_enabled ()) {unsigned long inv_cap = capacity_orig -thermal_load_avg (rq); -struct perf_domain *pd =rcu_dereference (rq->rd->pd); +struct perf_domain *pd; +rcu_read_lock (); + + pd =rcu_dereference (rq->rd->pd); rq->cpu_capacity_inverted =0 ;for (; pd; pd = pd->next) {struct cpumask *pd_span =perf_domain_span (pd);unsigned long pd_cap_orig, pd_cap; +/* We can't be inverted against our own pd */ +if (cpumask_test_cpu (cpu_of (rq), pd_span)) +continue ; + cpu =cpumask_any (pd_span); pd_cap_orig =arch_scale_cpu_capacity (cpu);
@@ -8397,6 +8404,8 @@ static void update_cpu_capacity(struct sbreak ; } } + +rcu_read_unlock (); }trace_sched_cpu_capacity_tp (rq);
Greg Kroah-Hartman
maintainerPATCH 91/104 ext4: refactor ext4_free_blocks() to pull out ext4_mb_clear_bb()
In reply to Greg Kroah-HartmanFrom: Ritesh Harjani <[email protected]>
commit 8ac3939db99f99667b8eb670cf4baf292896e72d upstream.
ext4_free_blocks() function became too long and confusing, this patch just pulls out the ext4_mb_clear_bb() function logic from it which clears the block bitmap and frees it.
No functionality change in this patch
--- fs/ext4/mballoc.c | 180 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 102 insertions(+), 78 deletions(-)
fs/ext4/mballoc.c +102 -78
@@ -5303,7 +5303,8 @@ static void ext4_free_blocks_simple(stru }/** -* ext4_free_blocks() -- Free given blocks and update quota +* ext4_mb_clear_bb() -- helper function for freeing blocks. +* Used by ext4_free_blocks() * @handle: handle for this transaction * @inode: inode * @bh: optional buffer of the block to be freed
@@ -5311,9 +5312,9 @@ static void ext4_free_blocks_simple(stru* @count: number of blocks to be freed * @flags: flags used by ext4_free_blocks */ -void ext4_free_blocks (handle_t *handle,struct inode *inode, -struct buffer_head *bh,ext4_fsblk_t block, -unsigned long count,int flags) +static void ext4_mb_clear_bb (handle_t *handle,struct inode *inode, +ext4_fsblk_t block,unsigned long count, +int flags) {struct buffer_head *bitmap_bh =NULL ;struct super_block *sb = inode->i_sb;
@@ -5330,80 +5331,6 @@ void ext4_free_blocks(handle_t *handle, sbi =EXT4_SB (sb); -if (sbi->s_mount_state &EXT4_FC_REPLAY ) { -ext4_free_blocks_simple (inode, block, count); -return ; - } - -might_sleep (); -if (bh) { -if (block) -BUG_ON (block != bh->b_blocknr); -else - block = bh->b_blocknr; - } - -if (!(flags &EXT4_FREE_BLOCKS_VALIDATED ) && - !ext4_inode_block_valid (inode, block, count)) { -ext4_error (sb,"Freeing blocks not in datazone - " -"block = %llu, count = %lu" , block, count); - goto error_return; - } - -ext4_debug ("freeing block %llu\n" , block); -trace_ext4_free_blocks (inode, block, count, flags); - -if (bh && (flags &EXT4_FREE_BLOCKS_FORGET )) { -BUG_ON (count >1 ); - -ext4_forget (handle, flags &EXT4_FREE_BLOCKS_METADATA , - inode, bh, block); - } - -/* -* If the extent to be freed does not begin on a cluster -* boundary, we need to deal with partial clusters at the -* beginning and end of the extent. Normally we will free -* blocks at the beginning or the end unless we are explicitly -* requested to avoid doing so. -*/ - overflow =EXT4_PBLK_COFF (sbi, block); -if (overflow) { -if (flags &EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER ) { - overflow = sbi->s_cluster_ratio - overflow; - block += overflow; -if (count > overflow) - count -= overflow; -else -return ; - }else { - block -= overflow; - count += overflow; - } - } - overflow =EXT4_LBLK_COFF (sbi, count); -if (overflow) { -if (flags &EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER ) { -if (count > overflow) - count -= overflow; -else -return ; - }else - count += sbi->s_cluster_ratio - overflow; - } - -if (!bh && (flags &EXT4_FREE_BLOCKS_FORGET )) { -int i; -int is_metadata = flags &EXT4_FREE_BLOCKS_METADATA ; - -for (i =0 ; i < count; i++) { -cond_resched (); -if (is_metadata) - bh =sb_find_get_block (inode->i_sb, block + i); -ext4_forget (handle, is_metadata, inode, bh, block + i); - } - } - do_more: overflow =0 ;ext4_get_group_no_and_offset (sb, block, &block_group, &bit);
@@ -5570,6 +5497,103 @@ error_return:return ; } +/** +* ext4_free_blocks() -- Free given blocks and update quota +* @handle: handle for this transaction +* @inode: inode +* @bh: optional buffer of the block to be freed +* @block: starting physical block to be freed +* @count: number of blocks to be freed +* @flags: flags used by ext4_free_blocks +*/ +void ext4_free_blocks (handle_t *handle,struct inode *inode, +struct buffer_head *bh,ext4_fsblk_t block, +unsigned long count,int flags) +{ +struct super_block *sb = inode->i_sb; +unsigned int overflow; +struct ext4_sb_info *sbi; + + sbi =EXT4_SB (sb); + +if (sbi->s_mount_state &EXT4_FC_REPLAY ) { +ext4_free_blocks_simple (inode, block, count); +return ; + } + +might_sleep (); +if (bh) { +if (block) +BUG_ON (block != bh->b_blocknr); +else + block = bh->b_blocknr; + } + +if (!(flags &EXT4_FREE_BLOCKS_VALIDATED ) && + !ext4_inode_block_valid (inode, block, count)) { +ext4_error (sb,"Freeing blocks not in datazone - " +"block = %llu, count = %lu" , block, count); +return ; + } + +ext4_debug ("freeing block %llu\n" , block); +trace_ext4_free_blocks (inode, block, count, flags); + +if (bh && (flags &EXT4_FREE_BLOCKS_FORGET )) { +BUG_ON (count >1 ); + +ext4_forget (handle, flags &EXT4_FREE_BLOCKS_METADATA , + inode, bh, block); + } + +/* +* If the extent to be freed does not begin on a cluster +* boundary, we need to deal with partial clusters at the +* beginning and end of the extent. Normally we will free +* blocks at the beginning or the end unless we are explicitly +* requested to avoid doing so. +*/ + overflow =EXT4_PBLK_COFF (sbi, block); +if (overflow) { +if (flags &EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER ) { + overflow = sbi->s_cluster_ratio - overflow; + block += overflow; +if (count > overflow) + count -= overflow; +else +return ; + }else { + block -= overflow; + count += overflow; + } + } + overflow =EXT4_LBLK_COFF (sbi, count); +if (overflow) { +if (flags &EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER ) { +if (count > overflow) + count -= overflow; +else +return ; + }else + count += sbi->s_cluster_ratio - overflow; + } + +if (!bh && (flags &EXT4_FREE_BLOCKS_FORGET )) { +int i; +int is_metadata = flags &EXT4_FREE_BLOCKS_METADATA ; + +for (i =0 ; i < count; i++) { +cond_resched (); +if (is_metadata) + bh =sb_find_get_block (inode->i_sb, block + i); +ext4_forget (handle, is_metadata, inode, bh, block + i); + } + } + +ext4_mb_clear_bb (handle, inode, block, count, flags); +return ; +} +/** * ext4_group_add_blocks() -- Add given blocks to an existing group * @handle: handle to this transaction
Greg Kroah-Hartman
maintainerPATCH 92/104 ext4: add ext4_sb_block_valid() refactored out of ext4_inode_block_valid()
In reply to Greg Kroah-HartmanFrom: Ritesh Harjani <[email protected]>
commit 6bc6c2bdf1baca6522b8d9ba976257d722423085 upstream.
This API will be needed at places where we don't have an inode for e.g. while freeing blocks in ext4_group_add_blocks()
--- fs/ext4/block_validity.c | 26 +++++++++++++++++--------- fs/ext4/ext4.h | 3 +++ 2 files changed, 20 insertions(+), 9 deletions(-)
fs/ext4/block_validity.c +17 -9
@@ -294,15 +294,10 @@ void ext4_release_system_zone(struct supcall_rcu (&system_blks->rcu, ext4_destroy_system_zone); } -/* -* Returns 1 if the passed-in block region (start_blk, -* start_blk+count) is valid; 0 if some part of the block region -* overlaps with some other filesystem metadata blocks. -*/ -int ext4_inode_block_valid (struct inode *inode,ext4_fsblk_t start_blk, -unsigned int count) +int ext4_sb_block_valid (struct super_block *sb,struct inode *inode, +ext4_fsblk_t start_blk,unsigned int count) { -struct ext4_sb_info *sbi =EXT4_SB (inode->i_sb); +struct ext4_sb_info *sbi =EXT4_SB (sb);struct ext4_system_blocks *system_blks;struct ext4_system_zone *entry;struct rb_node *n;
@@ -331,7 +326,9 @@ int ext4_inode_block_valid(struct inodeelse if (start_blk >= (entry->start_blk + entry->count)) n = n->rb_right;else { - ret = (entry->ino == inode->i_ino); + ret =0 ; +if (inode) + ret = (entry->ino == inode->i_ino);break ; } }
@@ -340,6 +337,17 @@ out_rcu:return ret; } +/* +* Returns 1 if the passed-in block region (start_blk, +* start_blk+count) is valid; 0 if some part of the block region +* overlaps with some other filesystem metadata blocks. +*/ +int ext4_inode_block_valid (struct inode *inode,ext4_fsblk_t start_blk, +unsigned int count) +{ +return ext4_sb_block_valid (inode->i_sb, inode, start_blk, count); +} +int ext4_check_blockref (const char *function,unsigned int line,struct inode *inode,__le32 *p,unsigned int max) {
fs/ext4/ext4.h +3 -0
@@ -3536,6 +3536,9 @@ extern int ext4_inode_block_valid(struct unsigned int count);extern int ext4_check_blockref (const char *,unsigned int ,struct inode *,__le32 *,unsigned int ); +extern int ext4_sb_block_valid (struct super_block *sb,struct inode *inode, +ext4_fsblk_t start_blk,unsigned int count); +/* extents.c */ struct ext4_ext_path ;
Greg Kroah-Hartman
maintainerPATCH 93/104 ext4: add strict range checks while freeing blocks
In reply to Greg Kroah-HartmanFrom: Ritesh Harjani <[email protected]>
commit a00b482b82fb098956a5bed22bd7873e56f152f1 upstream.
Currently ext4_mb_clear_bb() & ext4_group_add_blocks() only checks whether the given block ranges (which is to be freed) belongs to any FS metadata blocks or not, of the block's respective block group. But to detect any FS error early, it is better to add more strict checkings in those functions which checks whether the given blocks belongs to any critical FS metadata or not within system-zone.
--- fs/ext4/mballoc.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-)
fs/ext4/mballoc.c +3 -13
@@ -5361,13 +5361,7 @@ do_more: goto error_return; } -if (in_range (ext4_block_bitmap (sb, gdp), block, count) || -in_range (ext4_inode_bitmap (sb, gdp), block, count) || -in_range (block,ext4_inode_table (sb, gdp), - sbi->s_itb_per_group) || -in_range (block + count -1 ,ext4_inode_table (sb, gdp), - sbi->s_itb_per_group)) { - +if (!ext4_inode_block_valid (inode, block, count)) {ext4_error (sb,"Freeing blocks in system zone - " "Block = %llu, count = %lu" , block, count);/* err = 0. ext4_std_error should be a no op */
@@ -5437,7 +5431,7 @@ do_more: NULL);if (err && err != -EOPNOTSUPP )ext4_msg (sb,KERN_WARNING ,"discard request in" -" group:%d block:%d count:%lu failed" +" group:%u block:%d count:%lu failed" " with %d" , block_group, bit, count, err); }else
@@ -5650,11 +5644,7 @@ int ext4_group_add_blocks(handle_t *hand goto error_return; } -if (in_range (ext4_block_bitmap (sb, desc), block, count) || -in_range (ext4_inode_bitmap (sb, desc), block, count) || -in_range (block,ext4_inode_table (sb, desc), sbi->s_itb_per_group) || -in_range (block + count -1 ,ext4_inode_table (sb, desc), - sbi->s_itb_per_group)) { +if (!ext4_sb_block_valid (sb,NULL , block, count)) {ext4_error (sb,"Adding blocks in system zones - " "Block = %llu, count = %lu" , block, count);
Greg Kroah-Hartman
maintainerPATCH 94/104 ext4: block range must be validated before use in ext4_mb_clear_bb()
In reply to Greg Kroah-HartmanFrom: Lukas Czerner <[email protected]>
commit 1e1c2b86ef86a8477fd9b9a4f48a6bfe235606f6 upstream.
Block range to free is validated in ext4_free_blocks() using ext4_inode_block_valid() and then it's passed to ext4_mb_clear_bb(). However in some situations on bigalloc file system the range might be adjusted after the validation in ext4_free_blocks() which can lead to troubles on corrupted file systems such as one found by syzkaller that resulted in the following BUG
kernel BUG at fs/ext4/ext4.h:3319!
PREEMPT SMP NOPTI
CPU: 28 PID: 4243 Comm: repro Kdump: loaded Not tainted 5.19.0-rc6+ #1 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.15.0-1.fc35 04/01/2014 RIP: 0010:ext4_free_blocks+0x95e/0xa90 Call Trace: <TASK> ? lock_timer_base+0x61/0x80 ? __es_remove_extent+0x5a/0x760 ? __mod_timer+0x256/0x380 ? ext4_ind_truncate_ensure_credits+0x90/0x220 ext4_clear_blocks+0x107/0x1b0 ext4_free_data+0x15b/0x170 ext4_ind_truncate+0x214/0x2c0 ? _raw_spin_unlock+0x15/0x30 ? ext4_discard_preallocations+0x15a/0x410 ? ext4_journal_check_start+0xe/0x90 ? __ext4_journal_start_sb+0x2f/0x110 ext4_truncate+0x1b5/0x460 ? __ext4_journal_start_sb+0x2f/0x110 ext4_evict_inode+0x2b4/0x6f0 evict+0xd0/0x1d0 ext4_enable_quotas+0x11f/0x1f0 ext4_orphan_cleanup+0x3de/0x430 ? proc_create_seq_private+0x43/0x50 ext4_fill_super+0x295f/0x3ae0 ? snprintf+0x39/0x40 ? sget_fc+0x19c/0x330 ? ext4_reconfigure+0x850/0x850 get_tree_bdev+0x16d/0x260 vfs_get_tree+0x25/0xb0 path_mount+0x431/0xa70 __x64_sys_mount+0xe2/0x120 do_syscall_64+0x5b/0x80 ? do_user_addr_fault+0x1e2/0x670 ? exc_page_fault+0x70/0x170 entry_SYSCALL_64_after_hwframe+0x46/0xb0 RIP: 0033:0x7fdf4e512ace
Fix it by making sure that the block range is properly validated before used every time it changes in ext4_free_blocks() or ext4_mb_clear_bb().
--- fs/ext4/mballoc.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-)
fs/ext4/mballoc.c +20 -1
@@ -5331,6 +5331,15 @@ static void ext4_mb_clear_bb(handle_t *h sbi =EXT4_SB (sb); +if (!(flags &EXT4_FREE_BLOCKS_VALIDATED ) && + !ext4_inode_block_valid (inode, block, count)) { +ext4_error (sb,"Freeing blocks in system zone - " +"Block = %llu, count = %lu" , block, count); +/* err = 0. ext4_std_error should be a no op */ + goto error_return; + } + flags |=EXT4_FREE_BLOCKS_VALIDATED ; + do_more: overflow =0 ;ext4_get_group_no_and_offset (sb, block, &block_group, &bit);
@@ -5347,6 +5356,8 @@ do_more: overflow =EXT4_C2B (sbi, bit) + count -EXT4_BLOCKS_PER_GROUP (sb); count -= overflow; +/* The range changed so it's no longer validated */ + flags &= ~EXT4_FREE_BLOCKS_VALIDATED ; } count_clusters =EXT4_NUM_B2C (sbi, count); bitmap_bh =ext4_read_block_bitmap (sb, block_group);
@@ -5361,7 +5372,8 @@ do_more: goto error_return; } -if (!ext4_inode_block_valid (inode, block, count)) { +if (!(flags &EXT4_FREE_BLOCKS_VALIDATED ) && + !ext4_inode_block_valid (inode, block, count)) {ext4_error (sb,"Freeing blocks in system zone - " "Block = %llu, count = %lu" , block, count);/* err = 0. ext4_std_error should be a no op */
@@ -5483,6 +5495,8 @@ do_more: block += count; count = overflow;put_bh (bitmap_bh); +/* The range changed so it's no longer validated */ + flags &= ~EXT4_FREE_BLOCKS_VALIDATED ; goto do_more; } error_return:
@@ -5529,6 +5543,7 @@ void ext4_free_blocks(handle_t *handle, "block = %llu, count = %lu", block, count);return ; } + flags |=EXT4_FREE_BLOCKS_VALIDATED ;ext4_debug ("freeing block %llu\n" , block);trace_ext4_free_blocks (inode, block, count, flags);
@@ -5560,6 +5575,8 @@ void ext4_free_blocks(handle_t *handle, block -= overflow; count += overflow; } +/* The range changed so it's no longer validated */ + flags &= ~EXT4_FREE_BLOCKS_VALIDATED ; } overflow =EXT4_LBLK_COFF (sbi, count);if (overflow) {
@@ -5570,6 +5587,8 @@ void ext4_free_blocks(handle_t *handle,return ; }else count += sbi->s_cluster_ratio - overflow; +/* The range changed so it's no longer validated */ + flags &= ~EXT4_FREE_BLOCKS_VALIDATED ; }if (!bh && (flags &EXT4_FREE_BLOCKS_FORGET )) {
Greg Kroah-Hartman
maintainerPATCH 95/104 arch: fix broken BuildID for arm64 and riscv
In reply to Greg Kroah-HartmanFrom: Masahiro Yamada <[email protected]>
commit 99cb0d917ffa1ab628bb67364ca9b162c07699b1 upstream.
Dennis Gilmore reports that the BuildID is missing in the arm64 vmlinux since commit 994b7ac1697b ("arm64: remove special treatment for the link order of head.o").
The issue is that the type of .notes section, which contains the BuildID, changed from NOTES to PROGBITS.
Ard Biesheuvel figured out that whichever object gets linked first gets to decide the type of a section. The PROGBITS type is the result of the compiler emitting .note.GNU-stack as PROGBITS rather than NOTE.
While Ard provided a fix for arm64, I want to fix this globally because the same issue is happening on riscv since commit 2348e6bf4421 ("riscv:
remove special treatment for the link order of head.o"). This problem will happen in general for other architectures if they start to drop unneeded entries from scripts/head-object-list.txt.
Discard .note.GNU-stack in include/asm-generic/vmlinux.lds.h.
Though the above "Fixes:" commits are not in this kernel, the conditions which lead to a missing Build ID in arm64 vmlinux are similar.
Evidence points to these conditions:
1. ld version > 2.36 (exact binutils commit documented in a494398bde27)
2. first object which gets linked (head.o) has a PROGBITS .note.GNU-stack segment
These conditions can be observed when:
- 5.15.60+ OR 5.10.136+ OR 5.4.210+
- AND ld version > 2.36
- AND arch=arm64
- AND CONFIG_MODVERSIONS=y
There are notable differences in the vmlinux elf files produced before(bad) and after(good) applying this series.
Good: p_type:PT_NOTE segment exists.
Bad: p_type:PT_NOTE segment is missing.
Good: sh_name_str:.notes section has sh_type:SHT_NOTE
Bad: sh_name_str:.notes section has sh_type:SHT_PROGBITS
readelf -n (as of v2.40) searches for Build Id
by processing only the very first note in sh_type:SHT_NOTE sections.
This was previously bisected to the stable backport of 0d362be5b142.
Follow-up experiments were discussed here: https://lore.kernel.org/all/[email protected]/
which strongly hints at condition 2.
--- include/asm-generic/vmlinux.lds.h | 5 +++++ 1 file changed, 5 insertions(+)
include/asm-generic/vmlinux.lds.h +5 -0
@@ -906,7 +906,12 @@#define TRACEDATA #endif +/* +* Discard .note.GNU-stack, which is emitted as PROGBITS by the compiler. +* Otherwise, the type of .notes section would become PROGBITS instead of NOTES. +*/ #define NOTES \ + /DISCARD/ : { *(.note.GNU-stack) } \ .notes : AT(ADDR(.notes) - LOAD_OFFSET) { \ __start_notes = .; \ KEEP(*(.note.*)) \
Greg Kroah-Hartman
maintainerPATCH 96/104 powerpc/vmlinux.lds: Define RUNTIME_DISCARD_EXIT
In reply to Greg Kroah-HartmanFrom: Michael Ellerman <[email protected]>
commit 4b9880dbf3bdba3a7c56445137c3d0e30aaa0a40 upstream.
The powerpc linker script explicitly includes .exit.text, because otherwise the link fails due to references from __bug_table and __ex_table. The code is freed (discarded) at runtime along with .init.text and data.
That has worked in the past despite powerpc not defining RUNTIME_DISCARD_EXIT because DISCARDS appears late in the powerpc linker script (line 410), and the explicit inclusion of .exit.text earlier (line 280) supersedes the discard.
However commit 99cb0d917ffa ("arch: fix broken BuildID for arm64 and riscv") introduced an earlier use of DISCARD as part of the RO_DATA macro (line 136). With binutils < 2.36 that causes the DISCARD directives later in the script to be applied earlier [1], causing .exit.text to actually be discarded at link time, leading to build errors:
'.exit.text' referenced in section '__bug_table' of crypto/algboss.o: defined in discarded section '.exit.text' of crypto/algboss.o
'.exit.text' referenced in section '__ex_table' of drivers/nvdimm/core.o: defined in discarded section '.exit.text' of drivers/nvdimm/core.o
Fix it by defining RUNTIME_DISCARD_EXIT, which causes the generic DISCARDS macro to not include .exit.text at all.
1: https://lore.kernel.org/lkml/[email protected]/
--- arch/powerpc/kernel/vmlinux.lds.S | 1 + 1 file changed, 1 insertion(+)
arch/powerpc/kernel/vmlinux.lds.S +1 -0
@@ -8,6 +8,7 @@ #define BSS_FIRST_SECTIONS *(.bss.prominit) #define EMITS_PT_NOTE #define RO_EXCEPTION_TABLE_ALIGN 0 +#define RUNTIME_DISCARD_EXIT #include <asm/page.h> #include <asm-generic/vmlinux.lds.h>
Greg Kroah-Hartman
maintainerPATCH 97/104 powerpc/vmlinux.lds: Dont discard .rela* for relocatable builds
In reply to Greg Kroah-HartmanFrom: Michael Ellerman <[email protected]>
commit 07b050f9290ee012a407a0f64151db902a1520f5 upstream.
Relocatable kernels must not discard relocations, they need to be processed at runtime. As such they are included for CONFIG_RELOCATABLE builds in the powerpc linker script (line 340).
However they are also unconditionally discarded later in the script (line 414). Previously that worked because the earlier inclusion superseded the discard.
However commit 99cb0d917ffa ("arch: fix broken BuildID for arm64 and riscv") introduced an earlier use of DISCARD as part of the RO_DATA macro (line 137). With binutils < 2.36 that causes the DISCARD directives later in the script to be applied earlier, causing .rela* to actually be discarded at link time, leading to build warnings and a kernel that doesn't boot:
ld: warning: discarding dynamic section .rela.init.rodata
Fix it by conditionally discarding .rela* only when CONFIG_RELOCATABLE is disabled.
--- arch/powerpc/kernel/vmlinux.lds.S | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
arch/powerpc/kernel/vmlinux.lds.S +4 -1
@@ -379,9 +379,12 @@ SECTIONS DISCARDS /DISCARD/ : { *(*.EMB.apuinfo) - *(.glink .iplt .plt .rela* .comment) + *(.glink .iplt .plt .comment) *(.gnu.version*) *(.gnu.attributes) *(.eh_frame) +#ifndef CONFIG_RELOCATABLE + *(.rela*) +#endif } }
Greg Kroah-Hartman
maintainerPATCH 98/104 s390: define RUNTIME_DISCARD_EXIT to fix link error with GNU ld < 2.36
In reply to Greg Kroah-HartmanFrom: Masahiro Yamada <[email protected]>
commit a494398bde273143c2352dd373cad8211f7d94b2 upstream.
Nathan Chancellor reports that the s390 vmlinux fails to link with GNU ld < 2.36 since commit 99cb0d917ffa ("arch: fix broken BuildID for arm64 and riscv").
It happens for defconfig, or more specifically for CONFIG_EXPOLINE=y.
$ s390x-linux-gnu-ld --version | head -n1 GNU ld (GNU Binutils for Debian) 2.35.2 $ make -s ARCH=s390 CROSS_COMPILE=s390x-linux-gnu- allnoconfig $ ./scripts/config -e CONFIG_EXPOLINE $ make -s ARCH=s390 CROSS_COMPILE=s390x-linux-gnu- olddefconfig $ make -s ARCH=s390 CROSS_COMPILE=s390x-linux-gnu- `.exit.text' referenced in section `.s390_return_reg' of drivers/base/dd.o: defined in discarded section `.exit.text' of drivers/base/dd.o make[1]: *** [scripts/Makefile.vmlinux:34: vmlinux] Error 1 make: *** [Makefile:1252: vmlinux] Error 2
arch/s390/kernel/vmlinux.lds.S wants to keep EXIT_TEXT:
.exit.text : {
EXIT_TEXT
}But, at the same time, EXIT_TEXT is thrown away by DISCARD because s390 does not define RUNTIME_DISCARD_EXIT.
I still do not understand why the latter wins after 99cb0d917ffa, but defining RUNTIME_DISCARD_EXIT seems correct because the comment line in arch/s390/kernel/vmlinux.lds.S says:
/*
* .exit.text is discarded at runtime, not link time,
* to deal with references from __bug_table */
Nathan also found that binutils commit 21401fc7bf67 ("Duplicate output sections in scripts") cured this issue, so we cannot reproduce it with binutils 2.36+, but it is better to not rely on it.
--- arch/s390/kernel/vmlinux.lds.S | 2 ++ 1 file changed, 2 insertions(+)
arch/s390/kernel/vmlinux.lds.S +2 -0
@@ -15,6 +15,8 @@ /* Handle ro_after_init data on our own. */ #define RO_AFTER_INIT_DATA +#define RUNTIME_DISCARD_EXIT + #define EMITS_PT_NOTE #include <asm-generic/vmlinux.lds.h>
Greg Kroah-Hartman
maintainerPATCH 99/104 sh: define RUNTIME_DISCARD_EXIT
In reply to Greg Kroah-HartmanFrom: Tom Saeger <[email protected]>
commit c1c551bebf928889e7a8fef7415b44f9a64975f4 upstream.
sh vmlinux fails to link with GNU ld < 2.40 (likely < 2.36) since commit 99cb0d917ffa ("arch: fix broken BuildID for arm64 and riscv").
This is similar to fixes for powerpc and s390:
commit 4b9880dbf3bd ("powerpc/vmlinux.lds: Define RUNTIME_DISCARD_EXIT"). commit a494398bde27 ("s390: define RUNTIME_DISCARD_EXIT to fix link error with GNU ld < 2.36").
$ sh4-linux-gnu-ld --version | head -n1 GNU ld (GNU Binutils for Debian) 2.35.2
$ make ARCH=sh CROSS_COMPILE=sh4-linux-gnu- microdev_defconfig $ make ARCH=sh CROSS_COMPILE=sh4-linux-gnu-
.exit.text' referenced in section __bug_table' of crypto/algboss.o:
defined in discarded section .exit.text' of crypto/algboss.o .exit.text' referenced in section __bug_table' of drivers/char/hw_random/core.o: defined in discarded section .exit.text' of drivers/char/hw_random/core.o
make[2]: *** [scripts/Makefile.vmlinux:34: vmlinux] Error 1 make[1]: *** [Makefile:1252: vmlinux] Error 2
arch/sh/kernel/vmlinux.lds.S keeps EXIT_TEXT:
/*
* .exit.text is discarded at runtime, not link time, to deal with
* references from __bug_table
*/
.exit.text : AT(ADDR(.exit.text)) { EXIT_TEXT }However, EXIT_TEXT is thrown away by DISCARD(include/asm-generic/vmlinux.lds.h) because sh does not define RUNTIME_DISCARD_EXIT.
GNU ld 2.40 does not have this issue and builds fine.
This corresponds with Masahiro's comments in a494398bde27:
"Nathan [Chancellor] also found that binutils
commit 21401fc7bf67 ("Duplicate output sections in scripts") cured this issue, so we cannot reproduce it with binutils 2.36+, but it is better to not rely on it."
--- arch/sh/kernel/vmlinux.lds.S | 1 + 1 file changed, 1 insertion(+)
arch/sh/kernel/vmlinux.lds.S +1 -0
@@ -4,6 +4,7 @@ * Written by Niibe Yutaka and Paul Mundt */ OUTPUT_ARCH(sh) +#define RUNTIME_DISCARD_EXIT #include <asm/thread_info.h> #include <asm/cache.h> #include <asm/vmlinux.lds.h>
Greg Kroah-Hartman
maintainerPATCH 100/104 UML: define RUNTIME_DISCARD_EXIT
In reply to Greg Kroah-HartmanFrom: Masahiro Yamada <[email protected]>
commit b99ddbe8336ee680257c8ab479f75051eaa49dcf upstream.
With CONFIG_VIRTIO_UML=y, GNU ld < 2.36 fails to link UML vmlinux (w/wo CONFIG_LD_SCRIPT_STATIC).
.exit.text' referenced in section .uml.exitcall.exit' of arch/um/drivers/virtio_uml.o: defined in discarded section `.exit.text' of arch/um/drivers/virtio_uml.o
collect2: error: ld returned 1 exit status
This fix is similar to the following commits:
- 4b9880dbf3bd ("powerpc/vmlinux.lds: Define RUNTIME_DISCARD_EXIT")
- a494398bde27 ("s390: define RUNTIME_DISCARD_EXIT to fix link error with GNU ld < 2.36")
- c1c551bebf92 ("sh: define RUNTIME_DISCARD_EXIT")
--- arch/um/kernel/vmlinux.lds.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/um/kernel/vmlinux.lds.S +1 -1
@@ -1,4 +1,4 @@ - +#define RUNTIME_DISCARD_EXIT KERNEL_STACK_SIZE = 4096 * (1 << CONFIG_KERNEL_STACK_ORDER); #ifdef CONFIG_LD_SCRIPT_STATIC
Greg Kroah-Hartman
maintainerPATCH 101/104 KVM: nVMX: Dont use Enlightened MSR Bitmap for L3
In reply to Greg Kroah-HartmanFrom: Vitaly Kuznetsov <[email protected]>
commit 250552b925ce400c17d166422fde9bb215958481 upstream.
When KVM runs as a nested hypervisor on top of Hyper-V it uses Enlightened VMCS and enables Enlightened MSR Bitmap feature for its L1s and L2s (which are actually L2s and L3s from Hyper-V's perspective). When MSR bitmap is updated, KVM has to reset HV_VMX_ENLIGHTENED_CLEAN_FIELD_MSR_BITMAP from clean fields to make Hyper-V aware of the change. For KVM's L1s, this is done in vmx_disable_intercept_for_msr()/vmx_enable_intercept_for_msr(). MSR bitmap for L2 is build in nested_vmx_prepare_msr_bitmap() by blending MSR bitmap for L1 and L1's idea of MSR bitmap for L2. KVM, however, doesn't check if the resulting bitmap is different and never cleans HV_VMX_ENLIGHTENED_CLEAN_FIELD_MSR_BITMAP in eVMCS02. This is incorrect and may result in Hyper-V missing the update.
The issue could've been solved by calling evmcs_touch_msr_bitmap() for eVMCS02 from nested_vmx_prepare_msr_bitmap() unconditionally but doing so would not give any performance benefits (compared to not using Enlightened MSR Bitmap at all). 3-level nesting is also not a very common setup nowadays.
Don't enable 'Enlightened MSR Bitmap' feature for KVM's L2s (real L3s) for now.
Message-Id: <[email protected]>
--- arch/x86/kvm/vmx/vmx.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-)
arch/x86/kvm/vmx/vmx.c +13 -9
@@ -2725,15 +2725,6 @@ int alloc_loaded_vmcs(struct loaded_vmcsif (!loaded_vmcs->msr_bitmap) goto out_vmcs;memset (loaded_vmcs->msr_bitmap,0xff ,PAGE_SIZE ); - -if (IS_ENABLED (CONFIG_HYPERV ) && -static_branch_unlikely (&enable_evmcs) && - (ms_hyperv.nested_features &HV_X64_NESTED_MSR_BITMAP )) { -struct hv_enlightened_vmcs *evmcs = - (struct hv_enlightened_vmcs *)loaded_vmcs->vmcs; - - evmcs->hv_enlightenments_control.msr_bitmap =1 ; - } }memset (&loaded_vmcs->host_state,0 ,sizeof (struct vmcs_host_state ));
@@ -7029,6 +7020,19 @@ static int vmx_create_vcpu(struct kvm_vcif (err <0 ) goto free_pml; +/* +* Use Hyper-V 'Enlightened MSR Bitmap' feature when KVM runs as a +* nested (L1) hypervisor and Hyper-V in L0 supports it. Enable the +* feature only for vmcs01, KVM currently isn't equipped to realize any +* performance benefits from enabling it for vmcs02. +*/ +if (IS_ENABLED (CONFIG_HYPERV ) &&static_branch_unlikely (&enable_evmcs) && + (ms_hyperv.nested_features &HV_X64_NESTED_MSR_BITMAP )) { +struct hv_enlightened_vmcs *evmcs = (void *)vmx->vmcs01.vmcs; + + evmcs->hv_enlightenments_control.msr_bitmap =1 ; + } +/* The MSR bitmap starts with all ones */ bitmap_fill (vmx->shadow_msr_intercept.read,MAX_POSSIBLE_PASSTHROUGH_MSRS );bitmap_fill (vmx->shadow_msr_intercept.write,MAX_POSSIBLE_PASSTHROUGH_MSRS );
Greg Kroah-Hartman
maintainerPATCH 102/104 KVM: VMX: Introduce vmx_msr_bitmap_l01_changed() helper
In reply to Greg Kroah-HartmanFrom: Vitaly Kuznetsov <[email protected]>
commit b84155c38076b36d625043a06a2f1c90bde62903 upstream.
In preparation to enabling 'Enlightened MSR Bitmap' feature for Hyper-V guests move MSR bitmap update tracking to a dedicated helper.
Note: vmx_msr_bitmap_l01_changed() is called when MSR bitmap might be updated. KVM doesn't check if the bit we're trying to set is already set (or the bit it's trying to clear is already cleared). Such situations should not be common and a few false positives should not be a problem.
No functional change intended.
Message-Id: <[email protected]>
--- arch/x86/kvm/vmx/vmx.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
arch/x86/kvm/vmx/vmx.c +13 -4
@@ -3785,6 +3785,17 @@ static void vmx_set_msr_bitmap_write(ulo__set_bit (msr &0x1fff , msr_bitmap +0xc00 / f); } +static void vmx_msr_bitmap_l01_changed (struct vcpu_vmx *vmx) +{ +/* +* When KVM is a nested hypervisor on top of Hyper-V and uses +* 'Enlightened MSR Bitmap' feature L0 needs to know that MSR +* bitmap has changed. +*/ +if (static_branch_unlikely (&enable_evmcs)) +evmcs_touch_msr_bitmap (); +} + static __always_inline void vmx_disable_intercept_for_msr(struct kvm_vcpu *vcpu,u32 msr,int type) {
@@ -3794,8 +3805,7 @@ static __always_inline void vmx_disable_if (!cpu_has_vmx_msr_bitmap ())return ; -if (static_branch_unlikely (&enable_evmcs)) -evmcs_touch_msr_bitmap (); +vmx_msr_bitmap_l01_changed (vmx);/* * Mark the desired intercept state in shadow bitmap, this is needed
@@ -3840,8 +3850,7 @@ static __always_inline void vmx_enable_iif (!cpu_has_vmx_msr_bitmap ())return ; -if (static_branch_unlikely (&enable_evmcs)) -evmcs_touch_msr_bitmap (); +vmx_msr_bitmap_l01_changed (vmx);/* * Mark the desired intercept state in shadow bitmap, this is needed
Greg Kroah-Hartman
maintainerPATCH 103/104 KVM: VMX: Fix crash due to uninitialized current_vmcs
In reply to Greg Kroah-HartmanFrom: Alexandru Matei <[email protected]>
commit 93827a0a36396f2fd6368a54a020f420c8916e9b upstream.
KVM enables 'Enlightened VMCS' and 'Enlightened MSR Bitmap' when running as a nested hypervisor on top of Hyper-V. When MSR bitmap is updated, evmcs_touch_msr_bitmap function uses current_vmcs per-cpu variable to mark that the msr bitmap was changed.
vmx_vcpu_create() modifies the msr bitmap via vmx_disable_intercept_for_msr -> vmx_msr_bitmap_l01_changed which in the end calls this function. The function checks for current_vmcs if it is null but the check is insufficient because current_vmcs is not initialized. Because of this, the code might incorrectly write to the structure pointed by current_vmcs value left by another task. Preemption is not disabled, the current task can be preempted and moved to another CPU while current_vmcs is accessed multiple times from evmcs_touch_msr_bitmap() which leads to crash.
The manipulation of MSR bitmaps by callers happens only for vmcs01 so the solution is to use vmx->vmcs01.vmcs instead of current_vmcs.
BUG: kernel NULL pointer dereference, address: 0000000000000338 PGD 4e1775067 P4D 0 Oops: 0002 [#1] PREEMPT SMP NOPTI ... RIP: 0010:vmx_msr_bitmap_l01_changed+0x39/0x50 [kvm_intel] ... Call Trace: vmx_disable_intercept_for_msr+0x36/0x260 [kvm_intel] vmx_vcpu_create+0xe6/0x540 [kvm_intel] kvm_arch_vcpu_create+0x1d1/0x2e0 [kvm] kvm_vm_ioctl_create_vcpu+0x178/0x430 [kvm] kvm_vm_ioctl+0x53f/0x790 [kvm] __x64_sys_ioctl+0x8a/0xc0 do_syscall_64+0x5c/0x90 entry_SYSCALL_64_after_hwframe+0x63/0xcd
[manual backport: evmcs.h got renamed to hyperv.h in a later version, modified in evmcs.h instead]
--- arch/x86/kvm/vmx/evmcs.h | 11 ----------- arch/x86/kvm/vmx/vmx.c | 9 +++++++-- 2 files changed, 7 insertions(+), 13 deletions(-)
arch/x86/kvm/vmx/evmcs.h +0 -11
@@ -166,16 +166,6 @@ static inline u16 evmcs_read16(unsignedreturn *(u16 *)((char *)current_evmcs + offset); } -static inline void evmcs_touch_msr_bitmap (void ) -{ -if (unlikely (!current_evmcs)) -return ; - -if (current_evmcs->hv_enlightenments_control.msr_bitmap) - current_evmcs->hv_clean_fields &= - ~HV_VMX_ENLIGHTENED_CLEAN_FIELD_MSR_BITMAP ; -} -static inline void evmcs_load (u64 phys_addr) { struct hv_vp_assist_page *vp_ap =
@@ -196,7 +186,6 @@ static inline u64 evmcs_read64(unsignedstatic inline u32 evmcs_read32 (unsigned long field) {return 0 ; }static inline u16 evmcs_read16 (unsigned long field) {return 0 ; }static inline void evmcs_load (u64 phys_addr) {} -static inline void evmcs_touch_msr_bitmap (void ) {}#endif /* IS_ENABLED(CONFIG_HYPERV) */ enum nested_evmptrld_status {
arch/x86/kvm/vmx/vmx.c +7 -2
@@ -3792,8 +3792,13 @@ static void vmx_msr_bitmap_l01_changed(s* 'Enlightened MSR Bitmap' feature L0 needs to know that MSR * bitmap has changed. */ -if (static_branch_unlikely (&enable_evmcs)) -evmcs_touch_msr_bitmap (); +if (IS_ENABLED (CONFIG_HYPERV ) &&static_branch_unlikely (&enable_evmcs)) { +struct hv_enlightened_vmcs *evmcs = (void *)vmx->vmcs01.vmcs; + +if (evmcs->hv_enlightenments_control.msr_bitmap) + evmcs->hv_clean_fields &= + ~HV_VMX_ENLIGHTENED_CLEAN_FIELD_MSR_BITMAP ; + } } static __always_inline void vmx_disable_intercept_for_msr(struct kvm_vcpu *vcpu,
Greg Kroah-Hartman
maintainerPATCH 104/104 s390/dasd: add missing discipline function
In reply to Greg Kroah-HartmanFrom: Stefan Haberland <[email protected]>
commit c0c8a8397fa8a74d04915f4d3d28cb4a5d401427 upstream.
Fix crash with illegal operation exception in dasd_device_tasklet. Commit b72949328869 ("s390/dasd: Prepare for additional path event handling") renamed the verify_path function for ECKD but not for FBA and DIAG. This leads to a panic when the path verification function is called for a FBA or DIAG device.
Fix by defining a wrapper function for dasd_generic_verify_path().
--- drivers/s390/block/dasd_diag.c | 7 ++++++- drivers/s390/block/dasd_fba.c | 7 ++++++- drivers/s390/block/dasd_int.h | 1 - 3 files changed, 12 insertions(+), 3 deletions(-)
drivers/s390/block/dasd_diag.c +6 -1
@@ -642,12 +642,17 @@ static void dasd_diag_setup_blk_queue(stblk_queue_segment_boundary (q,PAGE_SIZE -1 ); } +static int dasd_diag_pe_handler (struct dasd_device *device,__u8 tbvpm) +{ +return dasd_generic_verify_path (device, tbvpm); +} +static struct dasd_discipline dasd_diag_discipline = { .owner =THIS_MODULE , .name ="DIAG" , .ebcname ="DIAG" , .check_device = dasd_diag_check_device, - .verify_path = dasd_generic_verify_path, + .pe_handler = dasd_diag_pe_handler, .fill_geometry = dasd_diag_fill_geometry, .setup_blk_queue = dasd_diag_setup_blk_queue, .start_IO = dasd_start_diag,
drivers/s390/block/dasd_fba.c +6 -1
@@ -803,13 +803,18 @@ static void dasd_fba_setup_blk_queue(strblk_queue_flag_set (QUEUE_FLAG_DISCARD , q); } +static int dasd_fba_pe_handler (struct dasd_device *device,__u8 tbvpm) +{ +return dasd_generic_verify_path (device, tbvpm); +} +static struct dasd_discipline dasd_fba_discipline = { .owner =THIS_MODULE , .name ="FBA " , .ebcname ="FBA " , .check_device = dasd_fba_check_characteristics, .do_analysis = dasd_fba_do_analysis, - .verify_path = dasd_generic_verify_path, + .pe_handler = dasd_fba_pe_handler, .setup_blk_queue = dasd_fba_setup_blk_queue, .fill_geometry = dasd_fba_fill_geometry, .start_IO = dasd_start_IO,
drivers/s390/block/dasd_int.h +0 -1
@@ -298,7 +298,6 @@ struct dasd_discipline {* e.g. verify that new path is compatible with the current * configuration. */ -int (*verify_path)(struct dasd_device *,__u8 );int (*pe_handler)(struct dasd_device *,__u8 );/*
Hello Greg,
Quoted 10 lines
From: Greg Kroah-Hartman <[email protected]>
Sent: 15 March 2023 12:12This is the start of the stable review cycle for the 5.10.175 release. There are 104 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 Fri, 17 Mar 2023 11:57:10 +0000. Anything received after that time might be too late.
CI Pipeline: https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/pipelines/807195733
We (CIP) are seeing some build issues with Linux 5.10.175-rc1 (420b6d10bae3).
1)
For a couple of arm configs we see a variation of:
In file included from kernel/sched/core.c:13:kernel/sched/sched.h: In function 'cpu_in_capacity_inversion':kernel/sched/sched.h:2560:20: error: 'struct rq' has no member named 'cpu_capacity_inverted'
2560 | return cpu_rq(cpu)->cpu_capacity_inverted;
| ^~
make[2]: *** [scripts/Makefile.build:286: kernel/sched/core.o] Error 1 make[1]: *** [scripts/Makefile.build:503: kernel/sched] Error 2
Full log: https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/jobs/3938632489#L1910
This code was added in "sched/fair: Detect capacity inversion".
Kind regards, Chris
Quoted 8 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.10.175 release. There are 104 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 Fri, 17 Mar 2023 11:57:10 +0000. Anything received after that time might be too late.
Building arc:tb10x_defconfig ... failed Building arcv2:allnoconfig ... failed Building c6x:dsk6455_defconfig ... failed Building h8300:allnoconfig ... failed Building hexagon:allnoconfig ... failed Building i386:allnoconfig ... failed Building i386:tinyconfig ... failed
... and many more.
--------------
Error log:
In file included from kernel/sched/core.c:13:kernel/sched/sched.h: In function 'cpu_in_capacity_inversion':kernel/sched/sched.h:2560:27: error: 'struct rq' has no member named 'cpu_capacity_inverted'
2560 | return cpu_rq(cpu)->cpu_capacity_inverted;
| ^~
In file included from kernel/sched/loadavg.c:9:kernel/sched/sched.h: In function 'cpu_in_capacity_inversion':kernel/sched/sched.h:2560:27: error: 'struct rq' has no member named 'cpu_capacity_inverted'
2560 | return cpu_rq(cpu)->cpu_capacity_inverted;
Guenter
Quoted 8 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.10.175 release. There are 104 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 Fri, 17 Mar 2023 11:57:10 +0000. Anything received after that time might be too late.
Another build failure, almost drowning in the noise.
Building riscv32:allmodconfig ... failed
--------------
Error log:drivers/pci/pci-driver.c: In function 'pci_pm_runtime_resume':drivers/pci/pci-driver.c:1297:9: error: implicit declaration of function 'pci_restore_standard_config' [-Werror=implicit-function-declaration]
1297 | pci_restore_standard_config(pci_dev);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
At top level:
drivers/pci/pci-driver.c:536:13: warning: 'pci_pm_default_resume_early' defined but not used [-Wunused-function]
536 | static void pci_pm_default_resume_early(struct pci_dev *pci_dev)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~Guenter
Greg Kroah-Hartman
maintainerQuoted 17 lines · Guenter Roeck
Quoted 8 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.10.175 release. There are 104 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 Fri, 17 Mar 2023 11:57:10 +0000. Anything received after that time might be too late.
Another build failure, almost drowning in the noise.
Building riscv32:allmodconfig ... failed
--------------
Error log:drivers/pci/pci-driver.c: In function 'pci_pm_runtime_resume':drivers/pci/pci-driver.c:1297:9: error: implicit declaration of function 'pci_restore_standard_config' [-Werror=implicit-function-declaration]
Quoted 6 lines
1297 | pci_restore_standard_config(pci_dev);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
At top level:
drivers/pci/pci-driver.c:536:13: warning: 'pci_pm_default_resume_early' defined but not used [-Wunused-function]
536 | static void pci_pm_default_resume_early(struct pci_dev *pci_dev)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~Ah, nice catch, I've now fixed this up and it should be good in -rc2
greg k-h
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.10.175 release. There are 104 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 Fri, 17 Mar 2023 11:57:10 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.175-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.10.y
and the diffstat can be found below.thanks,
greg k-h
On ARCH_BRCMSTB using 32-bit and 64-bit ARM kernels, build tested on BMIPS_GENERIC:
Signature · 1 line
Florian
Hello!
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.10.175 release. There are 104 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 Fri, 17 Mar 2023 11:57:10 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.175-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.10.y
and the diffstat can be found below.thanks,
greg k-h
Lots of failures here too.
For:
* ARC (allnoconfig)
* Arm (tinyconfig, footbridge_defconfig, multi_v5_defconfig-aa80e505, omap1_defconfig, sama5_defconfig)
* MIPS (tinyconfig, bcm63xx_defconfig, ath79_defconfig)
* PA-RISC (tinyconfig)
* PowerPC (allnoconfig, tinyconfig, tqm8xx_defconfig, mpc83xx_defconfig, ppc6xx_defconfig)
* RISC-V (allnoconfig, tinyconfig)
* SPARC (allnoconfig, tinyconfig)
* SuperH (allnoconfig, tinyconfig, dreamcast_defconfig, microdev_defconfig)
* x86 (allnoconfig, tinyconfig)
in combinations of GCC-8, GCC-9, GCC-11, GCC-12, Clang-16:
-----8<-----
In file included from /builds/linux/kernel/sched/core.c:13:
/builds/linux/kernel/sched/sched.h:2560:22: error: no member named 'cpu_capacity_inverted' in 'struct rq'
return cpu_rq(cpu)->cpu_capacity_inverted;
~~~~~~~~~~~ ^----->8-----
For PowerPC (cell_defconfig, mpc83xx_defconfig, ppc6xx_defconfig, tqm8xx_defconfig) with GCC-8, GCC-12, Clang-16:
-----8<-----
/builds/linux/drivers/tty/serial/cpm_uart/cpm_uart_core.c:1208:25: error: use of undeclared identifier 'NO_IRQ'; did you mean 'do_IRQ'?
if (pinfo->port.irq == NO_IRQ) {
^~~~~~
do_IRQ----->8-----
Greetings!
Daniel Díaz
[email protected]
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.10.175 release. There are 104 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 Fri, 17 Mar 2023 11:57:10 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.175-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.10.y
and the diffstat can be found below.thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
thanks,
-- Shuah
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.10.175 release. There are 104 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 Fri, 17 Mar 2023 11:57:10 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.175-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.10.y
and the diffstat can be found below.thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
thanks,
-- Shuah