5.4.75-rc1 review
Subsystems (2)
Greg Kroah-Hartman
maintainercover 5.4.75-rc1 review
This is the start of the stable review cycle for the 5.4.75 release. There are 214 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 05 Nov 2020 20:29:58 +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.4.75-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.4.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 5.4.75-rc1
Stephen Boyd <[email protected]>
KVM: arm64: ARM_SMCCC_ARCH_WORKAROUND_1 doesn't return SMCCC_RET_NOT_REQUIRED
Alexander Sverdlin <[email protected]>
staging: octeon: Drop on uncorrectable alignment or FCS error
Alexander Sverdlin <[email protected]>
staging: octeon: repair "fixed-link" support
Ian Abbott <[email protected]>
staging: comedi: cb_pcidas: Allow 2-channel commands for AO subdevice
Jing Xiangfeng <[email protected]>
staging: fieldbus: anybuss: jump to correct label in an error path
Marc Zyngier <[email protected]>
KVM: arm64: Fix AArch32 handling of DBGD{CCINT,SCRext} and DBGVCR
Andy Shevchenko <[email protected]>
device property: Don't clear secondary pointer for shared primary firmware node
Andy Shevchenko <[email protected]>
device property: Keep secondary firmware node secondary by type
Krzysztof Kozlowski <[email protected]>
ARM: s3c24xx: fix missing system reset
Krzysztof Kozlowski <[email protected]>
ARM: samsung: fix PM debug build with DEBUG_LL but !MMU
Frank Wunderlich <[email protected]>
arm: dts: mt7623: add missing pause for switchport
Helge Deller <[email protected]>
hil/parisc: Disable HIL driver when it gets stuck
Matthew Wilcox (Oracle) <[email protected]>
cachefiles: Handle readpage error correctly
Jisheng Zhang <[email protected]>
arm64: berlin: Select DW_APB_TIMER_OF
Linus Torvalds <[email protected]>
tty: make FONTX ioctl use the tty pointer they were actually passed
Evan Quan <[email protected]>
drm/amd/pm: increase mclk switch threshold to 200 us
Jisheng Zhang <[email protected]>
mmc: sdhci: Use Auto CMD Auto Select only when v4_mode is true
Michael Walle <[email protected]>
mmc: sdhci-of-esdhc: set timeout to max before tuning
Dave Airlie <[email protected]>
drm/ttm: fix eviction valuable range check.
Constantine Sapuntzakis <[email protected]>
ext4: fix superblock checksum calculation race
Luo Meng <[email protected]>
ext4: fix invalid inode checksum
Dinghao Liu <[email protected]>
ext4: fix error handling code in add_new_gdb
Eric Biggers <[email protected]>
ext4: fix leaking sysfs kobject after failed mount
Stefano Garzarella <[email protected]>
vringh: fix __vringh_iov() when riov and wiov are different
Qiujun Huang <[email protected]>
ring-buffer: Return 0 on success from ring_buffer_resize()
Matthew Wilcox (Oracle) <[email protected]>
9P: Cast to loff_t before multiplying
Ilya Dryomov <[email protected]>
libceph: clear con->out_msg on Policy::stateful_server faults
Matthew Wilcox (Oracle) <[email protected]>
ceph: promote to unsigned long long before shifting
Takashi Iwai <[email protected]>
drm/amd/display: Fix kernel panic by dal_gpio_open() error
Takashi Iwai <[email protected]>
drm/amd/display: Don't invoke kgdb_breakpoint() unconditionally
Christian König <[email protected]>
drm/amdgpu: increase the reserved VM size to 2MB
Andrey Grodzovsky <[email protected]>
drm/amd/display: Avoid MST manager resource leak.
Jay Cornwall <[email protected]>
drm/amdkfd: Use same SQ prefetch setting as amdgpu
Evan Quan <[email protected]>
drm/amdgpu: correct the gpu reset handling for job != NULL case
Wesley Chalmers <[email protected]>
drm/amd/display: Increase timeout for DP Disable
Madhav Chauhan <[email protected]>
drm/amdgpu: don't map BO in reserved region
Krzysztof Kozlowski <[email protected]>
i2c: imx: Fix external abort on interrupt in exit paths
Bartosz Golaszewski <[email protected]>
rtc: rx8010: don't modify the global rtc ops
Krzysztof Kozlowski <[email protected]>
ia64: fix build error with !COREDUMP
Zhihao Cheng <[email protected]>
ubi: check kthread_should_stop() after the setting of task state
Vineet Gupta <[email protected]>
ARC: perf: redo the pct irq missing in device-tree handling
Jiri Olsa <[email protected]>
perf python scripting: Fix printable strings in python3 scripts
Zhihao Cheng <[email protected]>
ubifs: mount_ubifs: Release authentication resource in error handling path
Zhihao Cheng <[email protected]>
ubifs: Don't parse authentication mount options in remount process
Zhihao Cheng <[email protected]>
ubifs: Fix a memleak after dumping authentication mount options
Richard Weinberger <[email protected]>
ubifs: journal: Make sure to not dirty twice for auth nodes
Zhihao Cheng <[email protected]>
ubifs: xattr: Fix some potential memory leaks while iterating entries
Zhihao Cheng <[email protected]>
ubifs: dent: Fix some potential memory leaks while iterating entries
Chuck Lever <[email protected]>
NFSD: Add missing NFSv2 .pc_func methods
Olga Kornievskaia <[email protected]>
NFSv4.2: support EXCHGID4_FLAG_SUPP_FENCE_OPS 4.2 EXCHANGE_ID flag
Benjamin Coddington <[email protected]>
NFSv4: Wait for stateid updates after CLOSE/OPEN_DOWNGRADE
Michael Neuling <[email protected]>
powerpc: Fix undetected data corruption with P9N DD2.1 VSX CI load emulation
Christophe Leroy <[email protected]>
powerpc/powermac: Fix low_sleep_handler with KUAP and KUEP
Mahesh Salgaonkar <[email protected]>
powerpc/powernv/elog: Fix race while processing OPAL error log event.
Aneesh Kumar K.V <[email protected]>
powerpc/memhotplug: Make lmb size 64bit
Joel Stanley <[email protected]>
powerpc: Warn about use of smt_snooze_delay
Andrew Donnellan <[email protected]>
powerpc/rtas: Restrict RTAS requests from userspace
Sven Schnelle <[email protected]>
s390/stp: add locking to sysfs functions
Maciej W. Rozycki <[email protected]>
MIPS: DEC: Restore bootmem reservation for firmware working memory area
Aneesh Kumar K.V <[email protected]>
powerpc/drmem: Make lmb_size 64 bit
Jonathan Cameron <[email protected]>
iio:gyro:itg3200: Fix timestamp alignment and prevent data leak.
Jonathan Cameron <[email protected]>
iio:adc:ti-adc12138 Fix alignment issue with timestamp
Jonathan Cameron <[email protected]>
iio:adc:ti-adc0832 Fix alignment issue with timestamp
Tobias Jordan <[email protected]>
iio: adc: gyroadc: fix leak of device node iterator
Jonathan Cameron <[email protected]>
iio:light:si1145: Fix timestamp alignment and prevent data leak.
Paul Cercueil <[email protected]>
dmaengine: dma-jz4780: Fix race in jz4780_dma_tx_status
Jan Kara <[email protected]>
udf: Fix memory leak when mounting
Jason Gerecke <[email protected]>
HID: wacom: Avoid entering wacom_wac_pen_report for pad / battery
Jiri Slaby <[email protected]>
vt: keyboard, extend func_buf_lock to readers
Jiri Slaby <[email protected]>
vt: keyboard, simplify vt_kdgkbsent
Chris Wilson <[email protected]>
drm/i915: Force VT'd workarounds when running as a guest OS
Ran Wang <[email protected]>
usb: host: fsl-mph-dr-of: check return of dma_set_mask()
Li Jun <[email protected]>
usb: typec: tcpm: reset hard_reset_count for any disconnect
Jerome Brunet <[email protected]>
usb: cdc-acm: fix cooldown mechanism
Thinh Nguyen <[email protected]>
usb: dwc3: gadget: END_TRANSFER before CLEAR_STALL command
Thinh Nguyen <[email protected]>
usb: dwc3: gadget: Resume pending requests after CLEAR_STALL
Li Jun <[email protected]>
usb: dwc3: core: don't trigger runtime pm when remove driver
Li Jun <[email protected]>
usb: dwc3: core: add phy cleanup for probe error handling
Thinh Nguyen <[email protected]>
usb: dwc3: gadget: Check MPS of the request length
Thinh Nguyen <[email protected]>
usb: dwc3: ep0: Fix ZLP for OUT ep0 requests
Raymond Tan <[email protected]>
usb: dwc3: pci: Allow Elkhart Lake to utilize DSM method for PM functionality
Sandeep Singh <[email protected]>
usb: xhci: Workaround for S3 issue on AMD SNPS 3.0 xHC
Filipe Manana <[email protected]>
btrfs: fix readahead hang and use-after-free after removing a device
Filipe Manana <[email protected]>
btrfs: fix use-after-free on readahead extent after failure to create it
Daniel Xu <[email protected]>
btrfs: tree-checker: validate number of chunk stripes and parity
Josef Bacik <[email protected]>
btrfs: cleanup cow block on error
Qu Wenruo <[email protected]>
btrfs: tree-checker: fix false alert caused by legacy btrfs root item
Denis Efremov <[email protected]>
btrfs: use kvzalloc() to allocate clone_roots in btrfs_ioctl_send()
Filipe Manana <[email protected]>
btrfs: send, recompute reference path after orphanization of a directory
Filipe Manana <[email protected]>
btrfs: send, orphanize first all conflicting inodes when processing references
Filipe Manana <[email protected]>
btrfs: reschedule if necessary when logging directory items
Anand Jain <[email protected]>
btrfs: improve device scanning messages
Qu Wenruo <[email protected]>
btrfs: qgroup: fix wrong qgroup metadata reserve for delayed inode
Xiang Chen <[email protected]>
PM: runtime: Remove link state checks in rpm_get/put_supplier()
Quinn Tran <[email protected]>
scsi: qla2xxx: Fix crash on session cleanup with unload
Helge Deller <[email protected]>
scsi: mptfusion: Fix null pointer dereferences in mptscsih_remove()
Martin Fuzzey <[email protected]>
w1: mxc_w1: Fix timeout resolution problem leading to bus error
Wei Huang <[email protected]>
acpi-cpufreq: Honor _PSD table setting on new AMD CPUs
Rafael J. Wysocki <[email protected]>
ACPI: EC: PM: Drop ec_no_wakeup check from acpi_ec_dispatch_gpe()
Rafael J. Wysocki <[email protected]>
ACPI: EC: PM: Flush EC work unconditionally after wakeup
Lukas Wunner <[email protected]>
PCI/ACPI: Whitelist hotplug ports for D3 if power managed by ACPI
Jamie Iles <[email protected]>
ACPI: debug: don't allow debugging when ACPI is disabled
Alex Hung <[email protected]>
ACPI: video: use ACPI backlight for HP 635 Notebook
Ben Hutchings <[email protected]>
ACPI / extlog: Check for RDMSR failure
[email protected] <[email protected]>
ACPI: button: fix handling lid state changes when input device closed
Ashish Sangwan <[email protected]>
NFS: fix nfs_path in case of a rename retry
Jan Kara <[email protected]>
fs: Don't invalidate page buffers in block_write_full_page()
Hans de Goede <[email protected]>
media: uvcvideo: Fix uvc_ctrl_fixup_xu_info() not having any effect
Marek Behún <[email protected]>
leds: bcm6328, bcm6358: use devres LED registering function
Krzysztof Kozlowski <[email protected]>
extcon: ptn5150: Fix usage of atomic GPIO with sleeping GPIO chips
Krzysztof Kozlowski <[email protected]>
spi: sprd: Release DMA channel also on probe deferral
Kim Phillips <[email protected]>
perf/x86/amd/ibs: Fix raw sample data accumulation
Kim Phillips <[email protected]>
perf/x86/amd/ibs: Don't include randomized bits in get_ibs_op_count()
Kan Liang <[email protected]>
perf/x86/intel: Fix Ice Lake event constraint table
Andy Lutomirski <[email protected]>
selftests/x86/fsgsbase: Test PTRACE_PEEKUSER for GSBASE with invalid LDT GS
Jann Horn <[email protected]>
seccomp: Make duplicate listener detection non-racy
Raul E Rangel <[email protected]>
mmc: sdhci-acpi: AMDI0040: Set SDHCI_QUIRK2_PRESET_VALUE_BROKEN
Adrian Hunter <[email protected]>
mmc: sdhci: Add LTR support for some Intel BYT based controllers
Song Liu <[email protected]>
md/raid5: fix oops during stripe resizing
Chao Leng <[email protected]>
nvme-rdma: fix crash when connect rejected
Douglas Gilbert <[email protected]>
sgl_alloc_order: fix memory leak
Xiubo Li <[email protected]>
nbd: make the config put is called before the notifying the waiter
Krzysztof Kozlowski <[email protected]>
ARM: dts: s5pv210: remove dedicated 'audio-subsystem' node
Krzysztof Kozlowski <[email protected]>
ARM: dts: s5pv210: move PMU node out of clock controller
Krzysztof Kozlowski <[email protected]>
ARM: dts: s5pv210: move fixed clocks under root node
Krzysztof Kozlowski <[email protected]>
ARM: dts: s5pv210: remove DMA controller bus node name to fix dtschema warnings
Dan Carpenter <[email protected]>
memory: emif: Remove bogus debugfs error handling
Tony Lindgren <[email protected]>
ARM: dts: omap4: Fix sgx clock rate for 4430
Yoshihiro Shimoda <[email protected]>
arm64: dts: renesas: ulcb: add full-pwr-cycle-in-suspend into eMMC nodes
Ronnie Sahlberg <[email protected]>
cifs: handle -EINTR in cifs_setattr
Anant Thazhemadam <[email protected]>
gfs2: add validation checks for size of superblock
Jamie Iles <[email protected]>
gfs2: use-after-free in sysfs deregistration
Fabiano Rosas <[email protected]>
KVM: PPC: Book3S HV: Do not allocate HPT for a nested guest
Jan Kara <[email protected]>
ext4: Detect already used quota file early
Madhuparna Bhowmik <[email protected]>
drivers: watchdog: rdc321x_wdt: Fix race condition bugs
Anant Thazhemadam <[email protected]>
net: 9p: initialize sun_server.sun_path to have addr's value only when addr is valid
Lorenzo Pieralisi <[email protected]>
asm-generic/io.h: Fix !CONFIG_GENERIC_IOMAP pci_iounmap() implementation
Tero Kristo <[email protected]>
clk: ti: clockdomain: fix static checker warning
Chris Lew <[email protected]>
rpmsg: glink: Use complete_all for open states
Michael Chan <[email protected]>
bnxt_en: Log unknown link speed appropriately.
Zhao Heming <[email protected]>
md/bitmap: md_bitmap_get_counter returns wrong blocks
Anand Jain <[email protected]>
btrfs: fix replace of seed device
Zhen Lei <[email protected]>
ARC: [dts] fix the errors detected by dtbs_check
Fangzhi Zuo <[email protected]>
drm/amd/display: HDMI remote sink need mode validation for Linux
Xiongfeng Wang <[email protected]>
power: supply: test_power: add missing newlines when printing parameters by sysfs
Jonathan Cameron <[email protected]>
ACPI: HMAT: Fix handling of changes from ACPI 6.2 to ACPI 6.3
Diana Craciun <[email protected]>
bus/fsl_mc: Do not rely on caller to provide non NULL mc_io
Xie He <[email protected]>
drivers/net/wan/hdlc_fr: Correctly handle special skb->protocol values
Wright Feng <[email protected]>
brcmfmac: Fix warning message after dongle setup failed
Jonathan Cameron <[email protected]>
ACPI: Add out of bounds and numa_off protections to pxm_to_node()
Darrick J. Wong <[email protected]>
xfs: don't free rt blocks when we're doing a REMAP bunmapi call
Joakim Zhang <[email protected]>
can: flexcan: disable clocks during stop mode
Zhengyuan Liu <[email protected]>
arm64/mm: return cpu_all_mask when node is NUMA_NO_NODE
Chuck Lever <[email protected]>
SUNRPC: Mitigate cond_resched() in xprt_transmit()
Peter Chen <[email protected]>
usb: xhci: omit duplicate actions when suspending a runtime suspended host.
Linu Cherian <[email protected]>
coresight: Make sysfs functional on topologies with per core sink
Lang Dai <[email protected]>
uio: free uio id after uio file node is freed
Oliver Neukum <[email protected]>
USB: adutux: fix debugging
Alain Volmat <[email protected]>
cpufreq: sti-cpufreq: add stih418 support
Zong Li <[email protected]>
riscv: Define AT_VECTOR_SIZE_ARCH for ARCH_DLINFO
Magnus Karlsson <[email protected]>
samples/bpf: Fix possible deadlock in xdpsock
Yonghong Song <[email protected]>
selftests/bpf: Define string const as global for test_sysctl_prog.c
Daniel W. S. Almeida <[email protected]>
media: uvcvideo: Fix dereference of out-of-bound list iterator
Yonghong Song <[email protected]>
bpf: Permit map_ptr arithmetic with opcode add and offset 0
Douglas Anderson <[email protected]>
kgdb: Make "kgdbcon" work properly with "kgdb_earlycon"
Masami Hiramatsu <[email protected]>
ia64: kprobes: Use generic kretprobe trampoline handler
John Ogness <[email protected]>
printk: reduce LOG_BUF_SHIFT range for H8300
Valentin Schneider <[email protected]>
arm64: topology: Stop using MPIDR for topology information
Antonio Borneo <[email protected]>
drm/bridge/synopsys: dsi: add support for non-continuous HS clock
Madhuparna Bhowmik <[email protected]>
mmc: via-sdmmc: Fix data race bug
Hans Verkuil <[email protected]>
media: imx274: fix frame interval handling
Tom Rix <[email protected]>
media: tw5864: check status of tw5864_frameinterval_get
Badhri Jagan Sridharan <[email protected]>
usb: typec: tcpm: During PR_SWAP, source caps should be sent only after tSwapSourceStart
Xia Jiang <[email protected]>
media: platform: Improve queue set up flow for bug fixing
Hans Verkuil <[email protected]>
media: videodev2.h: RGB BT2020 and HSV are always full range
Andy Lutomirski <[email protected]>
selftests/x86/fsgsbase: Reap a forgotten child
Nadezda Lutovinova <[email protected]>
drm/brige/megachips: Add checking if ge_b850v3_lvds_init() is working correctly
Sathishkumar Muruganandam <[email protected]>
ath10k: fix VHT NSS calculation when STBC is enabled
Wen Gong <[email protected]>
ath10k: start recovery process when payload length exceeds max htc length for sdio
Tom Rix <[email protected]>
video: fbdev: pvr2fb: initialize variables
Darrick J. Wong <[email protected]>
xfs: fix realtime bitmap/summary file truncation when growing rt volume
Krzysztof Kozlowski <[email protected]>
power: supply: bq27xxx: report "not charging" on all types
Dave Wysochanski <[email protected]>
NFS4: Fix oops when copy_file_range is attempted with NFS4.0 source
Douglas Anderson <[email protected]>
ARM: 8997/2: hw_breakpoint: Handle inexact watchpoint addresses
Jaegeuk Kim <[email protected]>
f2fs: handle errors of f2fs_get_meta_page_nofail
Johannes Berg <[email protected]>
um: change sigio_spinlock to a mutex
Vasily Gorbik <[email protected]>
s390/startup: avoid save_area_sync overflow
Chao Yu <[email protected]>
f2fs: fix to check segment boundary during SIT page readahead
Chao Yu <[email protected]>
f2fs: fix uninit-value in f2fs_lookup
Zhang Qilong <[email protected]>
f2fs: add trace exit in exception path
Nicholas Piggin <[email protected]>
sparc64: remove mm_cpumask clearing to fix kthread_use_mm race
Nicholas Piggin <[email protected]>
powerpc: select ARCH_WANT_IRQS_OFF_ACTIVATE_MM
Nicholas Piggin <[email protected]>
mm: fix exec activate_mm vs TLB shootdown and lazy tlb switching race
Oliver O'Halloran <[email protected]>
powerpc/powernv/smp: Fix spurious DBG() warning
Mateusz Nosek <[email protected]>
futex: Fix incorrect should_fail_futex() handling
Sascha Hauer <[email protected]>
ata: sata_nv: Fix retrieving of active qcs
Alok Prasad <[email protected]>
RDMA/qedr: Fix memory leak in iWARP CM
Amit Cohen <[email protected]>
mlxsw: core: Fix use-after-free in mlxsw_emad_trans_finish()
Jiri Slaby <[email protected]>
x86/unwind/orc: Fix inactive tasks with stack pointer in %sp on GCC 10 compiled kernels
Sudeep Holla <[email protected]>
firmware: arm_scmi: Add missing Rx size re-initialisation
Etienne Carriere <[email protected]>
firmware: arm_scmi: Fix ARCH_COLD_RESET
Juergen Gross <[email protected]>
xen/events: block rogue events for some time
Juergen Gross <[email protected]>
xen/events: defer eoi in case of excessive number of events
Juergen Gross <[email protected]>
xen/events: use a common cpu hotplug hook for event channels
Juergen Gross <[email protected]>
xen/events: switch user event channels to lateeoi model
Juergen Gross <[email protected]>
xen/pciback: use lateeoi irq binding
Juergen Gross <[email protected]>
xen/pvcallsback: use lateeoi irq binding
Juergen Gross <[email protected]>
xen/scsiback: use lateeoi irq binding
Juergen Gross <[email protected]>
xen/netback: use lateeoi irq binding
Juergen Gross <[email protected]>
xen/blkback: use lateeoi irq binding
Juergen Gross <[email protected]>
xen/events: add a new "late EOI" evtchn framework
Juergen Gross <[email protected]>
xen/events: fix race in evtchn_fifo_unmask()
Juergen Gross <[email protected]>
xen/events: add a proper barrier to 2-level uevent unmasking
Juergen Gross <[email protected]>
xen/events: avoid removing an event channel while handling it
-------------
Diffstat:
Documentation/admin-guide/kernel-parameters.txt | 8 + Documentation/media/uapi/v4l/colorspaces-defs.rst | 9 +- .../media/uapi/v4l/colorspaces-details.rst | 5 +- Makefile | 4 +- arch/Kconfig | 7 + arch/arc/boot/dts/axc001.dtsi | 2 +- arch/arc/boot/dts/axc003.dtsi | 2 +- arch/arc/boot/dts/axc003_idu.dtsi | 2 +- arch/arc/boot/dts/vdk_axc003.dtsi | 2 +- arch/arc/boot/dts/vdk_axc003_idu.dtsi | 2 +- arch/arc/kernel/perf_event.c | 27 +- arch/arm/Kconfig | 2 + arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts | 1 + arch/arm/boot/dts/omap4.dtsi | 2 +- arch/arm/boot/dts/omap443x.dtsi | 10 + arch/arm/boot/dts/s5pv210.dtsi | 163 ++++---- arch/arm/kernel/hw_breakpoint.c | 100 +++-- arch/arm/plat-samsung/Kconfig | 1 + arch/arm64/Kconfig.platforms | 1 + arch/arm64/boot/dts/renesas/ulcb.dtsi | 1 + arch/arm64/include/asm/kvm_host.h | 1 + arch/arm64/include/asm/numa.h | 3 + arch/arm64/kernel/topology.c | 32 +- arch/arm64/kvm/sys_regs.c | 6 +- arch/arm64/mm/numa.c | 6 +- arch/ia64/kernel/Makefile | 2 +- arch/ia64/kernel/kprobes.c | 77 +--- arch/mips/dec/setup.c | 9 +- arch/powerpc/Kconfig | 14 + arch/powerpc/include/asm/drmem.h | 4 +- arch/powerpc/include/asm/mmu_context.h | 2 +- arch/powerpc/kernel/head_32.S | 2 +- arch/powerpc/kernel/rtas.c | 153 ++++++++ arch/powerpc/kernel/sysfs.c | 42 +- arch/powerpc/kernel/traps.c | 2 +- arch/powerpc/kvm/book3s_hv.c | 6 + arch/powerpc/platforms/powermac/sleep.S | 9 +- arch/powerpc/platforms/powernv/opal-elog.c | 33 +- arch/powerpc/platforms/powernv/smp.c | 2 +- arch/powerpc/platforms/pseries/hotplug-memory.c | 43 ++- arch/riscv/include/uapi/asm/auxvec.h | 3 + arch/s390/boot/head.S | 21 +- arch/s390/kernel/time.c | 118 ++++-- arch/sparc/kernel/smp_64.c | 65 +--- arch/um/kernel/sigio.c | 6 +- arch/x86/events/amd/ibs.c | 38 +- arch/x86/events/intel/core.c | 2 +- arch/x86/include/asm/msr-index.h | 1 + arch/x86/kernel/unwind_orc.c | 9 +- drivers/acpi/acpi_dbg.c | 3 + drivers/acpi/acpi_extlog.c | 6 +- drivers/acpi/button.c | 13 +- drivers/acpi/ec.c | 10 +- drivers/acpi/hmat/hmat.c | 3 +- drivers/acpi/numa.c | 2 +- drivers/acpi/video_detect.c | 9 + drivers/ata/sata_nv.c | 2 +- drivers/base/core.c | 4 +- drivers/base/power/runtime.c | 5 +- drivers/block/nbd.c | 2 +- drivers/block/xen-blkback/blkback.c | 22 +- drivers/block/xen-blkback/xenbus.c | 5 +- drivers/bus/fsl-mc/mc-io.c | 7 +- drivers/clk/ti/clockdomain.c | 2 + drivers/cpufreq/acpi-cpufreq.c | 3 +- drivers/cpufreq/sti-cpufreq.c | 6 +- drivers/dma/dma-jz4780.c | 7 +- drivers/extcon/extcon-ptn5150.c | 8 +- drivers/firmware/arm_scmi/base.c | 2 + drivers/firmware/arm_scmi/clock.c | 2 + drivers/firmware/arm_scmi/common.h | 2 + drivers/firmware/arm_scmi/driver.c | 8 + drivers/firmware/arm_scmi/perf.c | 2 + drivers/firmware/arm_scmi/reset.c | 4 +- drivers/firmware/arm_scmi/sensors.c | 2 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 10 + drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 4 +- .../drm/amd/amdkfd/kfd_device_queue_manager_v10.c | 5 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 + drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- .../amd/display/dc/dcn10/dcn10_stream_encoder.c | 4 +- drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c | 4 +- drivers/gpu/drm/amd/display/dc/os_types.h | 2 +- drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 2 +- .../drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 12 +- drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 9 +- drivers/gpu/drm/i915/i915_drv.h | 6 +- drivers/gpu/drm/ttm/ttm_bo.c | 2 +- drivers/hid/wacom_wac.c | 4 +- drivers/hwtracing/coresight/coresight-priv.h | 3 +- drivers/hwtracing/coresight/coresight.c | 62 ++- drivers/i2c/busses/i2c-imx.c | 24 +- drivers/iio/adc/rcar-gyroadc.c | 21 +- drivers/iio/adc/ti-adc0832.c | 11 +- drivers/iio/adc/ti-adc12138.c | 13 +- drivers/iio/gyro/itg3200_buffer.c | 15 +- drivers/iio/light/si1145.c | 19 +- drivers/infiniband/hw/qedr/qedr_iw_cm.c | 1 + drivers/input/serio/hil_mlc.c | 21 +- drivers/input/serio/hp_sdc_mlc.c | 8 +- drivers/leds/leds-bcm6328.c | 2 +- drivers/leds/leds-bcm6358.c | 2 +- drivers/md/md-bitmap.c | 2 +- drivers/md/raid5.c | 4 +- drivers/media/i2c/imx274.c | 8 +- drivers/media/pci/tw5864/tw5864-video.c | 6 + drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c | 7 + drivers/media/usb/uvc/uvc_ctrl.c | 27 +- drivers/memory/emif.c | 33 +- drivers/message/fusion/mptscsih.c | 13 +- drivers/mmc/host/sdhci-acpi.c | 37 ++ drivers/mmc/host/sdhci-of-esdhc.c | 11 + drivers/mmc/host/sdhci-pci-core.c | 154 ++++++++ drivers/mmc/host/sdhci.c | 6 +- drivers/mmc/host/via-sdmmc.c | 3 + drivers/mtd/ubi/wl.c | 13 + drivers/net/can/flexcan.c | 30 +- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 6 +- drivers/net/ethernet/mellanox/mlxsw/core.c | 3 + drivers/net/wan/hdlc_fr.c | 98 ++--- drivers/net/wireless/ath/ath10k/htt_rx.c | 8 +- drivers/net/wireless/ath/ath10k/sdio.c | 4 + .../wireless/broadcom/brcm80211/brcmfmac/fweh.c | 10 +- drivers/net/xen-netback/common.h | 15 + drivers/net/xen-netback/interface.c | 61 ++- drivers/net/xen-netback/netback.c | 11 +- drivers/net/xen-netback/rx.c | 13 +- drivers/nvme/host/rdma.c | 1 - drivers/pci/pci-acpi.c | 10 + drivers/power/supply/bq27xxx_battery.c | 6 +- drivers/power/supply/test_power.c | 6 + drivers/rpmsg/qcom_glink_native.c | 6 +- drivers/rtc/rtc-rx8010.c | 24 +- drivers/scsi/qla2xxx/qla_target.c | 13 +- drivers/spi/spi-sprd.c | 2 +- drivers/staging/comedi/drivers/cb_pcidas.c | 1 + drivers/staging/fieldbus/anybuss/arcx-anybus.c | 2 +- drivers/staging/octeon/ethernet-mdio.c | 6 - drivers/staging/octeon/ethernet-rx.c | 34 +- drivers/staging/octeon/ethernet.c | 9 + drivers/tty/vt/keyboard.c | 39 +- drivers/tty/vt/vt_ioctl.c | 32 +- drivers/uio/uio.c | 4 +- drivers/usb/class/cdc-acm.c | 12 +- drivers/usb/class/cdc-acm.h | 3 +- drivers/usb/dwc3/core.c | 15 +- drivers/usb/dwc3/core.h | 1 + drivers/usb/dwc3/dwc3-pci.c | 3 +- drivers/usb/dwc3/ep0.c | 27 +- drivers/usb/dwc3/gadget.c | 60 ++- drivers/usb/dwc3/gadget.h | 1 + drivers/usb/host/fsl-mph-dr-of.c | 9 +- drivers/usb/host/xhci-pci.c | 17 + drivers/usb/host/xhci.c | 7 +- drivers/usb/host/xhci.h | 1 + drivers/usb/misc/adutux.c | 1 + drivers/usb/typec/tcpm/tcpm.c | 8 +- drivers/vhost/vringh.c | 9 +- drivers/video/fbdev/pvr2fb.c | 2 + drivers/w1/masters/mxc_w1.c | 14 +- drivers/watchdog/rdc321x_wdt.c | 5 +- drivers/xen/events/events_2l.c | 9 +- drivers/xen/events/events_base.c | 422 +++++++++++++++++++-- drivers/xen/events/events_fifo.c | 83 ++-- drivers/xen/events/events_internal.h | 20 +- drivers/xen/evtchn.c | 7 +- drivers/xen/pvcalls-back.c | 76 ++-- drivers/xen/xen-pciback/pci_stub.c | 14 +- drivers/xen/xen-pciback/pciback.h | 12 +- drivers/xen/xen-pciback/pciback_ops.c | 48 ++- drivers/xen/xen-pciback/xenbus.c | 2 +- drivers/xen/xen-scsiback.c | 23 +- fs/9p/vfs_file.c | 4 +- fs/btrfs/ctree.c | 6 + fs/btrfs/ctree.h | 2 + fs/btrfs/delayed-inode.c | 3 +- fs/btrfs/dev-replace.c | 7 +- fs/btrfs/reada.c | 47 +++ fs/btrfs/send.c | 201 ++++++++-- fs/btrfs/tree-checker.c | 35 +- fs/btrfs/tree-log.c | 8 + fs/btrfs/volumes.c | 17 +- fs/btrfs/volumes.h | 1 + fs/buffer.c | 16 - fs/cachefiles/rdwr.c | 3 +- fs/ceph/addr.c | 2 +- fs/cifs/inode.c | 13 +- fs/exec.c | 17 +- fs/ext4/inode.c | 11 +- fs/ext4/resize.c | 4 +- fs/ext4/super.c | 17 + fs/f2fs/checkpoint.c | 10 +- fs/f2fs/dir.c | 8 +- fs/f2fs/f2fs.h | 2 +- fs/f2fs/node.c | 2 +- fs/f2fs/segment.c | 12 +- fs/gfs2/incore.h | 1 + fs/gfs2/ops_fstype.c | 40 +- fs/gfs2/super.c | 1 + fs/gfs2/sys.c | 5 +- fs/nfs/namespace.c | 12 +- fs/nfs/nfs4_fs.h | 8 + fs/nfs/nfs4file.c | 3 +- fs/nfs/nfs4proc.c | 90 +++-- fs/nfs/nfs4trace.h | 1 + fs/nfsd/nfsproc.c | 16 + fs/ubifs/debug.c | 1 + fs/ubifs/journal.c | 6 +- fs/ubifs/orphan.c | 2 + fs/ubifs/super.c | 44 ++- fs/ubifs/tnc.c | 3 + fs/ubifs/xattr.c | 2 + fs/udf/super.c | 21 +- fs/xfs/libxfs/xfs_bmap.c | 19 +- fs/xfs/xfs_rtalloc.c | 10 +- include/asm-generic/io.h | 39 +- include/linux/arm-smccc.h | 2 + include/linux/hil_mlc.h | 2 +- include/linux/usb/pd.h | 1 + include/uapi/linux/btrfs_tree.h | 14 + include/uapi/linux/nfs4.h | 3 + include/uapi/linux/videodev2.h | 17 +- include/xen/events.h | 29 +- init/Kconfig | 3 +- kernel/bpf/verifier.c | 4 + kernel/debug/debug_core.c | 22 +- kernel/futex.c | 4 +- kernel/seccomp.c | 38 +- kernel/trace/ring_buffer.c | 8 +- lib/scatterlist.c | 2 +- net/9p/trans_fd.c | 2 +- net/ceph/messenger.c | 5 + net/sunrpc/xprt.c | 6 +- samples/bpf/xdpsock_user.c | 1 + tools/perf/util/print_binary.c | 2 +- .../testing/selftests/bpf/progs/test_sysctl_prog.c | 4 +- tools/testing/selftests/x86/fsgsbase.c | 68 ++++ virt/kvm/arm/psci.c | 2 +- 239 files changed, 2954 insertions(+), 1226 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/214 xen/events: avoid removing an event channel while handling it
From: Juergen Gross <[email protected]>
commit 073d0552ead5bfc7a3a9c01de590e924f11b5dd2 upstream.
Today it can happen that an event channel is being removed from the system while the event handling loop is active. This can lead to a race resulting in crashes or WARN() splats when trying to access the irq_info structure related to the event channel.
Fix this problem by using a rwlock taken as reader in the event handling loop and as writer when deallocating the irq_info structure.
As the observed problem was a NULL dereference in evtchn_from_irq() make this function more robust against races by testing the irq_info pointer to be not NULL before dereferencing it.
And finally make all accesses to evtchn_to_irq[row][col] atomic ones in order to avoid seeing partial updates of an array element in irq handling. Note that irq handling can be entered only for event channels which have been valid before, so any not populated row isn't a problem in this regard, as rows are only ever added and never removed.
This is XSA-331.
--- drivers/xen/events/events_base.c | 40 ++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-)
drivers/xen/events/events_base.c +35 -5
@@ -33,6 +33,7 @@#include <linux/slab.h> #include <linux/irqnr.h> #include <linux/pci.h> +#include <linux/spinlock.h> #ifdef CONFIG_X86 #include <asm/desc.h>
@@ -70,6 +71,23 @@ const struct evtchn_ops *evtchn_ops;*/ static DEFINE_MUTEX (irq_mapping_update_lock); +/* +* Lock protecting event handling loop against removing event channels. +* Adding of event channels is no issue as the associated IRQ becomes active +* only after everything is setup (before request_[threaded_]irq() the handler +* can't be entered for an event, as the event channel will be unmasked only +* then). +*/ +static DEFINE_RWLOCK (evtchn_rwlock); + +/* +* Lock hierarchy: +* +* irq_mapping_update_lock +* evtchn_rwlock +* IRQ-desc lock +*/ +static LIST_HEAD (xen_irq_list_head);/* IRQ <-> VIRQ mapping. */
@@ -104,7 +122,7 @@ static void clear_evtchn_to_irq_row(unsiunsigned col;for (col =0 ; col <EVTCHN_PER_ROW ; col++) - evtchn_to_irq[row][col] =-1 ; +WRITE_ONCE (evtchn_to_irq[row][col],-1 ); }static void clear_evtchn_to_irq_all (void )
@@ -141,7 +159,7 @@ static int set_evtchn_to_irq(unsigned evclear_evtchn_to_irq_row (row); } - evtchn_to_irq[row][col] = irq; +WRITE_ONCE (evtchn_to_irq[row][col], irq);return 0 ; }
@@ -151,7 +169,7 @@ int get_evtchn_to_irq(unsigned evtchn)return -1 ;if (evtchn_to_irq[EVTCHN_ROW (evtchn)] ==NULL )return -1 ; -return evtchn_to_irq[EVTCHN_ROW (evtchn)][EVTCHN_COL (evtchn)]; +return READ_ONCE (evtchn_to_irq[EVTCHN_ROW (evtchn)][EVTCHN_COL (evtchn)]); }/* Get info for IRQ */
@@ -260,10 +278,14 @@ static void xen_irq_info_cleanup(struct*/ unsigned int evtchn_from_irq (unsigned irq) { -if (WARN (irq >= nr_irqs,"Invalid irq %d!\n" , irq)) +const struct irq_info *info =NULL ; + +if (likely (irq < nr_irqs)) + info =info_for_irq (irq); +if (!info)return 0 ; -return info_for_irq (irq)->evtchn; +return info->evtchn; }unsigned irq_from_evtchn (unsigned int evtchn)
@@ -439,16 +461,21 @@ static int __must_check xen_allocate_irqstatic void xen_free_irq (unsigned irq) {struct irq_info *info =info_for_irq (irq); +unsigned long flags;if (WARN_ON (!info))return ; +write_lock_irqsave (&evtchn_rwlock, flags); +list_del (&info->list);set_info_for_irq (irq,NULL );WARN_ON (info->refcnt >0 ); +write_unlock_irqrestore (&evtchn_rwlock, flags); +kfree (info);/* Legacy IRQ descriptors are managed by the arch. */
@@ -1234,6 +1261,8 @@ static void __xen_evtchn_do_upcall(void)int cpu =get_cpu ();unsigned count; +read_lock (&evtchn_rwlock); + do { vcpu_info->evtchn_upcall_pending = 0;
@@ -1249,6 +1278,7 @@ static void __xen_evtchn_do_upcall(void) }while (count !=1 || vcpu_info->evtchn_upcall_pending); out: +read_unlock (&evtchn_rwlock);put_cpu (); }
Greg Kroah-Hartman
maintainerPATCH 2/214 xen/events: add a proper barrier to 2-level uevent unmasking
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit 4d3fe31bd993ef504350989786858aefdb877daa upstream.
A follow-up patch will require certain write to happen before an event channel is unmasked.
While the memory barrier is not strictly necessary for all the callers, the main one will need it. In order to avoid an extra memory barrier when using fifo event channels, mandate evtchn_unmask() to provide write ordering.
The 2-level event handling unmask operation is missing an appropriate barrier, so add it. Fifo event channels are fine in this regard due to using sync_cmpxchg().
This is part of XSA-332.
--- drivers/xen/events/events_2l.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/xen/events/events_2l.c +2 -0
@@ -91,6 +91,8 @@ static void evtchn_2l_unmask(unsigned poBUG_ON (!irqs_disabled ()); +smp_wmb ();/* All writes before unmask must be visible. */ +if (unlikely ((cpu !=cpu_from_evtchn (port)))) do_hypercall =1 ;else {
Greg Kroah-Hartman
maintainerPATCH 3/214 xen/events: fix race in evtchn_fifo_unmask()
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit f01337197419b7e8a492e83089552b77d3b5fb90 upstream.
Unmasking a fifo event channel can result in unmasking it twice, once directly in the kernel and once via a hypercall in case the event was pending.
Fix that by doing the local unmask only if the event is not pending.
This is part of XSA-332.
--- drivers/xen/events/events_fifo.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/xen/events/events_fifo.c +9 -4
@@ -227,19 +227,25 @@ static bool evtchn_fifo_is_masked(unsignreturn sync_test_bit (EVTCHN_FIFO_BIT (MASKED , word),BM (word)); }/* -* Clear MASKED, spinning if BUSY is set. +* Clear MASKED if not PENDING, spinning if BUSY is set. +* Return true if mask was cleared. */ -static void clear_masked (volatile event_word_t *word) +static bool clear_masked_cond (volatile event_word_t *word) {event_word_t new, old, w; w = *word;do { +if (w & (1 <<EVTCHN_FIFO_PENDING )) +return false; + old = w & ~(1 <<EVTCHN_FIFO_BUSY ); new = old & ~(1 <<EVTCHN_FIFO_MASKED ); w =sync_cmpxchg (word, old, new); }while (w != old); + +return true; }static void evtchn_fifo_unmask (unsigned port)
@@ -248,8 +254,7 @@ static void evtchn_fifo_unmask(unsignedBUG_ON (!irqs_disabled ()); -clear_masked (word); -if (evtchn_fifo_is_pending (port)) { +if (!clear_masked_cond (word)) {struct evtchn_unmask unmask = { .port = port }; (void )HYPERVISOR_event_channel_op (EVTCHNOP_unmask, &unmask); }
Greg Kroah-Hartman
maintainerPATCH 4/214 xen/events: add a new "late EOI" evtchn framework
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit 54c9de89895e0a36047fcc4ae754ea5b8655fb9d upstream.
In order to avoid tight event channel related IRQ loops add a new framework of "late EOI" handling: the IRQ the event channel is bound to will be masked until the event has been handled and the related driver is capable to handle another event. The driver is responsible for unmasking the event channel via the new function xen_irq_lateeoi().
This is similar to binding an event channel to a threaded IRQ, but without having to structure the driver accordingly.
In order to support a future special handling in case a rogue guest is sending lots of unsolicited events, add a flag to xen_irq_lateeoi() which can be set by the caller to indicate the event was a spurious one.
This is part of XSA-332.
--- drivers/xen/events/events_base.c | 151 ++++++++++++++++++++++++++++++++++----- include/xen/events.h | 29 ++++++- 2 files changed, 159 insertions(+), 21 deletions(-)
drivers/xen/events/events_base.c +134 -17
@@ -112,6 +112,7 @@ static bool (*pirq_needs_eoi)(unsigned istatic struct irq_info *legacy_info_ptrs[NR_IRQS_LEGACY ];static struct irq_chip xen_dynamic_chip; +static struct irq_chip xen_lateeoi_chip;static struct irq_chip xen_percpu_chip;static struct irq_chip xen_pirq_chip;static void enable_dynirq (struct irq_data *data);
@@ -396,6 +397,33 @@ void notify_remote_via_irq(int irq) }EXPORT_SYMBOL_GPL (notify_remote_via_irq); +static void xen_irq_lateeoi_locked (struct irq_info *info) +{ +evtchn_port_t evtchn; + + evtchn = info->evtchn; +if (!VALID_EVTCHN (evtchn)) +return ; + +unmask_evtchn (evtchn); +} + +void xen_irq_lateeoi (unsigned int irq,unsigned int eoi_flags) +{ +struct irq_info *info; +unsigned long flags; + +read_lock_irqsave (&evtchn_rwlock, flags); + + info =info_for_irq (irq); + +if (info) +xen_irq_lateeoi_locked (info); + +read_unlock_irqrestore (&evtchn_rwlock, flags); +} +EXPORT_SYMBOL_GPL (xen_irq_lateeoi); +static void xen_irq_init (unsigned irq) {struct irq_info *info;
@@ -867,7 +895,7 @@ int xen_pirq_from_irq(unsigned irq) }EXPORT_SYMBOL_GPL (xen_pirq_from_irq); -int bind_evtchn_to_irq (unsigned int evtchn) +static int bind_evtchn_to_irq_chip (evtchn_port_t evtchn,struct irq_chip *chip) {int irq;int ret;
@@ -884,7 +912,7 @@ int bind_evtchn_to_irq(unsigned int evtcif (irq <0 ) goto out; -irq_set_chip_and_handler_name (irq, &xen_dynamic_chip, +irq_set_chip_and_handler_name (irq, chip, handle_edge_irq,"event" ); ret =xen_irq_info_evtchn_setup (irq, evtchn);
@@ -905,8 +933,19 @@ out:return irq; } + +int bind_evtchn_to_irq (evtchn_port_t evtchn) +{ +return bind_evtchn_to_irq_chip (evtchn, &xen_dynamic_chip); +}EXPORT_SYMBOL_GPL (bind_evtchn_to_irq); +int bind_evtchn_to_irq_lateeoi (evtchn_port_t evtchn) +{ +return bind_evtchn_to_irq_chip (evtchn, &xen_lateeoi_chip); +} +EXPORT_SYMBOL_GPL (bind_evtchn_to_irq_lateeoi); +static int bind_ipi_to_irq (unsigned int ipi,unsigned int cpu) {struct evtchn_bind_ipi bind_ipi;
@@ -948,8 +987,9 @@ static int bind_ipi_to_irq(unsigned intreturn irq; } -int bind_interdomain_evtchn_to_irq (unsigned int remote_domain, -unsigned int remote_port) +static int bind_interdomain_evtchn_to_irq_chip (unsigned int remote_domain, +evtchn_port_t remote_port, +struct irq_chip *chip) {struct evtchn_bind_interdomain bind_interdomain;int err;
@@ -960,10 +1000,26 @@ int bind_interdomain_evtchn_to_irq(unsig err =HYPERVISOR_event_channel_op (EVTCHNOP_bind_interdomain, &bind_interdomain); -return err ? :bind_evtchn_to_irq (bind_interdomain.local_port); +return err ? :bind_evtchn_to_irq_chip (bind_interdomain.local_port, + chip); +} + +int bind_interdomain_evtchn_to_irq (unsigned int remote_domain, +evtchn_port_t remote_port) +{ +return bind_interdomain_evtchn_to_irq_chip (remote_domain, remote_port, + &xen_dynamic_chip); }EXPORT_SYMBOL_GPL (bind_interdomain_evtchn_to_irq); +int bind_interdomain_evtchn_to_irq_lateeoi (unsigned int remote_domain, +evtchn_port_t remote_port) +{ +return bind_interdomain_evtchn_to_irq_chip (remote_domain, remote_port, + &xen_lateeoi_chip); +} +EXPORT_SYMBOL_GPL (bind_interdomain_evtchn_to_irq_lateeoi); +static int find_virq (unsigned int virq,unsigned int cpu) {struct evtchn_status status;
@@ -1059,14 +1115,15 @@ static void unbind_from_irq(unsigned intmutex_unlock (&irq_mapping_update_lock); } -int bind_evtchn_to_irqhandler (unsigned int evtchn, -irq_handler_t handler, -unsigned long irqflags, -const char *devname,void *dev_id) +static int bind_evtchn_to_irqhandler_chip (evtchn_port_t evtchn, +irq_handler_t handler, +unsigned long irqflags, +const char *devname,void *dev_id, +struct irq_chip *chip) {int irq, retval; - irq =bind_evtchn_to_irq (evtchn); + irq =bind_evtchn_to_irq_chip (evtchn, chip);if (irq <0 )return irq; retval =request_irq (irq, handler, irqflags, devname, dev_id);
@@ -1077,18 +1134,38 @@ int bind_evtchn_to_irqhandler(unsigned ireturn irq; } + +int bind_evtchn_to_irqhandler (evtchn_port_t evtchn, +irq_handler_t handler, +unsigned long irqflags, +const char *devname,void *dev_id) +{ +return bind_evtchn_to_irqhandler_chip (evtchn, handler, irqflags, + devname, dev_id, + &xen_dynamic_chip); +}EXPORT_SYMBOL_GPL (bind_evtchn_to_irqhandler); -int bind_interdomain_evtchn_to_irqhandler (unsigned int remote_domain, -unsigned int remote_port, -irq_handler_t handler, -unsigned long irqflags, -const char *devname, -void *dev_id) +int bind_evtchn_to_irqhandler_lateeoi (evtchn_port_t evtchn, +irq_handler_t handler, +unsigned long irqflags, +const char *devname,void *dev_id) +{ +return bind_evtchn_to_irqhandler_chip (evtchn, handler, irqflags, + devname, dev_id, + &xen_lateeoi_chip); +} +EXPORT_SYMBOL_GPL (bind_evtchn_to_irqhandler_lateeoi); + +static int bind_interdomain_evtchn_to_irqhandler_chip ( +unsigned int remote_domain,evtchn_port_t remote_port, +irq_handler_t handler,unsigned long irqflags, +const char *devname,void *dev_id,struct irq_chip *chip) {int irq, retval; - irq =bind_interdomain_evtchn_to_irq (remote_domain, remote_port); + irq =bind_interdomain_evtchn_to_irq_chip (remote_domain, remote_port, + chip);if (irq <0 )return irq;
@@ -1100,8 +1177,33 @@ int bind_interdomain_evtchn_to_irqhandlereturn irq; } + +int bind_interdomain_evtchn_to_irqhandler (unsigned int remote_domain, +evtchn_port_t remote_port, +irq_handler_t handler, +unsigned long irqflags, +const char *devname, +void *dev_id) +{ +return bind_interdomain_evtchn_to_irqhandler_chip (remote_domain, + remote_port, handler, irqflags, devname, + dev_id, &xen_dynamic_chip); +}EXPORT_SYMBOL_GPL (bind_interdomain_evtchn_to_irqhandler); +int bind_interdomain_evtchn_to_irqhandler_lateeoi (unsigned int remote_domain, +evtchn_port_t remote_port, +irq_handler_t handler, +unsigned long irqflags, +const char *devname, +void *dev_id) +{ +return bind_interdomain_evtchn_to_irqhandler_chip (remote_domain, + remote_port, handler, irqflags, devname, + dev_id, &xen_lateeoi_chip); +} +EXPORT_SYMBOL_GPL (bind_interdomain_evtchn_to_irqhandler_lateeoi); +int bind_virq_to_irqhandler (unsigned int virq,unsigned int cpu,irq_handler_t handler,unsigned long irqflags,const char *devname,void *dev_id)
@@ -1642,6 +1744,21 @@ static struct irq_chip xen_dynamic_chip .irq_mask_ack = mask_ack_dynirq, .irq_set_affinity = set_affinity_irq, + .irq_retrigger = retrigger_dynirq, +}; + +static struct irq_chip xen_lateeoi_chip__read_mostly = { +/* The chip name needs to contain "xen-dyn" for irqbalance to work. */ + .name ="xen-dyn-lateeoi" , + + .irq_disable = disable_dynirq, + .irq_mask = disable_dynirq, + .irq_unmask = enable_dynirq, + + .irq_ack = mask_ack_dynirq, + .irq_mask_ack = mask_ack_dynirq, + + .irq_set_affinity = set_affinity_irq, .irq_retrigger = retrigger_dynirq, };
include/xen/events.h +25 -4
@@ -14,11 +14,16 @@unsigned xen_evtchn_nr_channels (void ); -int bind_evtchn_to_irq (unsigned int evtchn); -int bind_evtchn_to_irqhandler (unsigned int evtchn, +int bind_evtchn_to_irq (evtchn_port_t evtchn); +int bind_evtchn_to_irq_lateeoi (evtchn_port_t evtchn); +int bind_evtchn_to_irqhandler (evtchn_port_t evtchn,irq_handler_t handler,unsigned long irqflags,const char *devname,void *dev_id); +int bind_evtchn_to_irqhandler_lateeoi (evtchn_port_t evtchn, +irq_handler_t handler, +unsigned long irqflags,const char *devname, +void *dev_id);int bind_virq_to_irq (unsigned int virq,unsigned int cpu,bool percpu); int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu, irq_handler_t handler,
@@ -31,13 +36,21 @@ int bind_ipi_to_irqhandler(enum ipi_vectconst char *devname, void *dev_id);int bind_interdomain_evtchn_to_irq (unsigned int remote_domain, -unsigned int remote_port); +evtchn_port_t remote_port); +int bind_interdomain_evtchn_to_irq_lateeoi (unsigned int remote_domain, +evtchn_port_t remote_port);int bind_interdomain_evtchn_to_irqhandler (unsigned int remote_domain, -unsigned int remote_port, +evtchn_port_t remote_port,irq_handler_t handler,unsigned long irqflags,const char *devname,void *dev_id); +int bind_interdomain_evtchn_to_irqhandler_lateeoi (unsigned int remote_domain, +evtchn_port_t remote_port, +irq_handler_t handler, +unsigned long irqflags, +const char *devname, +void *dev_id);/* * Common unbind function for all event sources. Takes IRQ to unbind from.
@@ -46,6 +59,14 @@ int bind_interdomain_evtchn_to_irqhandle*/ void unbind_from_irqhandler (unsigned int irq,void *dev_id); +/* +* Send late EOI for an IRQ bound to an event channel via one of the *_lateeoi +* functions above. +*/ +void xen_irq_lateeoi (unsigned int irq,unsigned int eoi_flags); +/* Signal an event was spurious, i.e. there was no action resulting from it. */ +#define XEN_EOI_FLAG_SPURIOUS 0x00000001 +#define XEN_IRQ_PRIORITY_MAX EVTCHN_FIFO_PRIORITY_MAX#define XEN_IRQ_PRIORITY_DEFAULT EVTCHN_FIFO_PRIORITY_DEFAULT#define XEN_IRQ_PRIORITY_MIN EVTCHN_FIFO_PRIORITY_MIN
Greg Kroah-Hartman
maintainerPATCH 5/214 xen/blkback: use lateeoi irq binding
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit 01263a1fabe30b4d542f34c7e2364a22587ddaf2 upstream.
In order to reduce the chance for the system becoming unresponsive due to event storms triggered by a misbehaving blkfront use the lateeoi irq binding for blkback and unmask the event channel only after processing all pending requests.
As the thread processing requests is used to do purging work in regular intervals an EOI may be sent only after having received an event. If there was no pending I/O request flag the EOI as spurious.
This is part of XSA-332.
--- drivers/block/xen-blkback/blkback.c | 22 +++++++++++++++++----- drivers/block/xen-blkback/xenbus.c | 5 ++--- 2 files changed, 19 insertions(+), 8 deletions(-)
drivers/block/xen-blkback/blkback.c +17 -5
@@ -202,7 +202,7 @@ static inline void shrink_free_pagepool(#define vaddr (page) ((unsigned long)pfn_to_kaddr(page_to_pfn(page))) -static int do_block_io_op (struct xen_blkif_ring *ring); +static int do_block_io_op (struct xen_blkif_ring *ring,unsigned int *eoi_flags);static int dispatch_rw_block_io (struct xen_blkif_ring *ring,struct blkif_request *req,struct pending_req *pending_req);
@@ -615,6 +615,8 @@ int xen_blkif_schedule(void *arg)struct xen_vbd *vbd = &blkif->vbd;unsigned long timeout;int ret; +bool do_eoi; +unsigned int eoi_flags =XEN_EOI_FLAG_SPURIOUS ;set_freezable ();while (!kthread_should_stop ()) {
@@ -639,16 +641,23 @@ int xen_blkif_schedule(void *arg)if (timeout ==0 ) goto purge_gnt_list; + do_eoi = ring->waiting_reqs; + ring->waiting_reqs =0 ;smp_mb ();/* clear flag *before* checking for work */ - ret =do_block_io_op (ring); + ret =do_block_io_op (ring, &eoi_flags);if (ret >0 ) ring->waiting_reqs =1 ;if (ret == -EACCES )wait_event_interruptible (ring->shutdown_wq,kthread_should_stop ()); +if (do_eoi && !ring->waiting_reqs) { +xen_irq_lateeoi (ring->irq, eoi_flags); + eoi_flags |=XEN_EOI_FLAG_SPURIOUS ; + } + purge_gnt_list:if (blkif->vbd.feature_gnt_persistent &&time_after (jiffies, ring->next_lru)) {
@@ -1121,7 +1130,7 @@ static void end_block_io_op(struct bio ** and transmute it to the block API to hand it over to the proper block disk. */ static int -__do_block_io_op (struct xen_blkif_ring *ring) +__do_block_io_op (struct xen_blkif_ring *ring,unsigned int *eoi_flags) {union blkif_back_rings *blk_rings = &ring->blk_rings;struct blkif_request req;
@@ -1144,6 +1153,9 @@ __do_block_io_op(struct xen_blkif_ring *if (RING_REQUEST_CONS_OVERFLOW (&blk_rings->common, rc))break ; +/* We've seen a request, so clear spurious eoi flag. */ + *eoi_flags &= ~XEN_EOI_FLAG_SPURIOUS ; +if (kthread_should_stop ()) { more_to_do =1 ;break ;
@@ -1202,13 +1214,13 @@ done: }static int -do_block_io_op (struct xen_blkif_ring *ring) +do_block_io_op (struct xen_blkif_ring *ring,unsigned int *eoi_flags) {union blkif_back_rings *blk_rings = &ring->blk_rings;int more_to_do; do { - more_to_do = __do_block_io_op(ring); + more_to_do = __do_block_io_op(ring, eoi_flags); if (more_to_do) break;
drivers/block/xen-blkback/xenbus.c +2 -3
@@ -229,9 +229,8 @@ static int xen_blkif_map(struct xen_blkiBUG (); } - err =bind_interdomain_evtchn_to_irqhandler (blkif->domid, evtchn, - xen_blkif_be_int,0 , -"blkif-backend" , ring); + err =bind_interdomain_evtchn_to_irqhandler_lateeoi (blkif->domid, + evtchn, xen_blkif_be_int,0 ,"blkif-backend" , ring);if (err <0 ) {xenbus_unmap_ring_vfree (blkif->be->dev, ring->blk_ring); ring->blk_rings.common.sring =NULL ;
Greg Kroah-Hartman
maintainerPATCH 6/214 xen/netback: use lateeoi irq binding
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit 23025393dbeb3b8b3b60ebfa724cdae384992e27 upstream.
In order to reduce the chance for the system becoming unresponsive due to event storms triggered by a misbehaving netfront use the lateeoi irq binding for netback and unmask the event channel only just before going to sleep waiting for new events.
Make sure not to issue an EOI when none is pending by introducing an eoi_pending element to struct xenvif_queue.
When no request has been consumed set the spurious flag when sending the EOI for an interrupt.
This is part of XSA-332.
--- drivers/net/xen-netback/common.h | 15 ++++++++ drivers/net/xen-netback/interface.c | 61 ++++++++++++++++++++++++++++++------ drivers/net/xen-netback/netback.c | 11 +++++- drivers/net/xen-netback/rx.c | 13 +++++-- 4 files changed, 86 insertions(+), 14 deletions(-)
drivers/net/xen-netback/common.h +15 -0
@@ -140,6 +140,20 @@ struct xenvif_queue { /* Per-queue datachar name[QUEUE_NAME_SIZE ];/* DEVNAME-qN */ struct xenvif *vif;/* Parent VIF */ +/* +* TX/RX common EOI handling. +* When feature-split-event-channels = 0, interrupt handler sets +* NETBK_COMMON_EOI, otherwise NETBK_RX_EOI and NETBK_TX_EOI are set +* by the RX and TX interrupt handlers. +* RX and TX handler threads will issue an EOI when either +* NETBK_COMMON_EOI or their specific bits (NETBK_RX_EOI or +* NETBK_TX_EOI) are set and they will reset those bits. +*/ +atomic_t eoi_pending; +#define NETBK_RX_EOI 0x01 +#define NETBK_TX_EOI 0x02 +#define NETBK_COMMON_EOI 0x04 +/* Use NAPI for guest TX */ struct napi_struct napi;/* When feature-split-event-channels = 0, tx_irq = rx_irq. */
@@ -375,6 +389,7 @@ int xenvif_dealloc_kthread(void *data);irqreturn_t xenvif_ctrl_irq_fn (int irq,void *data); +bool xenvif_have_rx_work (struct xenvif_queue *queue,bool test_kthread);void xenvif_rx_action (struct xenvif_queue *queue);void xenvif_rx_queue_tail (struct xenvif_queue *queue,struct sk_buff *skb);
drivers/net/xen-netback/interface.c +52 -9
111 lines not on this page · raw message
drivers/net/xen-netback/netback.c +10 -1
@@ -162,6 +162,10 @@ void xenvif_napi_schedule_or_enable_evenif (more_to_do)napi_schedule (&queue->napi); +else if (atomic_fetch_andnot (NETBK_TX_EOI |NETBK_COMMON_EOI , + &queue->eoi_pending) & + (NETBK_TX_EOI |NETBK_COMMON_EOI )) +xen_irq_lateeoi (queue->tx_irq,0 ); }static void tx_add_credit (struct xenvif_queue *queue)
@@ -1622,9 +1626,14 @@ static bool xenvif_ctrl_work_todo(structirqreturn_t xenvif_ctrl_irq_fn (int irq,void *data) {struct xenvif *vif = data; +unsigned int eoi_flag =XEN_EOI_FLAG_SPURIOUS ; -while (xenvif_ctrl_work_todo (vif)) +while (xenvif_ctrl_work_todo (vif)) {xenvif_ctrl_action (vif); + eoi_flag =0 ; + } + +xen_irq_lateeoi (irq, eoi_flag);return IRQ_HANDLED ; }
drivers/net/xen-netback/rx.c +9 -4
@@ -490,13 +490,13 @@ static bool xenvif_rx_queue_ready(structreturn queue->stalled && prod - cons >=1 ; } -static bool xenvif_have_rx_work (struct xenvif_queue *queue) +bool xenvif_have_rx_work (struct xenvif_queue *queue,bool test_kthread) {return xenvif_rx_ring_slots_available (queue) || (queue->vif->stall_timeout && (xenvif_rx_queue_stalled (queue) ||xenvif_rx_queue_ready (queue))) || -kthread_should_stop () || + (test_kthread &&kthread_should_stop ()) || queue->vif->disabled; }
@@ -527,15 +527,20 @@ static void xenvif_wait_for_rx_work(stru {DEFINE_WAIT (wait); -if (xenvif_have_rx_work (queue)) +if (xenvif_have_rx_work (queue, true))return ;for (;;) {long ret;prepare_to_wait (&queue->wq, &wait,TASK_INTERRUPTIBLE ); -if (xenvif_have_rx_work (queue)) +if (xenvif_have_rx_work (queue, true))break ; +if (atomic_fetch_andnot (NETBK_RX_EOI |NETBK_COMMON_EOI , + &queue->eoi_pending) & + (NETBK_RX_EOI |NETBK_COMMON_EOI )) +xen_irq_lateeoi (queue->rx_irq,0 ); + ret =schedule_timeout (xenvif_rx_queue_timeout (queue));if (!ret)break ;
Greg Kroah-Hartman
maintainerPATCH 7/214 xen/scsiback: use lateeoi irq binding
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit 86991b6e7ea6c613b7692f65106076943449b6b7 upstream.
In order to reduce the chance for the system becoming unresponsive due to event storms triggered by a misbehaving scsifront use the lateeoi irq binding for scsiback and unmask the event channel only just before leaving the event handling function.
In case of a ring protocol error don't issue an EOI in order to avoid the possibility to use that for producing an event storm. This at once will result in no further call of scsiback_irq_fn(), so the ring_error struct member can be dropped and scsiback_do_cmd_fn() can signal the protocol error via a negative return value.
This is part of XSA-332.
--- drivers/xen/xen-scsiback.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-)
drivers/xen/xen-scsiback.c +13 -10
@@ -91,7 +91,6 @@ struct vscsibk_info {unsigned int irq;struct vscsiif_back_ring ring; -int ring_error;spinlock_t ring_lock;atomic_t nr_unreplied_reqs;
@@ -722,7 +721,8 @@ static struct vscsibk_pend *prepare_pendreturn pending_req; } -static int scsiback_do_cmd_fn (struct vscsibk_info *info) +static int scsiback_do_cmd_fn (struct vscsibk_info *info, +unsigned int *eoi_flags) {struct vscsiif_back_ring *ring = &info->ring;struct vscsiif_request ring_req;
@@ -739,11 +739,12 @@ static int scsiback_do_cmd_fn(struct vsc rc = ring->rsp_prod_pvt;pr_warn ("Dom%d provided bogus ring requests (%#x - %#x = %u). Halting ring processing\n" , info->domid, rp, rc, rp - rc); - info->ring_error =1 ; -return 0 ; +return -EINVAL ; }while ((rc != rp)) { + *eoi_flags &= ~XEN_EOI_FLAG_SPURIOUS ; +if (RING_REQUEST_CONS_OVERFLOW (ring, rc))break ;
@@ -802,13 +803,16 @@ static int scsiback_do_cmd_fn(struct vscstatic irqreturn_t scsiback_irq_fn (int irq,void *dev_id) {struct vscsibk_info *info = dev_id; +int rc; +unsigned int eoi_flags =XEN_EOI_FLAG_SPURIOUS ; -if (info->ring_error) -return IRQ_HANDLED ; - -while (scsiback_do_cmd_fn (info)) +while ((rc =scsiback_do_cmd_fn (info, &eoi_flags)) >0 )cond_resched (); +/* In case of a ring error we keep the event channel masked. */ +if (!rc) +xen_irq_lateeoi (irq, eoi_flags); +return IRQ_HANDLED ; }
@@ -829,7 +833,7 @@ static int scsiback_init_sring(struct vs sring = (struct vscsiif_sring *)area;BACK_RING_INIT (&info->ring, sring,PAGE_SIZE ); - err =bind_interdomain_evtchn_to_irq (info->domid, evtchn); + err =bind_interdomain_evtchn_to_irq_lateeoi (info->domid, evtchn);if (err <0 ) goto unmap_page;
@@ -1252,7 +1256,6 @@ static int scsiback_probe(struct xenbus_ info->domid = dev->otherend_id;spin_lock_init (&info->ring_lock); - info->ring_error =0 ;atomic_set (&info->nr_unreplied_reqs,0 );init_waitqueue_head (&info->waiting_to_free); info->dev = dev;
Greg Kroah-Hartman
maintainerPATCH 8/214 xen/pvcallsback: use lateeoi irq binding
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit c8d647a326f06a39a8e5f0f1af946eacfa1835f8 upstream.
In order to reduce the chance for the system becoming unresponsive due to event storms triggered by a misbehaving pvcallsfront use the lateeoi irq binding for pvcallsback and unmask the event channel only after handling all write requests, which are the ones coming in via an irq.
This requires modifying the logic a little bit to not require an event for each write request, but to keep the ioworker running until no further data is found on the ring page to be processed.
This is part of XSA-332.
--- drivers/xen/pvcalls-back.c | 76 +++++++++++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 30 deletions(-)
drivers/xen/pvcalls-back.c +46 -30
@@ -66,6 +66,7 @@ struct sock_mapping {atomic_t write;atomic_t io;atomic_t release; +atomic_t eoi;void (*saved_data_ready)(struct sock *sk);struct pvcalls_ioworker ioworker; };
@@ -87,7 +88,7 @@ static int pvcalls_back_release_active(sstruct pvcalls_fedata *fedata, struct sock_mapping *map); -static void pvcalls_conn_back_read (void *opaque) +static bool pvcalls_conn_back_read (void *opaque) {struct sock_mapping *map = (struct sock_mapping *)opaque;struct msghdr msg;
@@ -107,17 +108,17 @@ static void pvcalls_conn_back_read(voidvirt_mb ();if (error) -return ; +return false; size =pvcalls_queued (prod, cons, array_size);if (size >= array_size) -return ; +return false;spin_lock_irqsave (&map->sock->sk->sk_receive_queue.lock, flags);if (skb_queue_empty (&map->sock->sk->sk_receive_queue)) {atomic_set (&map->read,0 );spin_unlock_irqrestore (&map->sock->sk->sk_receive_queue.lock, flags); -return ; +return true; }spin_unlock_irqrestore (&map->sock->sk->sk_receive_queue.lock, flags); wanted = array_size - size;
@@ -141,7 +142,7 @@ static void pvcalls_conn_back_read(void ret =inet_recvmsg (map->sock, &msg, wanted,MSG_DONTWAIT );WARN_ON (ret > wanted);if (ret == -EAGAIN )/* shouldn't happen */ -return ; +return true;if (!ret) ret = -ENOTCONN ;spin_lock_irqsave (&map->sock->sk->sk_receive_queue.lock, flags);
@@ -160,10 +161,10 @@ static void pvcalls_conn_back_read(voidvirt_wmb ();notify_remote_via_irq (map->irq); -return ; +return true; } -static void pvcalls_conn_back_write (struct sock_mapping *map) +static bool pvcalls_conn_back_write (struct sock_mapping *map) {struct pvcalls_data_intf *intf = map->ring;struct pvcalls_data *data = &map->data;
@@ -180,7 +181,7 @@ static void pvcalls_conn_back_write(stru array_size =XEN_FLEX_RING_SIZE (map->ring_order); size =pvcalls_queued (prod, cons, array_size);if (size ==0 ) -return ; +return false;memset (&msg,0 ,sizeof (msg)); msg.msg_flags |=MSG_DONTWAIT ;
@@ -198,12 +199,11 @@ static void pvcalls_conn_back_write(struatomic_set (&map->write,0 ); ret =inet_sendmsg (map->sock, &msg, size); -if (ret == -EAGAIN || (ret >=0 && ret < size)) { +if (ret == -EAGAIN ) {atomic_inc (&map->write);atomic_inc (&map->io); +return true; } -if (ret == -EAGAIN ) -return ;/* write the data, then update the indexes */ virt_wmb ();
@@ -216,9 +216,13 @@ static void pvcalls_conn_back_write(stru }/* update the indexes, then notify the other end */ virt_wmb (); -if (prod != cons + ret) +if (prod != cons + ret) {atomic_inc (&map->write); +atomic_inc (&map->io); + }notify_remote_via_irq (map->irq); + +return true; }static void pvcalls_back_ioworker (struct work_struct *work)
@@ -227,6 +231,7 @@ static void pvcalls_back_ioworker(struct struct pvcalls_ioworker, register_work); struct sock_mapping *map = container_of(ioworker, struct sock_mapping, ioworker); +unsigned int eoi_flags =XEN_EOI_FLAG_SPURIOUS ;while (atomic_read (&map->io) >0 ) {if (atomic_read (&map->release) >0 ) {
@@ -234,10 +239,18 @@ static void pvcalls_back_ioworker(structreturn ; } -if (atomic_read (&map->read) >0 ) -pvcalls_conn_back_read (map); -if (atomic_read (&map->write) >0 ) -pvcalls_conn_back_write (map); +if (atomic_read (&map->read) >0 && +pvcalls_conn_back_read (map)) + eoi_flags =0 ; +if (atomic_read (&map->write) >0 && +pvcalls_conn_back_write (map)) + eoi_flags =0 ; + +if (atomic_read (&map->eoi) >0 && !atomic_read (&map->write)) { +atomic_set (&map->eoi,0 ); +xen_irq_lateeoi (map->irq, eoi_flags); + eoi_flags =XEN_EOI_FLAG_SPURIOUS ; + }atomic_dec (&map->io); }
@@ -334,12 +347,9 @@ static struct sock_mapping *pvcalls_new_ goto out; map->bytes = page; - ret =bind_interdomain_evtchn_to_irqhandler (fedata->dev->otherend_id, - evtchn, - pvcalls_back_conn_event, -0 , -"pvcalls-backend" , - map); + ret =bind_interdomain_evtchn_to_irqhandler_lateeoi ( + fedata->dev->otherend_id, evtchn, + pvcalls_back_conn_event,0 ,"pvcalls-backend" , map);if (ret <0 ) goto out; map->irq = ret;
@@ -873,15 +883,18 @@ static irqreturn_t pvcalls_back_event(in {struct xenbus_device *dev = dev_id;struct pvcalls_fedata *fedata =NULL ; +unsigned int eoi_flags =XEN_EOI_FLAG_SPURIOUS ; -if (dev ==NULL ) -return IRQ_HANDLED ; +if (dev) { + fedata =dev_get_drvdata (&dev->dev); +if (fedata) { +pvcalls_back_work (fedata); + eoi_flags =0 ; + } + } - fedata =dev_get_drvdata (&dev->dev); -if (fedata ==NULL ) -return IRQ_HANDLED ; +xen_irq_lateeoi (irq, eoi_flags); -pvcalls_back_work (fedata);return IRQ_HANDLED ; }
@@ -891,12 +904,15 @@ static irqreturn_t pvcalls_back_conn_evestruct pvcalls_ioworker *iow;if (map ==NULL || map->sock ==NULL || map->sock->sk ==NULL || - map->sock->sk->sk_user_data != map) + map->sock->sk->sk_user_data != map) { +xen_irq_lateeoi (irq,0 );return IRQ_HANDLED ; + } iow = &map->ioworker;atomic_inc (&map->write); +atomic_inc (&map->eoi);atomic_inc (&map->io);queue_work (iow->wq, &iow->register_work);
@@ -931,7 +947,7 @@ static int backend_connect(struct xenbus goto error; } - err =bind_interdomain_evtchn_to_irq (dev->otherend_id, evtchn); + err =bind_interdomain_evtchn_to_irq_lateeoi (dev->otherend_id, evtchn);if (err <0 ) goto error; fedata->irq = err;
Greg Kroah-Hartman
maintainerPATCH 9/214 xen/pciback: use lateeoi irq binding
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit c2711441bc961b37bba0615dd7135857d189035f upstream.
In order to reduce the chance for the system becoming unresponsive due to event storms triggered by a misbehaving pcifront use the lateeoi irq binding for pciback and unmask the event channel only just before leaving the event handling function.
Restructure the handling to support that scheme. Basically an event can come in for two reasons: either a normal request for a pciback action, which is handled in a worker, or in case the guest has finished an AER request which was requested by pciback.
When an AER request is issued to the guest and a normal pciback action is currently active issue an EOI early in order to be able to receive another event when the AER request has been finished by the guest.
Let the worker processing the normal requests run until no further request is pending, instead of starting a new worker ion that case. Issue the EOI only just before leaving the worker.
This scheme allows to drop calling the generic function xen_pcibk_test_and_schedule_op() after processing of any request as the handling of both request types is now separated more cleanly.
This is part of XSA-332.
--- drivers/xen/xen-pciback/pci_stub.c | 14 ++++----- drivers/xen/xen-pciback/pciback.h | 12 +++++++- drivers/xen/xen-pciback/pciback_ops.c | 48 ++++++++++++++++++++++++++-------- drivers/xen/xen-pciback/xenbus.c | 2 - 4 files changed, 56 insertions(+), 20 deletions(-)
drivers/xen/xen-pciback/pci_stub.c +7 -7
@@ -733,10 +733,17 @@ static pci_ers_result_t common_process(swmb ();notify_remote_via_irq (pdev->evtchn_irq); +/* Enable IRQ to signal "request done". */ +xen_pcibk_lateeoi (pdev,0 ); + ret =wait_event_timeout (xen_pcibk_aer_wait_queue, !(test_bit (_XEN_PCIB_active, (unsigned long *) &sh_info->flags)),300 *HZ ); +/* Enable IRQ for pcifront request if not already active. */ +if (!test_bit (_PDEVF_op_active, &pdev->flags)) +xen_pcibk_lateeoi (pdev,0 ); +if (!ret) {if (test_bit (_XEN_PCIB_active, (unsigned long *)&sh_info->flags)) {
@@ -750,13 +757,6 @@ static pci_ers_result_t common_process(s }clear_bit (_PCIB_op_pending, (unsigned long *)&pdev->flags); -if (test_bit (_XEN_PCIF_active, - (unsigned long *)&sh_info->flags)) { -dev_dbg (&psdev->dev->dev, -"schedule pci_conf service in " DRV_NAME "\n" ); -xen_pcibk_test_and_schedule_op (psdev->pdev); - } - res = (pci_ers_result_t )aer_op->err;return res; }
drivers/xen/xen-pciback/pciback.h +10 -2
@@ -14,6 +14,7 @@#include <linux/spinlock.h> #include <linux/workqueue.h> #include <linux/atomic.h> +#include <xen/events.h> #include <xen/interface/io/pciif.h> #define DRV_NAME "xen-pciback"
@@ -27,6 +28,8 @@ struct pci_dev_entry {#define PDEVF_op_active (1<<(_PDEVF_op_active))#define _PCIB_op_pending (1)#define PCIB_op_pending (1<<(_PCIB_op_pending)) +#define _EOI_pending (2) +#define EOI_pending (1<<(_EOI_pending))struct xen_pcibk_device {void *pci_dev_data;
@@ -182,12 +185,17 @@ static inline void xen_pcibk_release_devirqreturn_t xen_pcibk_handle_event (int irq,void *dev_id);void xen_pcibk_do_op (struct work_struct *data); +static inline void xen_pcibk_lateeoi (struct xen_pcibk_device *pdev, +unsigned int eoi_flag) +{ +if (test_and_clear_bit (_EOI_pending, &pdev->flags)) +xen_irq_lateeoi (pdev->evtchn_irq, eoi_flag); +} +int xen_pcibk_xenbus_register (void );void xen_pcibk_xenbus_unregister (void );extern int verbose_request; - -void xen_pcibk_test_and_schedule_op (struct xen_pcibk_device *pdev);#endif /* Handles shared IRQs that can to device domain and control domain. */
drivers/xen/xen-pciback/pciback_ops.c +38 -10
90 lines not on this page · raw message
drivers/xen/xen-pciback/xenbus.c +1 -1
@@ -123,7 +123,7 @@ static int xen_pcibk_do_attach(struct xe pdev->sh_info = vaddr; - err =bind_interdomain_evtchn_to_irqhandler ( + err =bind_interdomain_evtchn_to_irqhandler_lateeoi ( pdev->xdev->otherend_id, remote_evtchn, xen_pcibk_handle_event,0 ,DRV_NAME , pdev);if (err <0 ) {
Greg Kroah-Hartman
maintainerPATCH 10/214 xen/events: switch user event channels to lateeoi model
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit c44b849cee8c3ac587da3b0980e01f77500d158c upstream.
Instead of disabling the irq when an event is received and enabling it again when handled by the user process use the lateeoi model.
This is part of XSA-332.
--- drivers/xen/evtchn.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
drivers/xen/evtchn.c +3 -4
@@ -166,7 +166,6 @@ static irqreturn_t evtchn_interrupt(int"Interrupt for port %d, but apparently not enabled; per-user %p\n" , evtchn->port, u); -disable_irq_nosync (irq); evtchn->enabled = false;spin_lock (&u->ring_prod_lock);
@@ -292,7 +291,7 @@ static ssize_t evtchn_write(struct file evtchn =find_evtchn (u, port);if (evtchn && !evtchn->enabled) { evtchn->enabled = true; -enable_irq (irq_from_evtchn (port)); +xen_irq_lateeoi (irq_from_evtchn (port),0 ); } }
@@ -392,8 +391,8 @@ static int evtchn_bind_to_user(struct peif (rc <0 ) goto err; - rc =bind_evtchn_to_irqhandler (port, evtchn_interrupt,0 , - u->name, evtchn); + rc =bind_evtchn_to_irqhandler_lateeoi (port, evtchn_interrupt,0 , + u->name, evtchn);if (rc <0 ) goto err;
Greg Kroah-Hartman
maintainerPATCH 11/214 xen/events: use a common cpu hotplug hook for event channels
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit 7beb290caa2adb0a399e735a1e175db9aae0523a upstream.
Today only fifo event channels have a cpu hotplug callback. In order to prepare for more percpu (de)init work move that callback into events_base.c and add percpu_init() and percpu_deinit() hooks to struct evtchn_ops.
This is part of XSA-332.
--- drivers/xen/events/events_base.c | 25 +++++++++++++++++++++ drivers/xen/events/events_fifo.c | 40 ++++++++++++++++------------------- drivers/xen/events/events_internal.h | 3 ++ 3 files changed, 47 insertions(+), 21 deletions(-)
drivers/xen/events/events_base.c +25 -0
@@ -34,6 +34,7 @@#include <linux/irqnr.h> #include <linux/pci.h> #include <linux/spinlock.h> +#include <linux/cpuhotplug.h> #ifdef CONFIG_X86 #include <asm/desc.h>
@@ -1834,6 +1835,26 @@ void xen_callback_vector(void) {}static bool fifo_events = true;module_param (fifo_events, bool,0 ); +static int xen_evtchn_cpu_prepare (unsigned int cpu) +{ +int ret =0 ; + +if (evtchn_ops->percpu_init) + ret = evtchn_ops->percpu_init (cpu); + +return ret; +} + +static int xen_evtchn_cpu_dead (unsigned int cpu) +{ +int ret =0 ; + +if (evtchn_ops->percpu_deinit) + ret = evtchn_ops->percpu_deinit (cpu); + +return ret; +} +void __init xen_init_IRQ (void ) {int ret = -EINVAL ;
@@ -1844,6 +1865,10 @@ void __init xen_init_IRQ(void)if (ret <0 )xen_evtchn_2l_init (); +cpuhp_setup_state_nocalls (CPUHP_XEN_EVTCHN_PREPARE , +"xen/evtchn:prepare" , + xen_evtchn_cpu_prepare, xen_evtchn_cpu_dead); + evtchn_to_irq =kcalloc (EVTCHN_ROW (xen_evtchn_max_channels ()),sizeof (*evtchn_to_irq),GFP_KERNEL );BUG_ON (!evtchn_to_irq);
drivers/xen/events/events_fifo.c +19 -21
@@ -385,21 +385,6 @@ static void evtchn_fifo_resume(void) event_array_pages =0 ; } -static const struct evtchn_ops evtchn_ops_fifo = { - .max_channels = evtchn_fifo_max_channels, - .nr_channels = evtchn_fifo_nr_channels, - .setup = evtchn_fifo_setup, - .bind_to_cpu = evtchn_fifo_bind_to_cpu, - .clear_pending = evtchn_fifo_clear_pending, - .set_pending = evtchn_fifo_set_pending, - .is_pending = evtchn_fifo_is_pending, - .test_and_set_mask = evtchn_fifo_test_and_set_mask, - .mask = evtchn_fifo_mask, - .unmask = evtchn_fifo_unmask, - .handle_events = evtchn_fifo_handle_events, - .resume = evtchn_fifo_resume, -}; -static int evtchn_fifo_alloc_control_block (unsigned cpu) {void *control_block =NULL ;
@@ -422,19 +407,36 @@ static int evtchn_fifo_alloc_control_bloreturn ret; } -static int xen_evtchn_cpu_prepare (unsigned int cpu) +static int evtchn_fifo_percpu_init (unsigned int cpu) {if (!per_cpu (cpu_control_block, cpu))return evtchn_fifo_alloc_control_block (cpu);return 0 ; } -static int xen_evtchn_cpu_dead (unsigned int cpu) +static int evtchn_fifo_percpu_deinit (unsigned int cpu) {__evtchn_fifo_handle_events (cpu, true);return 0 ; } +static const struct evtchn_ops evtchn_ops_fifo = { + .max_channels = evtchn_fifo_max_channels, + .nr_channels = evtchn_fifo_nr_channels, + .setup = evtchn_fifo_setup, + .bind_to_cpu = evtchn_fifo_bind_to_cpu, + .clear_pending = evtchn_fifo_clear_pending, + .set_pending = evtchn_fifo_set_pending, + .is_pending = evtchn_fifo_is_pending, + .test_and_set_mask = evtchn_fifo_test_and_set_mask, + .mask = evtchn_fifo_mask, + .unmask = evtchn_fifo_unmask, + .handle_events = evtchn_fifo_handle_events, + .resume = evtchn_fifo_resume, + .percpu_init = evtchn_fifo_percpu_init, + .percpu_deinit = evtchn_fifo_percpu_deinit, +}; +int __init xen_evtchn_fifo_init (void ) {int cpu =smp_processor_id ();
@@ -448,9 +450,5 @@ int __init xen_evtchn_fifo_init(void) evtchn_ops = &evtchn_ops_fifo; -cpuhp_setup_state_nocalls (CPUHP_XEN_EVTCHN_PREPARE , -"xen/evtchn:prepare" , - xen_evtchn_cpu_prepare, xen_evtchn_cpu_dead); -return ret; }
drivers/xen/events/events_internal.h +3 -0
@@ -69,6 +69,9 @@ struct evtchn_ops {void (*handle_events)(unsigned cpu);void (*resume)(void ); + +int (*percpu_init)(unsigned int cpu); +int (*percpu_deinit)(unsigned int cpu); };extern const struct evtchn_ops *evtchn_ops;
Greg Kroah-Hartman
maintainerPATCH 12/214 xen/events: defer eoi in case of excessive number of events
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit e99502f76271d6bc4e374fe368c50c67a1fd3070 upstream.
In case rogue guests are sending events at high frequency it might happen that xen_evtchn_do_upcall() won't stop processing events in dom0. As this is done in irq handling a crash might be the result.
In order to avoid that, delay further inter-domain events after some time in xen_evtchn_do_upcall() by forcing eoi processing into a worker on the same cpu, thus inhibiting new events coming in.
The time after which eoi processing is to be delayed is configurable via a new module parameter "event_loop_timeout" which specifies the maximum event loop time in jiffies (default: 2, the value was chosen after some tests showing that a value of 2 was the lowest with an only slight drop of dom0 network throughput while multiple guests performed an event storm).
How long eoi processing will be delayed can be specified via another parameter "event_eoi_delay" (again in jiffies, default 10, again the value was chosen after testing with different delay values).
This is part of XSA-332.
--- Documentation/admin-guide/kernel-parameters.txt | 8 + drivers/xen/events/events_2l.c | 7 drivers/xen/events/events_base.c | 189 +++++++++++++++++++++++- drivers/xen/events/events_fifo.c | 30 +-- drivers/xen/events/events_internal.h | 14 + 5 files changed, 216 insertions(+), 32 deletions(-)
Documentation/admin-guide/kernel-parameters.txt +8 -0
@@ -5462,6 +5462,14 @@ as generic guest with no PV drivers. Currently support XEN HVM, KVM, HYPER_V and VMWARE guest. + xen.event_eoi_delay= [XEN] + How long to delay EOI handling in case of event + storms (jiffies). Default is 10. + + xen.event_loop_timeout= [XEN] + After which time (jiffies) the event handling loop + should start to delay EOI handling. Default is 2. + xirc2ps_cs= [NET,PCMCIA] Format: <irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]]
drivers/xen/events/events_2l.c +2 -5
@@ -161,7 +161,7 @@ static inline xen_ulong_t active_evtchns* a bitset of words which contain pending event bits. The second * level is a bitset of pending events themselves. */ -static void evtchn_2l_handle_events (unsigned cpu) +static void evtchn_2l_handle_events (unsigned cpu,struct evtchn_loop_ctrl *ctrl) {int irq;xen_ulong_t pending_words;
@@ -242,10 +242,7 @@ static void evtchn_2l_handle_events(unsi/* Process port. */ port = (word_idx *BITS_PER_EVTCHN_WORD ) + bit_idx; - irq =get_evtchn_to_irq (port); - -if (irq !=-1 ) -generic_handle_irq (irq); +handle_irq_for_port (port, ctrl); bit_idx = (bit_idx +1 ) %BITS_PER_EVTCHN_WORD ;
drivers/xen/events/events_base.c +184 -5
289 lines not on this page · raw message
drivers/xen/events/events_fifo.c +11 -19
@@ -275,19 +275,9 @@ static uint32_t clear_linked(volatile evreturn w &EVTCHN_FIFO_LINK_MASK ; } -static void handle_irq_for_port (unsigned port) -{ -int irq; - - irq =get_evtchn_to_irq (port); -if (irq !=-1 ) -generic_handle_irq (irq); -} - -static void consume_one_event (unsigned cpu, +static void consume_one_event (unsigned cpu,struct evtchn_loop_ctrl *ctrl,struct evtchn_fifo_control_block *control_block, -unsigned priority,unsigned long *ready, -bool drop) +unsigned priority,unsigned long *ready) {struct evtchn_fifo_queue *q = &per_cpu (cpu_queue, cpu);uint32_t head;
@@ -320,16 +310,17 @@ static void consume_one_event(unsigned cclear_bit (priority, ready);if (evtchn_fifo_is_pending (port) && !evtchn_fifo_is_masked (port)) { -if (unlikely (drop)) +if (unlikely (!ctrl))pr_warn ("Dropping pending event for port %u\n" , port);else -handle_irq_for_port (port); +handle_irq_for_port (port, ctrl); } q->head[priority] = head; } -static void __evtchn_fifo_handle_events (unsigned cpu,bool drop) +static void __evtchn_fifo_handle_events (unsigned cpu, +struct evtchn_loop_ctrl *ctrl) {struct evtchn_fifo_control_block *control_block;unsigned long ready;
@@ -341,14 +332,15 @@ static void __evtchn_fifo_handle_events(while (ready) { q =find_first_bit (&ready,EVTCHN_FIFO_MAX_QUEUES ); -consume_one_event (cpu, control_block, q, &ready, drop); +consume_one_event (cpu, ctrl, control_block, q, &ready); ready |=xchg (&control_block->ready,0 ); } } -static void evtchn_fifo_handle_events (unsigned cpu) +static void evtchn_fifo_handle_events (unsigned cpu, +struct evtchn_loop_ctrl *ctrl) { -__evtchn_fifo_handle_events (cpu, false); +__evtchn_fifo_handle_events (cpu, ctrl); }static void evtchn_fifo_resume (void )
@@ -416,7 +408,7 @@ static int evtchn_fifo_percpu_init(unsigstatic int evtchn_fifo_percpu_deinit (unsigned int cpu) { -__evtchn_fifo_handle_events (cpu, true); +__evtchn_fifo_handle_events (cpu,NULL );return 0 ; }
drivers/xen/events/events_internal.h +11 -3
@@ -30,11 +30,15 @@ enum xen_irq_type {*/ struct irq_info {struct list_head list; +struct list_head eoi_list;int refcnt;enum xen_irq_type type;/* type */ unsigned irq;unsigned int evtchn;/* event channel */ unsigned short cpu;/* cpu bound */ +unsigned short eoi_cpu;/* EOI must happen on this cpu */ +unsigned int irq_epoch;/* If eoi_cpu valid: irq_epoch of event */ +u64 eoi_time;/* Time in jiffies when to EOI. */ union {unsigned short virq;
@@ -53,6 +57,8 @@ struct irq_info {#define PIRQ_SHAREABLE (1 << 1)#define PIRQ_MSI_GROUP (1 << 2) +struct evtchn_loop_ctrl ; +struct evtchn_ops {unsigned (*max_channels)(void );unsigned (*nr_channels)(void );
@@ -67,7 +73,7 @@ struct evtchn_ops {void (*mask)(unsigned port);void (*unmask)(unsigned port); -void (*handle_events)(unsigned cpu); +void (*handle_events)(unsigned cpu,struct evtchn_loop_ctrl *ctrl);void (*resume)(void );int (*percpu_init)(unsigned int cpu);
@@ -78,6 +84,7 @@ extern const struct evtchn_ops *evtchn_oextern int **evtchn_to_irq;int get_evtchn_to_irq (unsigned int evtchn); +void handle_irq_for_port (evtchn_port_t port,struct evtchn_loop_ctrl *ctrl);struct irq_info *info_for_irq (unsigned irq);unsigned cpu_from_irq (unsigned irq);
@@ -135,9 +142,10 @@ static inline void unmask_evtchn(unsignereturn evtchn_ops->unmask (port); } -static inline void xen_evtchn_handle_events (unsigned cpu) +static inline void xen_evtchn_handle_events (unsigned cpu, +struct evtchn_loop_ctrl *ctrl) { -return evtchn_ops->handle_events (cpu); +return evtchn_ops->handle_events (cpu, ctrl); }static inline void xen_evtchn_resume (void )
Greg Kroah-Hartman
maintainerPATCH 13/214 xen/events: block rogue events for some time
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit 5f7f77400ab5b357b5fdb7122c3442239672186c upstream.
In order to avoid high dom0 load due to rogue guests sending events at high frequency, block those events in case there was no action needed in dom0 to handle the events.
This is done by adding a per-event counter, which set to zero in case an EOI without the XEN_EOI_FLAG_SPURIOUS is received from a backend driver, and incremented when this flag has been set. In case the counter is 2 or higher delay the EOI by 1 << (cnt - 2) jiffies, but not more than 1 second.
In order not to waste memory shorten the per-event refcnt to two bytes (it should normally never exceed a value of 2). Add an overflow check to evtchn_get() to make sure the 2 bytes really won't overflow.
This is part of XSA-332.
--- drivers/xen/events/events_base.c | 27 ++++++++++++++++++++++----- drivers/xen/events/events_internal.h | 3 ++- 2 files changed, 24 insertions(+), 6 deletions(-)
drivers/xen/events/events_base.c +22 -5
@@ -460,17 +460,34 @@ static void lateeoi_list_add(struct irq_spin_unlock_irqrestore (&eoi->eoi_list_lock, flags); } -static void xen_irq_lateeoi_locked (struct irq_info *info) +static void xen_irq_lateeoi_locked (struct irq_info *info,bool spurious) {evtchn_port_t evtchn;unsigned int cpu; +unsigned int delay =0 ; evtchn = info->evtchn;if (!VALID_EVTCHN (evtchn) || !list_empty (&info->eoi_list))return ; +if (spurious) { +if ((1 << info->spurious_cnt) < (HZ <<2 )) + info->spurious_cnt++; +if (info->spurious_cnt >1 ) { + delay =1 << (info->spurious_cnt -2 ); +if (delay >HZ ) + delay =HZ ; +if (!info->eoi_time) + info->eoi_cpu =smp_processor_id (); + info->eoi_time =get_jiffies_64 () + delay; + } + }else { + info->spurious_cnt =0 ; + } + cpu = info->eoi_cpu; -if (info->eoi_time && info->irq_epoch ==per_cpu (irq_epoch, cpu)) { +if (info->eoi_time && + (info->irq_epoch ==per_cpu (irq_epoch, cpu) || delay)) {lateeoi_list_add (info);return ; }
@@ -507,7 +524,7 @@ static void xen_irq_lateeoi_worker(struc info->eoi_time =0 ; -xen_irq_lateeoi_locked (info); +xen_irq_lateeoi_locked (info, false); }if (info)
@@ -536,7 +553,7 @@ void xen_irq_lateeoi(unsigned int irq, u info =info_for_irq (irq);if (info) -xen_irq_lateeoi_locked (info); +xen_irq_lateeoi_locked (info, eoi_flags &XEN_EOI_FLAG_SPURIOUS );read_unlock_irqrestore (&evtchn_rwlock, flags); }
@@ -1439,7 +1456,7 @@ int evtchn_get(unsigned int evtchn) goto done; err = -EINVAL ; -if (info->refcnt <=0 ) +if (info->refcnt <=0 || info->refcnt ==SHRT_MAX ) goto done; info->refcnt++;
drivers/xen/events/events_internal.h +2 -1
@@ -31,7 +31,8 @@ enum xen_irq_type {struct irq_info {struct list_head list;struct list_head eoi_list; -int refcnt; +short refcnt; +short spurious_cnt;enum xen_irq_type type;/* type */ unsigned irq;unsigned int evtchn;/* event channel */
Greg Kroah-Hartman
maintainerPATCH 14/214 firmware: arm_scmi: Fix ARCH_COLD_RESET
In reply to Greg Kroah-HartmanFrom: Etienne Carriere <[email protected]>
[ Upstream commit 45b9e04d5ba0b043783dfe2b19bb728e712cb32e ]
The defination for ARCH_COLD_RESET is wrong. Let us fix it according to the SCMI specification.
--- drivers/firmware/arm_scmi/reset.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
drivers/firmware/arm_scmi/reset.c +1 -3
@@ -35,9 +35,7 @@ struct scmi_msg_reset_domain_reset {#define EXPLICIT_RESET_ASSERT BIT(1)#define ASYNCHRONOUS_RESET BIT(2)__le32 reset_state; -#define ARCH_RESET_TYPE BIT(31) -#define COLD_RESET_STATE BIT(0) -#define ARCH_COLD_RESET (ARCH_RESET_TYPE | COLD_RESET_STATE) +#define ARCH_COLD_RESET 0 };struct reset_dom_info {
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 15/214 firmware: arm_scmi: Add missing Rx size re-initialisation
In reply to Greg Kroah-HartmanFrom: Sudeep Holla <[email protected]>
[ Upstream commit 9724722fde8f9bbd2b87340f00b9300c9284001e ]
Few commands provide the list of description partially and require to be called consecutively until all the descriptors are fetched completely. In such cases, we don't release the buffers and reuse them for consecutive transmits.
However, currently we don't reset the Rx size which will be set as per the response for the last transmit. This may result in incorrect response size being interpretted as the firmware may repond with size greater than the one set but we read only upto the size set by previous response.
Let us reset the receive buffer size to max possible in such cases as we don't know the exact size of the response.
--- drivers/firmware/arm_scmi/base.c | 2 ++ drivers/firmware/arm_scmi/clock.c | 2 ++ drivers/firmware/arm_scmi/common.h | 2 ++ drivers/firmware/arm_scmi/driver.c | 8 ++++++++ drivers/firmware/arm_scmi/perf.c | 2 ++ drivers/firmware/arm_scmi/sensors.c | 2 ++ 6 files changed, 18 insertions(+)
drivers/firmware/arm_scmi/base.c +2 -0
@@ -173,6 +173,8 @@ static int scmi_base_implementation_list_get(const struct scmi_handle *handle, protocols_imp[tot_num_ret + loop] = *(list + loop); tot_num_ret += loop_num_ret; + +scmi_reset_rx_to_maxsz (handle, t); }while (loop_num_ret);scmi_xfer_put (handle, t);
drivers/firmware/arm_scmi/clock.c +2 -0
@@ -177,6 +177,8 @@ scmi_clock_describe_rates_get(const struct scmi_handle *handle, u32 clk_id, } tot_rate_cnt += num_returned; + +scmi_reset_rx_to_maxsz (handle, t);/* * check for both returned and remaining to avoid infinite * loop due to buggy firmware
drivers/firmware/arm_scmi/common.h +2 -0
@@ -103,6 +103,8 @@ int scmi_do_xfer_with_response(const struct scmi_handle *h, struct scmi_xfer *xfer);int scmi_xfer_get_init (const struct scmi_handle *h,u8 msg_id,u8 prot_id,size_t tx_size,size_t rx_size,struct scmi_xfer **p); +void scmi_reset_rx_to_maxsz (const struct scmi_handle *handle, +struct scmi_xfer *xfer);int scmi_handle_put (const struct scmi_handle *handle);struct scmi_handle *scmi_handle_get (struct device *dev);void scmi_set_handle (struct scmi_device *scmi_dev);
drivers/firmware/arm_scmi/driver.c +8 -0
@@ -481,6 +481,14 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)return ret; } +void scmi_reset_rx_to_maxsz (const struct scmi_handle *handle, +struct scmi_xfer *xfer) +{ +struct scmi_info *info =handle_to_scmi_info (handle); + + xfer->rx.len = info->desc->max_msg_size; +} +#define SCMI_MAX_RESPONSE_TIMEOUT (2 * MSEC_PER_SEC)/**
drivers/firmware/arm_scmi/perf.c +2 -0
@@ -281,6 +281,8 @@ scmi_perf_describe_levels_get(const struct scmi_handle *handle, u32 domain, } tot_opp_cnt += num_returned; + +scmi_reset_rx_to_maxsz (handle, t);/* * check for both returned and remaining to avoid infinite * loop due to buggy firmware
drivers/firmware/arm_scmi/sensors.c +2 -0
@@ -154,6 +154,8 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle, } desc_index += num_returned; + +scmi_reset_rx_to_maxsz (handle, t);/* * check for both returned and remaining to avoid infinite * loop due to buggy firmware
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 16/214 x86/unwind/orc: Fix inactive tasks with stack pointer in %sp on GCC 10 compiled kernels
In reply to Greg Kroah-HartmanFrom: Jiri Slaby <[email protected]>
[ Upstream commit f2ac57a4c49d40409c21c82d23b5706df9b438af ]
GCC 10 optimizes the scheduler code differently than its predecessors.
When CONFIG_DEBUG_SECTION_MISMATCH=y, the Makefile forces GCC not to inline some functions (-fno-inline-functions-called-once). Before GCC 10, "no-inlined" __schedule() starts with the usual prologue:
push %bp
mov %sp, %bp
So the ORC unwinder simply picks stack pointer from %bp and unwinds from __schedule() just perfectly:
$ cat /proc/1/stack [<0>] ep_poll+0x3e9/0x450 [<0>] do_epoll_wait+0xaa/0xc0 [<0>] __x64_sys_epoll_wait+0x1a/0x20 [<0>] do_syscall_64+0x33/0x40 [<0>] entry_SYSCALL_64_after_hwframe+0x44/0xa9
But now, with GCC 10, there is no %bp prologue in __schedule():
$ cat /proc/1/stack <nothing>
The ORC entry of the point in __schedule() is:
sp:sp+88 bp:last_sp-48 type:call end:0
In this case, nobody subtracts sizeof "struct inactive_task_frame" in __unwind_start(). The struct is put on the stack by __switch_to_asm() and only then __switch_to_asm() stores %sp to task->thread.sp. But we start unwinding from a point in __schedule() (stored in frame->ret_addr by 'call') and not in __switch_to_asm().
So for these example values in __unwind_start():
sp=ffff94b50001fdc8 bp=ffff8e1f41d29340 ip=__schedule+0x1f0
The stack is:
ffff94b50001fdc8: ffff8e1f41578000 # struct inactive_task_frame
ffff94b50001fdd0: 0000000000000000
ffff94b50001fdd8: ffff8e1f41d29340
ffff94b50001fde0: ffff8e1f41611d40 # ...
ffff94b50001fde8: ffffffff93c41920 # bx
ffff94b50001fdf0: ffff8e1f41d29340 # bp
ffff94b50001fdf8: ffffffff9376cad0 # ret_addr (and end of the struct)
0xffffffff9376cad0 is __schedule+0x1f0 (after the call to __switch_to_asm). Now follow those 88 bytes from the ORC entry (sp+88). The entry is correct, __schedule() really pushes 48 bytes (8*7) + 32 bytes via subq to store some local values (like 4U below). So to unwind, look at the offset 88-sizeof(long) = 0x50 from here:
ffff94b50001fe00: ffff8e1f41578618
ffff94b50001fe08: 00000cc000000255
ffff94b50001fe10: 0000000500000004
ffff94b50001fe18: 7793fab6956b2d00 # NOTE (see below)
ffff94b50001fe20: ffff8e1f41578000
ffff94b50001fe28: ffff8e1f41578000
ffff94b50001fe30: ffff8e1f41578000
ffff94b50001fe38: ffff8e1f41578000
ffff94b50001fe40: ffff94b50001fed8
ffff94b50001fe48: ffff8e1f41577ff0
ffff94b50001fe50: ffffffff9376cf12
Here ^^^^^^^^^^^^^^^^ is the correct ret addr from__schedule(). It translates to schedule+0x42 (insn after a call to __schedule()).
BUT, unwind_next_frame() tries to take the address starting from 0xffff94b50001fdc8. That is exactly from thread.sp+88-sizeof(long) = 0xffff94b50001fdc8+88-8 = 0xffff94b50001fe18, which is garbage marked as NOTE above. So this quits the unwinding as 7793fab6956b2d00 is obviously not a kernel address.
There was a fix to skip 'struct inactive_task_frame' in unwind_get_return_address_ptr in the following commit:
187b96db5ca7 ("x86/unwind/orc: Fix unwind_get_return_address_ptr() for inactive tasks")
But we need to skip the struct already in the unwinder proper. So subtract the size (increase the stack pointer) of the structure in __unwind_start() directly. This allows for removal of the code added by commit 187b96db5ca7 completely, as the address is now at '(unsigned long *)state->sp - 1', the same as in the generic case.
[ mingo: Cleaned up the changelog a bit, for better readability. ]
--- arch/x86/kernel/unwind_orc.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-)
arch/x86/kernel/unwind_orc.c +1 -8
@@ -311,19 +311,12 @@ EXPORT_SYMBOL_GPL(unwind_get_return_address);unsigned long *unwind_get_return_address_ptr (struct unwind_state *state) { -struct task_struct *task = state->task; -if (unwind_done (state))return NULL ;if (state->regs)return &state->regs->ip; -if (task != current && state->sp == task->thread.sp) { -struct inactive_task_frame *frame = (void *)task->thread.sp; -return &frame->ret_addr; - } -if (state->sp)return (unsigned long *)state->sp -1 ;
@@ -653,7 +646,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task, }else {struct inactive_task_frame *frame = (void *)task->thread.sp; - state->sp = task->thread.sp; + state->sp = task->thread.sp +sizeof (*frame); state->bp =READ_ONCE_NOCHECK (frame->bp); state->ip =READ_ONCE_NOCHECK (frame->ret_addr); state->signal = (void *)state->ip == ret_from_fork;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 17/214 mlxsw: core: Fix use-after-free in mlxsw_emad_trans_finish()
In reply to Greg Kroah-HartmanFrom: Amit Cohen <[email protected]>
[ Upstream commit 0daf2bf5a2dcf33d446b76360908f109816e2e21 ]
Each EMAD transaction stores the skb used to issue the EMAD request ('trans->tx_skb') so that the request could be retried in case of a timeout. The skb can be freed when a corresponding response is received or as part of the retry logic (e.g., failed retransmit, exceeded maximum number of retries).
The two tasks (i.e., response processing and retransmits) are synchronized by the atomic 'trans->active' field which ensures that responses to inactive transactions are ignored.
In case of a failed retransmit the transaction is finished and all of its resources are freed. However, the current code does not mark it as inactive. Syzkaller was able to hit a race condition in which a concurrent response is processed while the transaction's resources are being freed, resulting in a use-after-free [1].
Fix the issue by making sure to mark the transaction as inactive after a failed retransmit and free its resources only if a concurrent task did not already do that.
[1]
BUG: KASAN: use-after-free in consume_skb+0x30/0x370
net/core/skbuff.c:833
Read of size 4 at addr ffff88804f570494 by task syz-executor.0/1004
CPU: 0 PID: 1004 Comm: syz-executor.0 Not tainted 5.8.0-rc7+ #68
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014
Call Trace:
__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0xf6/0x16e lib/dump_stack.c:118
print_address_description.constprop.0+0x1c/0x250
mm/kasan/report.c:383
__kasan_report mm/kasan/report.c:513 [inline]
kasan_report.cold+0x1f/0x37 mm/kasan/report.c:530
check_memory_region_inline mm/kasan/generic.c:186 [inline]
check_memory_region+0x14e/0x1b0 mm/kasan/generic.c:192
instrument_atomic_read include/linux/instrumented.h:56 [inline]
atomic_read include/asm-generic/atomic-instrumented.h:27 [inline]
refcount_read include/linux/refcount.h:147 [inline]
skb_unref include/linux/skbuff.h:1044 [inline]
consume_skb+0x30/0x370 net/core/skbuff.c:833
mlxsw_emad_trans_finish+0x64/0x1c0 drivers/net/ethernet/mellanox/mlxsw/core.c:592
mlxsw_emad_process_response drivers/net/ethernet/mellanox/mlxsw/core.c:651 [inline]
mlxsw_emad_rx_listener_func+0x5c9/0xac0 drivers/net/ethernet/mellanox/mlxsw/core.c:672
mlxsw_core_skb_receive+0x4df/0x770 drivers/net/ethernet/mellanox/mlxsw/core.c:2063
mlxsw_pci_cqe_rdq_handle drivers/net/ethernet/mellanox/mlxsw/pci.c:595 [inline]
mlxsw_pci_cq_tasklet+0x12a6/0x2520 drivers/net/ethernet/mellanox/mlxsw/pci.c:651
tasklet_action_common.isra.0+0x13f/0x3e0 kernel/softirq.c:550
__do_softirq+0x223/0x964 kernel/softirq.c:292
asm_call_on_stack+0x12/0x20 arch/x86/entry/entry_64.S:711
Allocated by task 1006:
save_stack+0x1b/0x40 mm/kasan/common.c:48
set_track mm/kasan/common.c:56 [inline]
__kasan_kmalloc mm/kasan/common.c:494 [inline]
__kasan_kmalloc.constprop.0+0xc2/0xd0 mm/kasan/common.c:467
slab_post_alloc_hook mm/slab.h:586 [inline]
slab_alloc_node mm/slub.c:2824 [inline]
slab_alloc mm/slub.c:2832 [inline]
kmem_cache_alloc+0xcd/0x2e0 mm/slub.c:2837
__build_skb+0x21/0x60 net/core/skbuff.c:311
__netdev_alloc_skb+0x1e2/0x360 net/core/skbuff.c:464
netdev_alloc_skb include/linux/skbuff.h:2810 [inline]
mlxsw_emad_alloc drivers/net/ethernet/mellanox/mlxsw/core.c:756 [inline]
mlxsw_emad_reg_access drivers/net/ethernet/mellanox/mlxsw/core.c:787 [inline]
mlxsw_core_reg_access_emad+0x1ab/0x1420 drivers/net/ethernet/mellanox/mlxsw/core.c:1817
mlxsw_reg_trans_query+0x39/0x50 drivers/net/ethernet/mellanox/mlxsw/core.c:1831
mlxsw_sp_sb_pm_occ_clear drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c:260 [inline]
mlxsw_sp_sb_occ_max_clear+0xbff/0x10a0 drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c:1365
mlxsw_devlink_sb_occ_max_clear+0x76/0xb0 drivers/net/ethernet/mellanox/mlxsw/core.c:1037
devlink_nl_cmd_sb_occ_max_clear_doit+0x1ec/0x280 net/core/devlink.c:1765
genl_family_rcv_msg_doit net/netlink/genetlink.c:669 [inline]
genl_family_rcv_msg net/netlink/genetlink.c:714 [inline]
genl_rcv_msg+0x617/0x980 net/netlink/genetlink.c:731
netlink_rcv_skb+0x152/0x440 net/netlink/af_netlink.c:2470
genl_rcv+0x24/0x40 net/netlink/genetlink.c:742
netlink_unicast_kernel net/netlink/af_netlink.c:1304 [inline]
netlink_unicast+0x53a/0x750 net/netlink/af_netlink.c:1330
netlink_sendmsg+0x850/0xd90 net/netlink/af_netlink.c:1919
sock_sendmsg_nosec net/socket.c:651 [inline]
sock_sendmsg+0x150/0x190 net/socket.c:671
____sys_sendmsg+0x6d8/0x840 net/socket.c:2359
___sys_sendmsg+0xff/0x170 net/socket.c:2413
__sys_sendmsg+0xe5/0x1b0 net/socket.c:2446
do_syscall_64+0x56/0xa0 arch/x86/entry/common.c:384
entry_SYSCALL_64_after_hwframe+0x44/0xa9
Freed by task 73:
save_stack+0x1b/0x40 mm/kasan/common.c:48
set_track mm/kasan/common.c:56 [inline]
kasan_set_free_info mm/kasan/common.c:316 [inline]
__kasan_slab_free+0x12c/0x170 mm/kasan/common.c:455
slab_free_hook mm/slub.c:1474 [inline]
slab_free_freelist_hook mm/slub.c:1507 [inline]
slab_free mm/slub.c:3072 [inline]
kmem_cache_free+0xbe/0x380 mm/slub.c:3088
kfree_skbmem net/core/skbuff.c:622 [inline]
kfree_skbmem+0xef/0x1b0 net/core/skbuff.c:616
__kfree_skb net/core/skbuff.c:679 [inline]
consume_skb net/core/skbuff.c:837 [inline]
consume_skb+0xe1/0x370 net/core/skbuff.c:831
mlxsw_emad_trans_finish+0x64/0x1c0 drivers/net/ethernet/mellanox/mlxsw/core.c:592
mlxsw_emad_transmit_retry.isra.0+0x9d/0xc0 drivers/net/ethernet/mellanox/mlxsw/core.c:613
mlxsw_emad_trans_timeout_work+0x43/0x50 drivers/net/ethernet/mellanox/mlxsw/core.c:625
process_one_work+0xa3e/0x17a0 kernel/workqueue.c:2269
worker_thread+0x9e/0x1050 kernel/workqueue.c:2415
kthread+0x355/0x470 kernel/kthread.c:291
ret_from_fork+0x22/0x30 arch/x86/entry/entry_64.S:293
The buggy address belongs to the object at ffff88804f5703c0
which belongs to the cache skbuff_head_cache of size 224
The buggy address is located 212 bytes inside of
224-byte region [ffff88804f5703c0, ffff88804f5704a0)
The buggy address belongs to the page:
page:ffffea00013d5c00 refcount:1 mapcount:0 mapping:0000000000000000
index:0x0
flags: 0x100000000000200(slab)
raw: 0100000000000200 dead000000000100 dead000000000122 ffff88806c625400
raw: 0000000000000000 00000000000c000c 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff88804f570380: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb
ffff88804f570400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff88804f570480: fb fb fb fb fc fc fc fc fc fc fc fc fc fc fc fc
^
ffff88804f570500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffff88804f570580: 00 00 00 00 00 00 00 00 00 00 00 00 fc fc fc fc--- drivers/net/ethernet/mellanox/mlxsw/core.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/ethernet/mellanox/mlxsw/core.c +3 -0
@@ -493,6 +493,9 @@ static void mlxsw_emad_transmit_retry(struct mlxsw_core *mlxsw_core, err =mlxsw_emad_transmit (trans->core, trans);if (err ==0 )return ; + +if (!atomic_dec_and_test (&trans->active)) +return ; }else { err = -EIO ; }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 18/214 RDMA/qedr: Fix memory leak in iWARP CM
In reply to Greg Kroah-HartmanFrom: Alok Prasad <[email protected]>
[ Upstream commit a2267f8a52eea9096861affd463f691be0f0e8c9 ]
Fixes memory leak in iWARP CM
--- drivers/infiniband/hw/qedr/qedr_iw_cm.c | 1 + 1 file changed, 1 insertion(+)
drivers/infiniband/hw/qedr/qedr_iw_cm.c +1 -0
@@ -727,6 +727,7 @@ int qedr_iw_destroy_listen(struct iw_cm_id *cm_id) listener->qed_handle); cm_id->rem_ref (cm_id); +kfree (listener);return rc; }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 19/214 ata: sata_nv: Fix retrieving of active qcs
In reply to Greg Kroah-HartmanFrom: Sascha Hauer <[email protected]>
[ Upstream commit 8e4c309f9f33b76c09daa02b796ef87918eee494 ]
ata_qc_complete_multiple() has to be called with the tags physically active, that is the hw tag is at bit 0. ap->qc_active has the same tag at bit ATA_TAG_INTERNAL instead, so call ata_qc_get_active() to fix that up. This is done in the vein of 8385d756e114 ("libata: Fix retrieving of active qcs").
--- drivers/ata/sata_nv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/ata/sata_nv.c +1 -1
@@ -2100,7 +2100,7 @@ static int nv_swncq_sdbfis(struct ata_port *ap) pp->dhfis_bits &= ~done_mask; pp->dmafis_bits &= ~done_mask; pp->sdbfis_bits |= done_mask; -ata_qc_complete_multiple (ap, ap->qc_active ^ done_mask); +ata_qc_complete_multiple (ap,ata_qc_get_active (ap) ^ done_mask);if (!ap->qc_active) {DPRINTK ("over\n" );
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 20/214 futex: Fix incorrect should_fail_futex() handling
In reply to Greg Kroah-HartmanFrom: Mateusz Nosek <[email protected]>
[ Upstream commit 921c7ebd1337d1a46783d7e15a850e12aed2eaa0 ]
If should_futex_fail() returns true in futex_wake_pi(), then the 'ret' variable is set to -EFAULT and then immediately overwritten. So the failure injection is non-functional.
Fix it by actually leaving the function and returning -EFAULT.
The Fixes tag is kinda blury because the initial commit which introduced failure injection was already sloppy, but the below mentioned commit broke it completely.
[ tglx: Massaged changelog ]
--- kernel/futex.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
kernel/futex.c +3 -1
@@ -1594,8 +1594,10 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_pi_state *pi_*/ newval =FUTEX_WAITERS |task_pid_vnr (new_owner); -if (unlikely (should_fail_futex (true))) +if (unlikely (should_fail_futex (true))) { ret = -EFAULT ; + goto out_unlock; + } ret =cmpxchg_futex_value_locked (&curval, uaddr, uval, newval);if (!ret && (curval != uval)) {
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 21/214 powerpc/powernv/smp: Fix spurious DBG() warning
In reply to Greg Kroah-HartmanFrom: Oliver O'Halloran <[email protected]>
[ Upstream commit f6bac19cf65c5be21d14a0c9684c8f560f2096dd ]
When building with W=1 we get the following warning:
arch/powerpc/platforms/powernv/smp.c: In function ‘pnv_smp_cpu_kill_self’:
arch/powerpc/platforms/powernv/smp.c:276:16: error: suggest braces around
empty body in an ‘if’ statement [-Werror=empty-body]
276 | cpu, srr1);
| ^
cc1: all warnings being treated as errors
The full context is this block:
if (srr1 && !generic_check_cpu_restart(cpu))
DBG("CPU%d Unexpected exit while offline srr1=%lx!\n",
cpu, srr1);
When building with DEBUG undefined DBG() expands to nothing and GCC emits the warning due to the lack of braces around an empty statement.
--- arch/powerpc/platforms/powernv/smp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/platforms/powernv/smp.c +1 -1
@@ -43,7 +43,7 @@#include <asm/udbg.h> #define DBG(fmt...) udbg_printf(fmt)#else -#define DBG(fmt...) +#define DBG(fmt...) do { } while (0)#endif static void pnv_smp_setup_cpu (int cpu)
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 22/214 mm: fix exec activate_mm vs TLB shootdown and lazy tlb switching race
In reply to Greg Kroah-HartmanFrom: Nicholas Piggin <[email protected]>
[ Upstream commit d53c3dfb23c45f7d4f910c3a3ca84bf0a99c6143 ]
Reading and modifying current->mm and current->active_mm and switching mm should be done with irqs off, to prevent races seeing an intermediate state.
This is similar to commit 38cf307c1f20 ("mm: fix kthread_use_mm() vs TLB invalidate"). At exec-time when the new mm is activated, the old one should usually be single-threaded and no longer used, unless something else is holding an mm_users reference (which may be possible).
Absent other mm_users, there is also a race with preemption and lazy tlb switching. Consider the kernel_execve case where the current thread is using a lazy tlb active mm:
call_usermodehelper()
kernel_execve()
old_mm = current->mm;
active_mm = current->active_mm;
*** preempt *** --------------------> schedule()
prev->active_mm = NULL;
mmdrop(prev active_mm);
...
<-------------------- schedule()
current->mm = mm;
current->active_mm = mm;
if (!old_mm)
mmdrop(active_mm);If we switch back to the kernel thread from a different mm, there is a double free of the old active_mm, and a missing free of the new one.
Closing this race only requires interrupts to be disabled while ->mm and ->active_mm are being switched, but the TLB problem requires also holding interrupts off over activate_mm. Unfortunately not all archs can do that yet, e.g., arm defers the switch if irqs are disabled and expects finish_arch_post_lock_switch() to be called to complete the flush; um takes a blocking lock in activate_mm().
So as a first step, disable interrupts across the mm/active_mm updates to close the lazy tlb preempt race, and provide an arch option to extend that to activate_mm which allows architectures doing IPI based TLB shootdowns to close the second race.
This is a bit ugly, but in the interest of fixing the bug and backporting before all architectures are converted this is a compromise.
--- arch/Kconfig | 7 +++++++ fs/exec.c | 17 +++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-)
arch/Kconfig +7 -0
@@ -405,6 +405,13 @@ config MMU_GATHER_NO_RANGE config HAVE_MMU_GATHER_NO_GATHER bool +config ARCH_WANT_IRQS_OFF_ACTIVATE_MM + bool + help + Temporary select until all architectures can be converted to have + irqs disabled over activate_mm. Architectures that do IPI based TLB + shootdowns should enable this. + config ARCH_HAVE_NMI_SAFE_CMPXCHG bool
fs/exec.c +15 -2
@@ -1044,11 +1044,24 @@ static int exec_mmap(struct mm_struct *mm) }task_lock (tsk); - active_mm = tsk->active_mm;membarrier_exec_mmap (mm); - tsk->mm = mm; + +local_irq_disable (); + active_mm = tsk->active_mm; tsk->active_mm = mm; + tsk->mm = mm; +/* +* This prevents preemption while active_mm is being loaded and +* it and mm are being updated, which could cause problems for +* lazy tlb mm refcounting when these are updated by context +* switches. Not all architectures can handle irqs off over +* activate_mm yet. +*/ +if (!IS_ENABLED (CONFIG_ARCH_WANT_IRQS_OFF_ACTIVATE_MM )) +local_irq_enable ();activate_mm (active_mm, mm); +if (IS_ENABLED (CONFIG_ARCH_WANT_IRQS_OFF_ACTIVATE_MM )) +local_irq_enable (); tsk->mm->vmacache_seqnum =0 ;vmacache_flush (tsk);task_unlock (tsk);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 23/214 powerpc: select ARCH_WANT_IRQS_OFF_ACTIVATE_MM
In reply to Greg Kroah-HartmanFrom: Nicholas Piggin <[email protected]>
[ Upstream commit 66acd46080bd9e5ad2be4b0eb1d498d5145d058e ]
powerpc uses IPIs in some situations to switch a kernel thread away from a lazy tlb mm, which is subject to the TLB flushing race described in the changelog introducing ARCH_WANT_IRQS_OFF_ACTIVATE_MM.
--- arch/powerpc/Kconfig | 1 + arch/powerpc/include/asm/mmu_context.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-)
arch/powerpc/Kconfig +1 -0
@@ -147,6 +147,7 @@ config PPC select ARCH_USE_BUILTIN_BSWAP select ARCH_USE_CMPXCHG_LOCKREF if PPC64 select ARCH_WANT_IPC_PARSE_VERSION + select ARCH_WANT_IRQS_OFF_ACTIVATE_MM select ARCH_WEAK_RELEASE_ACQUIRE select BINFMT_ELF select BUILDTIME_EXTABLE_SORT
arch/powerpc/include/asm/mmu_context.h +1 -1
@@ -216,7 +216,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,*/ static inline void activate_mm (struct mm_struct *prev,struct mm_struct *next) { -switch_mm (prev, next, current); +switch_mm_irqs_off (prev, next, current); }/* We don't currently use enter_lazy_tlb() for anything */
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 24/214 sparc64: remove mm_cpumask clearing to fix kthread_use_mm race
In reply to Greg Kroah-HartmanFrom: Nicholas Piggin <[email protected]>
[ Upstream commit bafb056ce27940c9994ea905336aa8f27b4f7275 ]
The de facto (and apparently uncommented) standard for using an mm had, thanks to this code in sparc if nothing else, been that you must have a reference on mm_users *and that reference must have been obtained with mmget()*, i.e., from a thread with a reference to mm_users that had used the mm.
The introduction of mmget_not_zero() in commit d2005e3f41d4 ("userfaultfd: don't pin the user memory in userfaultfd_file_create()") allowed mm_count holders to aoperate on user mappings asynchronously from the actual threads using the mm, but they were not to load those mappings into their TLB (i.e., walking vmas and page tables is okay, kthread_use_mm() is not).
io_uring 2b188cc1bb857 ("Add io_uring IO interface") added code which does a kthread_use_mm() from a mmget_not_zero() refcount.
The problem with this is code which previously assumed mm == current->mm and mm->mm_users == 1 implies the mm will remain single-threaded at least until this thread creates another mm_users reference, has now broken.
arch/sparc/kernel/smp_64.c:
if (atomic_read(&mm->mm_users) == 1) {
cpumask_copy(mm_cpumask(mm), cpumask_of(cpu));
goto local_flush_and_out;
}vs fs/io_uring.c
if (unlikely(!(ctx->flags & IORING_SETUP_SQPOLL) ||
!mmget_not_zero(ctx->sqo_mm)))
return -EFAULT;
kthread_use_mm(ctx->sqo_mm);mmget_not_zero() could come in right after the mm_users == 1 test, then kthread_use_mm() which sets its CPU in the mm_cpumask. That update could be lost if cpumask_copy() occurs afterward.
I propose we fix this by allowing mmget_not_zero() to be a first-class reference, and not have this obscure undocumented and unchecked restriction.
The basic fix for sparc64 is to remove its mm_cpumask clearing code. The optimisation could be effectively restored by sending IPIs to mm_cpumask members and having them remove themselves from mm_cpumask. This is more tricky so I leave it as an exercise for someone with a sparc64 SMP. powerpc has a (currently similarly broken) example.
--- arch/sparc/kernel/smp_64.c | 65 ++++++++------------------------------ 1 file changed, 14 insertions(+), 51 deletions(-)
arch/sparc/kernel/smp_64.c +14 -51
@@ -1039,38 +1039,9 @@ void smp_fetch_global_pmu(void)* are flush_tlb_*() routines, and these run after flush_cache_*() * which performs the flushw. * -* The SMP TLB coherency scheme we use works as follows: -* -* 1) mm->cpu_vm_mask is a bit mask of which cpus an address -* space has (potentially) executed on, this is the heuristic -* we use to avoid doing cross calls. -* -* Also, for flushing from kswapd and also for clones, we -* use cpu_vm_mask as the list of cpus to make run the TLB. -* -* 2) TLB context numbers are shared globally across all processors -* in the system, this allows us to play several games to avoid -* cross calls. -* -* One invariant is that when a cpu switches to a process, and -* that processes tsk->active_mm->cpu_vm_mask does not have the -* current cpu's bit set, that tlb context is flushed locally. -* -* If the address space is non-shared (ie. mm->count == 1) we avoid -* cross calls when we want to flush the currently running process's -* tlb state. This is done by clearing all cpu bits except the current -* processor's in current->mm->cpu_vm_mask and performing the -* flush locally only. This will force any subsequent cpus which run -* this task to flush the context from the local tlb if the process -* migrates to another cpu (again). -* -* 3) For shared address spaces (threads) and swapping we bite the -* bullet for most cases and perform the cross call (but only to -* the cpus listed in cpu_vm_mask). -* -* The performance gain from "optimizing" away the cross call for threads is -* questionable (in theory the big win for threads is the massive sharing of -* address space state across processors). +* mm->cpu_vm_mask is a bit mask of which cpus an address +* space has (potentially) executed on, this is the heuristic +* we use to limit cross calls. */ /* This currently is only used by the hugetlb arch pre-fault
@@ -1080,18 +1051,13 @@ void smp_fetch_global_pmu(void)void smp_flush_tlb_mm (struct mm_struct *mm) {u32 ctx =CTX_HWBITS (mm->context); -int cpu =get_cpu (); -if (atomic_read (&mm->mm_users) ==1 ) { -cpumask_copy (mm_cpumask (mm),cpumask_of (cpu)); - goto local_flush_and_out; - } +get_cpu ();smp_cross_call_masked (&xcall_flush_tlb_mm, ctx,0 ,0 ,mm_cpumask (mm)); -local_flush_and_out:__flush_tlb_mm (ctx,SECONDARY_CONTEXT );put_cpu ();
@@ -1114,17 +1080,15 @@ void smp_flush_tlb_pending(struct mm_struct *mm, unsigned long nr, unsigned long {u32 ctx =CTX_HWBITS (mm->context);struct tlb_pending_info info; -int cpu =get_cpu (); + +get_cpu (); info.ctx = ctx; info.nr = nr; info.vaddrs = vaddrs; -if (mm == current->mm &&atomic_read (&mm->mm_users) ==1 ) -cpumask_copy (mm_cpumask (mm),cpumask_of (cpu)); -else -smp_call_function_many (mm_cpumask (mm), tlb_pending_func, - &info,1 ); +smp_call_function_many (mm_cpumask (mm), tlb_pending_func, + &info,1 );__flush_tlb_pending (ctx, nr, vaddrs);
@@ -1134,14 +1098,13 @@ void smp_flush_tlb_pending(struct mm_struct *mm, unsigned long nr, unsigned longvoid smp_flush_tlb_page (struct mm_struct *mm,unsigned long vaddr) {unsigned long context =CTX_HWBITS (mm->context); -int cpu =get_cpu (); -if (mm == current->mm &&atomic_read (&mm->mm_users) ==1 ) -cpumask_copy (mm_cpumask (mm),cpumask_of (cpu)); -else -smp_cross_call_masked (&xcall_flush_tlb_page, - context, vaddr,0 , -mm_cpumask (mm)); +get_cpu (); + +smp_cross_call_masked (&xcall_flush_tlb_page, + context, vaddr,0 , +mm_cpumask (mm)); +__flush_tlb_page (context, vaddr);put_cpu ();
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 25/214 f2fs: add trace exit in exception path
In reply to Greg Kroah-HartmanFrom: Zhang Qilong <[email protected]>
[ Upstream commit 9b66482282888d02832b7d90239e1cdb18e4b431 ]
Missing the trace exit in f2fs_sync_dirty_inodes
--- fs/f2fs/checkpoint.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
fs/f2fs/checkpoint.c +5 -1
@@ -1044,8 +1044,12 @@ int f2fs_sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type)get_pages (sbi, is_dir ? F2FS_DIRTY_DENTS : F2FS_DIRTY_DATA)); retry: -if (unlikely (f2fs_cp_error (sbi))) +if (unlikely (f2fs_cp_error (sbi))) { +trace_f2fs_sync_dirty_inodes_exit (sbi->sb, is_dir, +get_pages (sbi, is_dir ? +F2FS_DIRTY_DENTS :F2FS_DIRTY_DATA ));return -EIO ; + }spin_lock (&sbi->inode_lock[type]);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 26/214 f2fs: fix uninit-value in f2fs_lookup
In reply to Greg Kroah-HartmanFrom: Chao Yu <[email protected]>
[ Upstream commit 6d7ab88a98c1b7a47c228f8ffb4f44d631eaf284 ]
As syzbot reported:
Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x21c/0x280 lib/dump_stack.c:118 kmsan_report+0xf7/0x1e0 mm/kmsan/kmsan_report.c:122 __msan_warning+0x58/0xa0 mm/kmsan/kmsan_instr.c:219 f2fs_lookup+0xe05/0x1a80 fs/f2fs/namei.c:503 lookup_open fs/namei.c:3082 [inline] open_last_lookups fs/namei.c:3177 [inline] path_openat+0x2729/0x6a90 fs/namei.c:3365 do_filp_open+0x2b8/0x710 fs/namei.c:3395 do_sys_openat2+0xa88/0x1140 fs/open.c:1168 do_sys_open fs/open.c:1184 [inline] __do_compat_sys_openat fs/open.c:1242 [inline] __se_compat_sys_openat+0x2a4/0x310 fs/open.c:1240 __ia32_compat_sys_openat+0x56/0x70 fs/open.c:1240 do_syscall_32_irqs_on arch/x86/entry/common.c:80 [inline] __do_fast_syscall_32+0x129/0x180 arch/x86/entry/common.c:139 do_fast_syscall_32+0x6a/0xc0 arch/x86/entry/common.c:162 do_SYSENTER_32+0x73/0x90 arch/x86/entry/common.c:205 entry_SYSENTER_compat_after_hwframe+0x4d/0x5c
In f2fs_lookup(), @res_page could be used before being initialized, because in __f2fs_find_entry(), once F2FS_I(dir)->i_current_depth was been fuzzed to zero, then @res_page will never be initialized, causing this kmsan warning, relocating @res_page initialization place to fix this bug.
--- fs/f2fs/dir.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
fs/f2fs/dir.c +3 -5
@@ -303,16 +303,15 @@ struct f2fs_dir_entry *__f2fs_find_entry(struct inode *dir,unsigned int max_depth;unsigned int level; + *res_page =NULL ; +if (f2fs_has_inline_dentry (dir)) { - *res_page =NULL ; de =f2fs_find_in_inline_dir (dir, fname, res_page); goto out; } -if (npages ==0 ) { - *res_page =NULL ; +if (npages ==0 ) goto out; - } max_depth =F2FS_I (dir)->i_current_depth;if (unlikely (max_depth >MAX_DIR_HASH_DEPTH )) {
@@ -323,7 +322,6 @@ struct f2fs_dir_entry *__f2fs_find_entry(struct inode *dir, }for (level =0 ; level < max_depth; level++) { - *res_page =NULL ; de =find_in_level (dir, level, fname, res_page);if (de ||IS_ERR (*res_page))break ;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 27/214 f2fs: fix to check segment boundary during SIT page readahead
In reply to Greg Kroah-HartmanFrom: Chao Yu <[email protected]>
[ Upstream commit 6a257471fa42c8c9c04a875cd3a2a22db148e0f0 ]
As syzbot reported:
kernel BUG at fs/f2fs/segment.h:657!
invalid opcode: 0000 [#1] PREEMPT SMP KASAN
CPU: 1 PID: 16220 Comm: syz-executor.0 Not tainted 5.9.0-rc5-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 RIP: 0010:f2fs_ra_meta_pages+0xa51/0xdc0 fs/f2fs/segment.h:657 Call Trace: build_sit_entries fs/f2fs/segment.c:4195 [inline] f2fs_build_segment_manager+0x4b8a/0xa3c0 fs/f2fs/segment.c:4779 f2fs_fill_super+0x377d/0x6b80 fs/f2fs/super.c:3633 mount_bdev+0x32e/0x3f0 fs/super.c:1417 legacy_get_tree+0x105/0x220 fs/fs_context.c:592 vfs_get_tree+0x89/0x2f0 fs/super.c:1547 do_new_mount fs/namespace.c:2875 [inline] path_mount+0x1387/0x2070 fs/namespace.c:3192 do_mount fs/namespace.c:3205 [inline] __do_sys_mount fs/namespace.c:3413 [inline] __se_sys_mount fs/namespace.c:3390 [inline] __x64_sys_mount+0x27f/0x300 fs/namespace.c:3390 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xa9
@blkno in f2fs_ra_meta_pages could exceed max segment count, causing panic in following sanity check in current_sit_addr(), add check condition to avoid this issue.
--- fs/f2fs/checkpoint.c | 2 ++ 1 file changed, 2 insertions(+)
fs/f2fs/checkpoint.c +2 -0
@@ -243,6 +243,8 @@ int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, blkno * NAT_ENTRY_PER_BLOCK);break ;case META_SIT : +if (unlikely (blkno >=TOTAL_SEGS (sbi))) + goto out;/* get sit block addr */ fio.new_blkaddr =current_sit_addr (sbi, blkno *SIT_ENTRY_PER_BLOCK );
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 28/214 s390/startup: avoid save_area_sync overflow
In reply to Greg Kroah-HartmanFrom: Vasily Gorbik <[email protected]>
[ Upstream commit 2835c2ea95d50625108e47a459e1a47f6be836ce ]
Currently we overflow save_area_sync and write over save_area_async. Although this is not a real problem make startup_pgm_check_handler consistent with late pgm check handler and store [%r0,%r7] directly into gpregs_save_area.
--- arch/s390/boot/head.S | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-)
arch/s390/boot/head.S +11 -10
@@ -360,22 +360,23 @@ ENTRY(startup_kdump) # the save area and does disabled wait with a faulty address. # ENTRY(startup_pgm_check_handler) - stmg %r0,%r15,__LC_SAVE_AREA_SYNC - la %r1,4095 - stctg %c0,%c15,__LC_CREGS_SAVE_AREA-4095(%r1) - mvc __LC_GPREGS_SAVE_AREA-4095(128,%r1),__LC_SAVE_AREA_SYNC - mvc __LC_PSW_SAVE_AREA-4095(16,%r1),__LC_PGM_OLD_PSW + stmg %r8,%r15,__LC_SAVE_AREA_SYNC + la %r8,4095 + stctg %c0,%c15,__LC_CREGS_SAVE_AREA-4095(%r8) + stmg %r0,%r7,__LC_GPREGS_SAVE_AREA-4095(%r8) + mvc __LC_GPREGS_SAVE_AREA-4095+64(64,%r8),__LC_SAVE_AREA_SYNC + mvc __LC_PSW_SAVE_AREA-4095(16,%r8),__LC_PGM_OLD_PSW mvc __LC_RETURN_PSW(16),__LC_PGM_OLD_PSW ni __LC_RETURN_PSW,0xfc # remove IO and EX bits ni __LC_RETURN_PSW+1,0xfb # remove MCHK bit oi __LC_RETURN_PSW+1,0x2 # set wait state bit - larl %r2,.Lold_psw_disabled_wait - stg %r2,__LC_PGM_NEW_PSW+8 - l %r15,.Ldump_info_stack-.Lold_psw_disabled_wait(%r2) + larl %r9,.Lold_psw_disabled_wait + stg %r9,__LC_PGM_NEW_PSW+8 + l %r15,.Ldump_info_stack-.Lold_psw_disabled_wait(%r9) brasl %r14,print_pgm_check_info .Lold_psw_disabled_wait: - la %r1,4095 - lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1) + la %r8,4095 + lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r8) lpswe __LC_RETURN_PSW # disabled wait .Ldump_info_stack: .long 0x5000 + PAGE_SIZE - STACK_FRAME_OVERHEAD
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 29/214 um: change sigio_spinlock to a mutex
In reply to Greg Kroah-HartmanFrom: Johannes Berg <[email protected]>
[ Upstream commit f2d05059e15af3f70502074f4e3a504530af504a ]
Lockdep complains at boot:
=============================
[ BUG: Invalid wait context ]
5.7.0-05093-g46d91ecd597b #98 Not tainted
-----------------------------
swapper/1 is trying to lock:0000000060931b98 (&desc[i].request_mutex){+.+.}-{3:3}, at: __setup_irq+0x11d/0x623 other info that might help us debug this:
context-{4:4}
1 lock held by swapper/1:
#0: 000000006074fed8 (sigio_spinlock){+.+.}-{2:2}, at: sigio_lock+0x1a/0x1c
stack backtrace: CPU: 0 PID: 1 Comm: swapper Not tainted 5.7.0-05093-g46d91ecd597b #98 Stack: 7fa4fab0 6028dfd1 0000002a 6008bea5 7fa50700 7fa50040 7fa4fac0 6028e016 7fa4fb50 6007f6da 60959c18 00000000 Call Trace: [<60023a0e>] show_stack+0x13b/0x155 [<6028e016>] dump_stack+0x2a/0x2c [<6007f6da>] __lock_acquire+0x515/0x15f2 [<6007eb50>] lock_acquire+0x245/0x273 [<6050d9f1>] __mutex_lock+0xbd/0x325 [<6050dc76>] mutex_lock_nested+0x1d/0x1f [<6008e27e>] __setup_irq+0x11d/0x623 [<6008e8ed>] request_threaded_irq+0x169/0x1a6 [<60021eb0>] um_request_irq+0x1ee/0x24b [<600234ee>] write_sigio_irq+0x3b/0x76 [<600383ca>] sigio_broken+0x146/0x2e4 [<60020bd8>] do_one_initcall+0xde/0x281
Because we hold sigio_spinlock and then get into requesting an interrupt with a mutex.
Change the spinlock to a mutex to avoid that.
--- arch/um/kernel/sigio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/um/kernel/sigio.c +3 -3
@@ -35,14 +35,14 @@ int write_sigio_irq(int fd) }/* These are called from os-Linux/sigio.c to protect its pollfds arrays. */ -static DEFINE_SPINLOCK (sigio_spinlock); +static DEFINE_MUTEX (sigio_mutex);void sigio_lock (void ) { -spin_lock (&sigio_spinlock); +mutex_lock (&sigio_mutex); }void sigio_unlock (void ) { -spin_unlock (&sigio_spinlock); +mutex_unlock (&sigio_mutex); }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 30/214 f2fs: handle errors of f2fs_get_meta_page_nofail
In reply to Greg Kroah-HartmanFrom: Jaegeuk Kim <[email protected]>
[ Upstream commit 86f33603f8c51537265ff7ac0320638fd2cbdb1b ]
First problem is we hit BUG_ON() in f2fs_get_sum_page given EIO on f2fs_get_meta_page_nofail().
Quick fix was not to give any error with infinite loop, but syzbot caught a case where it goes to that loop from fuzzed image. In turned out we abused f2fs_get_meta_page_nofail() like in the below call stack.
- f2fs_fill_super
- f2fs_build_segment_manager
- build_sit_entries
- get_current_sit_page
INFO: task syz-executor178:6870 can't die for more than 143 seconds.
task:syz-executor178 state:R
stack:26960 pid: 6870 ppid: 6869 flags:0x00004006
Call Trace:
Showing all locks held in the system:
1 lock held by khungtaskd/1179:
#0: ffffffff8a554da0 (rcu_read_lock){....}-{1:2}, at: debug_show_all_locks+0x53/0x260 kernel/locking/lockdep.c:6242
1 lock held by systemd-journal/3920:
1 lock held by in:imklog/6769:
#0: ffff88809eebc130 (&f->f_pos_lock){+.+.}-{3:3}, at: __fdget_pos+0xe9/0x100 fs/file.c:930
1 lock held by syz-executor178/6870:
#0: ffff8880925120e0 (&type->s_umount_key#47/1){+.+.}-{3:3}, at: alloc_super+0x201/0xaf0 fs/super.c:229Actually, we didn't have to use _nofail in this case, since we could return error to mount(2) already with the error handler.
As a result, this patch tries to 1) remove _nofail callers as much as possible,
2) deal with error case in last remaining caller, f2fs_get_sum_page().
--- fs/f2fs/checkpoint.c | 2 +- fs/f2fs/f2fs.h | 2 +- fs/f2fs/node.c | 2 +- fs/f2fs/segment.c | 12 +++++++++--- 4 files changed, 12 insertions(+), 6 deletions(-)
fs/f2fs/checkpoint.c +1 -1
@@ -108,7 +108,7 @@ struct page *f2fs_get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)return __get_meta_page (sbi, index, true); } -struct page *f2fs_get_meta_page_nofail (struct f2fs_sb_info *sbi,pgoff_t index) +struct page *f2fs_get_meta_page_retry (struct f2fs_sb_info *sbi,pgoff_t index) {struct page *page;int count =0 ;
fs/f2fs/f2fs.h +1 -1
@@ -3149,7 +3149,7 @@ enum rw_hint f2fs_io_type_to_rw_hint(struct f2fs_sb_info *sbi,void f2fs_stop_checkpoint (struct f2fs_sb_info *sbi,bool end_io);struct page *f2fs_grab_meta_page (struct f2fs_sb_info *sbi,pgoff_t index);struct page *f2fs_get_meta_page (struct f2fs_sb_info *sbi,pgoff_t index); -struct page *f2fs_get_meta_page_nofail (struct f2fs_sb_info *sbi,pgoff_t index); +struct page *f2fs_get_meta_page_retry (struct f2fs_sb_info *sbi,pgoff_t index);struct page *f2fs_get_tmp_page (struct f2fs_sb_info *sbi,pgoff_t index);bool f2fs_is_valid_blkaddr (struct f2fs_sb_info *sbi,block_t blkaddr,int type);
fs/f2fs/node.c +1 -1
@@ -109,7 +109,7 @@ static void clear_node_page_dirty(struct page *page)static struct page *get_current_nat_page (struct f2fs_sb_info *sbi,nid_t nid) { -return f2fs_get_meta_page_nofail (sbi,current_nat_addr (sbi, nid)); +return f2fs_get_meta_page (sbi,current_nat_addr (sbi, nid)); }static struct page *get_next_nat_page (struct f2fs_sb_info *sbi,nid_t nid)
fs/f2fs/segment.c +9 -3
@@ -2310,7 +2310,9 @@ int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra)*/ struct page *f2fs_get_sum_page (struct f2fs_sb_info *sbi,unsigned int segno) { -return f2fs_get_meta_page_nofail (sbi,GET_SUM_BLOCK (sbi, segno)); +if (unlikely (f2fs_cp_error (sbi))) +return ERR_PTR (-EIO ); +return f2fs_get_meta_page_retry (sbi,GET_SUM_BLOCK (sbi, segno)); } void f2fs_update_meta_page(struct f2fs_sb_info *sbi,
@@ -2582,7 +2584,11 @@ static void change_curseg(struct f2fs_sb_info *sbi, int type)__next_free_blkoff (sbi, curseg,0 ); sum_page =f2fs_get_sum_page (sbi, new_segno); -f2fs_bug_on (sbi,IS_ERR (sum_page)); +if (IS_ERR (sum_page)) { +/* GC won't be able to use stale summary pages by cp_error */ +memset (curseg->sum_blk,0 ,SUM_ENTRY_SIZE ); +return ; + } sum_node = (struct f2fs_summary_block *)page_address (sum_page);memcpy (curseg->sum_blk, sum_node,SUM_ENTRY_SIZE );f2fs_put_page (sum_page,1 );
@@ -3713,7 +3719,7 @@ int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type,static struct page *get_current_sit_page (struct f2fs_sb_info *sbi,unsigned int segno) { -return f2fs_get_meta_page_nofail (sbi,current_sit_addr (sbi, segno)); +return f2fs_get_meta_page (sbi,current_sit_addr (sbi, segno)); } static struct page *get_next_sit_page(struct f2fs_sb_info *sbi,
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 31/214 ARM: 8997/2: hw_breakpoint: Handle inexact watchpoint addresses
In reply to Greg Kroah-HartmanFrom: Douglas Anderson <[email protected]>
[ Upstream commit 22c9e58299e5f18274788ce54c03d4fb761e3c5d ]
This is commit fdfeff0f9e3d ("arm64: hw_breakpoint: Handle inexact watchpoint addresses") but ported to arm32, which has the same problem.
This problem was found by Android CTS tests, notably the "watchpoint_imprecise" test [1]. I tested locally against a copycat (simplified) version of the test though.
[1] https://android.googlesource.com/platform/bionic/+/master/tests/sys_ptrace_test.cpp
--- arch/arm/kernel/hw_breakpoint.c | 100 +++++++++++++++++++++++--------- 1 file changed, 72 insertions(+), 28 deletions(-)
arch/arm/kernel/hw_breakpoint.c +72 -28
@@ -680,6 +680,40 @@ static void disable_single_step(struct perf_event *bp)arch_install_hw_breakpoint (bp); } +/* +* Arm32 hardware does not always report a watchpoint hit address that matches +* one of the watchpoints set. It can also report an address "near" the +* watchpoint if a single instruction access both watched and unwatched +* addresses. There is no straight-forward way, short of disassembling the +* offending instruction, to map that address back to the watchpoint. This +* function computes the distance of the memory access from the watchpoint as a +* heuristic for the likelyhood that a given access triggered the watchpoint. +* +* See this same function in the arm64 platform code, which has the same +* problem. +* +* The function returns the distance of the address from the bytes watched by +* the watchpoint. In case of an exact match, it returns 0. +*/ +static u32 get_distance_from_watchpoint (unsigned long addr,u32 val, +struct arch_hw_breakpoint_ctrl *ctrl) +{ +u32 wp_low, wp_high; +u32 lens, lene; + + lens =__ffs (ctrl->len); + lene =__fls (ctrl->len); + + wp_low = val + lens; + wp_high = val + lene; +if (addr < wp_low) +return wp_low - addr; +else if (addr > wp_high) +return addr - wp_high; +else +return 0 ; +} +static int watchpoint_fault_on_uaccess (struct pt_regs *regs,struct arch_hw_breakpoint *info) {
@@ -689,23 +723,25 @@ static int watchpoint_fault_on_uaccess(struct pt_regs *regs,static void watchpoint_handler (unsigned long addr,unsigned int fsr,struct pt_regs *regs) { -int i, access; -u32 val, ctrl_reg, alignment_mask; +int i, access, closest_match =0 ; +u32 min_dist =-1 , dist; +u32 val, ctrl_reg;struct perf_event *wp, **slots;struct arch_hw_breakpoint *info;struct arch_hw_breakpoint_ctrl ctrl; slots =this_cpu_ptr (wp_on_reg); +/* +* Find all watchpoints that match the reported address. If no exact +* match is found. Attribute the hit to the closest watchpoint. +*/ +rcu_read_lock ();for (i =0 ; i < core_num_wrps; ++i) { -rcu_read_lock (); - wp = slots[i]; -if (wp ==NULL ) - goto unlock; +continue ; - info =counter_arch_bp (wp);/* * The DFAR is an unknown value on debug architectures prior * to 7.1. Since we only allow a single watchpoint on these
@@ -714,33 +750,31 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr,*/ if (debug_arch <ARM_DEBUG_ARCH_V7_1 ) {BUG_ON (i >0 ); + info =counter_arch_bp (wp); info->trigger = wp->attr.bp_addr; }else { -if (info->ctrl.len ==ARM_BREAKPOINT_LEN_8 ) - alignment_mask =0x7 ; -else - alignment_mask =0x3 ; - -/* Check if the watchpoint value matches. */ - val =read_wb_reg (ARM_BASE_WVR + i); -if (val != (addr & ~alignment_mask)) - goto unlock; - -/* Possible match, check the byte address select. */ - ctrl_reg =read_wb_reg (ARM_BASE_WCR + i); -decode_ctrl_reg (ctrl_reg, &ctrl); -if (!((1 << (addr & alignment_mask)) & ctrl.len)) - goto unlock; -/* Check that the access type matches. */ if (debug_exception_updates_fsr ()) { access = (fsr &ARM_FSR_ACCESS_MASK ) ?HW_BREAKPOINT_W :HW_BREAKPOINT_R ;if (!(access &hw_breakpoint_type (wp))) - goto unlock; +continue ; } + val =read_wb_reg (ARM_BASE_WVR + i); + ctrl_reg =read_wb_reg (ARM_BASE_WCR + i); +decode_ctrl_reg (ctrl_reg, &ctrl); + dist =get_distance_from_watchpoint (addr, val, &ctrl); +if (dist < min_dist) { + min_dist = dist; + closest_match = i; + } +/* Is this an exact match? */ +if (dist !=0 ) +continue ; +/* We have a winner. */ + info =counter_arch_bp (wp); info->trigger = addr; }
@@ -762,13 +796,23 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr,* we can single-step over the watchpoint trigger. */ if (!is_default_overflow_handler (wp)) - goto unlock; - +continue ; step:enable_single_step (wp,instruction_pointer (regs)); -unlock: -rcu_read_unlock (); } + +if (min_dist >0 && min_dist !=-1 ) { +/* No exact match found. */ + wp = slots[closest_match]; + info =counter_arch_bp (wp); + info->trigger = addr; +pr_debug ("watchpoint fired: address = 0x%x\n" , info->trigger); +perf_bp_event (wp, regs); +if (is_default_overflow_handler (wp)) +enable_single_step (wp,instruction_pointer (regs)); + } + +rcu_read_unlock (); }static void watchpoint_single_step_handler (unsigned long pc)
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 32/214 NFS4: Fix oops when copy_file_range is attempted with NFS4.0 source
In reply to Greg Kroah-HartmanFrom: Dave Wysochanski <[email protected]>
[ Upstream commit d8a6ad913c286d4763ae20b14c02fe6f39d7cd9f ]
The following oops is seen during xfstest/565 when the 'test' (source of the copy) is NFS4.0 and 'scratch' (destination) is NFS4.2
[ 59.692458] run fstests generic/565 at 2020-08-01 05:50:35 [ 60.613588] BUG: kernel NULL pointer dereference, address: 0000000000000008 [ 60.624970] #PF: supervisor read access in kernel mode [ 60.627671] #PF: error_code(0x0000) - not-present page [ 60.630347] PGD 0 P4D 0 [ 60.631853] Oops: 0000 [#1] SMP PTI [ 60.634086] CPU: 6 PID: 2828 Comm: xfs_io Kdump: loaded Not tainted 5.8.0-rc3 #1 [ 60.637676] Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011 [ 60.639901] RIP: 0010:nfs4_check_serverowner_major_id+0x5/0x30 [nfsv4] [ 60.642719] Code: 89 ff e8 3e b3 b8 e1 e9 71 fe ff ff 41 bc da d8 ff ff e9 c3 fe ff ff e8 e9 9d 08 e2 66 0f 1f 84 00 00 00 00 00 66 66 66 66 90 <8b> 57 08 31 c0 3b 56 08 75 12 48 83 c6 0c 48 83 c7 0c e8 c4 97 bb [ 60.652629] RSP: 0018:ffffc265417f7e10 EFLAGS: 00010287 [ 60.655379] RAX: ffffa0664b066400 RBX: 0000000000000000 RCX: 0000000000000001 [ 60.658754] RDX: ffffa066725fb000 RSI: ffffa066725fd000 RDI: 0000000000000000 [ 60.662292] RBP: 0000000000020000 R08: 0000000000020000 R09: 0000000000000000 [ 60.666189] R10: 0000000000000003 R11: 0000000000000000 R12: ffffa06648258d00 [ 60.669914] R13: 0000000000000000 R14: 0000000000000000 R15: ffffa06648258100 [ 60.673645] FS: 00007faa9fb35800(0000) GS:ffffa06677d80000(0000) knlGS:0000000000000000 [ 60.677698] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 60.680773] CR2: 0000000000000008 CR3: 0000000203f14000 CR4: 00000000000406e0 [ 60.684476] Call Trace: [ 60.685809] nfs4_copy_file_range+0xfc/0x230 [nfsv4] [ 60.688704] vfs_copy_file_range+0x2ee/0x310 [ 60.691104] __x64_sys_copy_file_range+0xd6/0x210 [ 60.693527] do_syscall_64+0x4d/0x90 [ 60.695512] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 60.698006] RIP: 0033:0x7faa9febc1bd
--- fs/nfs/nfs4file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/nfs/nfs4file.c +2 -1
@@ -138,7 +138,8 @@ static ssize_t __nfs4_copy_file_range(struct file *file_in, loff_t pos_in,/* Only offload copy if superblock is the same */ if (file_inode (file_in)->i_sb !=file_inode (file_out)->i_sb)return -EXDEV ; -if (!nfs_server_capable (file_inode (file_out),NFS_CAP_COPY )) +if (!nfs_server_capable (file_inode (file_out),NFS_CAP_COPY ) || + !nfs_server_capable (file_inode (file_in),NFS_CAP_COPY ))return -EOPNOTSUPP ;if (file_inode (file_in) ==file_inode (file_out))return -EOPNOTSUPP ;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 33/214 power: supply: bq27xxx: report "not charging" on all types
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
[ Upstream commit 7bf738ba110722b63e9dc8af760d3fb2aef25593 ]
Commit 6f24ff97e323 ("power: supply: bq27xxx_battery: Add the BQ27Z561 Battery monitor") and commit d74534c27775 ("power:bq27xxx_battery: Add support for additional bq27xxx family devices") added support for new device types by copying most of the code and adding necessary quirks.
However they did not copy the code in bq27xxx_battery_status() responsible for returning POWER_SUPPLY_STATUS_NOT_CHARGING.
Unify the bq27xxx_battery_status() so for all types when charger is supplied, it will return "not charging" status.
--- drivers/power/supply/bq27xxx_battery.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/power/supply/bq27xxx_battery.c +4 -2
@@ -1678,8 +1678,6 @@ static int bq27xxx_battery_status(struct bq27xxx_device_info *di, status =POWER_SUPPLY_STATUS_FULL ; else if (di->cache.flags & BQ27000_FLAG_CHGS) status =POWER_SUPPLY_STATUS_CHARGING ; - else if (power_supply_am_i_supplied(di->bat) > 0) - status =POWER_SUPPLY_STATUS_NOT_CHARGING ; else status =POWER_SUPPLY_STATUS_DISCHARGING ; }else {
@@ -1691,6 +1689,10 @@ static int bq27xxx_battery_status(struct bq27xxx_device_info *di, status =POWER_SUPPLY_STATUS_CHARGING ; } +if ((status ==POWER_SUPPLY_STATUS_DISCHARGING ) && + (power_supply_am_i_supplied (di->bat) >0 )) + status =POWER_SUPPLY_STATUS_NOT_CHARGING ; + val->intval = status;return 0 ;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 34/214 xfs: fix realtime bitmap/summary file truncation when growing rt volume
In reply to Greg Kroah-HartmanFrom: Darrick J. Wong <[email protected]>
[ Upstream commit f4c32e87de7d66074d5612567c5eac7325024428 ]
The realtime bitmap and summary files are regular files that are hidden away from the directory tree. Since they're regular files, inode inactivation will try to purge what it thinks are speculative preallocations beyond the incore size of the file. Unfortunately, xfs_growfs_rt forgets to update the incore size when it resizes the inodes, with the result that inactivating the rt inodes at unmount time will cause their contents to be truncated.
Fix this by updating the incore size when we change the ondisk size as part of updating the superblock. Note that we don't do this when we're allocating blocks to the rt inodes because we actually want those blocks to get purged if the growfs fails.
This fixes corruption complaints from the online rtsummary checker when running xfs/233. Since that test requires rmap, one can also trigger this by growing an rt volume, cycling the mount, and creating rt files.
--- fs/xfs/xfs_rtalloc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
fs/xfs/xfs_rtalloc.c +8 -2
@@ -1021,10 +1021,13 @@ xfs_growfs_rt(xfs_ilock (mp->m_rbmip,XFS_ILOCK_EXCL );xfs_trans_ijoin (tp, mp->m_rbmip,XFS_ILOCK_EXCL );/* -* Update the bitmap inode's size. +* Update the bitmap inode's size ondisk and incore. We need +* to update the incore size so that inode inactivation won't +* punch what it thinks are "posteof" blocks. */ mp->m_rbmip->i_d.di_size = nsbp->sb_rbmblocks * nsbp->sb_blocksize; +i_size_write (VFS_I (mp->m_rbmip), mp->m_rbmip->i_d.di_size);xfs_trans_log_inode (tp, mp->m_rbmip,XFS_ILOG_CORE );/* * Get the summary inode into the transaction.
@@ -1032,9 +1035,12 @@ xfs_growfs_rt(xfs_ilock (mp->m_rsumip,XFS_ILOCK_EXCL );xfs_trans_ijoin (tp, mp->m_rsumip,XFS_ILOCK_EXCL );/* -* Update the summary inode's size. +* Update the summary inode's size. We need to update the +* incore size so that inode inactivation won't punch what it +* thinks are "posteof" blocks. */ mp->m_rsumip->i_d.di_size = nmp->m_rsumsize; +i_size_write (VFS_I (mp->m_rsumip), mp->m_rsumip->i_d.di_size);xfs_trans_log_inode (tp, mp->m_rsumip,XFS_ILOG_CORE );/* * Copy summary data from old to new sizes.
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 35/214 video: fbdev: pvr2fb: initialize variables
In reply to Greg Kroah-HartmanFrom: Tom Rix <[email protected]>
[ Upstream commit 8e1ba47c60bcd325fdd097cd76054639155e5d2e ]
clang static analysis reports this repesentative error
pvr2fb.c:1049:2: warning: 1st function call argument
is an uninitialized value [core.CallAndMessage]
if (*cable_arg)
^~~~~~~~~~~~~~~Problem is that cable_arg depends on the input loop to set the cable_arg[0]. If it does not, then some random value from the stack is used.
A similar problem exists for output_arg.
So initialize cable_arg and output_arg.
--- drivers/video/fbdev/pvr2fb.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/video/fbdev/pvr2fb.c +2 -0
@@ -1016,6 +1016,8 @@ static int __init pvr2fb_setup(char *options)if (!options || !*options)return 0 ; + cable_arg[0 ] = output_arg[0 ] =0 ; +while ((this_opt =strsep (&options,"," ))) {if (!*this_opt)continue ;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 36/214 ath10k: start recovery process when payload length exceeds max htc length for sdio
In reply to Greg Kroah-HartmanFrom: Wen Gong <[email protected]>
[ Upstream commit 2fd3c8f34d08af0a6236085f9961866ad92ef9ec ]
When simulate random transfer fail for sdio write and read, it happened "payload length exceeds max htc length" and recovery later sometimes.
Test steps:
1. Add config and update kernel:CONFIG_FAIL_MMC_REQUEST=yCONFIG_FAULT_INJECTION=yCONFIG_FAULT_INJECTION_DEBUG_FS=y
2. Run simulate fail:
cd /sys/kernel/debug/mmc1/fail_mmc_request
echo 10 > probability
echo 10 > times # repeat until hitting issues
3. It happened payload length exceeds max htc length.
[ 199.935506] ath10k_sdio mmc1:0001:1: payload length 57005 exceeds max htc length: 4088 .... [ 264.990191] ath10k_sdio mmc1:0001:1: payload length 57005 exceeds max htc length: 4088
4. after some time, such as 60 seconds, it start recovery which triggered by wmi command timeout for periodic scan.
[ 269.229232] ieee80211 phy0: Hardware restart was requested [ 269.734693] ath10k_sdio mmc1:0001:1: device successfully recovered
The simulate fail of sdio is not a real sdio transter fail, it only set an error status in mmc_should_fail_request after the transfer end, actually the transfer is success, then sdio_io_rw_ext_helper will return error status and stop transfer the left data. For example, the really RX len is 286 bytes, then it will split to 2 blocks in sdio_io_rw_ext_helper, one is 256 bytes, left is 30 bytes, if the first 256 bytes get an error status by mmc_should_fail_request,then the left 30 bytes will not read in this RX operation. Then when the next RX arrive, the left 30 bytes will be considered as the header of the read, the top 4 bytes of the 30 bytes will be considered as lookaheads, but actually the 4 bytes is not the lookaheads, so the len from this lookaheads is not correct, it exceeds max htc length 4088 sometimes. When happened exceeds, the buffer chain is not matched between firmware and ath10k, then it need to start recovery ASAP. Recently then recovery will be started by wmi command timeout, but it will be long time later, for example, it is 60+ seconds later from the periodic scan, if it does not have periodic scan, it will be longer.
Start recovery when it happened "payload length exceeds max htc length" will be reasonable.
This patch only effect sdio chips.
Tested with QCA6174 SDIO with firmware WLAN.RMH.4.4.1-00029.
--- drivers/net/wireless/ath/ath10k/sdio.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/wireless/ath/ath10k/sdio.c +4 -0
@@ -550,6 +550,10 @@ static int ath10k_sdio_mbox_rx_alloc(struct ath10k *ar,le16_to_cpu (htc_hdr->len), ATH10K_HTC_MBOX_MAX_PAYLOAD_LENGTH); ret = -ENOMEM ; + +queue_work (ar->workqueue, &ar->restart_work); +ath10k_warn (ar,"exceeds length, start recovery\n" ); + goto err; }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 37/214 ath10k: fix VHT NSS calculation when STBC is enabled
In reply to Greg Kroah-HartmanFrom: Sathishkumar Muruganandam <[email protected]>
[ Upstream commit 99f41b8e43b8b4b31262adb8ac3e69088fff1289 ]
When STBC is enabled, NSTS_SU value need to be accounted for VHT NSS calculation for SU case.
Without this fix, 1SS + STBC enabled case was reported wrongly as 2SS in radiotap header on monitor mode capture.
Tested-on: QCA9984 10.4-3.10-00047
--- drivers/net/wireless/ath/ath10k/htt_rx.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/net/wireless/ath/ath10k/htt_rx.c +7 -1
@@ -949,6 +949,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,u8 preamble =0 ;u8 group_id;u32 info1, info2, info3; +u32 stbc, nsts_su; info1 =__le32_to_cpu (rxd->ppdu_start.info1); info2 =__le32_to_cpu (rxd->ppdu_start.info2);
@@ -993,11 +994,16 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,*/ bw = info2 &3 ; sgi = info3 &1 ; + stbc = (info2 >>3 ) &1 ; group_id = (info2 >>4 ) &0x3F ;if (GROUP_ID_IS_SU_MIMO (group_id)) { mcs = (info3 >>4 ) &0x0F ; - nss = ((info2 >>10 ) &0x07 ) +1 ; + nsts_su = ((info2 >>10 ) &0x07 ); +if (stbc) + nss = (nsts_su >>2 ) +1 ; +else + nss = (nsts_su +1 ); }else {/* Hardware doesn't decode VHT-SIG-B into Rx descriptor * so it's impossible to decode MCS. Also since
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 38/214 drm/brige/megachips: Add checking if ge_b850v3_lvds_init() is working correctly
In reply to Greg Kroah-HartmanFrom: Nadezda Lutovinova <[email protected]>
[ Upstream commit f688a345f0d7a6df4dd2aeca8e4f3c05e123a0ee ]
If ge_b850v3_lvds_init() does not allocate memory for ge_b850v3_lvds_ptr, then a null pointer dereference is accessed.
The patch adds checking of the return value of ge_b850v3_lvds_init().
Found by Linux Driver Verification project (linuxtesting.org).
--- .../gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c +10 -2
@@ -295,8 +295,12 @@ static int stdp4028_ge_b850v3_fw_probe(struct i2c_client *stdp4028_i2c, const struct i2c_device_id *id) {struct device *dev = &stdp4028_i2c->dev; +int ret; + + ret =ge_b850v3_lvds_init (dev); -ge_b850v3_lvds_init (dev); +if (ret) +return ret; ge_b850v3_lvds_ptr->stdp4028_i2c = stdp4028_i2c;i2c_set_clientdata (stdp4028_i2c, ge_b850v3_lvds_ptr);
@@ -354,8 +358,12 @@ static int stdp2690_ge_b850v3_fw_probe(struct i2c_client *stdp2690_i2c, const struct i2c_device_id *id) {struct device *dev = &stdp2690_i2c->dev; +int ret; + + ret =ge_b850v3_lvds_init (dev); -ge_b850v3_lvds_init (dev); +if (ret) +return ret; ge_b850v3_lvds_ptr->stdp2690_i2c = stdp2690_i2c;i2c_set_clientdata (stdp2690_i2c, ge_b850v3_lvds_ptr);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 39/214 selftests/x86/fsgsbase: Reap a forgotten child
In reply to Greg Kroah-HartmanFrom: Andy Lutomirski <[email protected]>
[ Upstream commit ab2dd173330a3f07142e68cd65682205036cd00f ]
The ptrace() test forgot to reap its child. Reap it.
--- tools/testing/selftests/x86/fsgsbase.c | 3 +++ 1 file changed, 3 insertions(+)
tools/testing/selftests/x86/fsgsbase.c +3 -0
@@ -499,6 +499,9 @@ static void test_ptrace_write_gsbase(void) END:ptrace (PTRACE_CONT , child,NULL ,NULL ); +wait (&status); +if (!WIFEXITED (status)) +printf ("[WARN]\tChild didn't exit cleanly.\n" ); }int main ()
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 40/214 media: videodev2.h: RGB BT2020 and HSV are always full range
In reply to Greg Kroah-HartmanFrom: Hans Verkuil <[email protected]>
[ Upstream commit b305dfe2e93434b12d438434461b709641f62af4 ]
The default RGB quantization range for BT.2020 is full range (just as for all the other RGB pixel encodings), not limited range.
Update the V4L2_MAP_QUANTIZATION_DEFAULT macro and documentation accordingly.
Also mention that HSV is always full range and cannot be limited range.
When RGB BT2020 was introduced in V4L2 it was not clear whether it should be limited or full range, but full range is the right (and consistent) choice.
--- .../media/uapi/v4l/colorspaces-defs.rst | 9 ++++----- .../media/uapi/v4l/colorspaces-details.rst | 5 ++--- include/uapi/linux/videodev2.h | 17 ++++++++--------- 3 files changed, 14 insertions(+), 17 deletions(-)
Documentation/media/uapi/v4l/colorspaces-defs.rst +4 -5
@@ -36,8 +36,7 @@ whole range, 0-255, dividing the angular value by 1.41. The enum :c:type:`v4l2_hsv_encoding` specifies which encoding is used. .. note:: The default R'G'B' quantization is full range for all - colorspaces except for BT.2020 which uses limited range R'G'B' - quantization. + colorspaces. HSV formats are always full range. .. tabularcolumns:: |p{6.7cm}|p{10.8cm}|
@@ -169,8 +168,8 @@ whole range, 0-255, dividing the angular value by 1.41. The enum - Details * - ``V4L2_QUANTIZATION_DEFAULT`` - Use the default quantization encoding as defined by the - colorspace. This is always full range for R'G'B' (except for the - BT.2020 colorspace) and HSV. It is usually limited range for Y'CbCr. + colorspace. This is always full range for R'G'B' and HSV. + It is usually limited range for Y'CbCr. * - ``V4L2_QUANTIZATION_FULL_RANGE`` - Use the full range quantization encoding. I.e. the range [0…1] is mapped to [0…255] (with possible clipping to [1…254] to avoid the
@@ -180,4 +179,4 @@ whole range, 0-255, dividing the angular value by 1.41. The enum * - ``V4L2_QUANTIZATION_LIM_RANGE`` - Use the limited range quantization encoding. I.e. the range [0…1] is mapped to [16…235]. Cb and Cr are mapped from [-0.5…0.5] to - [16…240]. + [16…240]. Limited Range cannot be used with HSV.
Documentation/media/uapi/v4l/colorspaces-details.rst +2 -3
@@ -377,9 +377,8 @@ Colorspace BT.2020 (V4L2_COLORSPACE_BT2020) The :ref:`itu2020` standard defines the colorspace used by Ultra-high definition television (UHDTV). The default transfer function is ``V4L2_XFER_FUNC_709``. The default Y'CbCr encoding is -``V4L2_YCBCR_ENC_BT2020``. The default R'G'B' quantization is limited -range (!), and so is the default Y'CbCr quantization. The chromaticities -of the primary colors and the white reference are: +``V4L2_YCBCR_ENC_BT2020``. The default Y'CbCr quantization is limited range. +The chromaticities of the primary colors and the white reference are:
include/uapi/linux/videodev2.h +8 -9
@@ -371,9 +371,9 @@ enum v4l2_hsv_encoding {enum v4l2_quantization {/* -* The default for R'G'B' quantization is always full range, except -* for the BT2020 colorspace. For Y'CbCr the quantization is always -* limited range, except for COLORSPACE_JPEG: this is full range. +* The default for R'G'B' quantization is always full range. +* For Y'CbCr the quantization is always limited range, except +* for COLORSPACE_JPEG: this is full range. */ V4L2_QUANTIZATION_DEFAULT =0 ,V4L2_QUANTIZATION_FULL_RANGE =1 ,
@@ -382,14 +382,13 @@ enum v4l2_quantization {/* * Determine how QUANTIZATION_DEFAULT should map to a proper quantization. -* This depends on whether the image is RGB or not, the colorspace and the -* Y'CbCr encoding. +* This depends on whether the image is RGB or not, the colorspace. +* The Y'CbCr encoding is not used anymore, but is still there for backwards +* compatibility. */ #define V4L2_MAP_QUANTIZATION_DEFAULT (is_rgb_or_hsv, colsp, ycbcr_enc) \ - (((is_rgb_or_hsv) && (colsp) == V4L2_COLORSPACE_BT2020) ? \ - V4L2_QUANTIZATION_LIM_RANGE : \ - (((is_rgb_or_hsv) || (colsp) == V4L2_COLORSPACE_JPEG) ? \ - V4L2_QUANTIZATION_FULL_RANGE : V4L2_QUANTIZATION_LIM_RANGE)) + (((is_rgb_or_hsv) || (colsp) == V4L2_COLORSPACE_JPEG) ? \ + V4L2_QUANTIZATION_FULL_RANGE : V4L2_QUANTIZATION_LIM_RANGE)/* * Deprecated names for opRGB colorspace (IEC 61966-2-5)
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 41/214 media: platform: Improve queue set up flow for bug fixing
In reply to Greg Kroah-HartmanFrom: Xia Jiang <[email protected]>
[ Upstream commit 5095a6413a0cf896ab468009b6142cb0fe617e66 ]
Add checking created buffer size follow in mtk_jpeg_queue_setup().
--- drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c +7 -0
@@ -571,6 +571,13 @@ static int mtk_jpeg_queue_setup(struct vb2_queue *q,if (!q_data)return -EINVAL ; +if (*num_planes) { +for (i =0 ; i < *num_planes; i++) +if (sizes[i] < q_data->sizeimage[i]) +return -EINVAL ; +return 0 ; + } + *num_planes = q_data->fmt->colplanes;for (i =0 ; i < q_data->fmt->colplanes; i++) { sizes[i] = q_data->sizeimage[i];
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 42/214 usb: typec: tcpm: During PR_SWAP, source caps should be sent only after tSwapSourceStart
In reply to Greg Kroah-HartmanFrom: Badhri Jagan Sridharan <[email protected]>
[ Upstream commit 6bbe2a90a0bb4af8dd99c3565e907fe9b5e7fd88 ]
The patch addresses the compliance test failures while running TD.PD.CP.E3, TD.PD.CP.E4, TD.PD.CP.E5 of the "Deterministic PD Compliance MOI" test plan published in https://www.usb.org/usbc.
For a product to be Type-C compliant, it's expected that these tests are run on usb.org certified Type-C compliance tester as mentioned in
https://www.usb.org/usbc.
The purpose of the tests TD.PD.CP.E3, TD.PD.CP.E4, TD.PD.CP.E5 is to verify the PR_SWAP response of the device. While doing so, the test asserts that Source Capabilities message is NOT received from the test device within tSwapSourceStart min (20 ms) from the time the last bit of GoodCRC corresponding to the RS_RDY message sent by the UUT was sent. If it does then the test fails.
This is in line with the requirements from the USB Power Delivery Specification Revision 3.0, Version 1.2:
"6.6.8.1 SwapSourceStartTimer
The SwapSourceStartTimer Shall be used by the new Source, after a Power Role Swap or Fast Role Swap, to ensure that it does not send Source_Capabilities Message before the new Sink is ready to receive theSource_Capabilities Message. The new Source Shall Not send the Source_Capabilities Message earlier than tSwapSourceStart after the last bit of the EOP of GoodCRC Message sent in response to the PS_RDY Message sent by the new Source indicating that its power supply is ready."
The patch makes sure that TCPM does not send the Source_Capabilities Message within tSwapSourceStart(20ms) by transitioning into SRC_STARTUP only after tSwapSourceStart(20ms).
--- drivers/usb/typec/tcpm/tcpm.c | 2 +- include/linux/usb/pd.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-)
drivers/usb/typec/tcpm/tcpm.c +1 -1
@@ -3482,7 +3482,7 @@ static void run_state_machine(struct tcpm_port *port)*/ tcpm_set_pwr_role (port,TYPEC_SOURCE );tcpm_pd_send_control (port,PD_CTRL_PS_RDY ); -tcpm_set_state (port,SRC_STARTUP ,0 ); +tcpm_set_state (port,SRC_STARTUP ,PD_T_SWAP_SRC_START );break ;case VCONN_SWAP_ACCEPT :
include/linux/usb/pd.h +1 -0
@@ -442,6 +442,7 @@ static inline unsigned int rdo_max_power(u32 rdo)#define PD_T_ERROR_RECOVERY 100/* minimum 25 is insufficient */ #define PD_T_SRCSWAPSTDBY 625/* Maximum of 650ms */ #define PD_T_NEWSRC 250/* Maximum of 275ms */ +#define PD_T_SWAP_SRC_START 20/* Minimum of 20ms */ #define PD_T_DRP_TRY 100/* 75 - 150 ms */ #define PD_T_DRP_TRYWAIT 600/* 400 - 800 ms */
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 43/214 media: tw5864: check status of tw5864_frameinterval_get
In reply to Greg Kroah-HartmanFrom: Tom Rix <[email protected]>
[ Upstream commit 780d815dcc9b34d93ae69385a8465c38d423ff0f ]
clang static analysis reports this problem
tw5864-video.c:773:32: warning: The left expression of the compound
assignment is an uninitialized value.
The computed value will also be garbage
fintv->stepwise.max.numerator *= std_max_fps;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^stepwise.max is set with frameinterval, which comes from
ret = tw5864_frameinterval_get(input, &frameinterval); fintv->stepwise.step = frameinterval; fintv->stepwise.min = frameinterval; fintv->stepwise.max = frameinterval; fintv->stepwise.max.numerator *= std_max_fps;
When tw5864_frameinterval_get() fails, frameinterval is not set. So check the status and fix another similar problem.
--- drivers/media/pci/tw5864/tw5864-video.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/media/pci/tw5864/tw5864-video.c +6 -0
@@ -767,6 +767,9 @@ static int tw5864_enum_frameintervals(struct file *file, void *priv, fintv->type =V4L2_FRMIVAL_TYPE_STEPWISE ; ret =tw5864_frameinterval_get (input, &frameinterval); +if (ret) +return ret; + fintv->stepwise.step = frameinterval; fintv->stepwise.min = frameinterval; fintv->stepwise.max = frameinterval;
@@ -785,6 +788,9 @@ static int tw5864_g_parm(struct file *file, void *priv, cp->capability =V4L2_CAP_TIMEPERFRAME ; ret =tw5864_frameinterval_get (input, &cp->timeperframe); +if (ret) +return ret; + cp->timeperframe.numerator *= input->frame_interval; cp->capturemode =0 ; cp->readbuffers =2 ;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 44/214 media: imx274: fix frame interval handling
In reply to Greg Kroah-HartmanFrom: Hans Verkuil <[email protected]>
[ Upstream commit 49b20d981d723fae5a93843c617af2b2c23611ec ]
1) the numerator and/or denominator might be 0, in that case fall back to the default frame interval. This is per the spec and this caused a v4l2-compliance failure.
2) the updated frame interval wasn't returned in the s_frame_interval subdev op.
--- drivers/media/i2c/imx274.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/media/i2c/imx274.c +5 -3
@@ -1235,6 +1235,8 @@ static int imx274_s_frame_interval(struct v4l2_subdev *sd, ret =imx274_set_frame_interval (imx274, fi->interval);if (!ret) { + fi->interval = imx274->frame_interval; +/* * exposure time range is decided by frame interval * need to update it after frame interval changes
@@ -1730,9 +1732,9 @@ static int imx274_set_frame_interval(struct stimx274 *priv, __func__, frame_interval.numerator, frame_interval.denominator); -if (frame_interval.numerator ==0 ) { - err = -EINVAL ; - goto fail; +if (frame_interval.numerator ==0 || frame_interval.denominator ==0 ) { + frame_interval.denominator =IMX274_DEF_FRAME_RATE ; + frame_interval.numerator =1 ; } req_frame_rate = (u32)(frame_interval.denominator
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 45/214 mmc: via-sdmmc: Fix data race bug
In reply to Greg Kroah-HartmanFrom: Madhuparna Bhowmik <[email protected]>
[ Upstream commit 87d7ad089b318b4f319bf57f1daa64eb6d1d10ad ]
via_save_pcictrlreg() should be called with host->lock held as it writes to pm_pcictrl_reg, otherwise there can be a race condition between via_sd_suspend() and via_sdc_card_detect(). The same pattern is used in the function via_reset_pcictrl() as well, where via_save_pcictrlreg() is called with host->lock held.
Found by Linux Driver Verification project (linuxtesting.org).
--- drivers/mmc/host/via-sdmmc.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/mmc/host/via-sdmmc.c +3 -0
@@ -1259,11 +1259,14 @@ static void via_init_sdc_pm(struct via_crdr_mmc_host *host)static int via_sd_suspend (struct pci_dev *pcidev,pm_message_t state) {struct via_crdr_mmc_host *host; +unsigned long flags; host =pci_get_drvdata (pcidev); +spin_lock_irqsave (&host->lock, flags);via_save_pcictrlreg (host);via_save_sdcreg (host); +spin_unlock_irqrestore (&host->lock, flags);pci_save_state (pcidev);pci_enable_wake (pcidev,pci_choose_state (pcidev, state),0 );
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 46/214 drm/bridge/synopsys: dsi: add support for non-continuous HS clock
In reply to Greg Kroah-HartmanFrom: Antonio Borneo <[email protected]>
[ Upstream commit c6d94e37bdbb6dfe7e581e937a915ab58399b8a5 ]
Current code enables the HS clock when video mode is started or to send out a HS command, and disables the HS clock to send out a LP command. This is not what DSI spec specify.
Enable HS clock either in command and in video mode. Set automatic HS clock management for panels and devices that support non-continuous HS clock.
--- drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +7 -2
@@ -365,7 +365,6 @@ static void dw_mipi_message_config(struct dw_mipi_dsi *dsi,if (lpm) val |=CMD_MODE_ALL_LP ; -dsi_write (dsi,DSI_LPCLK_CTRL , lpm ?0 :PHY_TXREQUESTCLKHS );dsi_write (dsi,DSI_CMD_MODE_CFG , val); }
@@ -541,16 +540,22 @@ static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi)static void dw_mipi_dsi_set_mode (struct dw_mipi_dsi *dsi,unsigned long mode_flags) { +u32 val; +dsi_write (dsi,DSI_PWR_UP ,RESET );if (mode_flags &MIPI_DSI_MODE_VIDEO ) {dsi_write (dsi,DSI_MODE_CFG ,ENABLE_VIDEO_MODE );dw_mipi_dsi_video_mode_config (dsi); -dsi_write (dsi,DSI_LPCLK_CTRL ,PHY_TXREQUESTCLKHS ); }else {dsi_write (dsi,DSI_MODE_CFG ,ENABLE_CMD_MODE ); } + val =PHY_TXREQUESTCLKHS ; +if (dsi->mode_flags &MIPI_DSI_CLOCK_NON_CONTINUOUS ) + val |=AUTO_CLKLANE_CTRL ; +dsi_write (dsi,DSI_LPCLK_CTRL , val); +dsi_write (dsi,DSI_PWR_UP ,POWERUP ); }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 47/214 arm64: topology: Stop using MPIDR for topology information
In reply to Greg Kroah-HartmanFrom: Valentin Schneider <[email protected]>
[ Upstream commit 3102bc0e6ac752cc5df896acb557d779af4d82a1 ]
In the absence of ACPI or DT topology data, we fallback to haphazardly decoding *something* out of MPIDR. Sadly, the contents of that register are mostly unusable due to the implementation leniancy and things like Aff0 having to be capped to 15 (despite being encoded on 8 bits).
Consider a simple system with a single package of 32 cores, all under the same LLC. We ought to be shoving them in the same core_sibling mask, but MPIDR is going to look like:
| CPU | 0 | ... | 15 | 16 | ... | 31 | |------+---+-----+----+----+-----+----+ | Aff0 | 0 | ... | 15 | 0 | ... | 15 | | Aff1 | 0 | ... | 0 | 1 | ... | 1 | | Aff2 | 0 | ... | 0 | 0 | ... | 0 |
Which will eventually yield
core_sibling(0-15) == 0-15
core_sibling(16-31) == 16-31
NUMA woes
=========
If we try to play games with this and set up NUMA boundaries within those groups of 16 cores via e.g. QEMU:
# Node0: 0-9; Node1: 10-19
$ qemu-system-aarch64 <blah> \
-smp 20 -numa node,cpus=0-9,nodeid=0 -numa node,cpus=10-19,nodeid=1The scheduler's MC domain (all CPUs with same LLC) is going to be built via
arch_topology.c::cpu_coregroup_mask()
In there we try to figure out a sensible mask out of the topology information we have. In short, here we'll pick the smallest of NUMA or core sibling mask.
node_mask(CPU9) == 0-9
core_sibling(CPU9) == 0-15
MC mask for CPU9 will thus be 0-9, not a problem.
node_mask(CPU10) == 10-19
core_sibling(CPU10) == 0-15
MC mask for CPU10 will thus be 10-19, not a problem.
node_mask(CPU16) == 10-19
core_sibling(CPU16) == 16-19
MC mask for CPU16 will thus be 16-19... Uh oh. CPUs 16-19 are in two different unique MC spans, and the scheduler has no idea what to make of that. That triggers the WARN_ON() added by commit
ccf74128d66c ("sched/topology: Assert non-NUMA topology masks don't (partially) overlap")
Fixing MPIDR-derived topology
=============================
We could try to come up with some cleverer scheme to figure out which of the available masks to pick, but really if one of those masks resulted from MPIDR then it should be discarded because it's bound to be bogus.
I was hoping to give MPIDR a chance for SMT, to figure out which threads are in the same core using Aff1-3 as core ID, but Sudeep and Robin pointed out to me that there are systems out there where *all* cores have non-zero values in their higher affinity fields (e.g. RK3288 has "5" in all of its cores' MPIDR.Aff1), which would expose a bogus core ID to userspace.
Stop using MPIDR for topology information. When no other source of topology information is available, mark each CPU as its own core and its NUMA node as its LLC domain.
--- arch/arm64/kernel/topology.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-)
arch/arm64/kernel/topology.c +17 -15
@@ -35,21 +35,23 @@ void store_cpu_topology(unsigned int cpuid)if (mpidr &MPIDR_UP_BITMASK )return ; -/* Create cpu topology mapping based on MPIDR. */ -if (mpidr &MPIDR_MT_BITMASK ) { -/* Multiprocessor system : Multi-threads per core */ - cpuid_topo->thread_id =MPIDR_AFFINITY_LEVEL (mpidr,0 ); - cpuid_topo->core_id =MPIDR_AFFINITY_LEVEL (mpidr,1 ); - cpuid_topo->package_id =MPIDR_AFFINITY_LEVEL (mpidr,2 ) | -MPIDR_AFFINITY_LEVEL (mpidr,3 ) <<8 ; - }else { -/* Multiprocessor system : Single-thread per core */ - cpuid_topo->thread_id =-1 ; - cpuid_topo->core_id =MPIDR_AFFINITY_LEVEL (mpidr,0 ); - cpuid_topo->package_id =MPIDR_AFFINITY_LEVEL (mpidr,1 ) | -MPIDR_AFFINITY_LEVEL (mpidr,2 ) <<8 | -MPIDR_AFFINITY_LEVEL (mpidr,3 ) <<16 ; - } +/* +* This would be the place to create cpu topology based on MPIDR. +* +* However, it cannot be trusted to depict the actual topology; some +* pieces of the architecture enforce an artificial cap on Aff0 values +* (e.g. GICv3's ICC_SGI1R_EL1 limits it to 15), leading to an +* artificial cycling of Aff1, Aff2 and Aff3 values. IOW, these end up +* having absolutely no relationship to the actual underlying system +* topology, and cannot be reasonably used as core / package ID. +* +* If the MT bit is set, Aff0 *could* be used to define a thread ID, but +* we still wouldn't be able to obtain a sane core ID. This means we +* need to entirely ignore MPIDR for any topology deduction. +*/ + cpuid_topo->thread_id =-1 ; + cpuid_topo->core_id = cpuid; + cpuid_topo->package_id =cpu_to_node (cpuid); pr_debug("CPU%u: cluster %d core %d thread %d mpidr %#016llx\n", cpuid, cpuid_topo->package_id, cpuid_topo->core_id,
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 48/214 printk: reduce LOG_BUF_SHIFT range for H8300
In reply to Greg Kroah-HartmanFrom: John Ogness <[email protected]>
[ Upstream commit 550c10d28d21bd82a8bb48debbb27e6ed53262f6 ]
The .bss section for the h8300 is relatively small. A value of CONFIG_LOG_BUF_SHIFT that is larger than 19 will create a static printk ringbuffer that is too large. Limit the range appropriately for the H8300.
--- init/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
init/Kconfig +2 -1
@@ -594,7 +594,8 @@ config IKHEADERS config LOG_BUF_SHIFT int "Kernel log buffer size (16 => 64KB, 17 => 128KB)" - range 12 25 + range 12 25 if !H8300 + range 12 19 if H8300 default 17 depends on PRINTK help
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 49/214 ia64: kprobes: Use generic kretprobe trampoline handler
In reply to Greg Kroah-HartmanFrom: Masami Hiramatsu <[email protected]>
[ Upstream commit e792ff804f49720ce003b3e4c618b5d996256a18 ]
Use the generic kretprobe trampoline handler. Don't use framepointer verification.
--- arch/ia64/kernel/kprobes.c | 77 +------------------------------------- 1 file changed, 2 insertions(+), 75 deletions(-)
arch/ia64/kernel/kprobes.c +2 -75
@@ -396,83 +396,9 @@ static void kretprobe_trampoline(void) { } -/* -* At this point the target function has been tricked into -* returning into our trampoline. Lookup the associated instance -* and then: -* - call the handler function -* - cleanup by marking the instance as unused -* - long jump back to the original return address -*/ int __kprobes trampoline_probe_handler (struct kprobe *p,struct pt_regs *regs) { -struct kretprobe_instance *ri =NULL ; -struct hlist_head *head, empty_rp; -struct hlist_node *tmp; -unsigned long flags, orig_ret_address =0 ; -unsigned long trampoline_address = - ((struct fnptr *)kretprobe_trampoline)->ip; - -INIT_HLIST_HEAD (&empty_rp); -kretprobe_hash_lock (current, &head, &flags); - -/* -* It is possible to have multiple instances associated with a given -* task either because an multiple functions in the call path -* have a return probe installed on them, and/or more than one return -* return probe was registered for a target function. -* -* We can handle this because: -* - instances are always inserted at the head of the list -* - when multiple return probes are registered for the same -* function, the first instance's ret_addr will point to the -* real return address, and all the rest will point to -* kretprobe_trampoline -*/ -hlist_for_each_entry_safe (ri, tmp, head, hlist) { -if (ri->task != current) -/* another task is sharing our hash bucket */ -continue ; - - orig_ret_address = (unsigned long )ri->ret_addr; -if (orig_ret_address != trampoline_address) -/* -* This is the real return address. Any other -* instances associated with this task are for -* other calls deeper on the call stack -*/ -break ; - } - - regs->cr_iip = orig_ret_address; - -hlist_for_each_entry_safe (ri, tmp, head, hlist) { -if (ri->task != current) -/* another task is sharing our hash bucket */ -continue ; - -if (ri->rp && ri->rp->handler) - ri->rp->handler (ri, regs); - - orig_ret_address = (unsigned long )ri->ret_addr; -recycle_rp_inst (ri, &empty_rp); - -if (orig_ret_address != trampoline_address) -/* -* This is the real return address. Any other -* instances associated with this task are for -* other calls deeper on the call stack -*/ -break ; - } -kretprobe_assert (ri, orig_ret_address, trampoline_address); - -kretprobe_hash_unlock (current, &flags); - -hlist_for_each_entry_safe (ri, tmp, &empty_rp, hlist) { -hlist_del (&ri->hlist); -kfree (ri); - } + regs->cr_iip =__kretprobe_trampoline_handler (regs, kretprobe_trampoline,NULL );/* * By returning a non-zero value, we are telling * kprobe_handler() that we don't want the post_handler
@@ -485,6 +411,7 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs) { ri->ret_addr = (kprobe_opcode_t *)regs->b0; + ri->fp =NULL ;/* Replace the return addr with trampoline addr */ regs->b0 = ((struct fnptr *)kretprobe_trampoline)->ip;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 50/214 kgdb: Make "kgdbcon" work properly with "kgdb_earlycon"
In reply to Greg Kroah-HartmanFrom: Douglas Anderson <[email protected]>
[ Upstream commit b18b099e04f450cdc77bec72acefcde7042bd1f3 ]
On my system the kernel processes the "kgdb_earlycon" parameter before the "kgdbcon" parameter. When we setup "kgdb_earlycon" we'll end up in kgdb_register_callbacks() and "kgdb_use_con" won't have been set yet so we'll never get around to starting "kgdbcon". Let's remedy this by detecting that the IO module was already registered when setting "kgdb_use_con" and registering the console then.
As part of this, to avoid pre-declaring things, move the handling of the "kgdbcon" further down in the file.
--- kernel/debug/debug_core.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-)
kernel/debug/debug_core.c +14 -8
@@ -96,14 +96,6 @@ int dbg_switch_cpu;/* Use kdb or gdbserver mode */ int dbg_kdb_mode =1 ; -static int __init opt_kgdb_con (char *str) -{ - kgdb_use_con =1 ; -return 0 ; -} - -early_param ("kgdbcon" , opt_kgdb_con); -module_param (kgdb_use_con, int,0644 );module_param (kgdbreboot, int,0644 );
@@ -876,6 +868,20 @@ static struct console kgdbcons = { .index = -1, }; +static int __init opt_kgdb_con (char *str) +{ + kgdb_use_con =1 ; + +if (kgdb_io_module_registered && !kgdb_con_registered) { +register_console (&kgdbcons); + kgdb_con_registered =1 ; + } + +return 0 ; +} + +early_param ("kgdbcon" , opt_kgdb_con); +#ifdef CONFIG_MAGIC_SYSRQ static void sysrq_handle_dbg (int key) {
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 51/214 bpf: Permit map_ptr arithmetic with opcode add and offset 0
In reply to Greg Kroah-HartmanFrom: Yonghong Song <[email protected]>
[ Upstream commit 7c6967326267bd5c0dded0a99541357d70dd11ac ]
Commit 41c48f3a98231 ("bpf: Support access
to bpf map fields") added support to access map fields with CORE support. For example,
struct bpf_map {
__u32 max_entries;
} __attribute__((preserve_access_index));
struct bpf_array {
struct bpf_map map;
__u32 elem_size;
} __attribute__((preserve_access_index));
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 4);
__type(key, __u32);
__type(value, __u32);
} m_array SEC(".maps");
SEC("cgroup_skb/egress")
int cg_skb(void *ctx)
{
struct bpf_array *array = (struct bpf_array *)&m_array;
/* .. array->map.max_entries .. */
}In kernel, bpf_htab has similar structure,
struct bpf_htab {
struct bpf_map map;
...
}In the above cg_skb(), to access array->map.max_entries, with CORE, the clang will generate two builtin's.
base = &m_array;
/* access array.map */
map_addr = __builtin_preserve_struct_access_info(base, 0, 0);
/* access array.map.max_entries */
max_entries_addr = __builtin_preserve_struct_access_info(map_addr, 0, 0);
max_entries = *max_entries_addr;In the current llvm, if two builtin's are in the same function or
in the same function after inlining, the compiler is smart enough to chain them together and generates like below:
base = &m_array;
max_entries = *(base + reloc_offset); /* reloc_offset = 0 in this case */
and we are fine.
But if we force no inlining for one of functions in test_map_ptr() selftest, e.g., check_default(), the above two __builtin_preserve_* will be in two different functions. In this case, we will have code like:
func check_hash():
reloc_offset_map = 0;
base = &m_array;
map_base = base + reloc_offset_map;
check_default(map_base, ...)
func check_default(map_base, ...):
max_entries = *(map_base + reloc_offset_max_entries);In kernel, map_ptr (CONST_PTR_TO_MAP) does not allow any arithmetic.
The above "map_base = base + reloc_offset_map" will trigger a verifier failure.
; VERIFY(check_default(&hash->map, map));
0: (18) r7 = 0xffffb4fe8018a004
2: (b4) w1 = 110
3: (63) *(u32 *)(r7 +0) = r1
R1_w=invP110 R7_w=map_value(id=0,off=4,ks=4,vs=8,imm=0) R10=fp0
; VERIFY_TYPE(BPF_MAP_TYPE_HASH, check_hash);
4: (18) r1 = 0xffffb4fe8018a000
6: (b4) w2 = 1
7: (63) *(u32 *)(r1 +0) = r2
R1_w=map_value(id=0,off=0,ks=4,vs=8,imm=0) R2_w=invP1 R7_w=map_value(id=0,off=4,ks=4,vs=8,imm=0) R10=fp0
8: (b7) r2 = 0
9: (18) r8 = 0xffff90bcb500c000
11: (18) r1 = 0xffff90bcb500c000
13: (0f) r1 += r2
R1 pointer arithmetic on map_ptr prohibited
To fix the issue, let us permit map_ptr + 0 arithmetic which will result in exactly the same map_ptr.
--- kernel/bpf/verifier.c | 4 ++++ 1 file changed, 4 insertions(+)
kernel/bpf/verifier.c +4 -0
@@ -4427,6 +4427,10 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, dst, reg_type_str[ptr_reg->type]);return -EACCES ;case CONST_PTR_TO_MAP : +/* smin_val represents the known value */ +if (known && smin_val ==0 && opcode ==BPF_ADD ) +break ; +/* fall-through */ case PTR_TO_PACKET_END :case PTR_TO_SOCKET :case PTR_TO_SOCKET_OR_NULL :
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 52/214 media: uvcvideo: Fix dereference of out-of-bound list iterator
In reply to Greg Kroah-HartmanFrom: Daniel W. S. Almeida <[email protected]>
[ Upstream commit f875bcc375c738bf2f599ff2e1c5b918dbd07c45 ]
Fixes the following coccinelle report:
drivers/media/usb/uvc/uvc_ctrl.c:1860:5-11:
ERROR: invalid reference to the index variable of the iterator on line 1854
by adding a boolean variable to check if the loop has found the
Found using - Coccinelle (http://coccinelle.lip6.fr)
[Replace cursor variable with bool found]
--- drivers/media/usb/uvc/uvc_ctrl.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/media/usb/uvc/uvc_ctrl.c +9 -4
@@ -1848,30 +1848,35 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain, {struct uvc_entity *entity;struct uvc_control *ctrl; -unsigned int i, found =0 ; +unsigned int i; +bool found;u32 reqflags;u16 size;u8 *data =NULL ;int ret;/* Find the extension unit. */ + found = false;list_for_each_entry (entity, &chain->entities, chain) {if (UVC_ENTITY_TYPE (entity) ==UVC_VC_EXTENSION_UNIT && - entity->id == xqry->unit) + entity->id == xqry->unit) { + found = true;break ; + } } -if (entity->id != xqry->unit) { +if (!found) {uvc_trace (UVC_TRACE_CONTROL ,"Extension unit %u not found.\n" , xqry->unit);return -ENOENT ; }/* Find the control and perform delayed initialization if needed. */ + found = false;for (i =0 ; i < entity->ncontrols; ++i) { ctrl = &entity->controls[i];if (ctrl->index == xqry->selector -1 ) { - found =1 ; + found = true;break ; } }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 53/214 selftests/bpf: Define string const as global for test_sysctl_prog.c
In reply to Greg Kroah-HartmanFrom: Yonghong Song <[email protected]>
[ Upstream commit 6e057fc15a2da4ee03eb1fa6889cf687e690106e ]
When tweaking llvm optimizations, I found that selftest build failed
with the following error:
libbpf: elf: skipping unrecognized data section(6) .rodata.str1.1
libbpf: prog 'sysctl_tcp_mem': bad map relo against '.L__const.is_tcp_mem.tcp_mem_name'
in section '.rodata.str1.1'
Error: failed to open BPF object file: Relocation failed
make: *** [/work/net-next/tools/testing/selftests/bpf/test_sysctl_prog.skel.h] Error 255
make: *** Deleting file `/work/net-next/tools/testing/selftests/bpf/test_sysctl_prog.skel.h'
The local string constant "tcp_mem_name" is put into '.rodata.str1.1' section which libbpf cannot handle. Using untweaked upstream llvm, "tcp_mem_name" is completely inlined after loop unrolling.
Commit 7fb5eefd7639 ("selftests/bpf: Fix test_sysctl_loop{1, 2} failure due to clang change") solved a similar problem by defining the string const as a global. Let us do the same here
for test_sysctl_prog.c so it can weather future potential llvm changes.
--- tools/testing/selftests/bpf/progs/test_sysctl_prog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/testing/selftests/bpf/progs/test_sysctl_prog.c +2 -2
@@ -19,11 +19,11 @@#define ARRAY_SIZE (x) (sizeof(x) / sizeof((x)[0]))#endif +const char tcp_mem_name[] ="net/ipv4/tcp_mem" ; static __always_inline int is_tcp_mem(struct bpf_sysctl *ctx) { -char tcp_mem_name[] ="net/ipv4/tcp_mem" ;unsigned char i; -char name[64 ]; +char name[sizeof (tcp_mem_name)];int ret;memset (name,0 ,sizeof (name));
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 54/214 samples/bpf: Fix possible deadlock in xdpsock
In reply to Greg Kroah-HartmanFrom: Magnus Karlsson <[email protected]>
[ Upstream commit 5a2a0dd88f0f267ac5953acd81050ae43a82201f ]
Fix a possible deadlock in the l2fwd application in xdpsock that can occur when there is no space in the Tx ring. There are two ways to get the kernel to consume entries in the Tx ring: calling sendto() to make it send packets and freeing entries from the completion ring, as the kernel will not send a packet if there is no space for it to add a completion entry in the completion ring. The Tx loop in l2fwd only used to call sendto(). This patches adds cleaning the completion ring in that loop.
--- samples/bpf/xdpsock_user.c | 1 + 1 file changed, 1 insertion(+)
samples/bpf/xdpsock_user.c +1 -0
@@ -677,6 +677,7 @@ static void l2fwd(struct xsk_socket_info *xsk, struct pollfd *fds)while (ret != rcvd) {if (ret <0 )exit_with_error (-ret); +complete_tx_l2fwd (xsk, fds);if (xsk_ring_prod__needs_wakeup (&xsk->tx))kick_tx (xsk); ret =xsk_ring_prod__reserve (&xsk->tx, rcvd, &idx_tx);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 55/214 riscv: Define AT_VECTOR_SIZE_ARCH for ARCH_DLINFO
In reply to Greg Kroah-HartmanFrom: Zong Li <[email protected]>
[ Upstream commit b5fca7c55f9fbab5ad732c3bce00f31af6ba5cfa ]
AT_VECTOR_SIZE_ARCH should be defined with the maximum number of NEW_AUX_ENT entries that ARCH_DLINFO can contain, but it wasn't defined for RISC-V at all even though ARCH_DLINFO will contain one NEW_AUX_ENT for the VDSO address.
--- arch/riscv/include/uapi/asm/auxvec.h | 3 +++ 1 file changed, 3 insertions(+)
arch/riscv/include/uapi/asm/auxvec.h +3 -0
@@ -10,4 +10,7 @@/* vDSO location */ #define AT_SYSINFO_EHDR 33 +/* entries in ARCH_DLINFO */ +#define AT_VECTOR_SIZE_ARCH 1 +#endif /* _UAPI_ASM_RISCV_AUXVEC_H */
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 56/214 cpufreq: sti-cpufreq: add stih418 support
In reply to Greg Kroah-HartmanFrom: Alain Volmat <[email protected]>
[ Upstream commit 01a163c52039e9426c7d3d3ab16ca261ad622597 ]
The STiH418 can be controlled the same way as STiH407 & STiH410 regarding cpufreq.
--- drivers/cpufreq/sti-cpufreq.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/cpufreq/sti-cpufreq.c +4 -2
@@ -141,7 +141,8 @@ static const struct reg_field sti_stih407_dvfs_regfields[DVFS_MAX_REGFIELDS] = {static const struct reg_field *sti_cpufreq_match (void ) {if (of_machine_is_compatible ("st,stih407" ) || -of_machine_is_compatible ("st,stih410" )) +of_machine_is_compatible ("st,stih410" ) || +of_machine_is_compatible ("st,stih418" ))return sti_stih407_dvfs_regfields;return NULL ;
@@ -258,7 +259,8 @@ static int sti_cpufreq_init(void)int ret;if ((!of_machine_is_compatible ("st,stih407" )) && - (!of_machine_is_compatible ("st,stih410" ))) + (!of_machine_is_compatible ("st,stih410" )) && + (!of_machine_is_compatible ("st,stih418" )))return -ENODEV ; ddata.cpu =get_cpu_device (0 );
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 57/214 USB: adutux: fix debugging
In reply to Greg Kroah-HartmanFrom: Oliver Neukum <[email protected]>
[ Upstream commit c56150c1bc8da5524831b1dac2eec3c67b89f587 ]
Handling for removal of the controller was missing at one place. Add it.
--- drivers/usb/misc/adutux.c | 1 + 1 file changed, 1 insertion(+)
drivers/usb/misc/adutux.c +1 -0
@@ -209,6 +209,7 @@ static void adu_interrupt_out_callback(struct urb *urb)if (status !=0 ) {if ((status != -ENOENT ) && + (status != -ESHUTDOWN ) && (status != -ECONNRESET )) { dev_dbg(&dev->udev->dev, "%s :nonzero status received: %d\n", __func__,
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 58/214 uio: free uio id after uio file node is freed
In reply to Greg Kroah-HartmanFrom: Lang Dai <[email protected]>
[ Upstream commit 8fd0e2a6df262539eaa28b0a2364cca10d1dc662 ]
uio_register_device() do two things.
1) get an uio id from a global pool, e.g. the id is <A>
2) create file nodes like /sys/class/uio/uio<A>
uio_unregister_device() do two things.
1) free the uio id <A> and return it to the global pool
2) free the file node /sys/class/uio/uio<A>
There is a situation is that one worker is calling uio_unregister_device(), and another worker is calling uio_register_device().
If the two workers are X and Y, they go as below sequence,
1) X free the uio id <AAA>
2) Y get an uio id <AAA>
3) Y create file node /sys/class/uio/uio<AAA>
4) X free the file note /sys/class/uio/uio<AAA>
Then it will failed at the 3rd step and cause the phenomenon we saw as it is creating a duplicated file node.
Failure reports as follows:
sysfs: cannot create duplicate filename '/class/uio/uio10'
Call Trace: sysfs_do_create_link_sd.isra.2+0x9e/0xb0 sysfs_create_link+0x25/0x40 device_add+0x2c4/0x640 __uio_register_device+0x1c5/0x576 [uio] adf_uio_init_bundle_dev+0x231/0x280 [intel_qat] adf_uio_register+0x1c0/0x340 [intel_qat] adf_dev_start+0x202/0x370 [intel_qat] adf_dev_start_async+0x40/0xa0 [intel_qat] process_one_work+0x14d/0x410 worker_thread+0x4b/0x460 kthread+0x105/0x140 ? process_one_work+0x410/0x410 ? kthread_bind+0x40/0x40 ret_from_fork+0x1f/0x40 Code: 85 c0 48 89 c3 74 12 b9 00 10 00 00 48 89 c2 31 f6 4c 89 ef e8 ec c4 ff ff 4c 89 e2 48 89 de 48 c7 c7 e8 b4 ee b4 e8 6a d4 d7 ff <0f> 0b 48 89 df e8 20 fa f3 ff 5b 41 5c 41 5d 5d c3 66 0f 1f 84 ---[ end trace a7531c1ed5269e84 ]--- c6xxvf b002:00:00.0: Failed to register UIO devices c6xxvf b002:00:00.0: Failed to register UIO devices
--- drivers/uio/uio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/uio/uio.c +2 -2
@@ -1010,8 +1010,6 @@ void uio_unregister_device(struct uio_info *info) idev = info->uio_dev; -uio_free_minor (idev); -mutex_lock (&idev->info_lock);uio_dev_del_attributes (idev);
@@ -1026,6 +1024,8 @@ void uio_unregister_device(struct uio_info *info)device_unregister (&idev->dev); +uio_free_minor (idev); +return ; }EXPORT_SYMBOL_GPL (uio_unregister_device);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 59/214 coresight: Make sysfs functional on topologies with per core sink
In reply to Greg Kroah-HartmanFrom: Linu Cherian <[email protected]>
[ Upstream commit 6d578258b955fc8888e1bbd9a8fefe7b10065a84 ]
Coresight driver assumes sink is common across all the ETMs, and tries to build a path between ETM and the first enabled sink found using bus based search. This breaks sysFS usage on implementations that has multiple per core sinks in enabled state.
To fix this, coresight_get_enabled_sink API is updated to do a connection based search starting from the given source, instead of bus based search.
With sink selection using sysfs depecrated for perf interface, provision for reset is removed as well in this API.
--- drivers/hwtracing/coresight/coresight-priv.h | 3 +- drivers/hwtracing/coresight/coresight.c | 62 +++++++++----------- 2 files changed, 29 insertions(+), 36 deletions(-)
drivers/hwtracing/coresight/coresight-priv.h +2 -1
@@ -147,7 +147,8 @@ static inline void coresight_write_reg_pair(void __iomem *addr, u64 val,void coresight_disable_path (struct list_head *path);int coresight_enable_path (struct list_head *path,u32 mode,void *sink_data);struct coresight_device *coresight_get_sink (struct list_head *path); -struct coresight_device *coresight_get_enabled_sink (bool reset); +struct coresight_device * +coresight_get_enabled_sink (struct coresight_device *source);struct coresight_device *coresight_get_sink_by_id (u32 id);struct list_head *coresight_build_path (struct coresight_device *csdev,struct coresight_device *sink);
drivers/hwtracing/coresight/coresight.c +27 -35
88 lines not on this page · raw message
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 60/214 usb: xhci: omit duplicate actions when suspending a runtime suspended host.
In reply to Greg Kroah-HartmanFrom: Peter Chen <[email protected]>
[ Upstream commit 18a367e8947d72dd91b6fc401e88a2952c6363f7 ]
If the xhci-plat.c is the platform driver, after the runtime pm is enabled, the xhci_suspend is called if nothing is connected on the port. When the system goes to suspend, it will call xhci_suspend again if USB wakeup is enabled.
Since the runtime suspend wakeup setting is not always the same as system suspend wakeup setting, eg, at runtime suspend we always need wakeup if the controller is in low power mode; but at system suspend, we may not need wakeup. So, we move the judgement after changing wakeup setting.
[commit message rewording -Mathias]
--- drivers/usb/host/xhci.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/usb/host/xhci.c +5 -2
@@ -982,12 +982,15 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) xhci->shared_hcd->state != HC_STATE_SUSPENDED)return -EINVAL ; -xhci_dbc_suspend (xhci); -/* Clear root port wake on bits if wakeup not allowed. */ if (!do_wakeup)xhci_disable_port_wake_on_bits (xhci); +if (!HCD_HW_ACCESSIBLE (hcd)) +return 0 ; + +xhci_dbc_suspend (xhci); +/* Don't poll the roothubs on bus suspend. */ xhci_dbg (xhci,"%s: stopping port polling.\n" , __func__);clear_bit (HCD_FLAG_POLL_RH , &hcd->flags);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 61/214 SUNRPC: Mitigate cond_resched() in xprt_transmit()
In reply to Greg Kroah-HartmanFrom: Chuck Lever <[email protected]>
[ Upstream commit 6f9f17287e78e5049931af2037b15b26d134a32a ]
The original purpose of this expensive call is to prevent a long queue of requests from blocking other work.
The cond_resched() call is unnecessary after just a single send operation.
For longer queues, instead of invoking the kernel scheduler, simply release the transport send lock and return to the RPC scheduler.
--- net/sunrpc/xprt.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
net/sunrpc/xprt.c +4 -2
@@ -1503,10 +1503,13 @@ xprt_transmit(struct rpc_task *task) {struct rpc_rqst *next, *req = task->tk_rqstp;struct rpc_xprt *xprt = req->rq_xprt; -int status; +int counter, status;spin_lock (&xprt->queue_lock); + counter =0 ;while (!list_empty (&xprt->xmit_queue)) { +if (++counter ==20 ) +break ; next =list_first_entry (&xprt->xmit_queue, struct rpc_rqst, rq_xmit);xprt_pin_rqst (next);
@@ -1514,7 +1517,6 @@ xprt_transmit(struct rpc_task *task) status =xprt_request_transmit (next, task);if (status == -EBADMSG && next != req) status =0 ; -cond_resched ();spin_lock (&xprt->queue_lock);xprt_unpin_rqst (next);if (status ==0 ) {
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 62/214 arm64/mm: return cpu_all_mask when node is NUMA_NO_NODE
In reply to Greg Kroah-HartmanFrom: Zhengyuan Liu <[email protected]>
[ Upstream commit a194c5f2d2b3a05428805146afcabe5140b5d378 ]
The @node passed to cpumask_of_node() can be NUMA_NO_NODE, in that case it will trigger the following WARN_ON(node >= nr_node_ids) due to mismatched data types of @node and @nr_node_ids. Actually we should return cpu_all_mask just like most other architectures do if passed NUMA_NO_NODE.
Also add a similar check to the inline cpumask_of_node() in numa.h.
--- arch/arm64/include/asm/numa.h | 3 +++ arch/arm64/mm/numa.c | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-)
arch/arm64/include/asm/numa.h +3 -0
@@ -25,6 +25,9 @@ const struct cpumask *cpumask_of_node(int node);/* Returns a pointer to the cpumask of CPUs on Node 'node'. */ static inline const struct cpumask *cpumask_of_node (int node) { +if (node ==NUMA_NO_NODE ) +return cpu_all_mask; +return node_to_cpumask_map[node]; }#endif
arch/arm64/mm/numa.c +5 -1
@@ -46,7 +46,11 @@ EXPORT_SYMBOL(node_to_cpumask_map);*/ const struct cpumask *cpumask_of_node (int node) { -if (WARN_ON (node >= nr_node_ids)) + +if (node ==NUMA_NO_NODE ) +return cpu_all_mask; + +if (WARN_ON (node <0 || node >= nr_node_ids))return cpu_none_mask;if (WARN_ON (node_to_cpumask_map[node] ==NULL ))
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 63/214 can: flexcan: disable clocks during stop mode
In reply to Greg Kroah-HartmanFrom: Joakim Zhang <[email protected]>
[ Upstream commit 02f71c6605e1f8259c07f16178330db766189a74 ]
Disable clocks while CAN core is in stop mode.
--- drivers/net/can/flexcan.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-)
drivers/net/can/flexcan.c +20 -10
@@ -1703,8 +1703,6 @@ static int __maybe_unused flexcan_suspend(struct device *device) err =flexcan_chip_disable (priv);if (err)return err; - - err =pm_runtime_force_suspend (device); }netif_stop_queue (dev);netif_device_detach (dev);
@@ -1730,10 +1728,6 @@ static int __maybe_unused flexcan_resume(struct device *device)if (err)return err; }else { - err =pm_runtime_force_resume (device); -if (err) -return err; - err =flexcan_chip_enable (priv); } }
@@ -1764,8 +1758,16 @@ static int __maybe_unused flexcan_noirq_suspend(struct device *device)struct net_device *dev =dev_get_drvdata (device);struct flexcan_priv *priv =netdev_priv (dev); -if (netif_running (dev) &&device_may_wakeup (device)) -flexcan_enable_wakeup_irq (priv, true); +if (netif_running (dev)) { +int err; + +if (device_may_wakeup (device)) +flexcan_enable_wakeup_irq (priv, true); + + err =pm_runtime_force_suspend (device); +if (err) +return err; + }return 0 ; }
@@ -1775,8 +1777,16 @@ static int __maybe_unused flexcan_noirq_resume(struct device *device)struct net_device *dev =dev_get_drvdata (device);struct flexcan_priv *priv =netdev_priv (dev); -if (netif_running (dev) &&device_may_wakeup (device)) -flexcan_enable_wakeup_irq (priv, false); +if (netif_running (dev)) { +int err; + + err =pm_runtime_force_resume (device); +if (err) +return err; + +if (device_may_wakeup (device)) +flexcan_enable_wakeup_irq (priv, false); + }return 0 ; }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 64/214 xfs: dont free rt blocks when were doing a REMAP bunmapi call
In reply to Greg Kroah-HartmanFrom: Darrick J. Wong <[email protected]>
[ Upstream commit 8df0fa39bdd86ca81a8d706a6ed9d33cc65ca625 ]
When callers pass XFS_BMAPI_REMAP into xfs_bunmapi, they want the extent to be unmapped from the given file fork without the extent being freed. We do this for non-rt files, but we forgot to do this for realtime files. So far this isn't a big deal since nobody makes a bunmapi call to a rt file with the REMAP flag set, but don't leave a logic bomb.
--- fs/xfs/libxfs/xfs_bmap.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-)
fs/xfs/libxfs/xfs_bmap.c +12 -7
@@ -4985,20 +4985,25 @@ xfs_bmap_del_extent_real( flags =XFS_ILOG_CORE ;if (whichfork ==XFS_DATA_FORK &&XFS_IS_REALTIME_INODE (ip)) { -xfs_fsblock_t bno;xfs_filblks_t len;xfs_extlen_t mod; - bno =div_u64_rem (del->br_startblock, mp->m_sb.sb_rextsize, - &mod); -ASSERT (mod ==0 ); len =div_u64_rem (del->br_blockcount, mp->m_sb.sb_rextsize, &mod);ASSERT (mod ==0 ); - error =xfs_rtfree_extent (tp, bno, (xfs_extlen_t )len); -if (error) - goto done; +if (!(bflags &XFS_BMAPI_REMAP )) { +xfs_fsblock_t bno; + + bno =div_u64_rem (del->br_startblock, + mp->m_sb.sb_rextsize, &mod); +ASSERT (mod ==0 ); + + error =xfs_rtfree_extent (tp, bno, (xfs_extlen_t )len); +if (error) + goto done; + } + do_fx =0 ; nblks = len * mp->m_sb.sb_rextsize; qfield =XFS_TRANS_DQ_RTBCOUNT ;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 65/214 ACPI: Add out of bounds and numa_off protections to pxm_to_node()
In reply to Greg Kroah-HartmanFrom: Jonathan Cameron <[email protected]>
[ Upstream commit 8a3decac087aa897df5af04358c2089e52e70ac4 ]
The function should check the validity of the pxm value before using it to index the pxm_to_node_map[] array.
Whilst hardening this code may be good in general, the main intent here is to enable following patches that use this function to replace acpi_map_pxm_to_node() for non SRAT usecases which should return NO_NUMA_NODE for PXM entries not matching with those in SRAT.
--- drivers/acpi/numa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/numa.c +1 -1
@@ -31,7 +31,7 @@ int acpi_numa __initdata;int pxm_to_node (int pxm) { -if (pxm <0 ) +if (pxm <0 || pxm >=MAX_PXM_DOMAINS || numa_off)return NUMA_NO_NODE ;return pxm_to_node_map[pxm]; }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 66/214 brcmfmac: Fix warning message after dongle setup failed
In reply to Greg Kroah-HartmanFrom: Wright Feng <[email protected]>
[ Upstream commit 6aa5a83a7ed8036c1388a811eb8bdfa77b21f19c ]
Brcmfmac showed warning message in fweh.c when checking the size of event queue which is not initialized. Therefore, we only cancel the worker and reset event handler only when it is initialized.
[ 145.505899] brcmfmac 0000:02:00.0: brcmf_pcie_setup: Dongle setup [ 145.929970] ------------[ cut here ]------------ [ 145.929994] WARNING: CPU: 0 PID: 288 at drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c:312 brcmf_fweh_detach+0xbc/0xd0 [brcmfmac] ... [ 145.930029] Call Trace: [ 145.930036] brcmf_detach+0x77/0x100 [brcmfmac] [ 145.930043] brcmf_pcie_remove+0x79/0x130 [brcmfmac] [ 145.930046] pci_device_remove+0x39/0xc0 [ 145.930048] device_release_driver_internal+0x141/0x200 [ 145.930049] device_release_driver+0x12/0x20 [ 145.930054] brcmf_pcie_setup+0x101/0x3c0 [brcmfmac] [ 145.930060] brcmf_fw_request_done+0x11d/0x1f0 [brcmfmac] [ 145.930062] ? lock_timer_base+0x7d/0xa0 [ 145.930063] ? internal_add_timer+0x1f/0xa0 [ 145.930064] ? add_timer+0x11a/0x1d0 [ 145.930066] ? __kmalloc_track_caller+0x18c/0x230 [ 145.930068] ? kstrdup_const+0x23/0x30 [ 145.930069] ? add_dr+0x46/0x80 [ 145.930070] ? devres_add+0x3f/0x50 [ 145.930072] ? usermodehelper_read_unlock+0x15/0x20 [ 145.930073] ? _request_firmware+0x288/0xa20 [ 145.930075] request_firmware_work_func+0x36/0x60 [ 145.930077] process_one_work+0x144/0x360 [ 145.930078] worker_thread+0x4d/0x3c0 [ 145.930079] kthread+0x112/0x150 [ 145.930080] ? rescuer_thread+0x340/0x340 [ 145.930081] ? kthread_park+0x60/0x60 [ 145.930083] ret_from_fork+0x25/0x30
--- .../net/wireless/broadcom/brcm80211/brcmfmac/fweh.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c +6 -4
@@ -304,10 +304,12 @@ void brcmf_fweh_detach(struct brcmf_pub *drvr) {struct brcmf_fweh_info *fweh = &drvr->fweh; -/* cancel the worker */ -cancel_work_sync (&fweh->event_work); -WARN_ON (!list_empty (&fweh->event_q)); -memset (fweh->evt_handler,0 ,sizeof (fweh->evt_handler)); +/* cancel the worker if initialized */ +if (fweh->event_work.func) { +cancel_work_sync (&fweh->event_work); +WARN_ON (!list_empty (&fweh->event_q)); +memset (fweh->evt_handler,0 ,sizeof (fweh->evt_handler)); + } }/**
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 67/214 drivers/net/wan/hdlc_fr: Correctly handle special skb->protocol values
In reply to Greg Kroah-HartmanFrom: Xie He <[email protected]>
[ Upstream commit 8306266c1d51aac9aa7aa907fe99032a58c6382c ]
The fr_hard_header function is used to prepend the header to skbs before transmission. It is used in 3 situations:
1) When a control packet is generated internally in this driver;
2) When a user sends an skb on an Ethernet-emulating PVC device;
3) When a user sends an skb on a normal PVC device.
These 3 situations need to be handled differently by fr_hard_header. Different headers should be prepended to the skb in different situations.
Currently fr_hard_header distinguishes these 3 situations using skb->protocol. For situation 1 and 2, a special skb->protocol value will be assigned before calling fr_hard_header, so that it can recognize these 2 situations. All skb->protocol values other than these special ones are treated by fr_hard_header as situation 3.
However, it is possible that in situation 3, the user sends an skb with one of the special skb->protocol values. In this case, fr_hard_header would incorrectly treat it as situation 1 or 2.
This patch tries to solve this issue by using skb->dev instead of skb->protocol to distinguish between these 3 situations. For situation 1, skb->dev would be NULL; for situation 2, skb->dev->type would be ARPHRD_ETHER; and for situation 3, skb->dev->type would be ARPHRD_DLCI.
This way fr_hard_header would be able to distinguish these 3 situations correctly regardless what skb->protocol value the user tries to use in situation 3.
--- drivers/net/wan/hdlc_fr.c | 98 ++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 47 deletions(-)
drivers/net/wan/hdlc_fr.c +51 -47
@@ -273,63 +273,69 @@ static inline struct net_device **get_dev_p(struct pvc_device *pvc,static int fr_hard_header (struct sk_buff **skb_p,u16 dlci) { -u16 head_len;struct sk_buff *skb = *skb_p; -switch (skb->protocol) { -case cpu_to_be16 (NLPID_CCITT_ANSI_LMI ): - head_len =4 ; -skb_push (skb, head_len); - skb->data[3 ] =NLPID_CCITT_ANSI_LMI ; -break ; - -case cpu_to_be16 (NLPID_CISCO_LMI ): - head_len =4 ; -skb_push (skb, head_len); - skb->data[3 ] =NLPID_CISCO_LMI ; -break ; - -case cpu_to_be16 (ETH_P_IP ): - head_len =4 ; -skb_push (skb, head_len); - skb->data[3 ] =NLPID_IP ; -break ; - -case cpu_to_be16 (ETH_P_IPV6 ): - head_len =4 ; -skb_push (skb, head_len); - skb->data[3 ] =NLPID_IPV6 ; -break ; - -case cpu_to_be16 (ETH_P_802_3 ): - head_len =10 ; -if (skb_headroom (skb) < head_len) { -struct sk_buff *skb2 =skb_realloc_headroom (skb, - head_len); +if (!skb->dev) {/* Control packets */ +switch (dlci) { +case LMI_CCITT_ANSI_DLCI : +skb_push (skb,4 ); + skb->data[3 ] =NLPID_CCITT_ANSI_LMI ; +break ; + +case LMI_CISCO_DLCI : +skb_push (skb,4 ); + skb->data[3 ] =NLPID_CISCO_LMI ; +break ; + +default : +return -EINVAL ; + } + + }else if (skb->dev->type ==ARPHRD_DLCI ) { +switch (skb->protocol) { +case htons (ETH_P_IP ): +skb_push (skb,4 ); + skb->data[3 ] =NLPID_IP ; +break ; + +case htons (ETH_P_IPV6 ): +skb_push (skb,4 ); + skb->data[3 ] =NLPID_IPV6 ; +break ; + +default : +skb_push (skb,10 ); + skb->data[3 ] =FR_PAD ; + skb->data[4 ] =NLPID_SNAP ; +/* OUI 00-00-00 indicates an Ethertype follows */ + skb->data[5 ] =0x00 ; + skb->data[6 ] =0x00 ; + skb->data[7 ] =0x00 ; +/* This should be an Ethertype: */ + *(__be16 *)(skb->data +8 ) = skb->protocol; + } + + }else if (skb->dev->type ==ARPHRD_ETHER ) { +if (skb_headroom (skb) <10 ) { +struct sk_buff *skb2 =skb_realloc_headroom (skb,10 );if (!skb2)return -ENOBUFS ;dev_kfree_skb (skb); skb = *skb_p = skb2; } -skb_push (skb, head_len); +skb_push (skb,10 ); skb->data[3 ] =FR_PAD ; skb->data[4 ] =NLPID_SNAP ; - skb->data[5 ] =FR_PAD ; +/* OUI 00-80-C2 stands for the 802.1 organization */ + skb->data[5 ] =0x00 ; skb->data[6 ] =0x80 ; skb->data[7 ] =0xC2 ; +/* PID 00-07 stands for Ethernet frames without FCS */ skb->data[8 ] =0x00 ; - skb->data[9 ] =0x07 ;/* bridged Ethernet frame w/out FCS */ -break ; + skb->data[9 ] =0x07 ; -default : - head_len =10 ; -skb_push (skb, head_len); - skb->data[3 ] =FR_PAD ; - skb->data[4 ] =NLPID_SNAP ; - skb->data[5 ] =FR_PAD ; - skb->data[6 ] =FR_PAD ; - skb->data[7 ] =FR_PAD ; - *(__be16 *)(skb->data +8 ) = skb->protocol; + }else { +return -EINVAL ; }dlci_to_q922 (skb->data, dlci);
@@ -425,8 +431,8 @@ static netdev_tx_t pvc_xmit(struct sk_buff *skb, struct net_device *dev)skb_put (skb, pad);memset (skb->data + len,0 , pad); } - skb->protocol =cpu_to_be16 (ETH_P_802_3 ); } + skb->dev = dev;if (!fr_hard_header (&skb, pvc->dlci)) { dev->stats.tx_bytes += skb->len; dev->stats.tx_packets++;
@@ -494,10 +500,8 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)memset (skb->data,0 , len);skb_reserve (skb,4 );if (lmi ==LMI_CISCO ) { - skb->protocol =cpu_to_be16 (NLPID_CISCO_LMI );fr_hard_header (&skb,LMI_CISCO_DLCI ); }else { - skb->protocol =cpu_to_be16 (NLPID_CCITT_ANSI_LMI );fr_hard_header (&skb,LMI_CCITT_ANSI_DLCI ); } data =skb_tail_pointer (skb);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 68/214 bus/fsl_mc: Do not rely on caller to provide non NULL mc_io
In reply to Greg Kroah-HartmanFrom: Diana Craciun <[email protected]>
[ Upstream commit 5026cf605143e764e1785bbf9158559d17f8d260 ]
Before destroying the mc_io, check first that it was allocated.
--- drivers/bus/fsl-mc/mc-io.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/bus/fsl-mc/mc-io.c +6 -1
@@ -129,7 +129,12 @@ error_destroy_mc_io:*/ void fsl_destroy_mc_io (struct fsl_mc_io *mc_io) { -struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; +struct fsl_mc_device *dpmcp_dev; + +if (!mc_io) +return ; + + dpmcp_dev = mc_io->dpmcp_dev;if (dpmcp_dev)fsl_mc_io_unset_dpmcp (mc_io);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 69/214 ACPI: HMAT: Fix handling of changes from ACPI 6.2 to ACPI 6.3
In reply to Greg Kroah-HartmanFrom: Jonathan Cameron <[email protected]>
[ Upstream commit 2c5b9bde95c96942f2873cea6ef383c02800e4a8 ]
In ACPI 6.3, the Memory Proximity Domain Attributes Structure changed substantially. One of those changes was that the flag for "Memory Proximity Domain field is valid" was deprecated.
This was because the field "Proximity Domain for the Memory" became a required field and hence having a validity flag makes no sense.
So the correct logic is to always assume the field is there. Current code assumes it never is.
--- drivers/acpi/hmat/hmat.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/acpi/hmat/hmat.c +2 -1
@@ -403,7 +403,8 @@ static int __init hmat_parse_proximity_domain(union acpi_subtable_headers *headepr_info ("HMAT: Memory Flags:%04x Processor Domain:%d Memory Domain:%d\n" , p->flags, p->processor_PD, p->memory_PD); -if (p->flags &ACPI_HMAT_MEMORY_PD_VALID && hmat_revision ==1 ) { +if ((hmat_revision ==1 && p->flags &ACPI_HMAT_MEMORY_PD_VALID ) || + hmat_revision >1 ) { target =find_mem_target (p->memory_PD);if (!target) {pr_debug ("HMAT: Memory Domain missing from SRAT\n" );
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 70/214 power: supply: test_power: add missing newlines when printing parameters by sysfs
In reply to Greg Kroah-HartmanFrom: Xiongfeng Wang <[email protected]>
[ Upstream commit c07fa6c1631333f02750cf59f22b615d768b4d8f ]
When I cat some module parameters by sysfs, it displays as follows. It's better to add a newline for easy reading.
root@syzkaller:~# cd /sys/module/test_power/parameters/ root@syzkaller:/sys/module/test_power/parameters# cat ac_online onroot@syzkaller:/sys/module/test_power/parameters# cat battery_present trueroot@syzkaller:/sys/module/test_power/parameters# cat battery_health goodroot@syzkaller:/sys/module/test_power/parameters# cat battery_status dischargingroot@syzkaller:/sys/module/test_power/parameters# cat battery_technology LIONroot@syzkaller:/sys/module/test_power/parameters# cat usb_online onroot@syzkaller:/sys/module/test_power/parameters#
--- drivers/power/supply/test_power.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/power/supply/test_power.c +6 -0
@@ -341,6 +341,7 @@ static int param_set_ac_online(const char *key, const struct kernel_param *kp)static int param_get_ac_online (char *buffer,const struct kernel_param *kp) {strcpy (buffer,map_get_key (map_ac_online, ac_online,"unknown" )); +strcat (buffer,"\n" );return strlen (buffer); }
@@ -354,6 +355,7 @@ static int param_set_usb_online(const char *key, const struct kernel_param *kp)static int param_get_usb_online (char *buffer,const struct kernel_param *kp) {strcpy (buffer,map_get_key (map_ac_online, usb_online,"unknown" )); +strcat (buffer,"\n" );return strlen (buffer); }
@@ -368,6 +370,7 @@ static int param_set_battery_status(const char *key,static int param_get_battery_status (char *buffer,const struct kernel_param *kp) {strcpy (buffer,map_get_key (map_status, battery_status,"unknown" )); +strcat (buffer,"\n" );return strlen (buffer); }
@@ -382,6 +385,7 @@ static int param_set_battery_health(const char *key,static int param_get_battery_health (char *buffer,const struct kernel_param *kp) {strcpy (buffer,map_get_key (map_health, battery_health,"unknown" )); +strcat (buffer,"\n" );return strlen (buffer); }
@@ -397,6 +401,7 @@ static int param_get_battery_present(char *buffer, const struct kernel_param *kp) {strcpy (buffer,map_get_key (map_present, battery_present,"unknown" )); +strcat (buffer,"\n" );return strlen (buffer); }
@@ -414,6 +419,7 @@ static int param_get_battery_technology(char *buffer, {strcpy (buffer,map_get_key (map_technology, battery_technology,"unknown" )); +strcat (buffer,"\n" );return strlen (buffer); }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 71/214 drm/amd/display: HDMI remote sink need mode validation for Linux
In reply to Greg Kroah-HartmanFrom: Fangzhi Zuo <[email protected]>
[ Upstream commit 95d620adb48f7728e67d82f56f756e8d451cf8d2 ]
[Why]
Currently mode validation is bypassed if remote sink exists. That leads to mode set issue when a BW bottle neck exists in the link path, e.g., a DP-to-HDMI converter that only supports HDMI 1.4.
Any invalid mode passed to Linux user space will cause the modeset failure due to limitation of Linux user space implementation.
[How]
Mode validation is skipped only if in edid override. For real remote sink, clock limit check should be done for HDMI remote sink.
Have HDMI related remote sink going through mode validation to elimiate modes which pixel clock exceeds BW limitation.
--- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/amd/display/dc/core/dc_link.c +1 -1
@@ -2268,7 +2268,7 @@ enum dc_status dc_link_validate_mode_timing(/* A hack to avoid failing any modes for EDID override feature on * topology change such as lower quality cable for DP or different dongle */ -if (link->remote_sinks[0 ]) +if (link->remote_sinks[0 ] && link->remote_sinks[0 ]->sink_signal ==SIGNAL_TYPE_VIRTUAL )return DC_OK ;/* Passive Dongle */
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 72/214 ARC: [dts] fix the errors detected by dtbs_check
In reply to Greg Kroah-HartmanFrom: Zhen Lei <[email protected]>
[ Upstream commit 05b1be68c4d6d76970025e6139bfd735c2256ee5 ]
xxx/arc/boot/dts/axs101.dt.yaml: dw-apb-ictl@e0012000: $nodename:0: \
'dw-apb-ictl@e0012000' does not match '^interrupt-controller(@[0-9a-f,]+)*$'
From schema: xxx/interrupt-controller/snps,dw-apb-ictl.yaml
The node name of the interrupt controller must start with "interrupt-controller" instead of "dw-apb-ictl".
--- arch/arc/boot/dts/axc001.dtsi | 2 +- arch/arc/boot/dts/axc003.dtsi | 2 +- arch/arc/boot/dts/axc003_idu.dtsi | 2 +- arch/arc/boot/dts/vdk_axc003.dtsi | 2 +- arch/arc/boot/dts/vdk_axc003_idu.dtsi | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-)
arch/arc/boot/dts/axc001.dtsi +1 -1
@@ -85,7 +85,7 @@ * avoid duplicating the MB dtsi file given that IRQ from * this intc to cpu intc are different for axs101 and axs103 */ - mb_intc: dw-apb-ictl@e0012000 { + mb_intc: interrupt-controller@e0012000 { #interrupt-cells = <1>; compatible = "snps,dw-apb-ictl"; reg = < 0x0 0xe0012000 0x0 0x200 >;
arch/arc/boot/dts/axc003.dtsi +1 -1
@@ -129,7 +129,7 @@ * avoid duplicating the MB dtsi file given that IRQ from * this intc to cpu intc are different for axs101 and axs103 */ - mb_intc: dw-apb-ictl@e0012000 { + mb_intc: interrupt-controller@e0012000 { #interrupt-cells = <1>; compatible = "snps,dw-apb-ictl"; reg = < 0x0 0xe0012000 0x0 0x200 >;
arch/arc/boot/dts/axc003_idu.dtsi +1 -1
@@ -135,7 +135,7 @@ * avoid duplicating the MB dtsi file given that IRQ from * this intc to cpu intc are different for axs101 and axs103 */ - mb_intc: dw-apb-ictl@e0012000 { + mb_intc: interrupt-controller@e0012000 { #interrupt-cells = <1>; compatible = "snps,dw-apb-ictl"; reg = < 0x0 0xe0012000 0x0 0x200 >;
arch/arc/boot/dts/vdk_axc003.dtsi +1 -1
@@ -46,7 +46,7 @@ }; - mb_intc: dw-apb-ictl@e0012000 { + mb_intc: interrupt-controller@e0012000 { #interrupt-cells = <1>; compatible = "snps,dw-apb-ictl"; reg = < 0xe0012000 0x200 >;
arch/arc/boot/dts/vdk_axc003_idu.dtsi +1 -1
@@ -54,7 +54,7 @@ }; - mb_intc: dw-apb-ictl@e0012000 { + mb_intc: interrupt-controller@e0012000 { #interrupt-cells = <1>; compatible = "snps,dw-apb-ictl"; reg = < 0xe0012000 0x200 >;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 73/214 btrfs: fix replace of seed device
In reply to Greg Kroah-HartmanFrom: Anand Jain <[email protected]>
[ Upstream commit c6a5d954950c5031444173ad2195efc163afcac9 ]
If you replace a seed device in a sprouted fs, it appears to have successfully replaced the seed device, but if you look closely, it didn't. Here is an example.
$ mkfs.btrfs /dev/sda $ btrfstune -S1 /dev/sda $ mount /dev/sda /btrfs $ btrfs device add /dev/sdb /btrfs $ umount /btrfs $ btrfs device scan --forget $ mount -o device=/dev/sda /dev/sdb /btrfs $ btrfs replace start -f /dev/sda /dev/sdc /btrfs $ echo $? 0
BTRFS info (device sdb): dev_replace from /dev/sda (devid 1) to /dev/sdc started BTRFS info (device sdb): dev_replace from /dev/sda (devid 1) to /dev/sdc finished
$ btrfs fi show Label: none uuid: ab2c88b7-be81-4a7e-9849-c3666e7f9f4f Total devices 2 FS bytes used 256.00KiB devid 1 size 3.00GiB used 520.00MiB path /dev/sdc devid 2 size 3.00GiB used 896.00MiB path /dev/sdb
Label: none uuid: 10bd3202-0415-43af-96a8-d5409f310a7e
Total devices 1 FS bytes used 128.00KiB
devid 1 size 3.00GiB used 536.00MiB path /dev/sda
So as per the replace start command and kernel log replace was successful. Now let's try to clean mount.
$ umount /btrfs $ btrfs device scan --forget
$ mount -o device=/dev/sdc /dev/sdb /btrfs mount: /btrfs: wrong fs type, bad option, bad superblock on /dev/sdb, missing codepage or helper program, or other error.
[ 636.157517] BTRFS error (device sdc): failed to read chunk tree: -2 [ 636.180177] BTRFS error (device sdc): open_ctree failed
That's because per dev items it is still looking for the original seed device.
$ btrfs inspect-internal dump-tree -d /dev/sdb
item 0 key (DEV_ITEMS DEV_ITEM 1) itemoff 16185 itemsize 98 devid 1 total_bytes 3221225472 bytes_used 545259520 io_align 4096 io_width 4096 sector_size 4096 type 0 generation 6 start_offset 0 dev_group 0 seek_speed 0 bandwidth 0 uuid 59368f50-9af2-4b17-91da-8a783cc418d4 <--- seed uuid fsid 10bd3202-0415-43af-96a8-d5409f310a7e <--- seed fsid item 1 key (DEV_ITEMS DEV_ITEM 2) itemoff 16087 itemsize 98 devid 2 total_bytes 3221225472 bytes_used 939524096 io_align 4096 io_width 4096 sector_size 4096 type 0 generation 0 start_offset 0 dev_group 0 seek_speed 0 bandwidth 0 uuid 56a0a6bc-4630-4998-8daf-3c3030c4256a <- sprout uuid fsid ab2c88b7-be81-4a7e-9849-c3666e7f9f4f <- sprout fsid
But the replaced target has the following uuid+fsid in its superblock which doesn't match with the expected uuid+fsid in its devitem.
$ btrfs in dump-super /dev/sdc | egrep '^generation|dev_item.uuid|dev_item.fsid|devid' generation 20 dev_item.uuid 59368f50-9af2-4b17-91da-8a783cc418d4 dev_item.fsid ab2c88b7-be81-4a7e-9849-c3666e7f9f4f [match] dev_item.devid 1
So if you provide the original seed device the mount shall be successful. Which so long happening in the test case btrfs/163.
$ btrfs device scan --forget $ mount -o device=/dev/sda /dev/sdb /btrfs
Fix in this patch:
If a seed is not sprouted then there is no replacement of it, because of its read-only filesystem with a read-only device. Similarly, in the case of a sprouted filesystem, the seed device is still read only. So, mark it as you can't replace a seed device, you can only add a new device and then delete the seed device. If replace is attempted then returns -EINVAL.
--- fs/btrfs/dev-replace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/btrfs/dev-replace.c +1 -1
@@ -190,7 +190,7 @@ static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,int ret =0 ; *device_out =NULL ; -if (fs_info->fs_devices->seeding) { +if (srcdev->fs_devices->seeding) {btrfs_err (fs_info,"the filesystem is a seed filesystem!" );return -EINVAL ; }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 74/214 md/bitmap: md_bitmap_get_counter returns wrong blocks
In reply to Greg Kroah-HartmanFrom: Zhao Heming <[email protected]>
[ Upstream commit d837f7277f56e70d82b3a4a037d744854e62f387 ]
md_bitmap_get_counter() has code:
```
if (bitmap->bp[page].hijacked ||
bitmap->bp[page].map == NULL)
csize = ((sector_t)1) << (bitmap->chunkshift +
PAGE_COUNTER_SHIFT - 1);
```The minus 1 is wrong, this branch should report 2048 bits of space. With "-1" action, this only report 1024 bit of space.
This bug code returns wrong blocks, but it doesn't inflence bitmap logic:
1. Most callers focus this function return value (the counter of offset), not the parameter blocks.
2. The bug is only triggered when hijacked is true or map is NULL. the hijacked true condition is very rare.
the "map == null" only true when array is creating or resizing.
3. Even the caller gets wrong blocks, current code makes caller just to call md_bitmap_get_counter() one more time.
--- drivers/md/md-bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/md/md-bitmap.c +1 -1
@@ -1372,7 +1372,7 @@ __acquires(bitmap->lock)if (bitmap->bp[page].hijacked || bitmap->bp[page].map ==NULL ) csize = ((sector_t )1 ) << (bitmap->chunkshift + -PAGE_COUNTER_SHIFT -1 ); +PAGE_COUNTER_SHIFT );else csize = ((sector_t )1 ) << bitmap->chunkshift; *blocks = csize - (offset & (csize -1 ));
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 75/214 bnxt_en: Log unknown link speed appropriately.
In reply to Greg Kroah-HartmanFrom: Michael Chan <[email protected]>
[ Upstream commit 8eddb3e7ce124dd6375d3664f1aae13873318b0f ]
If the VF virtual link is set to always enabled, the speed may be unknown when the physical link is down. The driver currently logs the link speed as 4294967295 Mbps which is SPEED_UNKNOWN. Modify the link up log message as "speed unknown" which makes more sense.
--- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/net/ethernet/broadcom/bnxt/bnxt.c +5 -1
@@ -8375,6 +8375,11 @@ static void bnxt_report_link(struct bnxt *bp)u16 fec;netif_carrier_on (bp->dev); + speed =bnxt_fw_to_ethtool_speed (bp->link_info.link_speed); +if (speed ==SPEED_UNKNOWN ) { +netdev_info (bp->dev,"NIC Link is Up, speed unknown\n" ); +return ; + }if (bp->link_info.duplex ==BNXT_LINK_DUPLEX_FULL ) duplex ="full" ;else
@@ -8387,7 +8392,6 @@ static void bnxt_report_link(struct bnxt *bp) flow_ctrl ="ON - receive" ; else flow_ctrl ="none" ; - speed =bnxt_fw_to_ethtool_speed (bp->link_info.link_speed);netdev_info (bp->dev,"NIC Link is Up, %u Mbps %s duplex, Flow control: %s\n" , speed, duplex, flow_ctrl);if (bp->flags &BNXT_FLAG_EEE_CAP )
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 76/214 rpmsg: glink: Use complete_all for open states
In reply to Greg Kroah-HartmanFrom: Chris Lew <[email protected]>
[ Upstream commit 4fcdaf6e28d11e2f3820d54dd23cd12a47ddd44e ]
The open_req and open_ack completion variables are the state variables to represet a remote channel as open. Use complete_all so there are no races with waiters and using completion_done.
--- drivers/rpmsg/qcom_glink_native.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/rpmsg/qcom_glink_native.c +3 -3
@@ -970,7 +970,7 @@ static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid)return -EINVAL ; } -complete (&channel->open_ack); +complete_all (&channel->open_ack);return 0 ; }
@@ -1178,7 +1178,7 @@ static int qcom_glink_announce_create(struct rpmsg_device *rpdev)__be32 *val = defaults;int size; -if (glink->intentless) +if (glink->intentless || !completion_done (&channel->open_ack))return 0 ; prop =of_find_property (np,"qcom,intents" ,NULL );
@@ -1413,7 +1413,7 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid, channel->rcid = ret;spin_unlock_irqrestore (&glink->idr_lock, flags); -complete (&channel->open_req); +complete_all (&channel->open_req);if (create_device) { rpdev =kzalloc (sizeof (*rpdev),GFP_KERNEL );
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 77/214 clk: ti: clockdomain: fix static checker warning
In reply to Greg Kroah-HartmanFrom: Tero Kristo <[email protected]>
[ Upstream commit b7a7943fe291b983b104bcbd2f16e8e896f56590 ]
Fix a memory leak induced by not calling clk_put after doing of_clk_get.
--- drivers/clk/ti/clockdomain.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/clk/ti/clockdomain.c +2 -0
@@ -146,10 +146,12 @@ static void __init of_ti_clockdomain_setup(struct device_node *node)if (!omap2_clk_is_hw_omap (clk_hw)) {pr_warn ("can't setup clkdm for basic clk %s\n" ,__clk_get_name (clk)); +clk_put (clk);continue ; }to_clk_hw_omap (clk_hw)->clkdm_name = clkdm_name;omap2_init_clk_clkdm (clk_hw); +clk_put (clk); } }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 78/214 asm-generic/io.h: Fix !CONFIG_GENERIC_IOMAP pci_iounmap() implementation
In reply to Greg Kroah-HartmanFrom: Lorenzo Pieralisi <[email protected]>
[ Upstream commit f5810e5c329238b8553ebd98b914bdbefd8e6737 ]
For arches that do not select CONFIG_GENERIC_IOMAP, the current pci_iounmap() function does nothing causing obvious memory leaks for mapped regions that are backed by MMIO physical space.
In order to detect if a mapped pointer is IO vs MMIO, a check must made available to the pci_iounmap() function so that it can actually detect whether the pointer has to be unmapped.
In configurations where CONFIG_HAS_IOPORT_MAP && !CONFIG_GENERIC_IOMAP, a mapped port is detected using an ioport_map() stub defined in asm-generic/io.h.
Use the same logic to implement a stub (ie __pci_ioport_unmap()) that detects if the passed in pointer in pci_iounmap() is IO vs MMIO to iounmap conditionally and call it in pci_iounmap() fixing the issue.
Leave __pci_ioport_unmap() as a NOP for all other config options.
--- include/asm-generic/io.h | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-)
include/asm-generic/io.h +27 -12
@@ -887,18 +887,6 @@ static inline void iowrite64_rep(volatile void __iomem *addr,#include <linux/vmalloc.h> #define __io_virt (x) ((void __force *)(x)) -#ifndef CONFIG_GENERIC_IOMAP -struct pci_dev ; -extern void __iomem *pci_iomap (struct pci_dev *dev,int bar,unsigned long max); - -#ifndef pci_iounmap -#define pci_iounmap pci_iounmap -static inline void pci_iounmap (struct pci_dev *dev,void __iomem *p) -{ -} -#endif -#endif /* CONFIG_GENERIC_IOMAP */ -/* * Change virtual addresses to physical addresses and vv. * These are pretty trivial
@@ -1013,6 +1001,16 @@ static inline void __iomem *ioport_map(unsigned long port, unsigned int nr) port &=IO_SPACE_LIMIT ; return (port > MMIO_UPPER_LIMIT) ? NULL : PCI_IOBASE + port; } +#define __pci_ioport_unmap __pci_ioport_unmap +static inline void __pci_ioport_unmap (void __iomem *p) +{ +uintptr_t start = (uintptr_t )PCI_IOBASE ; +uintptr_t addr = (uintptr_t ) p; + +if (addr >= start && addr < start +IO_SPACE_LIMIT ) +return ; +iounmap (p); +}#endif #ifndef ioport_unmap
@@ -1027,6 +1025,23 @@ extern void ioport_unmap(void __iomem *p);#endif /* CONFIG_GENERIC_IOMAP */ #endif /* CONFIG_HAS_IOPORT_MAP */ +#ifndef CONFIG_GENERIC_IOMAP +struct pci_dev ; +extern void __iomem *pci_iomap (struct pci_dev *dev,int bar,unsigned long max); + +#ifndef __pci_ioport_unmap +static inline void __pci_ioport_unmap (void __iomem *p) {} +#endif + +#ifndef pci_iounmap +#define pci_iounmap pci_iounmap +static inline void pci_iounmap (struct pci_dev *dev,void __iomem *p) +{ +__pci_ioport_unmap (p); +} +#endif +#endif /* CONFIG_GENERIC_IOMAP */ +/* * Convert a virtual cached pointer to an uncached pointer */
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 79/214 net: 9p: initialize sun_server.sun_path to have addrs value only when addr is valid
In reply to Greg Kroah-HartmanFrom: Anant Thazhemadam <[email protected]>
[ Upstream commit 7ca1db21ef8e0e6725b4d25deed1ca196f7efb28 ]
In p9_fd_create_unix, checking is performed to see if the addr (passed as an argument) is NULL or not.
However, no check is performed to see if addr is a valid address, i.e., it doesn't entirely consist of only 0's.
The initialization of sun_server.sun_path to be equal to this faulty addr value leads to an uninitialized variable, as detected by KMSAN. Checking for this (faulty addr) and returning a negative error number appropriately, resolves this issue.
--- net/9p/trans_fd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/9p/trans_fd.c +1 -1
@@ -1023,7 +1023,7 @@ p9_fd_create_unix(struct p9_client *client, const char *addr, char *args) csocket =NULL ; -if (addr ==NULL ) +if (!addr || !strlen (addr))return -EINVAL ;if (strlen (addr) >=UNIX_PATH_MAX ) {
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 80/214 drivers: watchdog: rdc321x_wdt: Fix race condition bugs
In reply to Greg Kroah-HartmanFrom: Madhuparna Bhowmik <[email protected]>
[ Upstream commit 4b2e7f99cdd314263c9d172bc17193b8b6bba463 ]
In rdc321x_wdt_probe(), rdc321x_wdt_device.queue is initialized after misc_register(), hence if ioctl is called before its initialization which can call rdc321x_wdt_start() function, it will see an uninitialized value of rdc321x_wdt_device.queue, hence initialize it before misc_register().
Also, rdc321x_wdt_device.default_ticks is accessed in reset() function called from write callback, thus initialize it before misc_register().
Found by Linux Driver Verification project (linuxtesting.org).
--- drivers/watchdog/rdc321x_wdt.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/watchdog/rdc321x_wdt.c +2 -3
@@ -230,6 +230,8 @@ static int rdc321x_wdt_probe(struct platform_device *pdev) rdc321x_wdt_device.sb_pdev = pdata->sb_pdev; rdc321x_wdt_device.base_reg = r->start; + rdc321x_wdt_device.queue =0 ; + rdc321x_wdt_device.default_ticks = ticks; err =misc_register (&rdc321x_wdt_misc);if (err <0 ) {
@@ -244,14 +246,11 @@ static int rdc321x_wdt_probe(struct platform_device *pdev) rdc321x_wdt_device.base_reg, RDC_WDT_RST);init_completion (&rdc321x_wdt_device.stop); - rdc321x_wdt_device.queue =0 ;clear_bit (0 , &rdc321x_wdt_device.inuse);timer_setup (&rdc321x_wdt_device.timer, rdc321x_wdt_trigger,0 ); - rdc321x_wdt_device.default_ticks = ticks; -dev_info (&pdev->dev,"watchdog init success\n" );return 0 ;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 81/214 ext4: Detect already used quota file early
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
[ Upstream commit e0770e91424f694b461141cbc99adf6b23006b60 ]
When we try to use file already used as a quota file again (for the same or different quota type), strange things can happen. At the very least lockdep annotations may be wrong but also inode flags may be wrongly set / reset. When the file is used for two quota types at once we can even corrupt the file and likely crash the kernel. Catch all these cases by checking whether passed file is already used as quota file and bail early in that case.
This fixes occasional generic/219 failure due to lockdep complaint.
--- fs/ext4/super.c | 5 +++++ 1 file changed, 5 insertions(+)
fs/ext4/super.c +5 -0
@@ -5856,6 +5856,11 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,/* Quotafile not on the same filesystem? */ if (path->dentry->d_sb != sb)return -EXDEV ; + +/* Quota already enabled for this file? */ +if (IS_NOQUOTA (d_inode (path->dentry))) +return -EBUSY ; +/* Journaling quota? */ if (EXT4_SB (sb)->s_qf_names[type]) {/* Quotafile not in fs root? */
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 82/214 KVM: PPC: Book3S HV: Do not allocate HPT for a nested guest
In reply to Greg Kroah-HartmanFrom: Fabiano Rosas <[email protected]>
[ Upstream commit 05e6295dc7de859c9d56334805485c4d20bebf25 ]
The current nested KVM code does not support HPT guests. This is informed/enforced in some ways:
- Hosts < P9 will not be able to enable the nested HV feature;
- The nested hypervisor MMU capabilities will not contain KVM_CAP_PPC_MMU_HASH_V3;
- QEMU reflects the MMU capabilities in the 'ibm,arch-vec-5-platform-support' device-tree property;
- The nested guest, at 'prom_parse_mmu_model' ignores the 'disable_radix' kernel command line option if HPT is not supported;
- The KVM_PPC_CONFIGURE_V3_MMU ioctl will fail if trying to use HPT.
There is, however, still a way to start a HPT guest by using max-compat-cpu=power8 at the QEMU machine options. This leads to the guest being set to use hash after QEMU calls the KVM_PPC_ALLOCATE_HTAB ioctl.
With the guest set to hash, the nested hypervisor goes through the entry path that has no knowledge of nesting (kvmppc_run_vcpu) and crashes when it tries to execute an hypervisor-privileged (mtspr HDEC) instruction at __kvmppc_vcore_entry:
root@L1:~ $ qemu-system-ppc64 -machine pseries,max-cpu-compat=power8 ...
<snip>
[ 538.543303] CPU: 83 PID: 25185 Comm: CPU 0/KVM Not tainted 5.9.0-rc4 #1
[ 538.543355] NIP: c00800000753f388 LR: c00800000753f368 CTR: c0000000001e5ec0
[ 538.543417] REGS: c0000013e91e33b0 TRAP: 0700 Not tainted (5.9.0-rc4)
[ 538.543470] MSR: 8000000002843033 <SF,VEC,VSX,FP,ME,IR,DR,RI,LE> CR: 22422882 XER: 20040000
[ 538.543546] CFAR: c00800000753f4b0 IRQMASK: 3
GPR00: c0080000075397a0 c0000013e91e3640 c00800000755e600 0000000080000000
GPR04: 0000000000000000 c0000013eab19800 c000001394de0000 00000043a054db72
GPR08: 00000000003b1652 0000000000000000 0000000000000000 c0080000075502e0
GPR12: c0000000001e5ec0 c0000007ffa74200 c0000013eab19800 0000000000000008
GPR16: 0000000000000000 c00000139676c6c0 c000000001d23948 c0000013e91e38b8
GPR20: 0000000000000053 0000000000000000 0000000000000001 0000000000000000
GPR24: 0000000000000001 0000000000000001 0000000000000000 0000000000000001
GPR28: 0000000000000001 0000000000000053 c0000013eab19800 0000000000000001
[ 538.544067] NIP [c00800000753f388] __kvmppc_vcore_entry+0x90/0x104 [kvm_hv]
[ 538.544121] LR [c00800000753f368] __kvmppc_vcore_entry+0x70/0x104 [kvm_hv]
[ 538.544173] Call Trace:
[ 538.544196] [c0000013e91e3640] [c0000013e91e3680] 0xc0000013e91e3680 (unreliable)
[ 538.544260] [c0000013e91e3820] [c0080000075397a0] kvmppc_run_core+0xbc8/0x19d0 [kvm_hv]
[ 538.544325] [c0000013e91e39e0] [c00800000753d99c] kvmppc_vcpu_run_hv+0x404/0xc00 [kvm_hv]
[ 538.544394] [c0000013e91e3ad0] [c0080000072da4fc] kvmppc_vcpu_run+0x34/0x48 [kvm]
[ 538.544472] [c0000013e91e3af0] [c0080000072d61b8] kvm_arch_vcpu_ioctl_run+0x310/0x420 [kvm]
[ 538.544539] [c0000013e91e3b80] [c0080000072c7450] kvm_vcpu_ioctl+0x298/0x778 [kvm]
[ 538.544605] [c0000013e91e3ce0] [c0000000004b8c2c] sys_ioctl+0x1dc/0xc90
[ 538.544662] [c0000013e91e3dc0] [c00000000002f9a4] system_call_exception+0xe4/0x1c0
[ 538.544726] [c0000013e91e3e20] [c00000000000d140] system_call_common+0xf0/0x27c
[ 538.544787] Instruction dump:
[ 538.544821] f86d1098 60000000 60000000 48000099 e8ad0fe8 e8c500a0 e9264140 75290002
[ 538.544886] 7d1602a6 7cec42a6 40820008 7d0807b4 <7d164ba6> 7d083a14 f90d10a0 480104fd
[ 538.544953] ---[ end trace 74423e2b948c2e0c ]---This patch makes the KVM_PPC_ALLOCATE_HTAB ioctl fail when running in the nested hypervisor, causing QEMU to abort.
--- arch/powerpc/kvm/book3s_hv.c | 6 ++++++ 1 file changed, 6 insertions(+)
arch/powerpc/kvm/book3s_hv.c +6 -0
@@ -5191,6 +5191,12 @@ static long kvm_arch_vm_ioctl_hv(struct file *filp,case KVM_PPC_ALLOCATE_HTAB : {u32 htab_order; +/* If we're a nested hypervisor, we currently only support radix */ +if (kvmhv_on_pseries ()) { + r = -EOPNOTSUPP ; +break ; + } + r = -EFAULT ;if (get_user (htab_order, (u32 __user *)argp))break ;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 83/214 gfs2: use-after-free in sysfs deregistration
In reply to Greg Kroah-HartmanFrom: Jamie Iles <[email protected]>
[ Upstream commit c2a04b02c060c4858762edce4674d5cba3e5a96f ]
syzkaller found the following splat with CONFIG_DEBUG_KOBJECT_RELEASE=y:
Read of size 1 at addr ffff000028e896b8 by task kworker/1:2/228 CPU: 1 PID: 228 Comm: kworker/1:2 Tainted: G S 5.9.0-rc8+ #101 Hardware name: linux,dummy-virt (DT) Workqueue: events kobject_delayed_cleanup Call trace: dump_backtrace+0x0/0x4d8 show_stack+0x34/0x48 dump_stack+0x174/0x1f8 print_address_description.constprop.0+0x5c/0x550 kasan_report+0x13c/0x1c0 __asan_report_load1_noabort+0x34/0x60 memcmp+0xd0/0xd8 gfs2_uevent+0xc4/0x188 kobject_uevent_env+0x54c/0x1240 kobject_uevent+0x2c/0x40 __kobject_del+0x190/0x1d8 kobject_delayed_cleanup+0x2bc/0x3b8 process_one_work+0x96c/0x18c0 worker_thread+0x3f0/0xc30 kthread+0x390/0x498 ret_from_fork+0x10/0x18 Allocated by task 1110: kasan_save_stack+0x28/0x58 __kasan_kmalloc.isra.0+0xc8/0xe8 kasan_kmalloc+0x10/0x20 kmem_cache_alloc_trace+0x1d8/0x2f0 alloc_super+0x64/0x8c0 sget_fc+0x110/0x620 get_tree_bdev+0x190/0x648 gfs2_get_tree+0x50/0x228 vfs_get_tree+0x84/0x2e8 path_mount+0x1134/0x1da8 do_mount+0x124/0x138 __arm64_sys_mount+0x164/0x238 el0_svc_common.constprop.0+0x15c/0x598 do_el0_svc+0x60/0x150 el0_svc+0x34/0xb0 el0_sync_handler+0xc8/0x5b4 el0_sync+0x15c/0x180 Freed by task 228: kasan_save_stack+0x28/0x58 kasan_set_track+0x28/0x40 kasan_set_free_info+0x24/0x48 __kasan_slab_free+0x118/0x190 kasan_slab_free+0x14/0x20 slab_free_freelist_hook+0x6c/0x210 kfree+0x13c/0x460
Use the same pattern as f2fs + ext4 where the kobject destruction must complete before allowing the FS itself to be freed. This means that we need an explicit free_sbd in the callers.
--- fs/gfs2/incore.h | 1 + fs/gfs2/ops_fstype.c | 22 +++++----------------- fs/gfs2/super.c | 1 + fs/gfs2/sys.c | 5 ++++- 4 files changed, 11 insertions(+), 18 deletions(-)
fs/gfs2/incore.h +1 -0
@@ -694,6 +694,7 @@ struct gfs2_sbd {struct super_block *sd_vfs;struct gfs2_pcpu_lkstats __percpu *sd_lkstats;struct kobject sd_kobj; +struct completion sd_kobj_unregister;unsigned long sd_flags;/* SDF_... */ struct gfs2_sb_host sd_sb;
fs/gfs2/ops_fstype.c +5 -17
@@ -1094,26 +1094,14 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) } error =init_names (sdp, silent); -if (error) { -/* In this case, we haven't initialized sysfs, so we have to -manually free the sdp. */ -free_sbd (sdp); - sb->s_fs_info =NULL ; -return error; - } +if (error) + goto fail_free;snprintf (sdp->sd_fsname,sizeof (sdp->sd_fsname),"%s" , sdp->sd_table_name); error =gfs2_sys_fs_add (sdp); -/* -* If we hit an error here, gfs2_sys_fs_add will have called function -* kobject_put which causes the sysfs usage count to go to zero, which -* causes sysfs to call function gfs2_sbd_release, which frees sdp. -* Subsequent error paths here will call gfs2_sys_fs_del, which also -* kobject_put to free sdp. -*/ if (error) -return error; + goto fail_free;gfs2_create_debugfs_file (sdp);
@@ -1210,9 +1198,9 @@ fail_lm:gfs2_lm_unmount (sdp); fail_debug:gfs2_delete_debugfs_file (sdp); -/* gfs2_sys_fs_del must be the last thing we do, since it causes -* sysfs to call function gfs2_sbd_release, which frees sdp. */ gfs2_sys_fs_del (sdp); +fail_free: +free_sbd (sdp); sb->s_fs_info =NULL ;return error; }
fs/gfs2/super.c +1 -0
@@ -695,6 +695,7 @@ restart:/* At this point, we're through participating in the lockspace */ gfs2_sys_fs_del (sdp); +free_sbd (sdp); }/**
fs/gfs2/sys.c +4 -1
@@ -302,7 +302,7 @@ static void gfs2_sbd_release(struct kobject *kobj) { struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj); -free_sbd (sdp); +complete (&sdp->sd_kobj_unregister); }static struct kobj_type gfs2_ktype = {
@@ -652,6 +652,7 @@ int gfs2_sys_fs_add(struct gfs2_sbd *sdp)sprintf (ro,"RDONLY=%d" ,sb_rdonly (sb));sprintf (spectator,"SPECTATOR=%d" , sdp->sd_args.ar_spectator ?1 :0 ); +init_completion (&sdp->sd_kobj_unregister); sdp->sd_kobj.kset = gfs2_kset; error =kobject_init_and_add (&sdp->sd_kobj, &gfs2_ktype,NULL ,"%s" , sdp->sd_table_name);
@@ -682,6 +683,7 @@ fail_tune: fail_reg:fs_err (sdp,"error %d adding sysfs files\n" , error);kobject_put (&sdp->sd_kobj); +wait_for_completion (&sdp->sd_kobj_unregister); sb->s_fs_info =NULL ;return error; }
@@ -692,6 +694,7 @@ void gfs2_sys_fs_del(struct gfs2_sbd *sdp)sysfs_remove_group (&sdp->sd_kobj, &tune_group);sysfs_remove_group (&sdp->sd_kobj, &lock_module_group);kobject_put (&sdp->sd_kobj); +wait_for_completion (&sdp->sd_kobj_unregister); } static int gfs2_uevent(struct kset *kset, struct kobject *kobj,
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 84/214 gfs2: add validation checks for size of superblock
In reply to Greg Kroah-HartmanFrom: Anant Thazhemadam <[email protected]>
[ Upstream commit 0ddc5154b24c96f20e94d653b0a814438de6032b ]
In gfs2_check_sb(), no validation checks are performed with regards to the size of the superblock.
syzkaller detected a slab-out-of-bounds bug that was primarily caused because the block size for a superblock was set to zero.
A valid size for a superblock is a power of 2 between 512 and PAGE_SIZE. Performing validation checks and ensuring that the size of the superblock is valid fixes this bug.
--- fs/gfs2/ops_fstype.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)
fs/gfs2/ops_fstype.c +11 -7
@@ -169,15 +169,19 @@ static int gfs2_check_sb(struct gfs2_sbd *sdp, int silent)return -EINVAL ; } -/* If format numbers match exactly, we're done. */ - -if (sb->sb_fs_format ==GFS2_FORMAT_FS && - sb->sb_multihost_format ==GFS2_FORMAT_MULTI ) -return 0 ; +if (sb->sb_fs_format !=GFS2_FORMAT_FS || + sb->sb_multihost_format !=GFS2_FORMAT_MULTI ) { +fs_warn (sdp,"Unknown on-disk format, unable to mount\n" ); +return -EINVAL ; + } -fs_warn (sdp,"Unknown on-disk format, unable to mount\n" ); +if (sb->sb_bsize <512 || sb->sb_bsize >PAGE_SIZE || + (sb->sb_bsize & (sb->sb_bsize -1 ))) { +pr_warn ("Invalid superblock size\n" ); +return -EINVAL ; + } -return -EINVAL ; +return 0 ; }static void end_bio_io_page (struct bio *bio)
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 85/214 cifs: handle -EINTR in cifs_setattr
In reply to Greg Kroah-HartmanFrom: Ronnie Sahlberg <[email protected]>
[ Upstream commit c6cc4c5a72505a0ecefc9b413f16bec512f38078 ]
RHBZ: 1848178
Some calls that set attributes, like utimensat(), are not supposed to return -EINTR and thus do not have handlers for this in glibc which causes us to leak -EINTR to the applications which are also unprepared to handle it.
For example tar will break if utimensat() return -EINTR and abort unpacking the archive. Other applications may break too.
To handle this we add checks, and retry, for -EINTR in cifs_setattr()
--- fs/cifs/inode.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
fs/cifs/inode.c +9 -4
@@ -2614,13 +2614,18 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs) {struct cifs_sb_info *cifs_sb =CIFS_SB (direntry->d_sb);struct cifs_tcon *pTcon =cifs_sb_master_tcon (cifs_sb); +int rc, retries =0 ; -if (pTcon->unix_ext) -return cifs_setattr_unix (direntry, attrs); - -return cifs_setattr_nounix (direntry, attrs); +do { +if (pTcon->unix_ext) + rc =cifs_setattr_unix (direntry, attrs); +else + rc =cifs_setattr_nounix (direntry, attrs); + retries++; + }while (is_retryable_error (rc) && retries <2 );/* BB: add cifs_setattr_legacy for really old servers */ +return rc; }#if 0
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 86/214 arm64: dts: renesas: ulcb: add full-pwr-cycle-in-suspend into eMMC nodes
In reply to Greg Kroah-HartmanFrom: Yoshihiro Shimoda <[email protected]>
[ Upstream commit 992d7a8b88c83c05664b649fc54501ce58e19132 ]
Add full-pwr-cycle-in-suspend property to do a graceful shutdown of the eMMC device in system suspend.
--- arch/arm64/boot/dts/renesas/ulcb.dtsi | 1 + 1 file changed, 1 insertion(+)
arch/arm64/boot/dts/renesas/ulcb.dtsi +1 -0
@@ -470,6 +470,7 @@ mmc-hs200-1_8v; mmc-hs400-1_8v; non-removable; + full-pwr-cycle-in-suspend; status = "okay"; };
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 87/214 ARM: dts: omap4: Fix sgx clock rate for 4430
In reply to Greg Kroah-HartmanFrom: Tony Lindgren <[email protected]>
[ Upstream commit 19d3e9a0bdd57b90175f30390edeb06851f5f9f3 ]
We currently have a different clock rate for droid4 compared to the stock v3.0.8 based Android Linux kernel:
# cat /sys/kernel/debug/clk/dpll_*_m7x2_ck/clk_rate 266666667 307200000 # cat /sys/kernel/debug/clk/l3_gfx_cm:clk:0000:0/clk_rate 307200000
Let's fix this by configuring sgx to use 153.6 MHz instead of 307.2 MHz. Looks like also at least duover needs this change to avoid hangs, so let's apply it for all 4430.
This helps a bit with thermal issues that seem to be related to memory corruption when using sgx. It seems that other driver related issues still remain though.
--- arch/arm/boot/dts/omap4.dtsi | 2 +- arch/arm/boot/dts/omap443x.dtsi | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-)
arch/arm/boot/dts/omap4.dtsi +1 -1
@@ -328,7 +328,7 @@ status = "disabled"; }; - target-module@56000000 { + sgx_module: target-module@56000000 { compatible = "ti,sysc-omap4", "ti,sysc"; reg = <0x5600fe00 0x4>, <0x5600fe10 0x4>;
arch/arm/boot/dts/omap443x.dtsi +10 -0
@@ -74,3 +74,13 @@ }; /include/ "omap443x-clocks.dtsi" + +/* + * Use dpll_per for sgx at 153.6MHz like droid4 stock v3.0.8 Android kernel + */ +&sgx_module { + assigned-clocks = <&l3_gfx_clkctrl OMAP4_GPU_CLKCTRL 24>, + <&dpll_per_m7x2_ck>; + assigned-clock-rates = <0>, <153600000>; + assigned-clock-parents = <&dpll_per_m7x2_ck>; +};
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 88/214 memory: emif: Remove bogus debugfs error handling
In reply to Greg Kroah-HartmanFrom: Dan Carpenter <[email protected]>
[ Upstream commit fd22781648080cc400772b3c68aa6b059d2d5420 ]
Callers are generally not supposed to check the return values from debugfs functions. Debugfs functions never return NULL so this error handling will never trigger. (Historically debugfs functions used to return a mix of NULL and error pointers but it was eventually deemed too complicated for something which wasn't intended to be used in normal situations).
Delete all the error handling.
--- drivers/memory/emif.c | 33 +++++---------------------------- 1 file changed, 5 insertions(+), 28 deletions(-)
drivers/memory/emif.c +5 -28
@@ -163,35 +163,12 @@ static const struct file_operations emif_mr4_fops = { static int __init_or_module emif_debugfs_init(struct emif_data *emif) { -struct dentry *dentry; -int ret; - - dentry =debugfs_create_dir (dev_name (emif->dev),NULL ); -if (!dentry) { - ret = -ENOMEM ; - goto err0; - } - emif->debugfs_root = dentry; - - dentry =debugfs_create_file ("regcache_dump" ,S_IRUGO , - emif->debugfs_root, emif, &emif_regdump_fops); -if (!dentry) { - ret = -ENOMEM ; - goto err1; - } - - dentry =debugfs_create_file ("mr4" ,S_IRUGO , - emif->debugfs_root, emif, &emif_mr4_fops); -if (!dentry) { - ret = -ENOMEM ; - goto err1; - } - + emif->debugfs_root =debugfs_create_dir (dev_name (emif->dev),NULL ); +debugfs_create_file ("regcache_dump" ,S_IRUGO , emif->debugfs_root, emif, + &emif_regdump_fops); +debugfs_create_file ("mr4" ,S_IRUGO , emif->debugfs_root, emif, + &emif_mr4_fops);return 0 ; -err1: -debugfs_remove_recursive (emif->debugfs_root); -err0: -return ret; } static void __exit emif_debugfs_exit(struct emif_data *emif)
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 89/214 ARM: dts: s5pv210: remove DMA controller bus node name to fix dtschema warnings
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
[ Upstream commit ea4e792f3c8931fffec4d700cf6197d84e9f35a6 ]
There is no need to keep DMA controller nodes under AMBA bus node. Remove the "amba" node to fix dtschema warnings like:
amba: $nodename:0: 'amba' does not match '^([a-z][a-z0-9\\-]+-bus|bus|soc|axi|ahb|apb)(@[0-9a-f]+)?$'
--- arch/arm/boot/dts/s5pv210.dtsi | 49 +++++++++++++++------------------- 1 file changed, 21 insertions(+), 28 deletions(-)
arch/arm/boot/dts/s5pv210.dtsi +21 -28
@@ -128,35 +128,28 @@ }; }; - amba { - #address-cells = <1>; - #size-cells = <1>; - compatible = "simple-bus"; - ranges; - - pdma0: dma@e0900000 { - compatible = "arm,pl330", "arm,primecell"; - reg = <0xe0900000 0x1000>; - interrupt-parent = <&vic0>; - interrupts = <19>; - clocks = <&clocks CLK_PDMA0>; - clock-names = "apb_pclk"; - #dma-cells = <1>; - #dma-channels = <8>; - #dma-requests = <32>; - }; + pdma0: dma@e0900000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0xe0900000 0x1000>; + interrupt-parent = <&vic0>; + interrupts = <19>; + clocks = <&clocks CLK_PDMA0>; + clock-names = "apb_pclk"; + #dma-cells = <1>; + #dma-channels = <8>; + #dma-requests = <32>; + }; - pdma1: dma@e0a00000 { - compatible = "arm,pl330", "arm,primecell"; - reg = <0xe0a00000 0x1000>; - interrupt-parent = <&vic0>; - interrupts = <20>; - clocks = <&clocks CLK_PDMA1>; - clock-names = "apb_pclk"; - #dma-cells = <1>; - #dma-channels = <8>; - #dma-requests = <32>; - }; + pdma1: dma@e0a00000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0xe0a00000 0x1000>; + interrupt-parent = <&vic0>; + interrupts = <20>; + clocks = <&clocks CLK_PDMA1>; + clock-names = "apb_pclk"; + #dma-cells = <1>; + #dma-channels = <8>; + #dma-requests = <32>; }; spi0: spi@e1300000 {
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 90/214 ARM: dts: s5pv210: move fixed clocks under root node
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
[ Upstream commit d38cae370e5f2094cbc38db3082b8e9509ae52ce ]
The fixed clocks are kept under dedicated 'external-clocks' node, thus a fake 'reg' was added. This is not correct with dtschema as fixed-clock binding does not have a 'reg' property. Moving fixed clocks out of 'soc' to root node fixes multiple dtbs_check warnings:
external-clocks: $nodename:0: 'external-clocks' does not match '^([a-z][a-z0-9\\-]+-bus|bus|soc|axi|ahb|apb)(@[0-9a-f]+)?$'
external-clocks: #size-cells:0:0: 0 is not one of [1, 2]
external-clocks: oscillator@0:reg:0: [0] is too short
external-clocks: oscillator@1:reg:0: [1] is too short
external-clocks: 'ranges' is a required property
oscillator@0: 'reg' does not match any of the regexes: 'pinctrl-[0-9]+'
--- arch/arm/boot/dts/s5pv210.dtsi | 36 +++++++++++++--------------------- 1 file changed, 14 insertions(+), 22 deletions(-)
arch/arm/boot/dts/s5pv210.dtsi +14 -22
@@ -52,34 +52,26 @@ }; }; + xxti: oscillator-0 { + compatible = "fixed-clock"; + clock-frequency = <0>; + clock-output-names = "xxti"; + #clock-cells = <0>; + }; + + xusbxti: oscillator-1 { + compatible = "fixed-clock"; + clock-frequency = <0>; + clock-output-names = "xusbxti"; + #clock-cells = <0>; + }; + soc { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; ranges; - external-clocks { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; - - xxti: oscillator@0 { - compatible = "fixed-clock"; - reg = <0>; - clock-frequency = <0>; - clock-output-names = "xxti"; - #clock-cells = <0>; - }; - - xusbxti: oscillator@1 { - compatible = "fixed-clock"; - reg = <1>; - clock-frequency = <0>; - clock-output-names = "xusbxti"; - #clock-cells = <0>; - }; - }; - onenand: onenand@b0600000 { compatible = "samsung,s5pv210-onenand"; reg = <0xb0600000 0x2000>,
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 91/214 ARM: dts: s5pv210: move PMU node out of clock controller
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
[ Upstream commit bb98fff84ad1ea321823759edaba573a16fa02bd ]
The Power Management Unit (PMU) is a separate device which has little common with clock controller. Moving it to one level up (from clock controller child to SoC) allows to remove fake simple-bus compatible and dtbs_check warnings like:
clock-controller@e0100000: $nodename:0:
'clock-controller@e0100000' does not match '^([a-z][a-z0-9\\-]+-bus|bus|soc|axi|ahb|apb)(@[0-9a-f]+)?$'
--- arch/arm/boot/dts/s5pv210.dtsi | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-)
arch/arm/boot/dts/s5pv210.dtsi +5 -8
@@ -92,19 +92,16 @@ }; clocks: clock-controller@e0100000 { - compatible = "samsung,s5pv210-clock", "simple-bus"; + compatible = "samsung,s5pv210-clock"; reg = <0xe0100000 0x10000>; clock-names = "xxti", "xusbxti"; clocks = <&xxti>, <&xusbxti>; #clock-cells = <1>; - #address-cells = <1>; - #size-cells = <1>; - ranges; + }; - pmu_syscon: syscon@e0108000 { - compatible = "samsung-s5pv210-pmu", "syscon"; - reg = <0xe0108000 0x8000>; - }; + pmu_syscon: syscon@e0108000 { + compatible = "samsung-s5pv210-pmu", "syscon"; + reg = <0xe0108000 0x8000>; }; pinctrl0: pinctrl@e0200000 {
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 92/214 ARM: dts: s5pv210: remove dedicated audio-subsystem node
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
[ Upstream commit 6c17a2974abf68a58517f75741b15c4aba42b4b8 ]
The 'audio-subsystem' node is an artificial creation, not representing real hardware. The hardware is described by its nodes - AUDSS clock controller and I2S0.
Remove the 'audio-subsystem' node along with its undocumented compatible to fix dtbs_check warnings like:
audio-subsystem: $nodename:0: 'audio-subsystem' does not match '^([a-z][a-z0-9\\-]+-bus|bus|soc|axi|ahb|apb)(@[0-9a-f]+)?$'
--- arch/arm/boot/dts/s5pv210.dtsi | 65 +++++++++++++++------------------- 1 file changed, 29 insertions(+), 36 deletions(-)
arch/arm/boot/dts/s5pv210.dtsi +29 -36
@@ -211,43 +211,36 @@ status = "disabled"; }; - audio-subsystem { - compatible = "samsung,s5pv210-audss", "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - clk_audss: clock-controller@eee10000 { - compatible = "samsung,s5pv210-audss-clock"; - reg = <0xeee10000 0x1000>; - clock-names = "hclk", "xxti", - "fout_epll", - "sclk_audio0"; - clocks = <&clocks DOUT_HCLKP>, <&xxti>, - <&clocks FOUT_EPLL>, - <&clocks SCLK_AUDIO0>; - #clock-cells = <1>; - }; + clk_audss: clock-controller@eee10000 { + compatible = "samsung,s5pv210-audss-clock"; + reg = <0xeee10000 0x1000>; + clock-names = "hclk", "xxti", + "fout_epll", + "sclk_audio0"; + clocks = <&clocks DOUT_HCLKP>, <&xxti>, + <&clocks FOUT_EPLL>, + <&clocks SCLK_AUDIO0>; + #clock-cells = <1>; + }; - i2s0: i2s@eee30000 { - compatible = "samsung,s5pv210-i2s"; - reg = <0xeee30000 0x1000>; - interrupt-parent = <&vic2>; - interrupts = <16>; - dma-names = "rx", "tx", "tx-sec"; - dmas = <&pdma1 9>, <&pdma1 10>, <&pdma1 11>; - clock-names = "iis", - "i2s_opclk0", - "i2s_opclk1"; - clocks = <&clk_audss CLK_I2S>, - <&clk_audss CLK_I2S>, - <&clk_audss CLK_DOUT_AUD_BUS>; - samsung,idma-addr = <0xc0010000>; - pinctrl-names = "default"; - pinctrl-0 = <&i2s0_bus>; - #sound-dai-cells = <0>; - status = "disabled"; - }; + i2s0: i2s@eee30000 { + compatible = "samsung,s5pv210-i2s"; + reg = <0xeee30000 0x1000>; + interrupt-parent = <&vic2>; + interrupts = <16>; + dma-names = "rx", "tx", "tx-sec"; + dmas = <&pdma1 9>, <&pdma1 10>, <&pdma1 11>; + clock-names = "iis", + "i2s_opclk0", + "i2s_opclk1"; + clocks = <&clk_audss CLK_I2S>, + <&clk_audss CLK_I2S>, + <&clk_audss CLK_DOUT_AUD_BUS>; + samsung,idma-addr = <0xc0010000>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s0_bus>; + #sound-dai-cells = <0>; + status = "disabled"; }; i2s1: i2s@e2100000 {
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 93/214 nbd: make the config put is called before the notifying the waiter
In reply to Greg Kroah-HartmanFrom: Xiubo Li <[email protected]>
[ Upstream commit 87aac3a80af5cbad93e63250e8a1e19095ba0d30 ]
There has one race case for ceph's rbd-nbd tool. When do mapping it may fail with EBUSY from ioctl(nbd, NBD_DO_IT), but actually the nbd device has already unmaped.
It dues to if just after the wake_up(), the recv_work() is scheduled out and defers calling the nbd_config_put(), though the map process has exited the "nbd->recv_task" is not cleared.
--- drivers/block/nbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/block/nbd.c +1 -1
@@ -787,9 +787,9 @@ static void recv_work(struct work_struct *work)blk_mq_complete_request (blk_mq_rq_from_pdu (cmd)); } +nbd_config_put (nbd);atomic_dec (&config->recv_threads);wake_up (&config->recv_wq); -nbd_config_put (nbd);kfree (args); }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 94/214 sgl_alloc_order: fix memory leak
In reply to Greg Kroah-HartmanFrom: Douglas Gilbert <[email protected]>
[ Upstream commit b2a182a40278bc5849730e66bca01a762188ed86 ]
sgl_alloc_order() can fail when 'length' is large on a memory constrained system. When order > 0 it will potentially be making several multi-page allocations with the later ones more likely to fail than the earlier one. So it is important that sgl_alloc_order() frees up any pages it has obtained before returning NULL. In the case when order > 0 it calls the wrong free page function and leaks. In testing the leak was sufficient to bring down my 8 GiB laptop with OOM.
--- lib/scatterlist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
lib/scatterlist.c +1 -1
@@ -514,7 +514,7 @@ struct scatterlist *sgl_alloc_order(unsigned long long length, elem_len =min_t (u64, length,PAGE_SIZE << order); page =alloc_pages (gfp, order);if (!page) { -sgl_free (sgl); +sgl_free_order (sgl, order);return NULL ; }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 95/214 nvme-rdma: fix crash when connect rejected
In reply to Greg Kroah-HartmanFrom: Chao Leng <[email protected]>
[ Upstream commit 43efdb8e870ee0f58633fd579aa5b5185bf5d39e ]
A crash can happened when a connect is rejected. The host establishes
the connection after received ConnectReply, and then continues to send the fabrics Connect command. If the controller does not receive the ReadyToUse capsule, host may receive a ConnectReject reply.
Call nvme_rdma_destroy_queue_ib after the host received the RDMA_CM_EVENT_REJECTED event. Then when the fabrics Connect command times out, nvme_rdma_timeout calls nvme_rdma_complete_rq to fail the request. A crash happenes due to use after free in nvme_rdma_complete_rq.
nvme_rdma_destroy_queue_ib is redundant when handling the RDMA_CM_EVENT_REJECTED event as nvme_rdma_destroy_queue_ib is already called in connection failure handler.
--- drivers/nvme/host/rdma.c | 1 - 1 file changed, 1 deletion(-)
drivers/nvme/host/rdma.c +0 -1
@@ -1679,7 +1679,6 @@ static int nvme_rdma_cm_handler(struct rdma_cm_id *cm_id,complete (&queue->cm_done);return 0 ;case RDMA_CM_EVENT_REJECTED : -nvme_rdma_destroy_queue_ib (queue); cm_error =nvme_rdma_conn_rejected (queue, ev);break ;case RDMA_CM_EVENT_ROUTE_ERROR :
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 96/214 md/raid5: fix oops during stripe resizing
In reply to Greg Kroah-HartmanFrom: Song Liu <[email protected]>
commit b44c018cdf748b96b676ba09fdbc5b34fc443ada upstream.
KoWei reported crash during raid5 reshape:
[ 1032.252932] Oops: 0002 [#1] SMP PTI [...] [ 1032.252943] RIP: 0010:memcpy_erms+0x6/0x10 [...] [ 1032.252947] RSP: 0018:ffffba1ac0c03b78 EFLAGS: 00010286 [ 1032.252949] RAX: 0000784ac0000000 RBX: ffff91bec3d09740 RCX: 0000000000001000 [ 1032.252951] RDX: 0000000000001000 RSI: ffff91be6781c000 RDI: 0000784ac0000000 [ 1032.252953] RBP: ffffba1ac0c03bd8 R08: 0000000000001000 R09: ffffba1ac0c03bf8 [ 1032.252954] R10: 0000000000000000 R11: 0000000000000000 R12: ffffba1ac0c03bf8 [ 1032.252955] R13: 0000000000001000 R14: 0000000000000000 R15: 0000000000000000 [ 1032.252958] FS: 0000000000000000(0000) GS:ffff91becf500000(0000) knlGS:0000000000000000 [ 1032.252959] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1032.252961] CR2: 0000784ac0000000 CR3: 000000031780a002 CR4: 00000000001606e0 [ 1032.252962] Call Trace: [ 1032.252969] ? async_memcpy+0x179/0x1000 [async_memcpy] [ 1032.252977] ? raid5_release_stripe+0x8e/0x110 [raid456] [ 1032.252982] handle_stripe_expansion+0x15a/0x1f0 [raid456] [ 1032.252988] handle_stripe+0x592/0x1270 [raid456] [ 1032.252993] handle_active_stripes.isra.0+0x3cb/0x5a0 [raid456] [ 1032.252999] raid5d+0x35c/0x550 [raid456] [ 1032.253002] ? schedule+0x42/0xb0 [ 1032.253006] ? schedule_timeout+0x10e/0x160 [ 1032.253011] md_thread+0x97/0x160 [ 1032.253015] ? wait_woken+0x80/0x80 [ 1032.253019] kthread+0x104/0x140 [ 1032.253022] ? md_start_sync+0x60/0x60 [ 1032.253024] ? kthread_park+0x90/0x90 [ 1032.253027] ret_from_fork+0x35/0x40
This is because cache_size_mutex was unlocked too early in resize_stripes, which races with grow_one_stripe() that grow_one_stripe() allocates a stripe with wrong pool_size.
Fix this issue by unlocking cache_size_mutex after updating pool_size.
--- drivers/md/raid5.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/md/raid5.c +2 -2
@@ -2407,8 +2407,6 @@ static int resize_stripes(struct r5conf }else err = -ENOMEM ; -mutex_unlock (&conf->cache_size_mutex); - conf->slab_cache = sc; conf->active_name =1 -conf->active_name;
@@ -2431,6 +2429,8 @@ static int resize_stripes(struct r5confif (!err) conf->pool_size = newsize; +mutex_unlock (&conf->cache_size_mutex); +return err; }
Greg Kroah-Hartman
maintainerPATCH 97/214 mmc: sdhci: Add LTR support for some Intel BYT based controllers
In reply to Greg Kroah-HartmanFrom: Adrian Hunter <[email protected]>
commit 46f4a69ec8ed6ab9f6a6172afe50df792c8bc1b6 upstream.
Some Intel BYT based host controllers support the setting of latency tolerance. Accordingly, implement the PM QoS ->set_latency_tolerance() callback. The raw register values are also exposed via debugfs.
Intel EHL controllers require this support.
--- drivers/mmc/host/sdhci-pci-core.c | 154 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+)
drivers/mmc/host/sdhci-pci-core.c +154 -0
@@ -24,6 +24,8 @@#include <linux/iopoll.h> #include <linux/gpio.h> #include <linux/pm_runtime.h> +#include <linux/pm_qos.h> +#include <linux/debugfs.h> #include <linux/mmc/slot-gpio.h> #include <linux/mmc/sdhci-pci-data.h> #include <linux/acpi.h>
@@ -520,6 +522,8 @@ struct intel_host {bool rpm_retune_ok;u32 glk_rx_ctrl1;u32 glk_tun_val; +u32 active_ltr; +u32 idle_ltr; }; static const guid_t intel_dsm_guid =
@@ -764,6 +768,108 @@ static int intel_execute_tuning(struct mreturn 0 ; } +#define INTEL_ACTIVELTR 0x804 +#define INTEL_IDLELTR 0x808 + +#define INTEL_LTR_REQ BIT(15) +#define INTEL_LTR_SCALE_MASK GENMASK(11, 10) +#define INTEL_LTR_SCALE_1US (2 << 10) +#define INTEL_LTR_SCALE_32US (3 << 10) +#define INTEL_LTR_VALUE_MASK GENMASK(9, 0) + +static void intel_cache_ltr (struct sdhci_pci_slot *slot) +{ +struct intel_host *intel_host =sdhci_pci_priv (slot); +struct sdhci_host *host = slot->host; + + intel_host->active_ltr =readl (host->ioaddr +INTEL_ACTIVELTR ); + intel_host->idle_ltr =readl (host->ioaddr +INTEL_IDLELTR ); +} + +static void intel_ltr_set (struct device *dev,s32 val) +{ +struct sdhci_pci_chip *chip =dev_get_drvdata (dev); +struct sdhci_pci_slot *slot = chip->slots[0 ]; +struct intel_host *intel_host =sdhci_pci_priv (slot); +struct sdhci_host *host = slot->host; +u32 ltr; + +pm_runtime_get_sync (dev); + +/* +* Program latency tolerance (LTR) accordingly what has been asked +* by the PM QoS layer or disable it in case we were passed +* negative value or PM_QOS_LATENCY_ANY. +*/ + ltr =readl (host->ioaddr +INTEL_ACTIVELTR ); + +if (val ==PM_QOS_LATENCY_ANY || val <0 ) { + ltr &= ~INTEL_LTR_REQ ; + }else { + ltr |=INTEL_LTR_REQ ; + ltr &= ~INTEL_LTR_SCALE_MASK ; + ltr &= ~INTEL_LTR_VALUE_MASK ; + +if (val >INTEL_LTR_VALUE_MASK ) { + val >>=5 ; +if (val >INTEL_LTR_VALUE_MASK ) + val =INTEL_LTR_VALUE_MASK ; + ltr |=INTEL_LTR_SCALE_32US | val; + }else { + ltr |=INTEL_LTR_SCALE_1US | val; + } + } + +if (ltr == intel_host->active_ltr) + goto out; + +writel (ltr, host->ioaddr +INTEL_ACTIVELTR ); +writel (ltr, host->ioaddr +INTEL_IDLELTR ); + +/* Cache the values into lpss structure */ +intel_cache_ltr (slot); +out: +pm_runtime_put_autosuspend (dev); +} + +static bool intel_use_ltr (struct sdhci_pci_chip *chip) +{ +switch (chip->pdev->device) { +case PCI_DEVICE_ID_INTEL_BYT_EMMC : +case PCI_DEVICE_ID_INTEL_BYT_EMMC2 : +case PCI_DEVICE_ID_INTEL_BYT_SDIO : +case PCI_DEVICE_ID_INTEL_BYT_SD : +case PCI_DEVICE_ID_INTEL_BSW_EMMC : +case PCI_DEVICE_ID_INTEL_BSW_SDIO : +case PCI_DEVICE_ID_INTEL_BSW_SD : +return false; +default : +return true; + } +} + +static void intel_ltr_expose (struct sdhci_pci_chip *chip) +{ +struct device *dev = &chip->pdev->dev; + +if (!intel_use_ltr (chip)) +return ; + + dev->power.set_latency_tolerance = intel_ltr_set; +dev_pm_qos_expose_latency_tolerance (dev); +} + +static void intel_ltr_hide (struct sdhci_pci_chip *chip) +{ +struct device *dev = &chip->pdev->dev; + +if (!intel_use_ltr (chip)) +return ; + +dev_pm_qos_hide_latency_tolerance (dev); + dev->power.set_latency_tolerance =NULL ; +} +static void byt_probe_slot (struct sdhci_pci_slot *slot) {struct mmc_host_ops *ops = &slot->host->mmc_host_ops;
@@ -778,6 +884,43 @@ static void byt_probe_slot(struct sdhci_ ops->start_signal_voltage_switch = intel_start_signal_voltage_switch;device_property_read_u32 (dev,"max-frequency" , &mmc->f_max); + +if (!mmc->slotno) { + slot->chip->slots[mmc->slotno] = slot; +intel_ltr_expose (slot->chip); + } +} + +static void byt_add_debugfs (struct sdhci_pci_slot *slot) +{ +struct intel_host *intel_host =sdhci_pci_priv (slot); +struct mmc_host *mmc = slot->host->mmc; +struct dentry *dir = mmc->debugfs_root; + +if (!intel_use_ltr (slot->chip)) +return ; + +debugfs_create_x32 ("active_ltr" ,0444 , dir, &intel_host->active_ltr); +debugfs_create_x32 ("idle_ltr" ,0444 , dir, &intel_host->idle_ltr); + +intel_cache_ltr (slot); +} + +static int byt_add_host (struct sdhci_pci_slot *slot) +{ +int ret =sdhci_add_host (slot->host); + +if (!ret) +byt_add_debugfs (slot); +return ret; +} + +static void byt_remove_slot (struct sdhci_pci_slot *slot,int dead) +{ +struct mmc_host *mmc = slot->host->mmc; + +if (!mmc->slotno) +intel_ltr_hide (slot->chip); }static int byt_emmc_probe_slot (struct sdhci_pci_slot *slot)
@@ -859,6 +1002,8 @@ static int glk_emmc_add_host(struct sdhcif (ret) goto cleanup; +byt_add_debugfs (slot); +return 0 ; cleanup:
@@ -1036,6 +1181,8 @@ static const struct sdhci_pci_fixes sdhc#endif .allow_runtime_pm = true, .probe_slot = byt_emmc_probe_slot, + .add_host = byt_add_host, + .remove_slot = byt_remove_slot, .quirks =SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | SDHCI_QUIRK_NO_LED, .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
@@ -1049,6 +1196,7 @@ static const struct sdhci_pci_fixes sdhc .allow_runtime_pm = true, .probe_slot = glk_emmc_probe_slot, .add_host = glk_emmc_add_host, + .remove_slot = byt_remove_slot, #ifdef CONFIG_PM_SLEEP .suspend = sdhci_cqhci_suspend, .resume = sdhci_cqhci_resume,
@@ -1079,6 +1227,8 @@ static const struct sdhci_pci_fixes sdhc SDHCI_QUIRK2_PRESET_VALUE_BROKEN, .allow_runtime_pm = true, .probe_slot = ni_byt_sdio_probe_slot, + .add_host = byt_add_host, + .remove_slot = byt_remove_slot, .ops = &sdhci_intel_byt_ops, .priv_size = sizeof(struct intel_host), };
@@ -1096,6 +1246,8 @@ static const struct sdhci_pci_fixes sdhc SDHCI_QUIRK2_PRESET_VALUE_BROKEN, .allow_runtime_pm = true, .probe_slot = byt_sdio_probe_slot, + .add_host = byt_add_host, + .remove_slot = byt_remove_slot, .ops = &sdhci_intel_byt_ops, .priv_size = sizeof(struct intel_host), };
@@ -1115,6 +1267,8 @@ static const struct sdhci_pci_fixes sdhc .allow_runtime_pm = true, .own_cd_for_runtime_pm = true, .probe_slot = byt_sd_probe_slot, + .add_host = byt_add_host, + .remove_slot = byt_remove_slot, .ops = &sdhci_intel_byt_ops, .priv_size = sizeof(struct intel_host), };
Greg Kroah-Hartman
maintainerPATCH 98/214 mmc: sdhci-acpi: AMDI0040: Set SDHCI_QUIRK2_PRESET_VALUE_BROKEN
In reply to Greg Kroah-HartmanFrom: Raul E Rangel <[email protected]>
commit f23cc3ba491af77395cea3f9d51204398729f26b upstream.
This change fixes HS400 tuning for devices with invalid presets.
SDHCI presets are not currently used for eMMC HS/HS200/HS400, but are used for DDR52. The HS400 retuning sequence is:
HS400->DDR52->HS->HS200->Perform Tuning->HS->HS400
This means that when HS400 tuning happens, we transition through DDR52 for a very brief period. This causes presets to be enabled unintentionally and stay enabled when transitioning back to HS200 or HS400. Some firmware has invalid presets, so we end up with driver strengths that can cause I/O problems.
--- drivers/mmc/host/sdhci-acpi.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+)
drivers/mmc/host/sdhci-acpi.c +37 -0
@@ -658,6 +658,43 @@ static int sdhci_acpi_emmc_amd_probe_slo (host->mmc->caps & MMC_CAP_1_8V_DDR)) host->mmc->caps2 =MMC_CAP2_HS400_1_8V ; +/* +* There are two types of presets out in the wild: +* 1) Default/broken presets. +* These presets have two sets of problems: +* a) The clock divisor for SDR12, SDR25, and SDR50 is too small. +* This results in clock frequencies that are 2x higher than +* acceptable. i.e., SDR12 = 25 MHz, SDR25 = 50 MHz, SDR50 = +* 100 MHz.x +* b) The HS200 and HS400 driver strengths don't match. +* By default, the SDR104 preset register has a driver strength of +* A, but the (internal) HS400 preset register has a driver +* strength of B. As part of initializing HS400, HS200 tuning +* needs to be performed. Having different driver strengths +* between tuning and operation is wrong. It results in different +* rise/fall times that lead to incorrect sampling. +* 2) Firmware with properly initialized presets. +* These presets have proper clock divisors. i.e., SDR12 => 12MHz, +* SDR25 => 25 MHz, SDR50 => 50 MHz. Additionally the HS200 and +* HS400 preset driver strengths match. +* +* Enabling presets for HS400 doesn't work for the following reasons: +* 1) sdhci_set_ios has a hard coded list of timings that are used +* to determine if presets should be enabled. +* 2) sdhci_get_preset_value is using a non-standard register to +* read out HS400 presets. The AMD controller doesn't support this +* non-standard register. In fact, it doesn't expose the HS400 +* preset register anywhere in the SDHCI memory map. This results +* in reading a garbage value and using the wrong presets. +* +* Since HS400 and HS200 presets must be identical, we could +* instead use the the SDR104 preset register. +* +* If the above issues are resolved we could remove this quirk for +* firmware that that has valid presets (i.e., SDR12 <= 12 MHz). +*/ + host->quirks2 |=SDHCI_QUIRK2_PRESET_VALUE_BROKEN ; + host->mmc_host_ops.select_drive_strength = amd_select_drive_strength; host->mmc_host_ops.set_ios = amd_set_ios; host->mmc_host_ops.execute_tuning = amd_sdhci_execute_tuning;
Greg Kroah-Hartman
maintainerPATCH 99/214 seccomp: Make duplicate listener detection non-racy
In reply to Greg Kroah-HartmanFrom: Jann Horn <[email protected]>
commit dfe719fef03d752f1682fa8aeddf30ba501c8555 upstream.
Currently, init_listener() tries to prevent adding a filter with SECCOMP_FILTER_FLAG_NEW_LISTENER if one of the existing filters already has a listener. However, this check happens without holding any lock that would prevent another thread from concurrently installing a new filter (potentially with a listener) on top of the ones we already have.
Theoretically, this is also a data race: The plain load from current->seccomp.filter can race with concurrent writes to the same location.
Fix it by moving the check into the region that holds the siglock to guard against concurrent TSYNC.
(The "Fixes" tag points to the commit that introduced the theoretical data race; concurrent installation of another filter with TSYNC only became possible later, in commit 51891498f2da ("seccomp: allow TSYNC and USER_NOTIF together").)
--- kernel/seccomp.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-)
kernel/seccomp.c +31 -7
@@ -1219,13 +1219,7 @@ static const struct file_operations seccstatic struct file *init_listener (struct seccomp_filter *filter) { -struct file *ret =ERR_PTR (-EBUSY ); -struct seccomp_filter *cur; - -for (cur = current->seccomp.filter; cur; cur = cur->prev) { -if (cur->notif) - goto out; - } +struct file *ret; ret =ERR_PTR (-ENOMEM ); filter->notif =kzalloc (sizeof (*(filter->notif)),GFP_KERNEL );
@@ -1252,6 +1246,31 @@ out:return ret; } +/* +* Does @new_child have a listener while an ancestor also has a listener? +* If so, we'll want to reject this filter. +* This only has to be tested for the current process, even in the TSYNC case, +* because TSYNC installs @child with the same parent on all threads. +* Note that @new_child is not hooked up to its parent at this point yet, so +* we use current->seccomp.filter. +*/ +static bool has_duplicate_listener (struct seccomp_filter *new_child) +{ +struct seccomp_filter *cur; + +/* must be protected against concurrent TSYNC */ +lockdep_assert_held (¤t->sighand->siglock); + +if (!new_child->notif) +return false; +for (cur = current->seccomp.filter; cur; cur = cur->prev) { +if (cur->notif) +return true; + } + +return false; +} +/** * seccomp_set_mode_filter: internal function for setting seccomp filter * @flags: flags to change filter behavior
@@ -1321,6 +1340,11 @@ static long seccomp_set_mode_filter(unsiif (!seccomp_may_assign_mode (seccomp_mode)) goto out; +if (has_duplicate_listener (prepared)) { + ret = -EBUSY ; + goto out; + } + ret =seccomp_attach_filter (flags, prepared);if (ret) goto out;
Greg Kroah-Hartman
maintainerPATCH 100/214 selftests/x86/fsgsbase: Test PTRACE_PEEKUSER for GSBASE with invalid LDT GS
In reply to Greg Kroah-HartmanFrom: Andy Lutomirski <[email protected]>
commit 1b9abd1755ad947d7c9913e92e7837b533124c90 upstream.
This tests commit:
8ab49526b53d ("x86/fsgsbase/64: Fix NULL deref in 86_fsgsbase_read_task")
Unpatched kernels will OOPS.
--- tools/testing/selftests/x86/fsgsbase.c | 65 +++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+)
tools/testing/selftests/x86/fsgsbase.c +65 -0
@@ -442,6 +442,68 @@ static void test_unexpected_base(void)#define USER_REGS_OFFSET (r) offsetof(struct user_regs_struct, r) +static void test_ptrace_write_gs_read_base (void ) +{ +int status; +pid_t child =fork (); + +if (child <0 ) +err (1 ,"fork" ); + +if (child ==0 ) { +printf ("[RUN]\tPTRACE_POKE GS, read GSBASE back\n" ); + +printf ("[RUN]\tARCH_SET_GS to 1\n" ); +if (syscall (SYS_arch_prctl,ARCH_SET_GS ,1 ) !=0 ) +err (1 ,"ARCH_SET_GS" ); + +if (ptrace (PTRACE_TRACEME ,0 ,NULL ,NULL ) !=0 ) +err (1 ,"PTRACE_TRACEME" ); + +raise (SIGTRAP ); +_exit (0 ); + } + +wait (&status); + +if (WSTOPSIG (status) ==SIGTRAP ) { +unsigned long base; +unsigned long gs_offset =USER_REGS_OFFSET (gs); +unsigned long base_offset =USER_REGS_OFFSET (gs_base); + +/* Read the initial base. It should be 1. */ + base =ptrace (PTRACE_PEEKUSER , child, base_offset,NULL ); +if (base ==1 ) { +printf ("[OK]\tGSBASE started at 1\n" ); + }else { + nerrs++; +printf ("[FAIL]\tGSBASE started at 0x%lx\n" , base); + } + +printf ("[RUN]\tSet GS = 0x7, read GSBASE\n" ); + +/* Poke an LDT selector into GS. */ +if (ptrace (PTRACE_POKEUSER , child, gs_offset,0x7 ) !=0 ) +err (1 ,"PTRACE_POKEUSER" ); + +/* And read the base. */ + base =ptrace (PTRACE_PEEKUSER , child, base_offset,NULL ); + +if (base ==0 || base ==1 ) { +printf ("[OK]\tGSBASE reads as 0x%lx with invalid GS\n" , base); + }else { + nerrs++; +printf ("[FAIL]\tGSBASE=0x%lx (should be 0 or 1)\n" , base); + } + } + +ptrace (PTRACE_CONT , child,NULL ,NULL ); + +wait (&status); +if (!WIFEXITED (status)) +printf ("[WARN]\tChild didn't exit cleanly.\n" ); +} +static void test_ptrace_write_gsbase (void ) {int status;
@@ -511,6 +573,9 @@ int main() shared_scratch =mmap (NULL ,4096 ,PROT_READ |PROT_WRITE ,MAP_ANONYMOUS |MAP_SHARED ,-1 ,0 ); +/* Do these tests before we have an LDT. */ +test_ptrace_write_gs_read_base (); +/* Probe FSGSBASE */ sethandler (SIGILL , sigill,0 );if (sigsetjmp (jmpbuf,1 ) ==0 ) {
Greg Kroah-Hartman
maintainerPATCH 101/214 perf/x86/intel: Fix Ice Lake event constraint table
In reply to Greg Kroah-HartmanFrom: Kan Liang <[email protected]>
commit 010cb00265f150bf82b23c02ad1fb87ce5c781e1 upstream.
An error occues when sampling non-PEBS INST_RETIRED.PREC_DIST(0x01c0) event.
perf record -e cpu/event=0xc0,umask=0x01/ -- sleep 1 Error:
The sys_perf_event_open() syscall returned with 22 (Invalid argument) for event (cpu/event=0xc0,umask=0x01/).
/bin/dmesg | grep -i perf may provide additional information.
The idxmsk64 of the event is set to 0. The event never be successfully scheduled.
The event should be limit to the fixed counter 0.
--- arch/x86/events/intel/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/events/intel/core.c +1 -1
@@ -243,7 +243,7 @@ static struct extra_reg intel_skl_extra_static struct event_constraint intel_icl_event_constraints[] = {FIXED_EVENT_CONSTRAINT (0x00c0 ,0 ),/* INST_RETIRED.ANY */ -INTEL_UEVENT_CONSTRAINT (0x1c0 ,0 ),/* INST_RETIRED.PREC_DIST */ +FIXED_EVENT_CONSTRAINT (0x01c0 ,0 ),/* INST_RETIRED.PREC_DIST */ FIXED_EVENT_CONSTRAINT (0x003c ,1 ),/* CPU_CLK_UNHALTED.CORE */ FIXED_EVENT_CONSTRAINT (0x0300 ,2 ),/* CPU_CLK_UNHALTED.REF */ FIXED_EVENT_CONSTRAINT (0x0400 ,3 ),/* SLOTS */
Greg Kroah-Hartman
maintainerPATCH 102/214 perf/x86/amd/ibs: Dont include randomized bits in get_ibs_op_count()
In reply to Greg Kroah-HartmanFrom: Kim Phillips <[email protected]>
commit 680d69635005ba0e58fe3f4c52fc162b8fc743b0 upstream.
get_ibs_op_count() adds hardware's current count (IbsOpCurCnt) bits to its count regardless of hardware's valid status.
According to the PPR for AMD Family 17h Model 31h B0 55803 Rev 0.54, if the counter rolls over, valid status is set, and the lower 7 bits of IbsOpCurCnt are randomized by hardware.
Don't include those bits in the driver's event count.
--- arch/x86/events/amd/ibs.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
arch/x86/events/amd/ibs.c +8 -4
@@ -335,11 +335,15 @@ static u64 get_ibs_op_count(u64 config) {u64 count =0 ; +/* +* If the internal 27-bit counter rolled over, the count is MaxCnt +* and the lower 7 bits of CurCnt are randomized. +* Otherwise CurCnt has the full 27-bit current counter value. +*/ if (config &IBS_OP_VAL ) - count += (config &IBS_OP_MAX_CNT ) <<4 ;/* cnt rolled over */ - -if (ibs_caps &IBS_CAPS_RDWROPCNT ) - count += (config &IBS_OP_CUR_CNT ) >>32 ; + count = (config &IBS_OP_MAX_CNT ) <<4 ; +else if (ibs_caps &IBS_CAPS_RDWROPCNT ) + count = (config &IBS_OP_CUR_CNT ) >>32 ;return count; }
Greg Kroah-Hartman
maintainerPATCH 103/214 perf/x86/amd/ibs: Fix raw sample data accumulation
In reply to Greg Kroah-HartmanFrom: Kim Phillips <[email protected]>
commit 36e1be8ada994d509538b3b1d0af8b63c351e729 upstream.
Neither IbsBrTarget nor OPDATA4 are populated in IBS Fetch mode. Don't accumulate them into raw sample user data in that case.
Also, in Fetch mode, add saving the IBS Fetch Control Extended MSR.
Technically, there is an ABI change here with respect to the IBS raw sample data format, but I don't see any perf driver version information being included in perf.data file headers, but, existing users can detect whether the size of the sample record has reduced by 8 bytes to determine whether the IBS driver has this fix.
--- arch/x86/events/amd/ibs.c | 26 ++++++++++++++++---------- arch/x86/include/asm/msr-index.h | 1 + 2 files changed, 17 insertions(+), 10 deletions(-)
arch/x86/events/amd/ibs.c +16 -10
@@ -636,18 +636,24 @@ fail: perf_ibs->offset_max, offset + 1); }while (offset < offset_max); +/* +* Read IbsBrTarget, IbsOpData4, and IbsExtdCtl separately +* depending on their availability. +* Can't add to offset_max as they are staggered +*/ if (event->attr.sample_type &PERF_SAMPLE_RAW ) { -/* -* Read IbsBrTarget and IbsOpData4 separately -* depending on their availability. -* Can't add to offset_max as they are staggered -*/ -if (ibs_caps &IBS_CAPS_BRNTRGT ) { -rdmsrl (MSR_AMD64_IBSBRTARGET , *buf++); - size++; +if (perf_ibs == &perf_ibs_op) { +if (ibs_caps &IBS_CAPS_BRNTRGT ) { +rdmsrl (MSR_AMD64_IBSBRTARGET , *buf++); + size++; + } +if (ibs_caps &IBS_CAPS_OPDATA4 ) { +rdmsrl (MSR_AMD64_IBSOPDATA4 , *buf++); + size++; + } } -if (ibs_caps &IBS_CAPS_OPDATA4 ) { -rdmsrl (MSR_AMD64_IBSOPDATA4 , *buf++); +if (perf_ibs == &perf_ibs_fetch && (ibs_caps &IBS_CAPS_FETCHCTLEXTD )) { +rdmsrl (MSR_AMD64_ICIBSEXTDCTL , *buf++); size++; } }
arch/x86/include/asm/msr-index.h +1 -0
@@ -432,6 +432,7 @@#define MSR_AMD64_IBSOP_REG_MASK ((1UL<<MSR_AMD64_IBSOP_REG_COUNT)-1)#define MSR_AMD64_IBSCTL 0xc001103a#define MSR_AMD64_IBSBRTARGET 0xc001103b +#define MSR_AMD64_ICIBSEXTDCTL 0xc001103c#define MSR_AMD64_IBSOPDATA4 0xc001103d#define MSR_AMD64_IBS_REG_COUNT_MAX 8/* includes MSR_AMD64_IBSBRTARGET */ #define MSR_AMD64_SEV 0xc0010131
Greg Kroah-Hartman
maintainerPATCH 104/214 spi: sprd: Release DMA channel also on probe deferral
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
commit 687a2e76186dcfa42f22c14b655c3fb159839e79 upstream.
If dma_request_chan() for TX channel fails with EPROBE_DEFER, the RX channel would not be released and on next re-probe it would be requested second time.
--- drivers/spi/spi-sprd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/spi/spi-sprd.c +1 -1
@@ -563,11 +563,11 @@ static int sprd_spi_dma_request(struct s ss->dma.dma_chan[SPRD_SPI_TX ] =dma_request_chan (ss->dev,"tx_chn" );if (IS_ERR_OR_NULL (ss->dma.dma_chan[SPRD_SPI_TX ])) { +dma_release_channel (ss->dma.dma_chan[SPRD_SPI_RX ]);if (PTR_ERR (ss->dma.dma_chan[SPRD_SPI_TX ]) == -EPROBE_DEFER )return PTR_ERR (ss->dma.dma_chan[SPRD_SPI_TX ]);dev_err (ss->dev,"request TX DMA channel failed!\n" ); -dma_release_channel (ss->dma.dma_chan[SPRD_SPI_RX ]);return PTR_ERR (ss->dma.dma_chan[SPRD_SPI_TX ]); }
Greg Kroah-Hartman
maintainerPATCH 105/214 extcon: ptn5150: Fix usage of atomic GPIO with sleeping GPIO chips
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
commit 6aaad58c872db062f7ea2761421ca748bd0931cc upstream.
The driver uses atomic version of gpiod_set_value() without any real reason. It is called in a workqueue under mutex so it could sleep there. Changing it to "can_sleep" flavor allows to use the driver with all GPIO chips.
--- drivers/extcon/extcon-ptn5150.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/extcon/extcon-ptn5150.c +4 -4
@@ -127,7 +127,7 @@ static void ptn5150_irq_work(struct workcase PTN5150_DFP_ATTACHED :extcon_set_state_sync (info->edev,EXTCON_USB_HOST , false); -gpiod_set_value (info->vbus_gpiod,0 ); +gpiod_set_value_cansleep (info->vbus_gpiod,0 );extcon_set_state_sync (info->edev,EXTCON_USB , true);break ;
@@ -138,9 +138,9 @@ static void ptn5150_irq_work(struct work PTN5150_REG_CC_VBUS_DETECTION_MASK) >> PTN5150_REG_CC_VBUS_DETECTION_SHIFT);if (vbus) -gpiod_set_value (info->vbus_gpiod,0 ); +gpiod_set_value_cansleep (info->vbus_gpiod,0 );else -gpiod_set_value (info->vbus_gpiod,1 ); +gpiod_set_value_cansleep (info->vbus_gpiod,1 );extcon_set_state_sync (info->edev,EXTCON_USB_HOST , true);
@@ -156,7 +156,7 @@ static void ptn5150_irq_work(struct work EXTCON_USB_HOST, false);extcon_set_state_sync (info->edev,EXTCON_USB , false); -gpiod_set_value (info->vbus_gpiod,0 ); +gpiod_set_value_cansleep (info->vbus_gpiod,0 ); } }
Greg Kroah-Hartman
maintainerPATCH 106/214 leds: bcm6328, bcm6358: use devres LED registering function
In reply to Greg Kroah-HartmanFrom: Marek Behún <[email protected]>
commit ff5c89d44453e7ad99502b04bf798a3fc32c758b upstream.
These two drivers do not provide remove method and use devres for allocation of other resources, yet they use led_classdev_register instead of the devres variant, devm_led_classdev_register.
Fix this.
--- drivers/leds/leds-bcm6328.c | 2 +- drivers/leds/leds-bcm6358.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/leds/leds-bcm6328.c +1 -1
@@ -332,7 +332,7 @@ static int bcm6328_led(struct device *de led->cdev.brightness_set = bcm6328_led_set; led->cdev.blink_set = bcm6328_blink_set; - rc =led_classdev_register (dev, &led->cdev); + rc =devm_led_classdev_register (dev, &led->cdev);if (rc <0 )return rc;
drivers/leds/leds-bcm6358.c +1 -1
@@ -137,7 +137,7 @@ static int bcm6358_led(struct device *de led->cdev.brightness_set = bcm6358_led_set; - rc =led_classdev_register (dev, &led->cdev); + rc =devm_led_classdev_register (dev, &led->cdev);if (rc <0 )return rc;
Greg Kroah-Hartman
maintainerPATCH 107/214 media: uvcvideo: Fix uvc_ctrl_fixup_xu_info() not having any effect
In reply to Greg Kroah-HartmanFrom: Hans de Goede <[email protected]>
commit 93df48d37c3f03886d84831992926333e7810640 upstream.
uvc_ctrl_add_info() calls uvc_ctrl_get_flags() which will override the fixed-up flags set by uvc_ctrl_fixup_xu_info().
uvc_ctrl_init_xu_ctrl() already calls uvc_ctrl_get_flags() before calling uvc_ctrl_add_info(), so the uvc_ctrl_get_flags() call in uvc_ctrl_add_info() is not necessary for xu ctrls.
This commit moves the uvc_ctrl_get_flags() call for normal controls from uvc_ctrl_add_info() to uvc_ctrl_init_ctrl(), so that we no longer call uvc_ctrl_get_flags() twice for xu controls and so that we no longer override the fixed-up flags set by uvc_ctrl_fixup_xu_info().
This fixes the xu motor controls not working properly on a Logitech 046d:08cc, and presumably also on the other Logitech models which have a quirk for this in the uvc_ctrl_fixup_xu_info() function.
--- drivers/media/usb/uvc/uvc_ctrl.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/media/usb/uvc/uvc_ctrl.c +7 -7
@@ -2033,13 +2033,6 @@ static int uvc_ctrl_add_info(struct uvc_ goto done; } -/* -* Retrieve control flags from the device. Ignore errors and work with -* default flag values from the uvc_ctrl array when the device doesn't -* properly implement GET_INFO on standard controls. -*/ -uvc_ctrl_get_flags (dev, ctrl, &ctrl->info); - ctrl->initialized =1 ; uvc_trace(UVC_TRACE_CONTROL, "Added control %pUl/%u to device %s "
@@ -2262,6 +2255,13 @@ static void uvc_ctrl_init_ctrl(struct uvif (uvc_entity_match_guid (ctrl->entity, info->entity) && ctrl->index == info->index) {uvc_ctrl_add_info (dev, ctrl, info); +/* +* Retrieve control flags from the device. Ignore errors +* and work with default flag values from the uvc_ctrl +* array when the device doesn't properly implement +* GET_INFO on standard controls. +*/ +uvc_ctrl_get_flags (dev, ctrl, &ctrl->info);break ; } }
Greg Kroah-Hartman
maintainerPATCH 108/214 fs: Dont invalidate page buffers in block_write_full_page()
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
commit 6dbf7bb555981fb5faf7b691e8f6169fc2b2e63b upstream.
If block_write_full_page() is called for a page that is beyond current inode size, it will truncate page buffers for the page and return 0. This logic has been added in 2.5.62 in commit 81eb69062588 ("fix ext3 BUG due to race with truncate") in history.git tree to fix a problem with ext3 in data=ordered mode. This particular problem doesn't exist anymore because ext3 is long gone and ext4 handles ordered data differently. Also normally buffers are invalidated by truncate code and there's no need to specially handle this in ->writepage() code.
This invalidation of page buffers in block_write_full_page() is causing issues to filesystems (e.g. ext4 or ocfs2) when block device is shrunk under filesystem's hands and metadata buffers get discarded while being tracked by the journalling layer. Although it is obviously "not supported" it can cause kernel crashes like:
[ 7986.689400] BUG: unable to handle kernel NULL pointer dereference at +0000000000000008 [ 7986.697197] PGD 0 P4D 0 [ 7986.699724] Oops: 0002 [#1] SMP PTI [ 7986.703200] CPU: 4 PID: 203778 Comm: jbd2/dm-3-8 Kdump: loaded Tainted: G +O --------- - - 4.18.0-147.5.0.5.h126.eulerosv2r9.x86_64 #1 [ 7986.716438] Hardware name: Huawei RH2288H V3/BC11HGSA0, BIOS 1.57 08/11/2015 [ 7986.723462] RIP: 0010:jbd2_journal_grab_journal_head+0x1b/0x40 [jbd2] ... [ 7986.810150] Call Trace: [ 7986.812595] __jbd2_journal_insert_checkpoint+0x23/0x70 [jbd2] [ 7986.818408] jbd2_journal_commit_transaction+0x155f/0x1b60 [jbd2] [ 7986.836467] kjournald2+0xbd/0x270 [jbd2]
which is not great. The crash happens because bh->b_private is suddently NULL although BH_JBD flag is still set (this is because block_invalidatepage() cleared BH_Mapped flag and subsequent bh lookup found buffer without BH_Mapped set, called init_page_buffers() which has rewritten bh->b_private). So just remove the invalidation in block_write_full_page().
Note that the buffer cache invalidation when block device changes size is already careful to avoid similar problems by using invalidate_mapping_pages() which skips busy buffers so it was only this odd block_write_full_page() behavior that could tear down bdev buffers under filesystem's hands.
--- fs/buffer.c | 16 ---------------- 1 file changed, 16 deletions(-)
fs/buffer.c +0 -16
@@ -2739,16 +2739,6 @@ int nobh_writepage(struct page *page, ge/* Is the page fully outside i_size? (truncate in progress) */ offset = i_size & (PAGE_SIZE -1 );if (page->index >= end_index+1 || !offset) { -/* -* The page may have dirty, unmapped buffers. For example, -* they may have been added in ext3_writepage(). Make them -* freeable here, so the page does not leak. -*/ -#if 0 -/* Not really sure about this - do we need this ? */ -if (page->mapping->a_ops->invalidatepage) - page->mapping->a_ops->invalidatepage (page, offset); -#endif unlock_page (page);return 0 ;/* don't care */ }
@@ -2943,12 +2933,6 @@ int block_write_full_page(struct page *p/* Is the page fully outside i_size? (truncate in progress) */ offset = i_size & (PAGE_SIZE -1 );if (page->index >= end_index+1 || !offset) { -/* -* The page may have dirty, unmapped buffers. For example, -* they may have been added in ext3_writepage(). Make them -* freeable here, so the page does not leak. -*/ -do_invalidatepage (page,0 ,PAGE_SIZE );unlock_page (page);return 0 ;/* don't care */ }
Greg Kroah-Hartman
maintainerPATCH 109/214 NFS: fix nfs_path in case of a rename retry
In reply to Greg Kroah-HartmanFrom: Ashish Sangwan <[email protected]>
commit 247db73560bc3e5aef6db50c443c3c0db115bc93 upstream.
We are generating incorrect path in case of rename retry because we are restarting from wrong dentry. We should restart from the dentry which was received in the call to nfs_path.
--- fs/nfs/namespace.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
fs/nfs/namespace.c +8 -4
@@ -31,9 +31,9 @@ int nfs_mountpoint_expiry_timeout = 500/* * nfs_path - reconstruct the path given an arbitrary dentry * @base - used to return pointer to the end of devname part of path -* @dentry - pointer to dentry +* @dentry_in - pointer to dentry * @buffer - result buffer -* @buflen - length of buffer +* @buflen_in - length of buffer * @flags - options (see below) * * Helper function for constructing the server pathname
@@ -48,15 +48,19 @@ int nfs_mountpoint_expiry_timeout = 500* the original device (export) name * (if unset, the original name is returned verbatim) */ -char *nfs_path (char **p,struct dentry *dentry,char *buffer,ssize_t buflen, -unsigned flags) +char *nfs_path (char **p,struct dentry *dentry_in,char *buffer, +ssize_t buflen_in,unsigned flags) {char *end;int namelen;unsigned seq;const char *base; +struct dentry *dentry; +ssize_t buflen; rename_retry: + buflen = buflen_in; + dentry = dentry_in; end = buffer+buflen; *--end ='\0' ; buflen--;
Greg Kroah-Hartman
maintainerPATCH 110/214 ACPI: button: fix handling lid state changes when input device closed
In reply to Greg Kroah-HartmanFrom: [email protected] <[email protected]>
commit 21988a8e51479ceffe7b0568b170effabb708dfe upstream.
The original intent of 84d3f6b76447 was to delay evaluating lid state until all drivers have been loaded, with input device being opened from userspace serving as a signal for this condition. Let's ensure that state updates happen even if userspace closed (or in the future inhibited) input device.
Note that if we go through suspend/resume cycle we assume the system has been fully initialized even if LID input device has not been opened yet.
This has a side-effect of fixing access to input->users outside of input->mutex protections by the way of eliminating said accesses and using driver private flag.
--- drivers/acpi/button.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/acpi/button.c +7 -6
@@ -136,6 +136,7 @@ struct acpi_button {int last_state;ktime_t last_time;bool suspended; +bool lid_state_initialized; };static BLOCKING_NOTIFIER_HEAD (acpi_lid_notifier);
@@ -391,6 +392,8 @@ static int acpi_lid_update_state(structstatic void acpi_lid_initialize_state (struct acpi_device *device) { +struct acpi_button *button =acpi_driver_data (device); +switch (lid_init_state) {case ACPI_BUTTON_LID_INIT_OPEN : (void )acpi_lid_notify_state (device,1 );
@@ -402,13 +405,14 @@ static void acpi_lid_initialize_state(stdefault :break ; } + + button->lid_state_initialized = true; }static void acpi_button_notify (struct acpi_device *device,u32 event) {struct acpi_button *button =acpi_driver_data (device);struct input_dev *input; -int users;switch (event) {case ACPI_FIXED_HARDWARE_EVENT :
@@ -417,10 +421,7 @@ static void acpi_button_notify(struct accase ACPI_BUTTON_NOTIFY_STATUS : input = button->input;if (button->type ==ACPI_BUTTON_TYPE_LID ) { -mutex_lock (&button->input->mutex); - users = button->input->users; -mutex_unlock (&button->input->mutex); -if (users) +if (button->lid_state_initialized)acpi_lid_update_state (device, true); }else {int keycode;
@@ -465,7 +466,7 @@ static int acpi_button_resume(struct devstruct acpi_button *button =acpi_driver_data (device); button->suspended = false; -if (button->type ==ACPI_BUTTON_TYPE_LID && button->input->users) { +if (button->type ==ACPI_BUTTON_TYPE_LID ) { button->last_state = !!acpi_lid_evaluate_state (device); button->last_time =ktime_get ();acpi_lid_initialize_state (device);
Greg Kroah-Hartman
maintainerPATCH 111/214 ACPI / extlog: Check for RDMSR failure
In reply to Greg Kroah-HartmanFrom: Ben Hutchings <[email protected]>
commit 7cecb47f55e00282f972a1e0b09136c8cd938221 upstream.
extlog_init() uses rdmsrl() to read an MSR, which on older CPUs provokes a error message at boot:
unchecked MSR access error: RDMSR from 0x179 at rIP: 0xcd047307 (native_read_msr+0x7/0x40)
Use rdmsrl_safe() instead, and return -ENODEV if it fails.
--- drivers/acpi/acpi_extlog.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/acpi/acpi_extlog.c +3 -3
@@ -223,9 +223,9 @@ static int __init extlog_init(void)u64 cap;int rc; -rdmsrl (MSR_IA32_MCG_CAP , cap); - -if (!(cap &MCG_ELOG_P ) || !extlog_get_l1addr ()) +if (rdmsrl_safe (MSR_IA32_MCG_CAP , &cap) || + !(cap &MCG_ELOG_P ) || + !extlog_get_l1addr ())return -ENODEV ;if (edac_get_report_status () ==EDAC_REPORTING_FORCE ) {
Greg Kroah-Hartman
maintainerPATCH 112/214 ACPI: video: use ACPI backlight for HP 635 Notebook
In reply to Greg Kroah-HartmanFrom: Alex Hung <[email protected]>
commit b226faab4e7890bbbccdf794e8b94276414f9058 upstream.
The default backlight interface is AMD's radeon_bl0 which does not work on this system, so use the ACPI backlight interface on it instead.
--- drivers/acpi/video_detect.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/acpi/video_detect.c +9 -0
@@ -282,6 +282,15 @@ static const struct dmi_system_id video_ DMI_MATCH(DMI_PRODUCT_NAME, "530U4E/540U4E"), }, }, +/* https://bugs.launchpad.net/bugs/1894667 */ + { + .callback = video_detect_force_video, + .ident = "HP 635 Notebook", + .matches = { +DMI_MATCH (DMI_SYS_VENDOR ,"Hewlett-Packard" ), + DMI_MATCH(DMI_PRODUCT_NAME, "HP 635 Notebook PC"), + }, + }, /* Non win8 machines which need native backlight nevertheless */ {
Greg Kroah-Hartman
maintainerPATCH 113/214 ACPI: debug: dont allow debugging when ACPI is disabled
In reply to Greg Kroah-HartmanFrom: Jamie Iles <[email protected]>
commit 0fada277147ffc6d694aa32162f51198d4f10d94 upstream.
If ACPI is disabled then loading the acpi_dbg module will result in the following splat when lock debugging is enabled.
DEBUG_LOCKS_WARN_ON(lock->magic != lock)
WARNING: CPU: 0 PID: 1 at kernel/locking/mutex.c:938 __mutex_lock+0xa10/0x1290 Kernel panic - not syncing: panic_on_warn set ... CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.9.0-rc8+ #103 Hardware name: linux,dummy-virt (DT) Call trace: dump_backtrace+0x0/0x4d8 show_stack+0x34/0x48 dump_stack+0x174/0x1f8 panic+0x360/0x7a0 __warn+0x244/0x2ec report_bug+0x240/0x398 bug_handler+0x50/0xc0 call_break_hook+0x160/0x1d8 brk_handler+0x30/0xc0 do_debug_exception+0x184/0x340 el1_dbg+0x48/0xb0 el1_sync_handler+0x170/0x1c8 el1_sync+0x80/0x100 __mutex_lock+0xa10/0x1290 mutex_lock_nested+0x6c/0xc0 acpi_register_debugger+0x40/0x88 acpi_aml_init+0xc4/0x114 do_one_initcall+0x24c/0xb10 kernel_init_freeable+0x690/0x728 kernel_init+0x20/0x1e8 ret_from_fork+0x10/0x18
This is because acpi_debugger.lock has not been initialized as acpi_debugger_init() is not called when ACPI is disabled. Fail module loading to avoid this and any subsequent problems that might arise by trying to debug AML when ACPI is disabled.
--- drivers/acpi/acpi_dbg.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/acpi/acpi_dbg.c +3 -0
@@ -749,6 +749,9 @@ int __init acpi_aml_init(void) {int ret; +if (acpi_disabled) +return -ENODEV ; +/* Initialize AML IO interface */ mutex_init (&acpi_aml_io.lock);init_waitqueue_head (&acpi_aml_io.wait);
Greg Kroah-Hartman
maintainerPATCH 114/214 PCI/ACPI: Whitelist hotplug ports for D3 if power managed by ACPI
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit c6e331312ebfb52b7186e5d82d517d68b4d2f2d8 upstream.
Recent laptops with dual AMD GPUs fail to suspend the discrete GPU, thus causing lockups on system sleep and high power consumption at runtime. The discrete GPU would normally be suspended to D3cold by turning off ACPI _PR3 Power Resources of the Root Port above the GPU.
However on affected systems, the Root Port is hotplug-capable and pci_bridge_d3_possible() only allows hotplug ports to go to D3 if they belong to a Thunderbolt device or if the Root Port possesses a "HotPlugSupportInD3" ACPI property. Neither is the case on affected laptops. The reason for whitelisting only specific, known to work hotplug ports for D3 is that there have been reports of SkyLake Xeon-SP systems raising Hardware Error NMIs upon suspending their hotplug ports:
https://lore.kernel.org/linux-pci/20170503180426.GA4058@otc-nc-03/
But if a hotplug port is power manageable by ACPI (as can be detected through presence of Power Resources and corresponding _PS0 and _PS3 methods) then it ought to be safe to suspend it to D3. To this end, amend acpi_pci_bridge_d3() to whitelist such ports for D3.
--- drivers/pci/pci-acpi.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
drivers/pci/pci-acpi.c +10 -0
@@ -944,6 +944,16 @@ static bool acpi_pci_bridge_d3(struct pcif (!dev->is_hotplug_bridge)return false; +/* Assume D3 support if the bridge is power-manageable by ACPI. */ + adev =ACPI_COMPANION (&dev->dev); +if (!adev && !pci_dev_is_added (dev)) { + adev =acpi_pci_find_companion (&dev->dev); +ACPI_COMPANION_SET (&dev->dev, adev); + } + +if (adev &&acpi_device_power_manageable (adev)) +return true; +/* * Look for a special _DSD property for the root port and if it * is set we know the hierarchy behind it supports D3 just fine.
Greg Kroah-Hartman
maintainerPATCH 115/214 ACPI: EC: PM: Flush EC work unconditionally after wakeup
In reply to Greg Kroah-HartmanFrom: Rafael J. Wysocki <[email protected]>
commit 5e92442bb4121562231e6daf8a2d1306cb5f8805 upstream.
Commit 607b9df63057 ("ACPI: EC: PM: Avoid flushing EC work when EC GPE is inactive") has been reported to cause some power button wakeup events to be missed on some systems, so modify acpi_ec_dispatch_gpe() to call acpi_ec_flush_work() unconditionally to effectively reverse the changes made by that commit.
Also note that the problem which prompted commit 607b9df63057 is not reproducible any more on the affected machine.
--- drivers/acpi/ec.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
drivers/acpi/ec.c +3 -4
@@ -1976,12 +1976,11 @@ bool acpi_ec_dispatch_gpe(void)* to allow the caller to process events properly after that. */ ret =acpi_dispatch_gpe (NULL , first_ec->gpe); -if (ret ==ACPI_INTERRUPT_HANDLED ) { +if (ret ==ACPI_INTERRUPT_HANDLED )pm_pr_dbg ("EC GPE dispatched\n" ); -/* Flush the event and query workqueues. */ -acpi_ec_flush_work (); - } +/* Flush the event and query workqueues. */ +acpi_ec_flush_work ();return false; }
Greg Kroah-Hartman
maintainerPATCH 116/214 ACPI: EC: PM: Drop ec_no_wakeup check from acpi_ec_dispatch_gpe()
In reply to Greg Kroah-HartmanFrom: Rafael J. Wysocki <[email protected]>
commit e0e9ce390d7bc6a705653d4a8aa4ea92c9a65e53 upstream.
It turns out that in some cases there are EC events to flush in acpi_ec_dispatch_gpe() even though the ec_no_wakeup kernel parameter is set and the EC GPE is disabled while sleeping, so drop the ec_no_wakeup check that prevents those events from being processed from acpi_ec_dispatch_gpe().
--- drivers/acpi/ec.c | 3 --- 1 file changed, 3 deletions(-)
drivers/acpi/ec.c +0 -3
@@ -1968,9 +1968,6 @@ bool acpi_ec_dispatch_gpe(void)if (acpi_any_gpe_status_set (first_ec->gpe))return true; -if (ec_no_wakeup) -return false; -/* * Dispatch the EC GPE in-band, but do not report wakeup in any case * to allow the caller to process events properly after that.
Greg Kroah-Hartman
maintainerPATCH 117/214 acpi-cpufreq: Honor _PSD table setting on new AMD CPUs
In reply to Greg Kroah-HartmanFrom: Wei Huang <[email protected]>
commit 5368512abe08a28525d9b24abbfc2a72493e8dba upstream.
acpi-cpufreq has a old quirk that overrides the _PSD table supplied by BIOS on AMD CPUs. However the _PSD table of new AMD CPUs (Family 19h+) now accurately reports the P-state dependency of CPU cores. Hence this quirk needs to be fixed in order to support new CPUs' frequency control.
--- drivers/cpufreq/acpi-cpufreq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/cpufreq/acpi-cpufreq.c +2 -1
@@ -688,7 +688,8 @@ static int acpi_cpufreq_cpu_init(structcpumask_copy (policy->cpus,topology_core_cpumask (cpu)); } -if (check_amd_hwpstate_cpu (cpu) && !acpi_pstate_strict) { +if (check_amd_hwpstate_cpu (cpu) && boot_cpu_data.x86 <0x19 && + !acpi_pstate_strict) {cpumask_clear (policy->cpus);cpumask_set_cpu (cpu, policy->cpus); cpumask_copy(data->freqdomain_cpus,
Greg Kroah-Hartman
maintainerPATCH 118/214 w1: mxc_w1: Fix timeout resolution problem leading to bus error
In reply to Greg Kroah-HartmanFrom: Martin Fuzzey <[email protected]>
commit c9723750a699c3bd465493ac2be8992b72ccb105 upstream.
On my platform (i.MX53) bus access sometimes fails with
w1_search: max_slave_count 64 reached, will continue next search.
The reason is the use of jiffies to implement a 200us timeout in mxc_w1_ds2_touch_bit().
On some platforms the jiffies timer resolution is insufficient for this.
Fix by replacing jiffies by ktime_get().
For consistency apply the same change to the other use of jiffies in mxc_w1_ds2_reset_bus().
--- drivers/w1/masters/mxc_w1.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/w1/masters/mxc_w1.c +7 -7
@@ -7,7 +7,7 @@#include <linux/clk.h> #include <linux/delay.h> #include <linux/io.h> -#include <linux/jiffies.h> +#include <linux/ktime.h> #include <linux/module.h> #include <linux/mod_devicetable.h> #include <linux/platform_device.h>
@@ -40,12 +40,12 @@ struct mxc_w1_device {static u8 mxc_w1_ds2_reset_bus (void *data) {struct mxc_w1_device *dev = data; -unsigned long timeout; +ktime_t timeout;writeb (MXC_W1_CONTROL_RPP , dev->regs +MXC_W1_CONTROL );/* Wait for reset sequence 511+512us, use 1500us for sure */ - timeout = jiffies +usecs_to_jiffies (1500 ); + timeout =ktime_add_us (ktime_get (),1500 );udelay (511 +512 );
@@ -55,7 +55,7 @@ static u8 mxc_w1_ds2_reset_bus(void *dat/* PST bit is valid after the RPP bit is self-cleared */ if (!(ctrl &MXC_W1_CONTROL_RPP ))return !(ctrl &MXC_W1_CONTROL_PST ); - }while (time_is_after_jiffies (timeout)); + }while (ktime_before (ktime_get (), timeout));return 1 ; }
@@ -68,12 +68,12 @@ static u8 mxc_w1_ds2_reset_bus(void *datstatic u8 mxc_w1_ds2_touch_bit (void *data,u8 bit) {struct mxc_w1_device *dev = data; -unsigned long timeout; +ktime_t timeout;writeb (MXC_W1_CONTROL_WR (bit), dev->regs +MXC_W1_CONTROL );/* Wait for read/write bit (60us, Max 120us), use 200us for sure */ - timeout = jiffies +usecs_to_jiffies (200 ); + timeout =ktime_add_us (ktime_get (),200 );udelay (60 );
@@ -83,7 +83,7 @@ static u8 mxc_w1_ds2_touch_bit(void *dat/* RDST bit is valid after the WR1/RD bit is self-cleared */ if (!(ctrl &MXC_W1_CONTROL_WR (bit)))return !!(ctrl &MXC_W1_CONTROL_RDST ); - }while (time_is_after_jiffies (timeout)); + }while (ktime_before (ktime_get (), timeout));return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 119/214 scsi: mptfusion: Fix null pointer dereferences in mptscsih_remove()
In reply to Greg Kroah-HartmanFrom: Helge Deller <[email protected]>
commit 2f4843b172c2c0360ee7792ad98025fae7baefde upstream.
The mptscsih_remove() function triggers a kernel oops if the Scsi_Host pointer (ioc->sh) is NULL, as can be seen in this syslog:
ioc0: LSI53C1030 B2: Capabilities={Initiator,Target}
Begin: Waiting for root file system ...
scsi host2: error handler thread failed to spawn, error = -4
mptspi: ioc0: WARNING - Unable to register controller with SCSI subsystem
Backtrace: [<000000001045b7cc>] mptspi_probe+0x248/0x3d0 [mptspi] [<0000000040946470>] pci_device_probe+0x1ac/0x2d8 [<0000000040add668>] really_probe+0x1bc/0x988 [<0000000040ade704>] driver_probe_device+0x160/0x218 [<0000000040adee24>] device_driver_attach+0x160/0x188 [<0000000040adef90>] __driver_attach+0x144/0x320 [<0000000040ad7c78>] bus_for_each_dev+0xd4/0x158 [<0000000040adc138>] driver_attach+0x4c/0x80 [<0000000040adb3ec>] bus_add_driver+0x3e0/0x498 [<0000000040ae0130>] driver_register+0xf4/0x298 [<00000000409450c4>] __pci_register_driver+0x78/0xa8 [<000000000007d248>] mptspi_init+0x18c/0x1c4 [mptspi]
This patch adds the necessary NULL-pointer checks. Successfully tested on a HP C8000 parisc workstation with buggy SCSI drives.
--- drivers/message/fusion/mptscsih.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/message/fusion/mptscsih.c +8 -5
@@ -1176,8 +1176,10 @@ mptscsih_remove(struct pci_dev *pdev)MPT_SCSI_HOST *hd;int sz1; -if ((hd =shost_priv (host)) ==NULL ) -return ; +if (host ==NULL ) + hd =NULL ; +else + hd =shost_priv (host);mptscsih_shutdown (pdev);
@@ -1193,14 +1195,15 @@ mptscsih_remove(struct pci_dev *pdev)"Free'd ScsiLookup (%d) memory\n" , ioc->name, sz1)); -kfree (hd->info_kbuf); +if (hd) +kfree (hd->info_kbuf);/* NULL the Scsi_Host pointer */ ioc->sh =NULL ; -scsi_host_put (host); - +if (host) +scsi_host_put (host);mpt_detach (pdev); }
Greg Kroah-Hartman
maintainerPATCH 120/214 scsi: qla2xxx: Fix crash on session cleanup with unload
In reply to Greg Kroah-HartmanFrom: Quinn Tran <[email protected]>
commit 50457dab670f396557e60c07f086358460876353 upstream.
On unload, session cleanup prematurely gave the signal for driver unload path to advance.
--- drivers/scsi/qla2xxx/qla_target.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/scsi/qla2xxx/qla_target.c +7 -6
@@ -1230,14 +1230,15 @@ void qlt_schedule_sess_for_deletion(strucase DSC_DELETE_PEND :return ;case DSC_DELETED : -if (tgt && tgt->tgt_stop && (tgt->sess_count ==0 )) -wake_up_all (&tgt->waitQ); -if (sess->vha->fcport_count ==0 ) -wake_up_all (&sess->vha->fcport_waitQ); -if (!sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN ] && - !sess->plogi_link[QLT_PLOGI_LINK_CONFLICT ]) + !sess->plogi_link[QLT_PLOGI_LINK_CONFLICT ]) { +if (tgt && tgt->tgt_stop && tgt->sess_count ==0 ) +wake_up_all (&tgt->waitQ); + +if (sess->vha->fcport_count ==0 ) +wake_up_all (&sess->vha->fcport_waitQ);return ; + }break ;case DSC_UPD_FCPORT :/*
Greg Kroah-Hartman
maintainerPATCH 121/214 PM: runtime: Remove link state checks in rpm_get/put_supplier()
In reply to Greg Kroah-HartmanFrom: Xiang Chen <[email protected]>
commit d12544fb2aa9944b180c35914031a8384ab082c1 upstream.
To support runtime PM for hisi SAS driver (the driver is in directory drivers/scsi/hisi_sas), we add device link between scsi_device->sdev_gendev (consumer device) and hisi_hba->dev(supplier device) with flags DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE.
After runtime suspended consumers and supplier, unload the dirver which causes a hung.
We found that it called function device_release_driver_internal() to release the supplier device (hisi_hba->dev), as the device link was busy, it set the device link state to DL_STATE_SUPPLIER_UNBIND, and then it called device_release_driver_internal() to release the consumer device (scsi_device->sdev_gendev).
Then it would try to call pm_runtime_get_sync() to resume the consumer device, but because consumer-supplier relation existed, it would try to resume the supplier first, but as the link state was already DL_STATE_SUPPLIER_UNBIND, so it skipped resuming the supplier and only resumed the consumer which hanged (it sends IOs to resume scsi_device while the SAS controller is suspended).
Simple flow is as follows:
device_release_driver_internal -> (supplier device)
if device_links_busy ->
device_links_unbind_consumers ->
...
WRITE_ONCE(link->status, DL_STATE_SUPPLIER_UNBIND)
device_release_driver_internal (consumer device)
pm_runtime_get_sync -> (consumer device)
...
__rpm_callback ->
rpm_get_suppliers ->
if link->state == DL_STATE_SUPPLIER_UNBIND -> skip the action of resuming the supplier
...
pm_runtime_clean_up_links
...Correct suspend/resume ordering between a supplier device and its consumer devices (resume the supplier device before resuming consumer devices, and suspend consumer devices before suspending the supplier device) should be guaranteed by runtime PM, but the state checks in rpm_get_supplier() and rpm_put_supplier() break this rule, so remove them.
--- drivers/base/power/runtime.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
drivers/base/power/runtime.c +1 -4
@@ -291,8 +291,7 @@ static int rpm_get_suppliers(struct devi device_links_read_lock_held()) {int retval; -if (!(link->flags &DL_FLAG_PM_RUNTIME ) || -READ_ONCE (link->status) ==DL_STATE_SUPPLIER_UNBIND ) +if (!(link->flags &DL_FLAG_PM_RUNTIME ))continue ; retval =pm_runtime_get_sync (link->supplier);
@@ -312,8 +311,6 @@ static void rpm_put_suppliers(struct devlist_for_each_entry_rcu (link, &dev->links.suppliers, c_node,device_links_read_lock_held ()) { -if (READ_ONCE (link->status) ==DL_STATE_SUPPLIER_UNBIND ) -continue ;while (refcount_dec_not_one (&link->rpm_active))pm_runtime_put (link->supplier);
Greg Kroah-Hartman
maintainerPATCH 122/214 btrfs: qgroup: fix wrong qgroup metadata reserve for delayed inode
In reply to Greg Kroah-HartmanFrom: Qu Wenruo <[email protected]>
commit b4c5d8fdfff3e2b6c4fa4a5043e8946dff500f8c upstream.
For delayed inode facility, qgroup metadata is reserved for it, and later freed.
However we're freeing more bytes than we reserved. In btrfs_delayed_inode_reserve_metadata():
num_bytes = btrfs_calc_metadata_size(fs_info, 1);
...
ret = btrfs_qgroup_reserve_meta_prealloc(root,
fs_info->nodesize, true);
...
if (!ret) {
node->bytes_reserved = num_bytes;But in btrfs_delayed_inode_release_metadata():
if (qgroup_free) btrfs_qgroup_free_meta_prealloc(node->root, node->bytes_reserved); else btrfs_qgroup_convert_reserved_meta(node->root, node->bytes_reserved);
This means, we're always releasing more qgroup metadata rsv than we have reserved.
This won't trigger selftest warning, as btrfs qgroup metadata rsv has extra protection against cases like quota enabled half-way.
But we still need to fix this problem any way.
This patch will use the same num_bytes for qgroup metadata rsv so we could handle it correctly.
--- fs/btrfs/delayed-inode.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
fs/btrfs/delayed-inode.c +1 -2
@@ -627,8 +627,7 @@ static int btrfs_delayed_inode_reserve_m*/ if (!src_rsv || (!trans->bytes_reserved && src_rsv->type !=BTRFS_BLOCK_RSV_DELALLOC )) { - ret =btrfs_qgroup_reserve_meta_prealloc (root, - fs_info->nodesize, true); + ret =btrfs_qgroup_reserve_meta_prealloc (root, num_bytes, true);if (ret <0 )return ret; ret = btrfs_block_rsv_add(root, dst_rsv, num_bytes,
Greg Kroah-Hartman
maintainerPATCH 123/214 btrfs: improve device scanning messages
In reply to Greg Kroah-HartmanFrom: Anand Jain <[email protected]>
commit 79dae17d8d44b2d15779e332180080af45df5352 upstream.
Systems booting without the initramfs seems to scan an unusual kind of device path (/dev/root). And at a later time, the device is updated to the correct path. We generally print the process name and PID of the process scanning the device but we don't capture the same information if the device path is rescanned with a different pathname.
The current message is too long, so drop the unnecessary UUID and add process name and PID.
While at this also update the duplicate device warning to include the process name and PID so the messages are consistent
CC: [email protected] # 4.19+
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=89721
--- fs/btrfs/volumes.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
fs/btrfs/volumes.c +8 -6
@@ -1123,16 +1123,18 @@ static noinline struct btrfs_device *devbdput (path_bdev);mutex_unlock (&fs_devices->device_list_mutex);btrfs_warn_in_rcu (device->fs_info, -"duplicate device fsid:devid for %pU:%llu old:%s new:%s" , - disk_super->fsid, devid, -rcu_str_deref (device->name), path); +"duplicate device %s devid %llu generation %llu scanned by %s (%d)" , + path, devid, found_transid, + current->comm, +task_pid_nr (current));return ERR_PTR (-EEXIST ); }bdput (path_bdev);btrfs_info_in_rcu (device->fs_info, -"device fsid %pU devid %llu moved old:%s new:%s" , - disk_super->fsid, devid, -rcu_str_deref (device->name), path); +"devid %llu device path %s changed to %s scanned by %s (%d)" , + devid,rcu_str_deref (device->name), + path, current->comm, +task_pid_nr (current)); } name =rcu_string_strdup (path,GFP_NOFS );
Greg Kroah-Hartman
maintainerPATCH 124/214 btrfs: reschedule if necessary when logging directory items
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
commit bb56f02f26fe23798edb1b2175707419b28c752a upstream.
Logging directories with many entries can take a significant amount of time, and in some cases monopolize a cpu/core for a long time if the logging task doesn't happen to block often enough.
Johannes and Lu Fengqi reported test case generic/041 triggering a soft lockup when the kernel has CONFIG_SOFTLOCKUP_DETECTOR=y. For this test case we log an inode with 3002 hard links, and because the test removed one hard link before fsyncing the file, the inode logging causes the parent directory do be logged as well, which has 6004 directory items to log (3002 BTRFS_DIR_ITEM_KEY items plus 3002 BTRFS_DIR_INDEX_KEY items), so it can take a significant amount of time and trigger the soft lockup.
So just make tree-log.c:log_dir_items() reschedule when necessary, releasing the current search path before doing so and then resume from where it was before the reschedule.
The stack trace produced when the soft lockup happens is the following:
[10480.277653] watchdog: BUG: soft lockup - CPU#2 stuck for 22s! [xfs_io:28172] [10480.279418] Modules linked in: dm_thin_pool dm_persistent_data (...) [10480.284915] irq event stamp: 29646366 [10480.285987] hardirqs last enabled at (29646365): [<ffffffff85249b66>] __slab_alloc.constprop.0+0x56/0x60 [10480.288482] hardirqs last disabled at (29646366): [<ffffffff8579b00d>] irqentry_enter+0x1d/0x50 [10480.290856] softirqs last enabled at (4612): [<ffffffff85a00323>] __do_softirq+0x323/0x56c [10480.293615] softirqs last disabled at (4483): [<ffffffff85800dbf>] asm_call_on_stack+0xf/0x20 [10480.296428] CPU: 2 PID: 28172 Comm: xfs_io Not tainted 5.9.0-rc4-default+ #1248 [10480.298948] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-59-gc9ba527-rebuilt.opensuse.org 04/01/2014 [10480.302455] RIP: 0010:__slab_alloc.constprop.0+0x19/0x60 [10480.304151] Code: 86 e8 31 75 21 00 66 66 2e 0f 1f 84 00 00 00 (...) [10480.309558] RSP: 0018:ffffadbe09397a58 EFLAGS: 00000282 [10480.311179] RAX: ffff8a495ab92840 RBX: 0000000000000282 RCX: 0000000000000006 [10480.313242] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffffff85249b66 [10480.315260] RBP: ffff8a497d04b740 R08: 0000000000000001 R09: 0000000000000001 [10480.317229] R10: ffff8a497d044800 R11: ffff8a495ab93c40 R12: 0000000000000000 [10480.319169] R13: 0000000000000000 R14: 0000000000000c40 R15: ffffffffc01daf70 [10480.321104] FS: 00007fa1dc5c0e40(0000) GS:ffff8a497da00000(0000) knlGS:0000000000000000 [10480.323559] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [10480.325235] CR2: 00007fa1dc5befb8 CR3: 0000000004f8a006 CR4: 0000000000170ea0 [10480.327259] Call Trace: [10480.328286] ? overwrite_item+0x1f0/0x5a0 [btrfs] [10480.329784] __kmalloc+0x831/0xa20 [10480.331009] ? btrfs_get_32+0xb0/0x1d0 [btrfs] [10480.332464] overwrite_item+0x1f0/0x5a0 [btrfs] [10480.333948] log_dir_items+0x2ee/0x570 [btrfs] [10480.335413] log_directory_changes+0x82/0xd0 [btrfs] [10480.336926] btrfs_log_inode+0xc9b/0xda0 [btrfs] [10480.338374] ? init_once+0x20/0x20 [btrfs] [10480.339711] btrfs_log_inode_parent+0x8d3/0xd10 [btrfs] [10480.341257] ? dget_parent+0x97/0x2e0 [10480.342480] btrfs_log_dentry_safe+0x3a/0x50 [btrfs] [10480.343977] btrfs_sync_file+0x24b/0x5e0 [btrfs] [10480.345381] do_fsync+0x38/0x70 [10480.346483] __x64_sys_fsync+0x10/0x20 [10480.347703] do_syscall_64+0x2d/0x70 [10480.348891] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [10480.350444] RIP: 0033:0x7fa1dc80970b [10480.351642] Code: 0f 05 48 3d 00 f0 ff ff 77 45 c3 0f 1f 40 00 48 (...) [10480.356952] RSP: 002b:00007fffb3d081d0 EFLAGS: 00000293 ORIG_RAX: 000000000000004a [10480.359458] RAX: ffffffffffffffda RBX: 0000562d93d45e40 RCX: 00007fa1dc80970b [10480.361426] RDX: 0000562d93d44ab0 RSI: 0000562d93d45e60 RDI: 0000000000000003 [10480.363367] RBP: 0000000000000001 R08: 0000000000000000 R09: 00007fa1dc7b2a40 [10480.365317] R10: 0000562d93d0e366 R11: 0000000000000293 R12: 0000000000000001 [10480.367299] R13: 0000562d93d45290 R14: 0000562d93d45e40 R15: 0000562d93d45e60
--- fs/btrfs/tree-log.c | 8 ++++++++ 1 file changed, 8 insertions(+)
fs/btrfs/tree-log.c +8 -0
@@ -3639,6 +3639,7 @@ static noinline int log_dir_items(struct* search and this search we'll not find the key again and can just * bail. */ +search: ret =btrfs_search_slot (NULL , root, &min_key, path,0 ,0 );if (ret !=0 ) goto done;
@@ -3658,6 +3659,13 @@ static noinline int log_dir_items(structif (min_key.objectid != ino || min_key.type != key_type) goto done; + +if (need_resched ()) { +btrfs_release_path (path); +cond_resched (); + goto search; + } + ret =overwrite_item (trans, log, dst_path, src, i, &min_key);if (ret) {
Greg Kroah-Hartman
maintainerPATCH 125/214 btrfs: send, orphanize first all conflicting inodes when processing references
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
commit 98272bb77bf4cc20ed1ffca89832d713e70ebf09 upstream.
When doing an incremental send it is possible that when processing the new references for an inode we end up issuing rename or link operations that have an invalid path, which contains the orphanized name of a directory before we actually orphanized it, causing the receiver to fail.
The following reproducer triggers such scenario:
$ cat reproducer.sh #!/bin/bash
mkfs.btrfs -f /dev/sdi >/dev/null
mount /dev/sdi /mnt/sdi
touch /mnt/sdi/a
touch /mnt/sdi/b
mkdir /mnt/sdi/testdir
# We want "a" to have a lower inode number then "testdir" (257 vs 259). mv /mnt/sdi/a /mnt/sdi/testdir/a
# Filesystem looks like:
#
# . (ino 256) # |----- testdir/ (ino 259) # | |----- a (ino 257) # | # |----- b (ino 258)
btrfs subvolume snapshot -r /mnt/sdi /mnt/sdi/snap1 btrfs send -f /tmp/snap1.send /mnt/sdi/snap1
# Now rename 259 to "testdir_2", then change the name of 257 to # "testdir" and make it a direct descendant of the root inode (256). # Also create a new link for inode 257 with the old name of inode 258. # By swapping the names and location of several inodes and create a
# nasty dependency chain of rename and link operations. mv /mnt/sdi/testdir/a /mnt/sdi/a2 touch /mnt/sdi/testdir/a mv /mnt/sdi/b /mnt/sdi/b2 ln /mnt/sdi/a2 /mnt/sdi/b mv /mnt/sdi/testdir /mnt/sdi/testdir_2 mv /mnt/sdi/a2 /mnt/sdi/testdir
# Filesystem now looks like:
#
# . (ino 256) # |----- testdir_2/ (ino 259) # | |----- a (ino 260) # | # |----- testdir (ino 257) # |----- b (ino 257) # |----- b2 (ino 258)
btrfs subvolume snapshot -r /mnt/sdi /mnt/sdi/snap2 btrfs send -f /tmp/snap2.send -p /mnt/sdi/snap1 /mnt/sdi/snap2
mkfs.btrfs -f /dev/sdj >/dev/null
mount /dev/sdj /mnt/sdj
btrfs receive -f /tmp/snap1.send /mnt/sdj
btrfs receive -f /tmp/snap2.send /mnt/sdj
umount /mnt/sdi
umount /mnt/sdj
When running the reproducer, the receive of the incremental send stream fails:
$ ./reproducer.sh Create a readonly snapshot of '/mnt/sdi' in '/mnt/sdi/snap1' At subvol /mnt/sdi/snap1 Create a readonly snapshot of '/mnt/sdi' in '/mnt/sdi/snap2' At subvol /mnt/sdi/snap2 At subvol snap1 At snapshot snap2 ERROR: link b -> o259-6-0/a failed: No such file or directory
The problem happens because of the following:
1) Before we start iterating the list of new references for inode 257, we generate its current path and store it at @valid_path, done at the very beginning of process_recorded_refs(). The generated path is "o259-6-0/a", containing the orphanized name for inode 259;
2) Then we iterate over the list of new references, which has the references "b" and "testdir" in that specific order;
3) We process reference "b" first, because it is in the list before reference "testdir". We then issue a link operation to create the new reference "b" using a target path corresponding to the content at @valid_path, which corresponds to "o259-6-0/a". However we haven't yet orphanized inode 259, its name is still "testdir", and not "o259-6-0". The orphanization of 259 did not happen yet because we will process the reference named "testdir" for inode 257 only in the next iteration of the loop that goes over the list of new references.
Fix the issue by having a preliminar iteration over all the new references at process_recorded_refs(). This iteration is responsible only for doing the orphanization of other inodes that have and old reference that conflicts with one of the new references of the inode we are currently processing. The emission of rename and link operations happen now in the next iteration of the new references.
A test case for fstests will follow soon.
--- fs/btrfs/send.c | 127 ++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 87 insertions(+), 40 deletions(-)
fs/btrfs/send.c +87 -40
@@ -3880,52 +3880,56 @@ static int process_recorded_refs(struct goto out; } +/* +* Before doing any rename and link operations, do a first pass on the +* new references to orphanize any unprocessed inodes that may have a +* reference that conflicts with one of the new references of the current +* inode. This needs to happen first because a new reference may conflict +* with the old reference of a parent directory, so we must make sure +* that the path used for link and rename commands don't use an +* orphanized name when an ancestor was not yet orphanized. +* +* Example: +* +* Parent snapshot: +* +* . (ino 256) +* |----- testdir/ (ino 259) +* | |----- a (ino 257) +* | +* |----- b (ino 258) +* +* Send snapshot: +* +* . (ino 256) +* |----- testdir_2/ (ino 259) +* | |----- a (ino 260) +* | +* |----- testdir (ino 257) +* |----- b (ino 257) +* |----- b2 (ino 258) +* +* Processing the new reference for inode 257 with name "b" may happen +* before processing the new reference with name "testdir". If so, we +* must make sure that by the time we send a link command to create the +* hard link "b", inode 259 was already orphanized, since the generated +* path in "valid_path" already contains the orphanized name for 259. +* We are processing inode 257, so only later when processing 259 we do +* the rename operation to change its temporary (orphanized) name to +* "testdir_2". +*/ list_for_each_entry (cur, &sctx->new_refs, list) { -/* -* We may have refs where the parent directory does not exist -* yet. This happens if the parent directories inum is higher -* than the current inum. To handle this case, we create the -* parent directory out of order. But we need to check if this -* did already happen before due to other refs in the same dir. -*/ ret =get_cur_inode_state (sctx, cur->dir, cur->dir_gen);if (ret <0 ) goto out; -if (ret == inode_state_will_create) { - ret =0 ; -/* -* First check if any of the current inodes refs did -* already create the dir. -*/ -list_for_each_entry (cur2, &sctx->new_refs, list) { -if (cur == cur2) -break ; -if (cur2->dir == cur->dir) { - ret =1 ; -break ; - } - } - -/* -* If that did not happen, check if a previous inode -* did already create the dir. -*/ -if (!ret) - ret =did_create_dir (sctx, cur->dir); -if (ret <0 ) - goto out; -if (!ret) { - ret =send_create_inode (sctx, cur->dir); -if (ret <0 ) - goto out; - } - } +if (ret == inode_state_will_create) +continue ;/* -* Check if this new ref would overwrite the first ref of -* another unprocessed inode. If yes, orphanize the -* overwritten inode. If we find an overwritten ref that is -* not the first ref, simply unlink it. +* Check if this new ref would overwrite the first ref of another +* unprocessed inode. If yes, orphanize the overwritten inode. +* If we find an overwritten ref that is not the first ref, +* simply unlink it. */ ret = will_overwrite_ref(sctx, cur->dir, cur->dir_gen, cur->name, cur->name_len,
@@ -4002,6 +4006,49 @@ static int process_recorded_refs(structif (ret <0 ) goto out; } + } + + } + +list_for_each_entry (cur, &sctx->new_refs, list) { +/* +* We may have refs where the parent directory does not exist +* yet. This happens if the parent directories inum is higher +* than the current inum. To handle this case, we create the +* parent directory out of order. But we need to check if this +* did already happen before due to other refs in the same dir. +*/ + ret =get_cur_inode_state (sctx, cur->dir, cur->dir_gen); +if (ret <0 ) + goto out; +if (ret == inode_state_will_create) { + ret =0 ; +/* +* First check if any of the current inodes refs did +* already create the dir. +*/ +list_for_each_entry (cur2, &sctx->new_refs, list) { +if (cur == cur2) +break ; +if (cur2->dir == cur->dir) { + ret =1 ; +break ; + } + } + +/* +* If that did not happen, check if a previous inode +* did already create the dir. +*/ +if (!ret) + ret =did_create_dir (sctx, cur->dir); +if (ret <0 ) + goto out; +if (!ret) { + ret =send_create_inode (sctx, cur->dir); +if (ret <0 ) + goto out; + } }if (S_ISDIR (sctx->cur_inode_mode) && sctx->parent_root) {
Greg Kroah-Hartman
maintainerPATCH 126/214 btrfs: send, recompute reference path after orphanization of a directory
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
commit 9c2b4e0347067396ceb3ae929d6888c81d610259 upstream.
During an incremental send, when an inode has multiple new references we might end up emitting rename operations for orphanizations that have a source path that is no longer valid due to a previous orphanization of some directory inode. This causes the receiver to fail since it tries to rename a path that does not exists.
Example reproducer:
$ cat reproducer.sh #!/bin/bash
mkfs.btrfs -f /dev/sdi >/dev/null
mount /dev/sdi /mnt/sdi
touch /mnt/sdi/f1
touch /mnt/sdi/f2
mkdir /mnt/sdi/d1
mkdir /mnt/sdi/d1/d2
# Filesystem looks like:
#
# . (ino 256) # |----- f1 (ino 257) # |----- f2 (ino 258) # |----- d1/ (ino 259) # |----- d2/ (ino 260)
btrfs subvolume snapshot -r /mnt/sdi /mnt/sdi/snap1 btrfs send -f /tmp/snap1.send /mnt/sdi/snap1
# Now do a series of changes such that:
#
# *) inode 258 has one new hardlink and the previous name changed #
# *) both names conflict with the old names of two other inodes:
#
# 1) the new name "d1" conflicts with the old name of inode 259,
# under directory inode 256 (root)
#
# 2) the new name "d2" conflicts with the old name of inode 260
# under directory inode 259
#
# *) inodes 259 and 260 now have the old names of inode 258 #
# *) inode 257 is now located under inode 260 - an inode with a number
# smaller than the inode (258) for which we created a second hard
# link and swapped its names with inodes 259 and 260
#
ln /mnt/sdi/f2 /mnt/sdi/d1/f2_link
mv /mnt/sdi/f1 /mnt/sdi/d1/d2/f1
# Swap d1 and f2.
mv /mnt/sdi/d1 /mnt/sdi/tmp
mv /mnt/sdi/f2 /mnt/sdi/d1
mv /mnt/sdi/tmp /mnt/sdi/f2
# Swap d2 and f2_link
mv /mnt/sdi/f2/d2 /mnt/sdi/tmp
mv /mnt/sdi/f2/f2_link /mnt/sdi/f2/d2
mv /mnt/sdi/tmp /mnt/sdi/f2/f2_link
# Filesystem now looks like:
#
# . (ino 256) # |----- d1 (ino 258) # |----- f2/ (ino 259) # |----- f2_link/ (ino 260) # | |----- f1 (ino 257) # | # |----- d2 (ino 258)
btrfs subvolume snapshot -r /mnt/sdi /mnt/sdi/snap2 btrfs send -f /tmp/snap2.send -p /mnt/sdi/snap1 /mnt/sdi/snap2
mkfs.btrfs -f /dev/sdj >/dev/null
mount /dev/sdj /mnt/sdj
btrfs receive -f /tmp/snap1.send /mnt/sdj
btrfs receive -f /tmp/snap2.send /mnt/sdj
umount /mnt/sdi
umount /mnt/sdj
When executed the receive of the incremental stream fails:
$ ./reproducer.sh Create a readonly snapshot of '/mnt/sdi' in '/mnt/sdi/snap1' At subvol /mnt/sdi/snap1 Create a readonly snapshot of '/mnt/sdi' in '/mnt/sdi/snap2' At subvol /mnt/sdi/snap2 At subvol snap1 At snapshot snap2 ERROR: rename d1/d2 -> o260-6-0 failed: No such file or directory
This happens because:
1) When processing inode 257 we end up computing the name for inode 259 because it is an ancestor in the send snapshot, and at that point it still has its old name, "d1", from the parent snapshot because inode 259 was not yet processed. We then cache that name, which is valid until we start processing inode 259 (or set the progress to 260 after processing its references);
2) Later we start processing inode 258 and collecting all its new references into the list sctx->new_refs. The first reference in the list happens to be the reference for name "d1" while the reference for name "d2" is next (the last element of the list).
We compute the full path "d1/d2" for this second reference and store it in the reference (its ->full_path member). The path used for the new parent directory was "d1" and not "f2" because inode 259, the new parent, was not yet processed;
3) When we start processing the new references at process_recorded_refs() we start with the first reference in the list, for the new name "d1". Because there is a conflicting inode that was not yet processed, which is directory inode 259, we orphanize it, renaming it from "d1" to "o259-6-0";
4) Then we start processing the new reference for name "d2", and we realize it conflicts with the reference of inode 260 in the parent snapshot. So we issue an orphanization operation for inode 260 by emitting a rename operation with a destination path of "o260-6-0" and a source path of "d1/d2" - this source path is the value we stored in the reference earlier at step 2), corresponding to the ->full_path member of the reference, however that path is no longer valid due to the orphanization of the directory inode 259 in step 3). This makes the receiver fail since the path does not exists, it should have been "o259-6-0/d2".
Fix this by recomputing the full path of a reference before emitting an orphanization if we previously orphanized any directory, since that directory could be a parent in the new path. This is a rare scenario so keeping it simple and not checking if that previously orphanized directory is in fact an ancestor of the inode we are trying to orphanize.
A test case for fstests follows soon.
--- fs/btrfs/send.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+)
fs/btrfs/send.c +72 -0
@@ -3813,6 +3813,72 @@ static int update_ref_path(struct send_c }/* +* When processing the new references for an inode we may orphanize an existing +* directory inode because its old name conflicts with one of the new references +* of the current inode. Later, when processing another new reference of our +* inode, we might need to orphanize another inode, but the path we have in the +* reference reflects the pre-orphanization name of the directory we previously +* orphanized. For example: +* +* parent snapshot looks like: +* +* . (ino 256) +* |----- f1 (ino 257) +* |----- f2 (ino 258) +* |----- d1/ (ino 259) +* |----- d2/ (ino 260) +* +* send snapshot looks like: +* +* . (ino 256) +* |----- d1 (ino 258) +* |----- f2/ (ino 259) +* |----- f2_link/ (ino 260) +* | |----- f1 (ino 257) +* | +* |----- d2 (ino 258) +* +* When processing inode 257 we compute the name for inode 259 as "d1", and we +* cache it in the name cache. Later when we start processing inode 258, when +* collecting all its new references we set a full path of "d1/d2" for its new +* reference with name "d2". When we start processing the new references we +* start by processing the new reference with name "d1", and this results in +* orphanizing inode 259, since its old reference causes a conflict. Then we +* move on the next new reference, with name "d2", and we find out we must +* orphanize inode 260, as its old reference conflicts with ours - but for the +* orphanization we use a source path corresponding to the path we stored in the +* new reference, which is "d1/d2" and not "o259-6-0/d2" - this makes the +* receiver fail since the path component "d1/" no longer exists, it was renamed +* to "o259-6-0/" when processing the previous new reference. So in this case we +* must recompute the path in the new reference and use it for the new +* orphanization operation. +*/ +static int refresh_ref_path (struct send_ctx *sctx,struct recorded_ref *ref) +{ +char *name; +int ret; + + name =kmemdup (ref->name, ref->name_len,GFP_KERNEL ); +if (!name) +return -ENOMEM ; + +fs_path_reset (ref->full_path); + ret =get_cur_path (sctx, ref->dir, ref->dir_gen, ref->full_path); +if (ret <0 ) + goto out; + + ret =fs_path_add (ref->full_path, name, ref->name_len); +if (ret <0 ) + goto out; + +/* Update the reference's base name pointer. */ +set_ref_path (ref, ref->full_path); +out: +kfree (name); +return ret; +} + +/* * This does all the move/link/unlink/rmdir magic. */ static int process_recorded_refs (struct send_ctx *sctx,int *pending_move)
@@ -3946,6 +4012,12 @@ static int process_recorded_refs(structstruct name_cache_entry *nce;struct waiting_dir_move *wdm; +if (orphanized_dir) { + ret =refresh_ref_path (sctx, cur); +if (ret <0 ) + goto out; + } + ret =orphanize_inode (sctx, ow_inode, ow_gen, cur->full_path);if (ret <0 )
Greg Kroah-Hartman
maintainerPATCH 127/214 btrfs: use kvzalloc() to allocate clone_roots in btrfs_ioctl_send()
In reply to Greg Kroah-HartmanFrom: Denis Efremov <[email protected]>
commit 8eb2fd00153a3a96a19c62ac9c6d48c2efebe5e8 upstream.
btrfs_ioctl_send() used open-coded kvzalloc implementation earlier. The code was accidentally replaced with kzalloc() call [1]. Restore the original code by using kvzalloc() to allocate sctx->clone_roots.
[1] https://patchwork.kernel.org/patch/9757891/#20529627
--- fs/btrfs/send.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/btrfs/send.c +1 -1
@@ -7352,7 +7352,7 @@ long btrfs_ioctl_send(struct file *mnt_f alloc_size =sizeof (struct clone_root ) * (arg->clone_sources_count +1 ); - sctx->clone_roots =kzalloc (alloc_size,GFP_KERNEL ); + sctx->clone_roots =kvzalloc (alloc_size,GFP_KERNEL );if (!sctx->clone_roots) { ret = -ENOMEM ; goto out;
Greg Kroah-Hartman
maintainerPATCH 128/214 btrfs: tree-checker: fix false alert caused by legacy btrfs root item
In reply to Greg Kroah-HartmanFrom: Qu Wenruo <[email protected]>
commit 1465af12e254a68706e110846f59cf0f09683184 upstream.
Commit 259ee7754b67 ("btrfs: tree-checker: Add ROOT_ITEM check") introduced btrfs root item size check, however btrfs root item has two versions, the legacy one which just ends before generation_v2 member, is smaller than current btrfs root item size.
This caused btrfs kernel to reject valid but old tree root leaves.
Fix this problem by also allowing legacy root item, since kernel can already handle them pretty well and upgrade to newer root item format when needed.
--- fs/btrfs/tree-checker.c | 17 ++++++++++++----- include/uapi/linux/btrfs_tree.h | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 5 deletions(-)
fs/btrfs/tree-checker.c +12 -5
@@ -869,7 +869,7 @@ static int check_root_item(struct extent int slot) {struct btrfs_fs_info *fs_info = leaf->fs_info; -struct btrfs_root_item ri; +struct btrfs_root_item ri = {0 };const u64 valid_root_flags =BTRFS_ROOT_SUBVOL_RDONLY |BTRFS_ROOT_SUBVOL_DEAD ;
@@ -889,14 +889,21 @@ static int check_root_item(struct extentreturn -EUCLEAN ; } -if (btrfs_item_size_nr (leaf, slot) !=sizeof (ri)) { +if (btrfs_item_size_nr (leaf, slot) !=sizeof (ri) && +btrfs_item_size_nr (leaf, slot) !=btrfs_legacy_root_item_size ()) {generic_err (leaf, slot, -"invalid root item size, have %u expect %zu" , -btrfs_item_size_nr (leaf, slot),sizeof (ri)); +"invalid root item size, have %u expect %zu or %u" , +btrfs_item_size_nr (leaf, slot),sizeof (ri), +btrfs_legacy_root_item_size ()); } +/* +* For legacy root item, the members starting at generation_v2 will be +* all filled with 0. +* And since we allow geneartion_v2 as 0, it will still pass the check. +*/ read_extent_buffer (leaf, &ri,btrfs_item_ptr_offset (leaf, slot), -sizeof (ri)); +btrfs_item_size_nr (leaf, slot));/* Generation related */ if (btrfs_root_generation(&ri) >
include/uapi/linux/btrfs_tree.h +14 -0
@@ -4,6 +4,11 @@#include <linux/btrfs.h> #include <linux/types.h> +#ifdef __KERNEL__ +#include <linux/stddef.h> +#else +#include <stddef.h> +#endif /* * This header contains the structure definitions and constants used
@@ -651,6 +656,15 @@ struct btrfs_root_item { } __attribute__ ((__packed__));/* +* Btrfs root item used to be smaller than current size. The old format ends +* at where member generation_v2 is. +*/ +static inline __u32 btrfs_legacy_root_item_size (void ) +{ +return offsetof(struct btrfs_root_item , generation_v2); +} + +/* * this is used for both forward and backward root refs */ struct btrfs_root_ref {
Greg Kroah-Hartman
maintainerPATCH 129/214 btrfs: cleanup cow block on error
In reply to Greg Kroah-HartmanFrom: Josef Bacik <[email protected]>
commit 572c83acdcdafeb04e70aa46be1fa539310be20c upstream.
In fstest btrfs/064 a transaction abort in __btrfs_cow_block could lead to a system lockup. It gets stuck trying to write back inodes, and the write back thread was trying to lock an extent buffer:
$ cat /proc/2143497/stack [<0>] __btrfs_tree_lock+0x108/0x250 [<0>] lock_extent_buffer_for_io+0x35e/0x3a0 [<0>] btree_write_cache_pages+0x15a/0x3b0 [<0>] do_writepages+0x28/0xb0 [<0>] __writeback_single_inode+0x54/0x5c0 [<0>] writeback_sb_inodes+0x1e8/0x510 [<0>] wb_writeback+0xcc/0x440 [<0>] wb_workfn+0xd7/0x650 [<0>] process_one_work+0x236/0x560 [<0>] worker_thread+0x55/0x3c0 [<0>] kthread+0x13a/0x150 [<0>] ret_from_fork+0x1f/0x30
This is because we got an error while COWing a block, specifically here
if (test_bit(BTRFS_ROOT_SHAREABLE, &root->state)) {
ret = btrfs_reloc_cow_block(trans, root, buf, cow);
if (ret) {
btrfs_abort_transaction(trans, ret);
return ret;
}
}[16402.241552] BTRFS: Transaction aborted (error -2) [16402.242362] WARNING: CPU: 1 PID: 2563188 at fs/btrfs/ctree.c:1074 __btrfs_cow_block+0x376/0x540 [16402.249469] CPU: 1 PID: 2563188 Comm: fsstress Not tainted 5.9.0-rc6+ #8 [16402.249936] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-2.fc32 04/01/2014 [16402.250525] RIP: 0010:__btrfs_cow_block+0x376/0x540 [16402.252417] RSP: 0018:ffff9cca40e578b0 EFLAGS: 00010282 [16402.252787] RAX: 0000000000000025 RBX: 0000000000000002 RCX: ffff9132bbd19388 [16402.253278] RDX: 00000000ffffffd8 RSI: 0000000000000027 RDI: ffff9132bbd19380 [16402.254063] RBP: ffff9132b41a49c0 R08: 0000000000000000 R09: 0000000000000000 [16402.254887] R10: 0000000000000000 R11: ffff91324758b080 R12: ffff91326ef17ce0 [16402.255694] R13: ffff91325fc0f000 R14: ffff91326ef176b0 R15: ffff9132815e2000 [16402.256321] FS: 00007f542c6d7b80(0000) GS:ffff9132bbd00000(0000) knlGS:0000000000000000 [16402.256973] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [16402.257374] CR2: 00007f127b83f250 CR3: 0000000133480002 CR4: 0000000000370ee0 [16402.257867] Call Trace: [16402.258072] btrfs_cow_block+0x109/0x230 [16402.258356] btrfs_search_slot+0x530/0x9d0 [16402.258655] btrfs_lookup_file_extent+0x37/0x40 [16402.259155] __btrfs_drop_extents+0x13c/0xd60 [16402.259628] ? btrfs_block_rsv_migrate+0x4f/0xb0 [16402.259949] btrfs_replace_file_extents+0x190/0x820 [16402.260873] btrfs_clone+0x9ae/0xc00 [16402.261139] btrfs_extent_same_range+0x66/0x90 [16402.261771] btrfs_remap_file_range+0x353/0x3b1 [16402.262333] vfs_dedupe_file_range_one.part.0+0xd5/0x140 [16402.262821] vfs_dedupe_file_range+0x189/0x220 [16402.263150] do_vfs_ioctl+0x552/0x700 [16402.263662] __x64_sys_ioctl+0x62/0xb0 [16402.264023] do_syscall_64+0x33/0x40 [16402.264364] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [16402.264862] RIP: 0033:0x7f542c7d15cb [16402.266901] RSP: 002b:00007ffd35944ea8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 [16402.267627] RAX: ffffffffffffffda RBX: 00000000009d1968 RCX: 00007f542c7d15cb [16402.268298] RDX: 00000000009d2490 RSI: 00000000c0189436 RDI: 0000000000000003 [16402.268958] RBP: 00000000009d2520 R08: 0000000000000036 R09: 00000000009d2e64 [16402.269726] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000002 [16402.270659] R13: 000000000001f000 R14: 00000000009d1970 R15: 00000000009d2e80 [16402.271498] irq event stamp: 0 [16402.271846] hardirqs last enabled at (0): [<0000000000000000>] 0x0 [16402.272497] hardirqs last disabled at (0): [<ffffffff910dbf59>] copy_process+0x6b9/0x1ba0 [16402.273343] softirqs last enabled at (0): [<ffffffff910dbf59>] copy_process+0x6b9/0x1ba0 [16402.273905] softirqs last disabled at (0): [<0000000000000000>] 0x0 [16402.274338] ---[ end trace 737874a5a41a8236 ]--- [16402.274669] BTRFS: error (device dm-9) in __btrfs_cow_block:1074: errno=-2 No such entry [16402.276179] BTRFS info (device dm-9): forced readonly [16402.277046] BTRFS: error (device dm-9) in btrfs_replace_file_extents:2723: errno=-2 No such entry [16402.278744] BTRFS: error (device dm-9) in __btrfs_cow_block:1074: errno=-2 No such entry [16402.279968] BTRFS: error (device dm-9) in __btrfs_cow_block:1074: errno=-2 No such entry [16402.280582] BTRFS info (device dm-9): balance: ended with status: -30
The problem here is that as soon as we allocate the new block it is locked and marked dirty in the btree inode. This means that we could attempt to writeback this block and need to lock the extent buffer. However we're not unlocking it here and thus we deadlock.
Fix this by unlocking the cow block if we have any errors inside of __btrfs_cow_block, and also free it so we do not leak it.
--- fs/btrfs/ctree.c | 6 ++++++ 1 file changed, 6 insertions(+)
fs/btrfs/ctree.c +6 -0
@@ -1103,6 +1103,8 @@ static noinline int __btrfs_cow_block(st ret =update_ref_for_cow (trans, root, buf, cow, &last_ref);if (ret) { +btrfs_tree_unlock (cow); +free_extent_buffer (cow);btrfs_abort_transaction (trans, ret);return ret; }
@@ -1110,6 +1112,8 @@ static noinline int __btrfs_cow_block(stif (test_bit (BTRFS_ROOT_REF_COWS , &root->state)) { ret =btrfs_reloc_cow_block (trans, root, buf, cow);if (ret) { +btrfs_tree_unlock (cow); +free_extent_buffer (cow);btrfs_abort_transaction (trans, ret);return ret; }
@@ -1142,6 +1146,8 @@ static noinline int __btrfs_cow_block(stif (last_ref) { ret =tree_mod_log_free_eb (buf);if (ret) { +btrfs_tree_unlock (cow); +free_extent_buffer (cow);btrfs_abort_transaction (trans, ret);return ret; }
Greg Kroah-Hartman
maintainerPATCH 130/214 btrfs: tree-checker: validate number of chunk stripes and parity
In reply to Greg Kroah-HartmanFrom: Daniel Xu <[email protected]>
commit 85d07fbe09efd1c529ff3e025e2f0d2c6c96a1b7 upstream.
If there's no parity and num_stripes < ncopies, a crafted image can trigger a division by zero in calc_stripe_length().
The image was generated through fuzzing.
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=209587
--- fs/btrfs/tree-checker.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
fs/btrfs/tree-checker.c +18 -0
@@ -577,18 +577,36 @@ int btrfs_check_chunk_valid(struct extenu64 type;u64 features;bool mixed = false; +int raid_index; +int nparity; +int ncopies; length =btrfs_chunk_length (leaf, chunk); stripe_len =btrfs_chunk_stripe_len (leaf, chunk); num_stripes =btrfs_chunk_num_stripes (leaf, chunk); sub_stripes =btrfs_chunk_sub_stripes (leaf, chunk); type =btrfs_chunk_type (leaf, chunk); + raid_index =btrfs_bg_flags_to_raid_index (type); + ncopies = btrfs_raid_array[raid_index].ncopies; + nparity = btrfs_raid_array[raid_index].nparity;if (!num_stripes) {chunk_err (leaf, chunk, logical,"invalid chunk num_stripes, have %u" , num_stripes);return -EUCLEAN ; } +if (num_stripes < ncopies) { +chunk_err (leaf, chunk, logical, +"invalid chunk num_stripes < ncopies, have %u < %d" , + num_stripes, ncopies); +return -EUCLEAN ; + } +if (nparity && num_stripes == nparity) { +chunk_err (leaf, chunk, logical, +"invalid chunk num_stripes == nparity, have %u == %d" , + num_stripes, nparity); +return -EUCLEAN ; + }if (!IS_ALIGNED (logical, fs_info->sectorsize)) { chunk_err(leaf, chunk, logical, "invalid chunk logical, have %llu should aligned to %u",
Greg Kroah-Hartman
maintainerPATCH 131/214 btrfs: fix use-after-free on readahead extent after failure to create it
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
commit 83bc1560e02e25c6439341352024ebe8488f4fbd upstream.
If we fail to find suitable zones for a new readahead extent, we end up leaving a stale pointer in the global readahead extents radix tree (fs_info->reada_tree), which can trigger the following trace later on:
[13367.696354] BUG: kernel NULL pointer dereference, address: 00000000000000b0 [13367.696802] #PF: supervisor read access in kernel mode [13367.697249] #PF: error_code(0x0000) - not-present page [13367.697721] PGD 0 P4D 0 [13367.698171] Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC PTI [13367.698632] CPU: 6 PID: 851214 Comm: btrfs Tainted: G W 5.9.0-rc6-btrfs-next-69 #1 [13367.699100] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 [13367.700069] RIP: 0010:__lock_acquire+0x20a/0x3970 [13367.700562] Code: ff 1f 0f b7 c0 48 0f (...) [13367.701609] RSP: 0018:ffffb14448f57790 EFLAGS: 00010046 [13367.702140] RAX: 0000000000000000 RBX: 29b935140c15e8cf RCX: 0000000000000000 [13367.702698] RDX: 0000000000000002 RSI: ffffffffb3d66bd0 RDI: 0000000000000046 [13367.703240] RBP: ffff8a52ba8ac040 R08: 00000c2866ad9288 R09: 0000000000000001 [13367.703783] R10: 0000000000000001 R11: 00000000b66d9b53 R12: ffff8a52ba8ac9b0 [13367.704330] R13: 0000000000000000 R14: ffff8a532b6333e8 R15: 0000000000000000 [13367.704880] FS: 00007fe1df6b5700(0000) GS:ffff8a5376600000(0000) knlGS:0000000000000000 [13367.705438] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [13367.705995] CR2: 00000000000000b0 CR3: 000000022cca8004 CR4: 00000000003706e0 [13367.706565] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [13367.707127] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [13367.707686] Call Trace: [13367.708246] ? ___slab_alloc+0x395/0x740 [13367.708820] ? reada_add_block+0xae/0xee0 [btrfs] [13367.709383] lock_acquire+0xb1/0x480 [13367.709955] ? reada_add_block+0xe0/0xee0 [btrfs] [13367.710537] ? reada_add_block+0xae/0xee0 [btrfs] [13367.711097] ? rcu_read_lock_sched_held+0x5d/0x90 [13367.711659] ? kmem_cache_alloc_trace+0x8d2/0x990 [13367.712221] ? lock_acquired+0x33b/0x470 [13367.712784] _raw_spin_lock+0x34/0x80 [13367.713356] ? reada_add_block+0xe0/0xee0 [btrfs] [13367.713966] reada_add_block+0xe0/0xee0 [btrfs] [13367.714529] ? btrfs_root_node+0x15/0x1f0 [btrfs] [13367.715077] btrfs_reada_add+0x117/0x170 [btrfs] [13367.715620] scrub_stripe+0x21e/0x10d0 [btrfs] [13367.716141] ? kvm_sched_clock_read+0x5/0x10 [13367.716657] ? __lock_acquire+0x41e/0x3970 [13367.717184] ? scrub_chunk+0x60/0x140 [btrfs] [13367.717697] ? find_held_lock+0x32/0x90 [13367.718254] ? scrub_chunk+0x60/0x140 [btrfs] [13367.718773] ? lock_acquired+0x33b/0x470 [13367.719278] ? scrub_chunk+0xcd/0x140 [btrfs] [13367.719786] scrub_chunk+0xcd/0x140 [btrfs] [13367.720291] scrub_enumerate_chunks+0x270/0x5c0 [btrfs] [13367.720787] ? finish_wait+0x90/0x90 [13367.721281] btrfs_scrub_dev+0x1ee/0x620 [btrfs] [13367.721762] ? rcu_read_lock_any_held+0x8e/0xb0 [13367.722235] ? preempt_count_add+0x49/0xa0 [13367.722710] ? __sb_start_write+0x19b/0x290 [13367.723192] btrfs_ioctl+0x7f5/0x36f0 [btrfs] [13367.723660] ? __fget_files+0x101/0x1d0 [13367.724118] ? find_held_lock+0x32/0x90 [13367.724559] ? __fget_files+0x101/0x1d0 [13367.724982] ? __x64_sys_ioctl+0x83/0xb0 [13367.725399] __x64_sys_ioctl+0x83/0xb0 [13367.725802] do_syscall_64+0x33/0x80 [13367.726188] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [13367.726574] RIP: 0033:0x7fe1df7add87 [13367.726948] Code: 00 00 00 48 8b 05 09 91 (...) [13367.727763] RSP: 002b:00007fe1df6b4d48 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 [13367.728179] RAX: ffffffffffffffda RBX: 000055ce1fb596a0 RCX: 00007fe1df7add87 [13367.728604] RDX: 000055ce1fb596a0 RSI: 00000000c400941b RDI: 0000000000000003 [13367.729021] RBP: 0000000000000000 R08: 00007fe1df6b5700 R09: 0000000000000000 [13367.729431] R10: 00007fe1df6b5700 R11: 0000000000000246 R12: 00007ffd922b07de [13367.729842] R13: 00007ffd922b07df R14: 00007fe1df6b4e40 R15: 0000000000802000 [13367.730275] Modules linked in: btrfs blake2b_generic xor (...) [13367.732638] CR2: 00000000000000b0 [13367.733166] ---[ end trace d298b6805556acd9 ]---
What happens is the following:
1) At reada_find_extent() we don't find any existing readahead extent for the metadata extent starting at logical address X;
2) So we proceed to create a new one. We then call btrfs_map_block() to get information about which stripes contain extent X;
3) After that we iterate over the stripes and create only one zone for the readahead extent - only one because reada_find_zone() returned NULL for all iterations except for one, either because a memory allocation failed or it couldn't find the block group of the extent (it may have just been deleted);
4) We then add the new readahead extent to the readahead extents radix tree at fs_info->reada_tree;
5) Then we iterate over each zone of the new readahead extent, and find that the device used for that zone no longer exists, because it was removed or it was the source device of a device replace operation. Since this left 'have_zone' set to 0, after finishing the loop we jump to the 'error' label, call kfree() on the new readahead extent and return without removing it from the radix tree at fs_info->reada_tree;
6) Any future call to reada_find_extent() for the logical address X will find the stale pointer in the readahead extents radix tree, increment its reference counter, which can trigger the use-after-free right away or return it to the caller reada_add_block() that results in the use-after-free of the example trace above.
So fix this by making sure we delete the readahead extent from the radix tree if we fail to setup zones for it (when 'have_zone = 0').
--- fs/btrfs/reada.c | 2 ++ 1 file changed, 2 insertions(+)
fs/btrfs/reada.c +2 -0
@@ -445,6 +445,8 @@ static struct reada_extent *reada_find_e } have_zone =1 ; } +if (!have_zone) +radix_tree_delete (&fs_info->reada_tree, index);spin_unlock (&fs_info->reada_lock);up_read (&fs_info->dev_replace.rwsem);
Greg Kroah-Hartman
maintainerPATCH 132/214 btrfs: fix readahead hang and use-after-free after removing a device
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
commit 66d204a16c94f24ad08290a7663ab67e7fc04e82 upstream.
Very sporadically I had test case btrfs/069 from fstests hanging (for years, it is not a recent regression), with the following traces in dmesg/syslog:
[162301.160628] BTRFS info (device sdc): dev_replace from /dev/sdd (devid 2) to /dev/sdg started
[162301.181196] BTRFS info (device sdc): scrub: finished on devid 4 with status: 0
[162301.287162] BTRFS info (device sdc): dev_replace from /dev/sdd (devid 2) to /dev/sdg finished
[162513.513792] INFO: task btrfs-transacti:1356167 blocked for more than 120 seconds.
[162513.514318] Not tainted 5.9.0-rc6-btrfs-next-69 #1
[162513.514522] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[162513.514747] task:btrfs-transacti state:D stack: 0 pid:1356167 ppid: 2 flags:0x00004000
[162513.514751] Call Trace:
[162513.514761] __schedule+0x5ce/0xd00
[162513.514765] ? _raw_spin_unlock_irqrestore+0x3c/0x60
[162513.514771] schedule+0x46/0xf0
[162513.514844] wait_current_trans+0xde/0x140 [btrfs]
[162513.514850] ? finish_wait+0x90/0x90
[162513.514864] start_transaction+0x37c/0x5f0 [btrfs]
[162513.514879] transaction_kthread+0xa4/0x170 [btrfs]
[162513.514891] ? btrfs_cleanup_transaction+0x660/0x660 [btrfs]
[162513.514894] kthread+0x153/0x170
[162513.514897] ? kthread_stop+0x2c0/0x2c0
[162513.514902] ret_from_fork+0x22/0x30
[162513.514916] INFO: task fsstress:1356184 blocked for more than 120 seconds.
[162513.515192] Not tainted 5.9.0-rc6-btrfs-next-69 #1
[162513.515431] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[162513.515680] task:fsstress state:D stack: 0 pid:1356184 ppid:1356177 flags:0x00004000
[162513.515682] Call Trace:
[162513.515688] __schedule+0x5ce/0xd00
[162513.515691] ? _raw_spin_unlock_irqrestore+0x3c/0x60
[162513.515697] schedule+0x46/0xf0
[162513.515712] wait_current_trans+0xde/0x140 [btrfs]
[162513.515716] ? finish_wait+0x90/0x90
[162513.515729] start_transaction+0x37c/0x5f0 [btrfs]
[162513.515743] btrfs_attach_transaction_barrier+0x1f/0x50 [btrfs]
[162513.515753] btrfs_sync_fs+0x61/0x1c0 [btrfs]
[162513.515758] ? __ia32_sys_fdatasync+0x20/0x20
[162513.515761] iterate_supers+0x87/0xf0
[162513.515765] ksys_sync+0x60/0xb0
[162513.515768] __do_sys_sync+0xa/0x10
[162513.515771] do_syscall_64+0x33/0x80
[162513.515774] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[162513.515781] RIP: 0033:0x7f5238f50bd7
[162513.515782] Code: Bad RIP value.
[162513.515784] RSP: 002b:00007fff67b978e8 EFLAGS: 00000206 ORIG_RAX: 00000000000000a2
[162513.515786] RAX: ffffffffffffffda RBX: 000055b1fad2c560 RCX: 00007f5238f50bd7
[162513.515788] RDX: 00000000ffffffff RSI: 000000000daf0e74 RDI: 000000000000003a
[162513.515789] RBP: 0000000000000032 R08: 000000000000000a R09: 00007f5239019be0
[162513.515791] R10: fffffffffffff24f R11: 0000000000000206 R12: 000000000000003a
[162513.515792] R13: 00007fff67b97950 R14: 00007fff67b97906 R15: 000055b1fad1a340
[162513.515804] INFO: task fsstress:1356185 blocked for more than 120 seconds.
[162513.516064] Not tainted 5.9.0-rc6-btrfs-next-69 #1
[162513.516329] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[162513.516617] task:fsstress state:D stack: 0 pid:1356185 ppid:1356177 flags:0x00000000
[162513.516620] Call Trace:
[162513.516625] __schedule+0x5ce/0xd00
[162513.516628] ? _raw_spin_unlock_irqrestore+0x3c/0x60
[162513.516634] schedule+0x46/0xf0
[162513.516647] wait_current_trans+0xde/0x140 [btrfs]
[162513.516650] ? finish_wait+0x90/0x90
[162513.516662] start_transaction+0x4d7/0x5f0 [btrfs]
[162513.516679] btrfs_setxattr_trans+0x3c/0x100 [btrfs]
[162513.516686] __vfs_setxattr+0x66/0x80
[162513.516691] __vfs_setxattr_noperm+0x70/0x200
[162513.516697] vfs_setxattr+0x6b/0x120
[162513.516703] setxattr+0x125/0x240
[162513.516709] ? lock_acquire+0xb1/0x480
[162513.516712] ? mnt_want_write+0x20/0x50
[162513.516721] ? rcu_read_lock_any_held+0x8e/0xb0
[162513.516723] ? preempt_count_add+0x49/0xa0
[162513.516725] ? __sb_start_write+0x19b/0x290
[162513.516727] ? preempt_count_add+0x49/0xa0
[162513.516732] path_setxattr+0xba/0xd0
[162513.516739] __x64_sys_setxattr+0x27/0x30
[162513.516741] do_syscall_64+0x33/0x80
[162513.516743] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[162513.516745] RIP: 0033:0x7f5238f56d5a
[162513.516746] Code: Bad RIP value.
[162513.516748] RSP: 002b:00007fff67b97868 EFLAGS: 00000202 ORIG_RAX: 00000000000000bc
[162513.516750] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007f5238f56d5a
[162513.516751] RDX: 000055b1fbb0d5a0 RSI: 00007fff67b978a0 RDI: 000055b1fbb0d470
[162513.516753] RBP: 000055b1fbb0d5a0 R08: 0000000000000001 R09: 00007fff67b97700
[162513.516754] R10: 0000000000000004 R11: 0000000000000202 R12: 0000000000000004
[162513.516756] R13: 0000000000000024 R14: 0000000000000001 R15: 00007fff67b978a0
[162513.516767] INFO: task fsstress:1356196 blocked for more than 120 seconds.
[162513.517064] Not tainted 5.9.0-rc6-btrfs-next-69 #1
[162513.517365] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[162513.517763] task:fsstress state:D stack: 0 pid:1356196 ppid:1356177 flags:0x00004000
[162513.517780] Call Trace:
[162513.517786] __schedule+0x5ce/0xd00
[162513.517789] ? _raw_spin_unlock_irqrestore+0x3c/0x60
[162513.517796] schedule+0x46/0xf0
[162513.517810] wait_current_trans+0xde/0x140 [btrfs]
[162513.517814] ? finish_wait+0x90/0x90
[162513.517829] start_transaction+0x37c/0x5f0 [btrfs]
[162513.517845] btrfs_attach_transaction_barrier+0x1f/0x50 [btrfs]
[162513.517857] btrfs_sync_fs+0x61/0x1c0 [btrfs]
[162513.517862] ? __ia32_sys_fdatasync+0x20/0x20
[162513.517865] iterate_supers+0x87/0xf0
[162513.517869] ksys_sync+0x60/0xb0
[162513.517872] __do_sys_sync+0xa/0x10
[162513.517875] do_syscall_64+0x33/0x80
[162513.517878] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[162513.517881] RIP: 0033:0x7f5238f50bd7
[162513.517883] Code: Bad RIP value.
[162513.517885] RSP: 002b:00007fff67b978e8 EFLAGS: 00000206 ORIG_RAX: 00000000000000a2
[162513.517887] RAX: ffffffffffffffda RBX: 000055b1fad2c560 RCX: 00007f5238f50bd7
[162513.517889] RDX: 0000000000000000 RSI: 000000007660add2 RDI: 0000000000000053
[162513.517891] RBP: 0000000000000032 R08: 0000000000000067 R09: 00007f5239019be0
[162513.517893] R10: fffffffffffff24f R11: 0000000000000206 R12: 0000000000000053
[162513.517895] R13: 00007fff67b97950 R14: 00007fff67b97906 R15: 000055b1fad1a340
[162513.517908] INFO: task fsstress:1356197 blocked for more than 120 seconds.
[162513.518298] Not tainted 5.9.0-rc6-btrfs-next-69 #1
[162513.518672] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[162513.519157] task:fsstress state:D stack: 0 pid:1356197 ppid:1356177 flags:0x00000000
[162513.519160] Call Trace:
[162513.519165] __schedule+0x5ce/0xd00
[162513.519168] ? _raw_spin_unlock_irqrestore+0x3c/0x60
[162513.519174] schedule+0x46/0xf0
[162513.519190] wait_current_trans+0xde/0x140 [btrfs]
[162513.519193] ? finish_wait+0x90/0x90
[162513.519206] start_transaction+0x4d7/0x5f0 [btrfs]
[162513.519222] btrfs_create+0x57/0x200 [btrfs]
[162513.519230] lookup_open+0x522/0x650
[162513.519246] path_openat+0x2b8/0xa50
[162513.519270] do_filp_open+0x91/0x100
[162513.519275] ? find_held_lock+0x32/0x90
[162513.519280] ? lock_acquired+0x33b/0x470
[162513.519285] ? do_raw_spin_unlock+0x4b/0xc0
[162513.519287] ? _raw_spin_unlock+0x29/0x40
[162513.519295] do_sys_openat2+0x20d/0x2d0
[162513.519300] do_sys_open+0x44/0x80
[162513.519304] do_syscall_64+0x33/0x80
[162513.519307] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[162513.519309] RIP: 0033:0x7f5238f4a903
[162513.519310] Code: Bad RIP value.
[162513.519312] RSP: 002b:00007fff67b97758 EFLAGS: 00000246 ORIG_RAX: 0000000000000055
[162513.519314] RAX: ffffffffffffffda RBX: 00000000ffffffff RCX: 00007f5238f4a903
[162513.519316] RDX: 0000000000000000 RSI: 00000000000001b6 RDI: 000055b1fbb0d470
[162513.519317] RBP: 00007fff67b978c0 R08: 0000000000000001 R09: 0000000000000002
[162513.519319] R10: 00007fff67b974f7 R11: 0000000000000246 R12: 0000000000000013
[162513.519320] R13: 00000000000001b6 R14: 00007fff67b97906 R15: 000055b1fad1c620
[162513.519332] INFO: task btrfs:1356211 blocked for more than 120 seconds.
[162513.519727] Not tainted 5.9.0-rc6-btrfs-next-69 #1
[162513.520115] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[162513.520508] task:btrfs state:D stack: 0 pid:1356211 ppid:1356178 flags:0x00004002
[162513.520511] Call Trace:
[162513.520516] __schedule+0x5ce/0xd00
[162513.520519] ? _raw_spin_unlock_irqrestore+0x3c/0x60
[162513.520525] schedule+0x46/0xf0
[162513.520544] btrfs_scrub_pause+0x11f/0x180 [btrfs]
[162513.520548] ? finish_wait+0x90/0x90
[162513.520562] btrfs_commit_transaction+0x45a/0xc30 [btrfs]
[162513.520574] ? start_transaction+0xe0/0x5f0 [btrfs]
[162513.520596] btrfs_dev_replace_finishing+0x6d8/0x711 [btrfs]
[162513.520619] btrfs_dev_replace_by_ioctl.cold+0x1cc/0x1fd [btrfs]
[162513.520639] btrfs_ioctl+0x2a25/0x36f0 [btrfs]
[162513.520643] ? do_sigaction+0xf3/0x240
[162513.520645] ? find_held_lock+0x32/0x90
[162513.520648] ? do_sigaction+0xf3/0x240
[162513.520651] ? lock_acquired+0x33b/0x470
[162513.520655] ? _raw_spin_unlock_irq+0x24/0x50
[162513.520657] ? lockdep_hardirqs_on+0x7d/0x100
[162513.520660] ? _raw_spin_unlock_irq+0x35/0x50
[162513.520662] ? do_sigaction+0xf3/0x240
[162513.520671] ? __x64_sys_ioctl+0x83/0xb0
[162513.520672] __x64_sys_ioctl+0x83/0xb0
[162513.520677] do_syscall_64+0x33/0x80
[162513.520679] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[162513.520681] RIP: 0033:0x7fc3cd307d87
[162513.520682] Code: Bad RIP value.
[162513.520684] RSP: 002b:00007ffe30a56bb8 EFLAGS: 00000202 ORIG_RAX: 0000000000000010
[162513.520686] RAX: ffffffffffffffda RBX: 0000000000000004 RCX: 00007fc3cd307d87
[162513.520687] RDX: 00007ffe30a57a30 RSI: 00000000ca289435 RDI: 0000000000000003
[162513.520689] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
[162513.520690] R10: 0000000000000008 R11: 0000000000000202 R12: 0000000000000003
[162513.520692] R13: 0000557323a212e0 R14: 00007ffe30a5a520 R15: 0000000000000001
[162513.520703]
Showing all locks held in the system:
[162513.520712] 1 lock held by khungtaskd/54:
[162513.520713] #0: ffffffffb40a91a0 (rcu_read_lock){....}-{1:2}, at: debug_show_all_locks+0x15/0x197
[162513.520728] 1 lock held by in:imklog/596:
[162513.520729] #0: ffff8f3f0d781400 (&f->f_pos_lock){+.+.}-{3:3}, at: __fdget_pos+0x4d/0x60
[162513.520782] 1 lock held by btrfs-transacti/1356167:
[162513.520784] #0: ffff8f3d810cc848 (&fs_info->transaction_kthread_mutex){+.+.}-{3:3}, at: transaction_kthread+0x4a/0x170 [btrfs]
[162513.520798] 1 lock held by btrfs/1356190:
[162513.520800] #0: ffff8f3d57644470 (sb_writers#15){.+.+}-{0:0}, at: mnt_want_write_file+0x22/0x60
[162513.520805] 1 lock held by fsstress/1356184:
[162513.520806] #0: ffff8f3d576440e8 (&type->s_umount_key#62){++++}-{3:3}, at: iterate_supers+0x6f/0xf0
[162513.520811] 3 locks held by fsstress/1356185:
[162513.520812] #0: ffff8f3d57644470 (sb_writers#15){.+.+}-{0:0}, at: mnt_want_write+0x20/0x50
[162513.520815] #1: ffff8f3d80a650b8 (&type->i_mutex_dir_key#10){++++}-{3:3}, at: vfs_setxattr+0x50/0x120
[162513.520820] #2: ffff8f3d57644690 (sb_internal#2){.+.+}-{0:0}, at: start_transaction+0x40e/0x5f0 [btrfs]
[162513.520833] 1 lock held by fsstress/1356196:
[162513.520834] #0: ffff8f3d576440e8 (&type->s_umount_key#62){++++}-{3:3}, at: iterate_supers+0x6f/0xf0
[162513.520838] 3 locks held by fsstress/1356197:
[162513.520839] #0: ffff8f3d57644470 (sb_writers#15){.+.+}-{0:0}, at: mnt_want_write+0x20/0x50
[162513.520843] #1: ffff8f3d506465e8 (&type->i_mutex_dir_key#10){++++}-{3:3}, at: path_openat+0x2a7/0xa50
[162513.520846] #2: ffff8f3d57644690 (sb_internal#2){.+.+}-{0:0}, at: start_transaction+0x40e/0x5f0 [btrfs]
[162513.520858] 2 locks held by btrfs/1356211:
[162513.520859] #0: ffff8f3d810cde30 (&fs_info->dev_replace.lock_finishing_cancel_unmount){+.+.}-{3:3}, at: btrfs_dev_replace_finishing+0x52/0x711 [btrfs]
[162513.520877] #1: ffff8f3d57644690 (sb_internal#2){.+.+}-{0:0}, at: start_transaction+0x40e/0x5f0 [btrfs]This was weird because the stack traces show that a transaction commit, triggered by a device replace operation, is blocking trying to pause any running scrubs but there are no stack traces of blocked tasks doing a scrub.
After poking around with drgn, I noticed there was a scrub task that was constantly running and blocking for shorts periods of time:
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
t =
find_task(prog, 1356190)prog.stack_trace(t)
#0 __schedule+0x5ce/0xcfc #1 schedule+0x46/0xe4 #2 schedule_timeout+0x1df/0x475 #3 btrfs_reada_wait+0xda/0x132 #4 scrub_stripe+0x2a8/0x112f #5 scrub_chunk+0xcd/0x134 #6 scrub_enumerate_chunks+0x29e/0x5ee #7 btrfs_scrub_dev+0x2d5/0x91b #8 btrfs_ioctl+0x7f5/0x36e7 #9 __x64_sys_ioctl+0x83/0xb0
#10 do_syscall_64+0x33/0x77
#11 entry_SYSCALL_64+0x7c/0x156
Which corresponds to:
int btrfs_reada_wait(void *handle)
{
struct reada_control *rc = handle;
struct btrfs_fs_info *fs_info = rc->fs_info;
while (atomic_read(&rc->elems)) {
if (!atomic_read(&fs_info->reada_works_cnt))
reada_start_machine(fs_info);
wait_event_timeout(rc->wait, atomic_read(&rc->elems) == 0,
(HZ + 9) / 10);
}(...)
So the counter "rc->elems" was set to 1 and never decreased to 0, causing the scrub task to loop forever in that function. Then I used the following script for drgn to check the readahead requests:
$ cat dump_reada.py
import sys
import drgn
from drgn import NULL, Object, cast, container_of, execscript, \
reinterpret, sizeof
from drgn.helpers.linux import * mnt_path = b"/home/fdmanana/btrfs-tests/scratch_1"
mnt = None
for mnt in for_each_mount(prog, dst = mnt_path):
pass
if mnt is None:
sys.stderr.write(f'Error: mount point {mnt_path} not found\n') sys.exit(1)
fs_info = cast('struct btrfs_fs_info *', mnt.mnt.mnt_sb.s_fs_info)
def dump_re(re):
nzones = re.nzones.value_()
print(f're at {hex(re.value_())}')
print(f'\t logical {re.logical.value_()}') print(f'\t refcnt {re.refcnt.value_()}') print(f'\t nzones {nzones}')
for i in range(nzones):
dev = re.zones[i].device
name = dev.name.str.string_()
print(f'\t\t dev id {dev.devid.value_()} name {name}')
print()
for _, e in radix_tree_for_each(fs_info.reada_tree):
re = cast('struct reada_extent *', e) dump_re(re)
$ drgn dump_reada.py
re at 0xffff8f3da9d25ad8
logical 38928384
refcnt 1
nzones 1
dev id 0 name b'/dev/sdd'
$So there was one readahead extent with a single zone corresponding to the source device of that last device replace operation logged in dmesg/syslog. Also the ID of that zone's device was 0 which is a special value set in the source device of a device replace operation when the operation finishes (constant BTRFS_DEV_REPLACE_DEVID set at btrfs_dev_replace_finishing()), confirming again that device /dev/sdd was the source of a device replace operation.
Normally there should be as many zones in the readahead extent as there are devices, and I wasn't expecting the extent to be in a block group with a 'single' profile, so I went and confirmed with the following drgn script that there weren't any single profile block groups:
$ cat dump_block_groups.py
import sys
import drgn
from drgn import NULL, Object, cast, container_of, execscript, \
reinterpret, sizeof
from drgn.helpers.linux import * mnt_path = b"/home/fdmanana/btrfs-tests/scratch_1"
mnt = None
for mnt in for_each_mount(prog, dst = mnt_path):
pass
if mnt is None:
sys.stderr.write(f'Error: mount point {mnt_path} not found\n') sys.exit(1)
fs_info = cast('struct btrfs_fs_info *', mnt.mnt.mnt_sb.s_fs_info)
BTRFS_BLOCK_GROUP_DATA = (1 << 0)
BTRFS_BLOCK_GROUP_SYSTEM = (1 << 1)
BTRFS_BLOCK_GROUP_METADATA = (1 << 2)
BTRFS_BLOCK_GROUP_RAID0 = (1 << 3)
BTRFS_BLOCK_GROUP_RAID1 = (1 << 4)
BTRFS_BLOCK_GROUP_DUP = (1 << 5)
BTRFS_BLOCK_GROUP_RAID10 = (1 << 6)
BTRFS_BLOCK_GROUP_RAID5 = (1 << 7)
BTRFS_BLOCK_GROUP_RAID6 = (1 << 8)
BTRFS_BLOCK_GROUP_RAID1C3 = (1 << 9)
BTRFS_BLOCK_GROUP_RAID1C4 = (1 << 10)
def bg_flags_string(bg):
flags = bg.flags.value_()
ret = ''
if flags & BTRFS_BLOCK_GROUP_DATA:
ret = 'data'
if flags & BTRFS_BLOCK_GROUP_METADATA:
if len(ret) > 0:
ret += '|'
ret += 'meta'
if flags & BTRFS_BLOCK_GROUP_SYSTEM:
if len(ret) > 0:
ret += '|'
ret += 'system'
if flags & BTRFS_BLOCK_GROUP_RAID0:
ret += ' raid0'
elif flags & BTRFS_BLOCK_GROUP_RAID1:
ret += ' raid1'
elif flags & BTRFS_BLOCK_GROUP_DUP:
ret += ' dup'
elif flags & BTRFS_BLOCK_GROUP_RAID10:
ret += ' raid10'
elif flags & BTRFS_BLOCK_GROUP_RAID5:
ret += ' raid5'
elif flags & BTRFS_BLOCK_GROUP_RAID6:
ret += ' raid6'
elif flags & BTRFS_BLOCK_GROUP_RAID1C3:
ret += ' raid1c3'
elif flags & BTRFS_BLOCK_GROUP_RAID1C4:
ret += ' raid1c4'
else:
ret += ' single'
return ret def dump_bg(bg):
print()
print(f'block group at {hex(bg.value_())}')
print(f'\t start {bg.start.value_()} length {bg.length.value_()}')
print(f'\t flags {bg.flags.value_()} - {bg_flags_string(bg)}') bg_root = fs_info.block_group_cache_tree.address_of_()
for bg in rbtree_inorder_for_each_entry('struct btrfs_block_group', bg_root, 'cache_node'):
dump_bg(bg)
$ drgn dump_block_groups.py
block group at 0xffff8f3d673b0400
start 22020096 length 16777216
flags 258 - system raid6
block group at 0xffff8f3d53ddb400
start 38797312 length 536870912
flags 260 - meta raid6
block group at 0xffff8f3d5f4d9c00
start 575668224 length 2147483648
flags 257 - data raid6
block group at 0xffff8f3d08189000
start 2723151872 length 67108864
flags 258 - system raid6
block group at 0xffff8f3db70ff000
start 2790260736 length 1073741824
flags 260 - meta raid6
block group at 0xffff8f3d5f4dd800
start 3864002560 length 67108864
flags 258 - system raid6
block group at 0xffff8f3d67037000
start 3931111424 length 2147483648
flags 257 - data raid6
$
So there were only 2 reasons left for having a readahead extent with a single zone: reada_find_zone(), called when creating a readahead extent, returned NULL either because we failed to find the corresponding block group or because a memory allocation failed. With some additional and custom tracing I figured out that on every further ocurrence of the problem the block group had just been deleted when we were looping to create the zones for the readahead extent (at reada_find_extent()), so we ended up with only one zone in the readahead extent, corresponding to a device that ends up getting replaced.
So after figuring that out it became obvious why the hang happens:
1) Task A starts a scrub on any device of the filesystem, except for device /dev/sdd;
2) Task B starts a device replace with /dev/sdd as the source device;
3) Task A calls btrfs_reada_add() from scrub_stripe() and it is currently starting to scrub a stripe from block group X. This call to btrfs_reada_add() is the one for the extent tree. When btrfs_reada_add() calls reada_add_block(), it passes the logical address of the extent tree's root node as its 'logical' argument - a value of 38928384;
4) Task A then enters reada_find_extent(), called from reada_add_block(). It finds there isn't any existing readahead extent for the logical address 38928384, so it proceeds to the path of creating a new one.
It calls btrfs_map_block() to find out which stripes exist for the block group X. On the first iteration of the for loop that iterates over the stripes, it finds the stripe for device /dev/sdd, so it creates one zone for that device and adds it to the readahead extent. Before getting into the second iteration of the loop, the cleanup kthread deletes block group X because it was empty. So in the iterations for the remaining stripes it does not add more zones to the readahead extent, because the calls to reada_find_zone() returned NULL because they couldn't find block group X anymore.
As a result the new readahead extent has a single zone, corresponding to the device /dev/sdd;
4) Before task A returns to btrfs_reada_add() and queues the readahead job for the readahead work queue, task B finishes the device replace and at btrfs_dev_replace_finishing() swaps the device /dev/sdd with the new device /dev/sdg;
5) Task A returns to reada_add_block(), which increments the counter "->elems" of the reada_control structure allocated at btrfs_reada_add().
Then it returns back to btrfs_reada_add() and calls reada_start_machine(). This queues a job in the readahead work queue to run the function reada_start_machine_worker(), which calls __reada_start_machine().
At __reada_start_machine() we take the device list mutex and for each device found in the current device list, we call reada_start_machine_dev() to start the readahead work. However at this point the device /dev/sdd was already freed and is not in the device list anymore.
This means the corresponding readahead for the extent at 38928384 is never started, and therefore the "->elems" counter of the reada_control structure allocated at btrfs_reada_add() never goes down to 0, causing the call to btrfs_reada_wait(), done by the scrub task, to wait forever.
Note that the readahead request can be made either after the device replace started or before it started, however in pratice it is very unlikely that a device replace is able to start after a readahead request is made and is able to complete before the readahead request completes - maybe only on a very small and nearly empty filesystem.
This hang however is not the only problem we can have with readahead and device removals. When the readahead extent has other zones other than the one corresponding to the device that is being removed (either by a device replace or a device remove operation), we risk having a use-after-free on the device when dropping the last reference of the readahead extent.
For example if we create a readahead extent with two zones, one for the device /dev/sdd and one for the device /dev/sde:
1) Before the readahead worker starts, the device /dev/sdd is removed, and the corresponding btrfs_device structure is freed. However the readahead extent still has the zone pointing to the device structure;
2) When the readahead worker starts, it only finds device /dev/sde in the current device list of the filesystem;
3) It starts the readahead work, at reada_start_machine_dev(), using the device /dev/sde;
4) Then when it finishes reading the extent from device /dev/sde, it calls __readahead_hook() which ends up dropping the last reference on the readahead extent through the last call to reada_extent_put();
5) At reada_extent_put() it iterates over each zone of the readahead extent and attempts to delete an element from the device's 'reada_extents' radix tree, resulting in a use-after-free, as the device pointer of the zone for /dev/sdd is now stale. We can also access the device after dropping the last reference of a zone, through reada_zone_release(), also called by reada_extent_put().
And a device remove suffers the same problem, however since it shrinks the device size down to zero before removing the device, it is very unlikely to still have readahead requests not completed by the time we free the device, the only possibility is if the device has a very little space allocated.
While the hang problem is exclusive to scrub, since it is currently the only user of btrfs_reada_add() and btrfs_reada_wait(), the use-after-free problem affects any path that triggers readhead, which includes btree_readahead_hook() and __readahead_hook() (a readahead worker can trigger readahed for the children of a node) for example - any path that ends up calling reada_add_block() can trigger the use-after-free after a device is removed.
So fix this by waiting for any readahead requests for a device to complete before removing a device, ensuring that while waiting for existing ones no new ones can be made.
This problem has been around for a very long time - the readahead code was added in 2011, device remove exists since 2008 and device replace was introduced in 2013, hard to pick a specific commit for a git Fixes tag.
--- fs/btrfs/ctree.h | 2 ++ fs/btrfs/dev-replace.c | 5 +++++ fs/btrfs/reada.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ fs/btrfs/volumes.c | 3 +++ fs/btrfs/volumes.h | 1 + 5 files changed, 56 insertions(+)
fs/btrfs/ctree.h +2 -0
@@ -3404,6 +3404,8 @@ struct reada_control *btrfs_reada_add(stint btrfs_reada_wait (void *handle);void btrfs_reada_detach (void *handle);int btree_readahead_hook (struct extent_buffer *eb,int err); +void btrfs_reada_remove_dev (struct btrfs_device *dev); +void btrfs_reada_undo_remove_dev (struct btrfs_device *dev);static inline int is_fstree (u64 rootid) {
fs/btrfs/dev-replace.c +5 -0
@@ -631,6 +631,9 @@ static int btrfs_dev_replace_finishing(s }btrfs_wait_ordered_roots (fs_info,U64_MAX ,0 , (u64)-1 ); +if (!scrub_ret) +btrfs_reada_remove_dev (src_device); +/* * We have to use this loop approach because at this point src_device * has to be available for transaction commit to complete, yet new
@@ -639,6 +642,7 @@ static int btrfs_dev_replace_finishing(swhile (1 ) { trans =btrfs_start_transaction (root,0 );if (IS_ERR (trans)) { +btrfs_reada_undo_remove_dev (src_device);mutex_unlock (&dev_replace->lock_finishing_cancel_unmount);return PTR_ERR (trans); }
@@ -689,6 +693,7 @@ error:up_write (&dev_replace->rwsem);mutex_unlock (&fs_info->chunk_mutex);mutex_unlock (&fs_info->fs_devices->device_list_mutex); +btrfs_reada_undo_remove_dev (src_device);btrfs_rm_dev_replace_blocked (fs_info);if (tgt_device)btrfs_destroy_dev_replace_tgtdev (tgt_device);
fs/btrfs/reada.c +45 -0
54 lines not on this page · raw message
fs/btrfs/volumes.c +3 -0
@@ -2208,6 +2208,8 @@ int btrfs_rm_device(struct btrfs_fs_infomutex_unlock (&uuid_mutex); ret =btrfs_shrink_device (device,0 ); +if (!ret) +btrfs_reada_remove_dev (device);mutex_lock (&uuid_mutex);if (ret) goto error_undo;
@@ -2294,6 +2296,7 @@ out:return ret; error_undo: +btrfs_reada_undo_remove_dev (device);if (test_bit (BTRFS_DEV_STATE_WRITEABLE , &device->dev_state)) {mutex_lock (&fs_info->chunk_mutex); list_add(&device->dev_alloc_list,
fs/btrfs/volumes.h +1 -0
@@ -56,6 +56,7 @@ struct btrfs_io_geometry {#define BTRFS_DEV_STATE_MISSING (2)#define BTRFS_DEV_STATE_REPLACE_TGT (3)#define BTRFS_DEV_STATE_FLUSH_SENT (4) +#define BTRFS_DEV_STATE_NO_READA (5)struct btrfs_device {struct list_head dev_list;/* device_list_mutex */
Greg Kroah-Hartman
maintainerPATCH 133/214 usb: xhci: Workaround for S3 issue on AMD SNPS 3.0 xHC
In reply to Greg Kroah-HartmanFrom: Sandeep Singh <[email protected]>
commit 2a632815683d2d34df52b701a36fe5ac6654e719 upstream.
On some platform of AMD, S3 fails with HCE and SRE errors. To fix this, need to disable a bit which is enable in sparse controller.
--- drivers/usb/host/xhci-pci.c | 17 +++++++++++++++++ drivers/usb/host/xhci.h | 1 + 2 files changed, 18 insertions(+)
drivers/usb/host/xhci-pci.c +17 -0
@@ -21,6 +21,8 @@#define SSIC_PORT_CFG2_OFFSET 0x30#define PROG_DONE (1 << 30)#define SSIC_PORT_UNUSED (1 << 31) +#define SPARSE_DISABLE_BIT 17 +#define SPARSE_CNTL_ENABLE 0xC12C/* Device for a quirk */ #define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
@@ -149,6 +151,9 @@ static void xhci_pci_quirks(struct devic (pdev->device == 0x15e0 || pdev->device == 0x15e1)) xhci->quirks |= XHCI_SNPS_BROKEN_SUSPEND; +if (pdev->vendor ==PCI_VENDOR_ID_AMD && pdev->device ==0x15e5 ) + xhci->quirks |=XHCI_DISABLE_SPARSE ; +if (pdev->vendor ==PCI_VENDOR_ID_AMD ) xhci->quirks |=XHCI_TRUST_TX_LENGTH ;
@@ -467,6 +472,15 @@ static void xhci_pme_quirk(struct usb_hcreadl (reg); } +static void xhci_sparse_control_quirk (struct usb_hcd *hcd) +{ +u32 reg; + + reg =readl (hcd->regs +SPARSE_CNTL_ENABLE ); + reg &= ~BIT (SPARSE_DISABLE_BIT ); +writel (reg, hcd->regs +SPARSE_CNTL_ENABLE ); +} +static int xhci_pci_suspend (struct usb_hcd *hcd,bool do_wakeup) {struct xhci_hcd *xhci =hcd_to_xhci (hcd);
@@ -486,6 +500,9 @@ static int xhci_pci_suspend(struct usb_hif (xhci->quirks &XHCI_SSIC_PORT_UNUSED )xhci_ssic_port_unused_quirk (hcd, true); +if (xhci->quirks &XHCI_DISABLE_SPARSE ) +xhci_sparse_control_quirk (hcd); + ret =xhci_suspend (xhci, do_wakeup);if (ret && (xhci->quirks &XHCI_SSIC_PORT_UNUSED ))xhci_ssic_port_unused_quirk (hcd, false);
drivers/usb/host/xhci.h +1 -0
@@ -1873,6 +1873,7 @@ struct xhci_hcd {#define XHCI_DEFAULT_PM_RUNTIME_ALLOW BIT_ULL(33)#define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34)#define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35) +#define XHCI_DISABLE_SPARSE BIT_ULL(38)unsigned int num_active_eps;unsigned int limit_active_eps;
Greg Kroah-Hartman
maintainerPATCH 134/214 usb: dwc3: pci: Allow Elkhart Lake to utilize DSM method for PM functionality
In reply to Greg Kroah-HartmanFrom: Raymond Tan <[email protected]>
commit a609ce2a13360d639b384b6ca783b38c1247f2db upstream.
Similar to some other IA platforms, Elkhart Lake too depends on the PMU register write to request transition of Dx power state.
Thus, we add the PCI_DEVICE_ID_INTEL_EHLLP to the list of devices that shall execute the ACPI _DSM method during D0/D3 sequence.
[[email protected]: included Fixes tag]
--- drivers/usb/dwc3/dwc3-pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/usb/dwc3/dwc3-pci.c +2 -1
@@ -147,7 +147,8 @@ static int dwc3_pci_quirks(struct dwc3_pif (pdev->vendor ==PCI_VENDOR_ID_INTEL ) {if (pdev->device ==PCI_DEVICE_ID_INTEL_BXT || - pdev->device ==PCI_DEVICE_ID_INTEL_BXT_M ) { + pdev->device ==PCI_DEVICE_ID_INTEL_BXT_M || + pdev->device ==PCI_DEVICE_ID_INTEL_EHLLP ) {guid_parse (PCI_INTEL_BXT_DSM_GUID , &dwc->guid); dwc->has_dsm_for_pm = true; }
Greg Kroah-Hartman
maintainerPATCH 135/214 usb: dwc3: ep0: Fix ZLP for OUT ep0 requests
In reply to Greg Kroah-HartmanFrom: Thinh Nguyen <[email protected]>
commit 66706077dc89c66a4777a4c6298273816afb848c upstream.
The current ZLP handling for ep0 requests is only for control IN requests. For OUT direction, DWC3 needs to check and setup for MPS alignment.
Usually, control OUT requests can indicate its transfer size via the wLength field of the control message. So usb_request->zero is usually not needed for OUT direction. To handle ZLP OUT for control endpoint, make sure the TRB is MPS size.
--- drivers/usb/dwc3/ep0.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
drivers/usb/dwc3/ep0.c +9 -2
@@ -942,12 +942,16 @@ static void dwc3_ep0_xfer_complete(strucstatic void __dwc3_ep0_do_control_data (struct dwc3 *dwc,struct dwc3_ep *dep,struct dwc3_request *req) { +unsigned int trb_length =0 ;int ret; req->direction = !!dep->number;if (req->request.length ==0 ) { -dwc3_ep0_prepare_one_trb (dep, dwc->ep0_trb_addr,0 , +if (!req->direction) + trb_length = dep->endpoint.maxpacket; + +dwc3_ep0_prepare_one_trb (dep, dwc->bounce_addr, trb_length,DWC3_TRBCTL_CONTROL_DATA , false); ret =dwc3_ep0_start_trans (dep); } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket)
@@ -994,9 +998,12 @@ static void __dwc3_ep0_do_control_data(s req->trb = &dwc->ep0_trb[dep->trb_enqueue -1 ]; +if (!req->direction) + trb_length = dep->endpoint.maxpacket; +/* Now prepare one extra TRB to align transfer size */ dwc3_ep0_prepare_one_trb (dep, dwc->bounce_addr, -0 ,DWC3_TRBCTL_CONTROL_DATA , + trb_length,DWC3_TRBCTL_CONTROL_DATA , false); ret =dwc3_ep0_start_trans (dep); }else {
Greg Kroah-Hartman
maintainerPATCH 136/214 usb: dwc3: gadget: Check MPS of the request length
In reply to Greg Kroah-HartmanFrom: Thinh Nguyen <[email protected]>
commit ca3df3468eec87f6374662f7de425bc44c3810c1 upstream.
When preparing for SG, not all the entries are prepared at once. When resume, don't use the remaining request length to calculate for MPS alignment. Use the entire request->length to do that.
--- drivers/usb/dwc3/gadget.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/usb/dwc3/gadget.c +2 -2
@@ -1057,6 +1057,8 @@ static void dwc3_prepare_one_trb_sg(strustruct scatterlist *s;int i;unsigned int length = req->request.length; +unsigned int maxp =usb_endpoint_maxp (dep->endpoint.desc); +unsigned int rem = length % maxp;unsigned int remaining = req->request.num_mapped_sgs - req->num_queued_sgs;
@@ -1068,8 +1070,6 @@ static void dwc3_prepare_one_trb_sg(stru length -=sg_dma_len (s);for_each_sg (sg, s, remaining, i) { -unsigned int maxp =usb_endpoint_maxp (dep->endpoint.desc); -unsigned int rem = length % maxp;unsigned int trb_length;unsigned chain = true;
Greg Kroah-Hartman
maintainerPATCH 137/214 usb: dwc3: core: add phy cleanup for probe error handling
In reply to Greg Kroah-HartmanFrom: Li Jun <[email protected]>
commit 03c1fd622f72c7624c81b64fdba4a567ae5ee9cb upstream.
Add the phy cleanup if dwc3 mode init fail, which is the missing part of de-init for dwc3 core init.
--- drivers/usb/dwc3/core.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
drivers/usb/dwc3/core.c +11 -0
@@ -1535,6 +1535,17 @@ static int dwc3_probe(struct platform_de err5:dwc3_event_buffers_cleanup (dwc); + +usb_phy_shutdown (dwc->usb2_phy); +usb_phy_shutdown (dwc->usb3_phy); +phy_exit (dwc->usb2_generic_phy); +phy_exit (dwc->usb3_generic_phy); + +usb_phy_set_suspend (dwc->usb2_phy,1 ); +usb_phy_set_suspend (dwc->usb3_phy,1 ); +phy_power_off (dwc->usb2_generic_phy); +phy_power_off (dwc->usb3_generic_phy); +dwc3_ulpi_exit (dwc); err4:
Greg Kroah-Hartman
maintainerPATCH 138/214 usb: dwc3: core: dont trigger runtime pm when remove driver
In reply to Greg Kroah-HartmanFrom: Li Jun <[email protected]>
commit 266d0493900ac5d6a21cdbe6b1624ed2da94d47a upstream.
No need to trigger runtime pm in driver removal, otherwise if user disable auto suspend via sys file, runtime suspend may be entered, which will call dwc3_core_exit() again and there will be clock disable not balance warning:
[ 2026.820154] xhci-hcd xhci-hcd.0.auto: remove, state 4 [ 2026.825268] usb usb2: USB disconnect, device number 1 [ 2026.831017] xhci-hcd xhci-hcd.0.auto: USB bus 2 deregistered [ 2026.836806] xhci-hcd xhci-hcd.0.auto: remove, state 4 [ 2026.842029] usb usb1: USB disconnect, device number 1 [ 2026.848029] xhci-hcd xhci-hcd.0.auto: USB bus 1 deregistered [ 2026.865889] ------------[ cut here ]------------ [ 2026.870506] usb2_ctrl_root_clk already disabled [ 2026.875082] WARNING: CPU: 0 PID: 731 at drivers/clk/clk.c:958 clk_core_disable+0xa0/0xa8 [ 2026.883170] Modules linked in: dwc3(-) phy_fsl_imx8mq_usb [last unloaded: dwc3] [ 2026.890488] CPU: 0 PID: 731 Comm: rmmod Not tainted 5.8.0-rc7-00280-g9d08cca-dirty #245 [ 2026.898489] Hardware name: NXP i.MX8MQ EVK (DT) [ 2026.903020] pstate: 20000085 (nzCv daIf -PAN -UAO BTYPE=--) [ 2026.908594] pc : clk_core_disable+0xa0/0xa8 [ 2026.912777] lr : clk_core_disable+0xa0/0xa8 [ 2026.916958] sp : ffff8000121b39a0 [ 2026.920271] x29: ffff8000121b39a0 x28: ffff0000b11f3700 [ 2026.925583] x27: 0000000000000000 x26: ffff0000b539c700 [ 2026.930895] x25: 000001d7e44e1232 x24: ffff0000b76fa800 [ 2026.936208] x23: ffff0000b76fa6f8 x22: ffff800008d01040 [ 2026.941520] x21: ffff0000b539ce00 x20: ffff0000b7105000 [ 2026.946832] x19: ffff0000b7105000 x18: 0000000000000010 [ 2026.952144] x17: 0000000000000001 x16: 0000000000000000 [ 2026.957456] x15: ffff0000b11f3b70 x14: ffffffffffffffff [ 2026.962768] x13: ffff8000921b36f7 x12: ffff8000121b36ff [ 2026.968080] x11: ffff8000119e1000 x10: ffff800011bf26d0 [ 2026.973392] x9 : 0000000000000000 x8 : ffff800011bf3000 [ 2026.978704] x7 : ffff800010695d68 x6 : 0000000000000252 [ 2026.984016] x5 : ffff0000bb9881f0 x4 : 0000000000000000 [ 2026.989327] x3 : 0000000000000027 x2 : 0000000000000023 [ 2026.994639] x1 : ac2fa471aa7cab00 x0 : 0000000000000000 [ 2026.999951] Call trace: [ 2027.002401] clk_core_disable+0xa0/0xa8 [ 2027.006238] clk_core_disable_lock+0x20/0x38 [ 2027.010508] clk_disable+0x1c/0x28 [ 2027.013911] clk_bulk_disable+0x34/0x50 [ 2027.017758] dwc3_core_exit+0xec/0x110 [dwc3] [ 2027.022122] dwc3_suspend_common+0x84/0x188 [dwc3] [ 2027.026919] dwc3_runtime_suspend+0x74/0x9c [dwc3] [ 2027.031712] pm_generic_runtime_suspend+0x28/0x40 [ 2027.036419] genpd_runtime_suspend+0xa0/0x258 [ 2027.040777] __rpm_callback+0x88/0x140 [ 2027.044526] rpm_callback+0x20/0x80 [ 2027.048015] rpm_suspend+0xd0/0x418 [ 2027.051503] __pm_runtime_suspend+0x58/0xa0 [ 2027.055693] dwc3_runtime_idle+0x7c/0x90 [dwc3] [ 2027.060224] __rpm_callback+0x88/0x140 [ 2027.063973] rpm_idle+0x78/0x150 [ 2027.067201] __pm_runtime_idle+0x58/0xa0 [ 2027.071130] dwc3_remove+0x64/0xc0 [dwc3] [ 2027.075140] platform_drv_remove+0x28/0x48 [ 2027.079239] device_release_driver_internal+0xf4/0x1c0 [ 2027.084377] driver_detach+0x4c/0xd8 [ 2027.087954] bus_remove_driver+0x54/0xa8 [ 2027.091877] driver_unregister+0x2c/0x58 [ 2027.095799] platform_driver_unregister+0x10/0x18 [ 2027.100509] dwc3_driver_exit+0x14/0x1408 [dwc3] [ 2027.105129] __arm64_sys_delete_module+0x178/0x218 [ 2027.109922] el0_svc_common.constprop.0+0x68/0x160 [ 2027.114714] do_el0_svc+0x20/0x80 [ 2027.118031] el0_sync_handler+0x88/0x190 [ 2027.121953] el0_sync+0x140/0x180 [ 2027.125267] ---[ end trace 027f4f8189958f1f ]--- [ 2027.129976] ------------[ cut here ]------------
--- drivers/usb/dwc3/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/usb/dwc3/core.c +2 -2
@@ -1581,9 +1581,9 @@ static int dwc3_remove(struct platform_ddwc3_core_exit (dwc);dwc3_ulpi_exit (dwc); -pm_runtime_put_sync (&pdev->dev); -pm_runtime_allow (&pdev->dev);pm_runtime_disable (&pdev->dev); +pm_runtime_put_noidle (&pdev->dev); +pm_runtime_set_suspended (&pdev->dev);dwc3_free_event_buffers (dwc);dwc3_free_scratch_buffers (dwc);
Greg Kroah-Hartman
maintainerPATCH 139/214 usb: dwc3: gadget: Resume pending requests after CLEAR_STALL
In reply to Greg Kroah-HartmanFrom: Thinh Nguyen <[email protected]>
commit c503672abe1348f10f5a54a662336358c6e1a297 upstream.
The function driver may queue new requests right after halting the endpoint (i.e. queue new requests while the endpoint is stalled). There's no restriction preventing it from doing so. However, dwc3 currently drops those requests after CLEAR_STALL. The driver should only drop started requests. Keep the pending requests in the pending list to resume and process them after the host issues ClearFeature(Halt) to the endpoint.
--- drivers/usb/dwc3/gadget.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-)
drivers/usb/dwc3/gadget.c +14 -8
@@ -1521,8 +1521,13 @@ static int __dwc3_gadget_ep_queue(structlist_add_tail (&req->list, &dep->pending_list); req->status =DWC3_REQUEST_STATUS_QUEUED ; -/* Start the transfer only after the END_TRANSFER is completed */ -if (dep->flags &DWC3_EP_END_TRANSFER_PENDING ) { +/* +* Start the transfer only after the END_TRANSFER is completed +* and endpoint STALL is cleared. +*/ +if ((dep->flags &DWC3_EP_END_TRANSFER_PENDING ) || + (dep->flags &DWC3_EP_WEDGE ) || + (dep->flags &DWC3_EP_STALL )) { dep->flags |=DWC3_EP_DELAY_START ;return 0 ; }
@@ -1728,13 +1733,14 @@ int __dwc3_gadget_ep_set_halt(struct dwclist_for_each_entry_safe (req, tmp, &dep->started_list, list)dwc3_gadget_move_cancelled_request (req); -list_for_each_entry_safe (req, tmp, &dep->pending_list, list) -dwc3_gadget_move_cancelled_request (req); - -if (!(dep->flags &DWC3_EP_END_TRANSFER_PENDING )) { - dep->flags &= ~DWC3_EP_DELAY_START ; +if (!(dep->flags &DWC3_EP_END_TRANSFER_PENDING ))dwc3_gadget_ep_cleanup_cancelled_requests (dep); - } + +if ((dep->flags &DWC3_EP_DELAY_START ) && + !usb_endpoint_xfer_isoc (dep->endpoint.desc)) +__dwc3_gadget_kick_transfer (dep); + + dep->flags &= ~DWC3_EP_DELAY_START ; }return ret;
Greg Kroah-Hartman
maintainerPATCH 140/214 usb: dwc3: gadget: END_TRANSFER before CLEAR_STALL command
In reply to Greg Kroah-HartmanFrom: Thinh Nguyen <[email protected]>
commit d97c78a1908e59a1fdbcbece87cd0440b5d7a1f2 upstream.
According the programming guide (for all DWC3 IPs), when the driver handles ClearFeature(halt) request, it should issue CLEAR_STALL command _after_ the END_TRANSFER command completes. The END_TRANSFER command may take some time to complete. So, delay the ClearFeature(halt) request control status stage and wait for END_TRANSFER command completion interrupt. Only after END_TRANSFER command completes that the driver may issue CLEAR_STALL command.
--- drivers/usb/dwc3/core.h | 1 + drivers/usb/dwc3/ep0.c | 16 ++++++++++++++++ drivers/usb/dwc3/gadget.c | 40 ++++++++++++++++++++++++++++++++-------- drivers/usb/dwc3/gadget.h | 1 + 4 files changed, 50 insertions(+), 8 deletions(-)
drivers/usb/dwc3/core.h +1 -0
@@ -700,6 +700,7 @@ struct dwc3_ep {#define DWC3_EP_END_TRANSFER_PENDING BIT(4)#define DWC3_EP_PENDING_REQUEST BIT(5)#define DWC3_EP_DELAY_START BIT(6) +#define DWC3_EP_PENDING_CLEAR_STALL BIT(11)/* This last one is specific to EP0 */ #define DWC3_EP0_DIR_IN BIT(31)
drivers/usb/dwc3/ep0.c +16 -0
@@ -524,6 +524,11 @@ static int dwc3_ep0_handle_endpoint(stru ret =__dwc3_gadget_ep_set_halt (dep, set, true);if (ret)return -EINVAL ; + +/* ClearFeature(Halt) may need delayed status */ +if (!set && (dep->flags &DWC3_EP_END_TRANSFER_PENDING )) +return USB_GADGET_DELAYED_STATUS ; +break ;default :return -EINVAL ;
@@ -1049,6 +1054,17 @@ static void dwc3_ep0_do_control_status(s__dwc3_ep0_do_control_status (dwc, dep); } +void dwc3_ep0_send_delayed_status (struct dwc3 *dwc) +{ +unsigned int direction = !dwc->ep0_expect_in; + +if (dwc->ep0state !=EP0_STATUS_PHASE ) +return ; + + dwc->delayed_status = false; +__dwc3_ep0_do_control_status (dwc, dwc->eps[direction]); +} +static void dwc3_ep0_end_control_data (struct dwc3 *dwc,struct dwc3_ep *dep) {struct dwc3_gadget_ep_cmd_params params;
drivers/usb/dwc3/gadget.c +32 -8
@@ -1719,6 +1719,18 @@ int __dwc3_gadget_ep_set_halt(struct dwcreturn 0 ; } +dwc3_stop_active_transfer (dep, true, true); + +list_for_each_entry_safe (req, tmp, &dep->started_list, list) +dwc3_gadget_move_cancelled_request (req); + +if (dep->flags &DWC3_EP_END_TRANSFER_PENDING ) { + dep->flags |=DWC3_EP_PENDING_CLEAR_STALL ; +return 0 ; + } + +dwc3_gadget_ep_cleanup_cancelled_requests (dep); + ret =dwc3_send_clear_stall_ep_cmd (dep);if (ret) { dev_err(dwc->dev, "failed to clear STALL on %s\n",
@@ -1728,14 +1740,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc dep->flags &= ~(DWC3_EP_STALL |DWC3_EP_WEDGE ); -dwc3_stop_active_transfer (dep, true, true); - -list_for_each_entry_safe (req, tmp, &dep->started_list, list) -dwc3_gadget_move_cancelled_request (req); - -if (!(dep->flags &DWC3_EP_END_TRANSFER_PENDING )) -dwc3_gadget_ep_cleanup_cancelled_requests (dep); -if ((dep->flags &DWC3_EP_DELAY_START ) && !usb_endpoint_xfer_isoc (dep->endpoint.desc))__dwc3_gadget_kick_transfer (dep);
@@ -2767,6 +2771,26 @@ static void dwc3_endpoint_interrupt(stru dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING ; dep->flags &= ~DWC3_EP_TRANSFER_STARTED ;dwc3_gadget_ep_cleanup_cancelled_requests (dep); + +if (dep->flags &DWC3_EP_PENDING_CLEAR_STALL ) { +struct dwc3 *dwc = dep->dwc; + + dep->flags &= ~DWC3_EP_PENDING_CLEAR_STALL ; +if (dwc3_send_clear_stall_ep_cmd (dep)) { +struct usb_ep *ep0 = &dwc->eps[0 ]->endpoint; + +dev_err (dwc->dev,"failed to clear STALL on %s\n" , + dep->name); +if (dwc->delayed_status) +__dwc3_gadget_ep0_set_halt (ep0,1 ); +return ; + } + + dep->flags &= ~(DWC3_EP_STALL |DWC3_EP_WEDGE ); +if (dwc->delayed_status) +dwc3_ep0_send_delayed_status (dwc); + } +if ((dep->flags &DWC3_EP_DELAY_START ) && !usb_endpoint_xfer_isoc (dep->endpoint.desc))__dwc3_gadget_kick_transfer (dep);
drivers/usb/dwc3/gadget.h +1 -0
@@ -111,6 +111,7 @@ int dwc3_gadget_ep0_set_halt(struct usb_int dwc3_gadget_ep0_queue (struct usb_ep *ep,struct usb_request *request,gfp_t gfp_flags);int __dwc3_gadget_ep_set_halt (struct dwc3_ep *dep,int value,int protocol); +void dwc3_ep0_send_delayed_status (struct dwc3 *dwc);/** * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW