5.4.19-stable review
Subsystems (3)
Greg Kroah-Hartman
maintainercover 5.4.19-stable review
This is the start of the stable review cycle for the 5.4.19 release. There are 309 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 Wed, 12 Feb 2020 12:18:57 +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.19-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.19-rc1
Christophe Leroy <[email protected]>
powerpc/kuap: Fix set direction in allow/prevent_user_access()
Stephen Rothwell <[email protected]>
regulator fix for "regulator: core: Add regulator_is_equal() helper"
David Howells <[email protected]>
rxrpc: Fix service call disconnection
Song Liu <[email protected]>
perf/core: Fix mlock accounting in perf_mmap()
Konstantin Khlebnikov <[email protected]>
clocksource: Prevent double add_timer_on() for watchdog_timer
Thomas Gleixner <[email protected]>
x86/apic/msi: Plug non-maskable MSI affinity race
Aurelien Aptel <[email protected]>
cifs: fix mode bits from dir listing when mounted with modefromsid
Ronnie Sahlberg <[email protected]>
cifs: fail i/o on soft mounts if sessionsetup errors out
Sean Christopherson <[email protected]>
KVM: Play nice with read-only memslots when querying host page size
Sean Christopherson <[email protected]>
KVM: Use vcpu-specific gva->hva translation when querying host page size
Miaohe Lin <[email protected]>
KVM: nVMX: vmread should not set rflags to specify success in case of #PF
Paolo Bonzini <[email protected]>
KVM: x86: fix overlap between SPTE_MMIO_MASK and generation
Sean Christopherson <[email protected]>
KVM: x86: Use gpa_t for cr2/gpa to fix TDP support on 32-bit KVM
Paolo Bonzini <[email protected]>
KVM: x86: use CPUID to locate host page table reserved bits
Sean Christopherson <[email protected]>
KVM: x86/mmu: Apply max PA check for MMIO sptes to 32-bit KVM
Wayne Lin <[email protected]>
drm/dp_mst: Remove VCPI while disabling topology mgr
Josef Bacik <[email protected]>
btrfs: free block groups after free'ing fs trees
Anand Jain <[email protected]>
btrfs: use bool argument in free_root_pointers()
Thomas Gleixner <[email protected]>
x86/timer: Don't skip PIT setup when APIC is disabled or in legacy mode
Matti Vaittinen <[email protected]>
mfd: bd70528: Fix hour register mask
Andreas Kemnade <[email protected]>
mfd: rn5t618: Mark ADC control register volatile
Marco Felsch <[email protected]>
mfd: da9062: Fix watchdog compatible string
Cezary Rojewski <[email protected]>
ASoC: Intel: skl_hda_dsp_common: Fix global-out-of-bounds bug
Tariq Toukan <[email protected]>
net/mlx5: Deprecate usage of generic TLS HW capability bit
Maor Gottlieb <[email protected]>
net/mlx5: Fix deadlock in fs_core
Ido Schimmel <[email protected]>
drop_monitor: Do not cancel uninitialized work item
Sudarsana Reddy Kalluru <[email protected]>
qed: Fix timestamping issue for L2 unicast ptp packets.
Eric Dumazet <[email protected]>
ipv6/addrconf: fix potential NULL deref in inet6_set_link_af()
Vinicius Costa Gomes <[email protected]>
taprio: Fix dropping packets when using taprio + ETF offloading
Vinicius Costa Gomes <[email protected]>
taprio: Use taprio_reset_tc() to reset Traffic Classes configuration
Vinicius Costa Gomes <[email protected]>
taprio: Add missing policy validation for flags
Vinicius Costa Gomes <[email protected]>
taprio: Fix still allowing changing the flags during runtime
Vinicius Costa Gomes <[email protected]>
taprio: Fix enabling offload with wrong number of traffic classes
Harini Katakam <[email protected]>
net: macb: Limit maximum GEM TX length in TSO
Harini Katakam <[email protected]>
net: macb: Remove unnecessary alignment check for TSO
Raed Salem <[email protected]>
net/mlx5: IPsec, fix memory leak at mlx5_fpga_ipsec_delete_sa_ctx
Raed Salem <[email protected]>
net/mlx5: IPsec, Fix esp modify function attribute
Florian Fainelli <[email protected]>
net: systemport: Avoid RBUF stuck in Wake-on-LAN mode
Dejin Zheng <[email protected]>
net: stmmac: fix a possible endless loop
Cong Wang <[email protected]>
net_sched: fix a resource leak in tcindex_set_parms()
Lorenzo Bianconi <[email protected]>
net: mvneta: move rx_dropped and rx_errors in per-cpu stats
Razvan Stefanescu <[email protected]>
net: dsa: microchip: enable module autoprobe
Florian Fainelli <[email protected]>
net: dsa: bcm_sf2: Only 7278 supports 2Gb/sec IMP port
Florian Fainelli <[email protected]>
net: dsa: b53: Always use dev->vlan_enabled in b53_configure_vlan()
Madalin Bucur <[email protected]>
dpaa_eth: support all modes with rate adapting PHYs
Jacob Keller <[email protected]>
devlink: report 0 after hitting end in region read
Eric Dumazet <[email protected]>
bonding/alb: properly access headers in bond_alb_xmit()
Marek Vasut <[email protected]>
ASoC: sgtl5000: Fix VDDA and VDDIO comparison
Marek Vasut <[email protected]>
regulator: core: Add regulator_is_equal() helper
Quanyang Wang <[email protected]>
ubifs: Fix memory leak from c->sup_node
Dan Carpenter <[email protected]>
ubi: Fix an error pointer dereference in error handling code
Sascha Hauer <[email protected]>
ubi: fastmap: Fix inverted logic in seen selfcheck
David Hildenbrand <[email protected]>
virtio_balloon: Fix memory leaks on errors in virtballoon_probe()
David Hildenbrand <[email protected]>
virtio-balloon: Fix memory leak when unloading while hinting is in progress
Trond Myklebust <[email protected]>
nfsd: Return the correct number of bytes written to the file
Arnd Bergmann <[email protected]>
nfsd: fix jiffies/time_t mixup in LRU list
Arnd Bergmann <[email protected]>
nfsd: fix delay timer on 32-bit architectures
Yishai Hadas <[email protected]>
IB/core: Fix ODP get user pages flow
Prabhath Sajeepa <[email protected]>
IB/mlx5: Fix outstanding_pi index for GSI qps
Nathan Chancellor <[email protected]>
net: tulip: Adjust indentation in {dmfe, uli526x}_init_module
Nathan Chancellor <[email protected]>
net: smc911x: Adjust indentation in smc911x_phy_configure
Nathan Chancellor <[email protected]>
ppp: Adjust indentation into ppp_async_input
Nathan Chancellor <[email protected]>
NFC: pn544: Adjust indentation in pn544_hci_check_presence
Nathan Chancellor <[email protected]>
drm: msm: mdp4: Adjust indentation in mdp4_dsi_encoder_enable
Nathan Chancellor <[email protected]>
powerpc/44x: Adjust indentation in ibm4xx_denali_fixup_memsize
Nathan Chancellor <[email protected]>
ext2: Adjust indentation in ext2_fill_super
Nathan Chancellor <[email protected]>
phy: qualcomm: Adjust indentation in read_poll_timeout
Vignesh Raghavendra <[email protected]>
mtd: spi-nor: Split mt25qu512a (n25q512a) entry into two
Asutosh Das <[email protected]>
scsi: ufs: Recheck bkops level if bkops is disabled
Nathan Chancellor <[email protected]>
scsi: qla4xxx: Adjust indentation in qla4xxx_mem_free
Nathan Chancellor <[email protected]>
scsi: csiostor: Adjust indentation in csio_device_reset
Bart Van Assche <[email protected]>
scsi: qla2xxx: Fix the endianness of the qla82xx_get_fw_size() return type
Jerome Brunet <[email protected]>
ASoC: meson: axg-fifo: fix fifo threshold setup
Erdem Aktas <[email protected]>
percpu: Separate decrypted varaibles anytime encryption can be enabled
Casey Schaufler <[email protected]>
broken ping to ipv6 linklocal addresses on debian buster
Miklos Szeredi <[email protected]>
fix up iter on short count in fuse_direct_io()
Daniel Verkamp <[email protected]>
virtio-pci: check name when counting MSI-X vectors
Daniel Verkamp <[email protected]>
virtio-balloon: initialize all vq callbacks
Lyude Paul <[email protected]>
drm/amd/dm/mst: Ignore payload update failures
Stephen Warren <[email protected]>
clk: tegra: Mark fuse clock as critical
Peter Zijlstra <[email protected]>
mm/mmu_gather: invalidate TLB correctly on batch allocation failure and flush
Niklas Cassel <[email protected]>
arm64: dts: qcom: qcs404-evb: Set vdd_apc regulator in high power mode
David Hildenbrand <[email protected]>
mm/page_alloc.c: fix uninitialized memmaps on a partially populated last section
Gang He <[email protected]>
ocfs2: fix oops when writing cloned file
Christian Borntraeger <[email protected]>
KVM: s390: do not clobber registers during guest reset/store status
Sean Christopherson <[email protected]>
KVM: x86: Revert "KVM: X86: Fix fpu state crash in kvm guest"
Sean Christopherson <[email protected]>
KVM: x86: Ensure guest's FPU state is loaded when accessing for emulation
Sean Christopherson <[email protected]>
KVM: x86: Handle TIF_NEED_FPU_LOAD in kvm_{load,put}_guest_fpu()
Sean Christopherson <[email protected]>
KVM: x86: Free wbinvd_dirty_mask if vCPU creation fails
Sean Christopherson <[email protected]>
KVM: x86: Don't let userspace set host-reserved cr4 bits
Sean Christopherson <[email protected]>
KVM: VMX: Add non-canonical check on writes to RTIT address MSRs
Boris Ostrovsky <[email protected]>
x86/KVM: Clean up host's steal time structure
Boris Ostrovsky <[email protected]>
x86/kvm: Cache gfn to pfn translation
Boris Ostrovsky <[email protected]>
x86/KVM: Make sure KVM_VCPU_FLUSH_TLB flag is not missed
Boris Ostrovsky <[email protected]>
x86/kvm: Introduce kvm_(un)map_gfn()
Boris Ostrovsky <[email protected]>
x86/kvm: Be careful not to clear KVM_VCPU_FLUSH_TLB bit
John Allen <[email protected]>
kvm/svm: PKU not currently supported
Sean Christopherson <[email protected]>
KVM: PPC: Book3S PR: Free shared page if mmu initialization fails
Sean Christopherson <[email protected]>
KVM: PPC: Book3S HV: Uninit vCPU if vcore creation fails
Sean Christopherson <[email protected]>
KVM: x86: Fix potential put_fpu() w/o load_fpu() on MPX platform
Marios Pomonis <[email protected]>
KVM: x86: Protect MSR-based index computations in fixed_msr_to_seg_unit() from Spectre-v1/L1TF attacks
Marios Pomonis <[email protected]>
KVM: x86: Protect x86_decode_insn from Spectre-v1/L1TF attacks
Marios Pomonis <[email protected]>
KVM: x86: Protect MSR-based index computations from Spectre-v1/L1TF attacks in x86.c
Marios Pomonis <[email protected]>
KVM: x86: Protect ioapic_read_indirect() from Spectre-v1/L1TF attacks
Marios Pomonis <[email protected]>
KVM: x86: Protect MSR-based index computations in pmu.h from Spectre-v1/L1TF attacks
Marios Pomonis <[email protected]>
KVM: x86: Protect ioapic_write_indirect() from Spectre-v1/L1TF attacks
Marios Pomonis <[email protected]>
KVM: x86: Protect kvm_hv_msr_[get|set]_crash_data() from Spectre-v1/L1TF attacks
Marios Pomonis <[email protected]>
KVM: x86: Protect kvm_lapic_reg_write() from Spectre-v1/L1TF attacks
Marios Pomonis <[email protected]>
KVM: x86: Protect DR-based index computations from Spectre-v1/L1TF attacks
Marios Pomonis <[email protected]>
KVM: x86: Protect pmu_intel.c from Spectre-v1/L1TF attacks
Marios Pomonis <[email protected]>
KVM: x86: Refactor prefix decoding to prevent Spectre-v1/L1TF attacks
Marios Pomonis <[email protected]>
KVM: x86: Refactor picdev_write() to prevent Spectre-v1/L1TF attacks
Jens Axboe <[email protected]>
aio: prevent potential eventfd recursion on poll
Jens Axboe <[email protected]>
eventfd: track eventfd_signal() recursion depth
Coly Li <[email protected]>
bcache: add readahead cache policy options via sysfs interface
Vladis Dronov <[email protected]>
watchdog: fix UAF in reboot notifier handling in watchdog core code
Juergen Gross <[email protected]>
xen/balloon: Support xend-based toolstack take two
Gavin Shan <[email protected]>
tools/kvm_stat: Fix kvm_exit filter name
Sean Young <[email protected]>
media: rc: ensure lirc is initialized before registering input device
Johan Hovold <[email protected]>
media: iguanair: fix endpoint sanity check
Ville Syrjälä <[email protected]>
drm/rect: Avoid division by zero
Peter Rosin <[email protected]>
drm: atmel-hlcdc: prefer a lower pixel-clock than requested
Claudiu Beznea <[email protected]>
drm: atmel-hlcdc: enable clock before configuring timing engine
Claudiu Beznea <[email protected]>
drm: atmel-hlcdc: use double rate for pixel clock only if supported
Andreas Gruenbacher <[email protected]>
gfs2: fix O_SYNC write handling
Christoph Hellwig <[email protected]>
gfs2: move setting current->backing_dev_info
Abhi Das <[email protected]>
gfs2: fix gfs2_find_jhead that returns uninitialized jhead with seq 0
Roberto Bergantinos Corpas <[email protected]>
sunrpc: expiry_time should be seconds not timeval
Brian Norris <[email protected]>
mwifiex: fix unbalanced locking in mwifiex_process_country_ie()
Luca Coelho <[email protected]>
iwlwifi: don't throw error when trying to remove IGTK
Stephen Warren <[email protected]>
ARM: tegra: Enable PLLP bypass during Tegra124 LP1
Nikolay Borisov <[email protected]>
btrfs: Correctly handle empty trees in find_first_clear_extent_bit
Josef Bacik <[email protected]>
btrfs: flush write bio if we loop in extent_write_cache_pages
Filipe Manana <[email protected]>
Btrfs: fix race between adding and putting tree mod seq elements and nodes
Josef Bacik <[email protected]>
btrfs: drop log root for dropped roots
Josef Bacik <[email protected]>
btrfs: set trans->drity in btrfs_commit_transaction
Filipe Manana <[email protected]>
Btrfs: fix infinite loop during fsync after rename operations
Filipe Manana <[email protected]>
Btrfs: make deduplication with range including the last block work
Filipe Manana <[email protected]>
Btrfs: fix missing hole after hole punching and fsync when using NO_HOLES
Eric Biggers <[email protected]>
ext4: fix race conditions in ->d_compare() and ->d_hash()
Eric Biggers <[email protected]>
ext4: fix deadlock allocating crypto bounce page from mempool
Vasily Averin <[email protected]>
jbd2_seq_info_next should increase position index
Trond Myklebust <[email protected]>
nfsd: fix filecache lookup
Trond Myklebust <[email protected]>
NFS: Directory page cache pages need to be locked when read
Trond Myklebust <[email protected]>
NFS: Fix memory leaks and corruption in readdir
Arun Easi <[email protected]>
scsi: qla2xxx: Fix unbound NVME response length
Michael Ellerman <[email protected]>
powerpc/futex: Fix incorrect user access blocking
Chuhong Yuan <[email protected]>
crypto: picoxcell - adjust the position of tasklet_init and fix missed tasklet_kill
Herbert Xu <[email protected]>
crypto: api - Fix race condition in crypto_spawn_alg
Tudor Ambarus <[email protected]>
crypto: atmel-aes - Fix counter overflow in CTR mode
Herbert Xu <[email protected]>
crypto: pcrypt - Do not clear MAY_SLEEP flag in original request
Ard Biesheuvel <[email protected]>
crypto: arm64/ghash-neon - bump priority to 150
Ard Biesheuvel <[email protected]>
crypto: ccp - set max RSA modulus size for v3 platform devices as well
Jonathan Cameron <[email protected]>
crypto: hisilicon - Use the offset fields in sqe to avoid need to split scatterlists
Herbert Xu <[email protected]>
crypto: api - fix unexpectedly getting generic implementation
Lorenz Bauer <[email protected]>
selftests: bpf: Ignore FIN packets for reuseport tests
Lorenz Bauer <[email protected]>
selftests: bpf: Use a temporary file in test_sockmap
Hangbin Liu <[email protected]>
selftests/bpf: Skip perf hw events test if the setup disabled it
Alexei Starovoitov <[email protected]>
selftests/bpf: Fix test_attach_probe
Jesper Dangaard Brouer <[email protected]>
samples/bpf: Xdp_redirect_cpu fix missing tracepoint attach
Toke Høiland-Jørgensen <[email protected]>
samples/bpf: Don't try to remove user's homedir on clean
Davide Caratti <[email protected]>
tc-testing: fix eBPF tests failure on linux fresh clones
Andrii Nakryiko <[email protected]>
libbpf: Fix realloc usage in bpf_core_find_cands
Amol Grover <[email protected]>
bpf, devmap: Pass lockdep expression to RCU lists
Andrii Nakryiko <[email protected]>
selftests/bpf: Fix perf_buffer test on systems w/ offline CPUs
Björn Töpel <[email protected]>
riscv, bpf: Fix broken BPF tail calls
Nikolay Borisov <[email protected]>
btrfs: Handle another split brain scenario with metadata uuid feature
Josef Bacik <[email protected]>
btrfs: fix improper setting of scanned for range cyclic write cache pages
Herbert Xu <[email protected]>
crypto: pcrypt - Avoid deadlock by using per-instance padata queues
Steven Rostedt (VMware) <[email protected]>
ftrace: Protect ftrace_graph_hash with ftrace_sync
Steven Rostedt (VMware) <[email protected]>
ftrace: Add comment to why rcu_dereference_sched() is open coded
Amol Grover <[email protected]>
tracing: Annotate ftrace_graph_notrace_hash pointer with __rcu
Amol Grover <[email protected]>
tracing: Annotate ftrace_graph_hash pointer with __rcu
Pierre-Louis Bossart <[email protected]>
ASoC: SOF: core: release resources on errors in probe_continue
Ranjani Sridharan <[email protected]>
ASoC: SOF: Introduce state machine for FW boot
Quinn Tran <[email protected]>
scsi: qla2xxx: Fix stuck login session using prli_pend_timer
Mike Snitzer <[email protected]>
dm: fix potential for q->make_request_fn NULL pointer
Mike Snitzer <[email protected]>
dm thin metadata: use pool locking at end of dm_pool_metadata_close
Milan Broz <[email protected]>
dm crypt: fix benbi IV constructor crash if used in authenticated mode
Mikulas Patocka <[email protected]>
dm crypt: fix GFP flags passed to skcipher_request_alloc()
Mikulas Patocka <[email protected]>
dm writecache: fix incorrect flush sequence when doing SSD mode commit
Joe Thornber <[email protected]>
dm space map common: fix to ensure new block isn't already in use
Dmitry Fomichev <[email protected]>
dm zoned: support zone sizes smaller than 128MiB
Chen-Yu Tsai <[email protected]>
ARM: dma-api: fix max_pfn off-by-one error in __dma_supported()
Michael Ellerman <[email protected]>
of: Add OF_DMA_DEFAULT_COHERENT & select it on powerpc
Rafael J. Wysocki <[email protected]>
cpufreq: Avoid creating excessively large stack frames
Rafael J. Wysocki <[email protected]>
PM: core: Fix handling of devices deleted during system-wide resume
Eric Biggers <[email protected]>
f2fs: fix race conditions in ->d_compare() and ->d_hash()
Eric Biggers <[email protected]>
f2fs: fix dcache lookup of !casefolded directories
Chengguang Xu <[email protected]>
f2fs: code cleanup for f2fs_statfs_project()
Chengguang Xu <[email protected]>
f2fs: fix miscounted block limit in f2fs_statfs_project()
Chengguang Xu <[email protected]>
f2fs: choose hardlimit when softlimit is larger than hardlimit in f2fs_statfs_project()
Miklos Szeredi <[email protected]>
ovl: fix lseek overflow on 32bit
Amir Goldstein <[email protected]>
ovl: fix wrong WARN_ON() in ovl_cache_update_ino()
Sven Van Asbroeck <[email protected]>
power: supply: ltc2941-battery-gauge: fix use-after-free
Samuel Holland <[email protected]>
power: supply: axp20x_ac_power: Fix reporting online status
Thomas Renninger <[email protected]>
cpupower: Revert library ABI changes from commit ae2917093fb60bdc1ed3e
Quinn Tran <[email protected]>
scsi: qla2xxx: Fix mtcp dump collection failure
Anand Lodnoor <[email protected]>
scsi: megaraid_sas: Do not initiate OCR if controller is not in ready state
Gao Xiang <[email protected]>
erofs: fix out-of-bound read for shifted uncompressed block
Geert Uytterhoeven <[email protected]>
scripts/find-unused-docs: Fix massive false positives
Filipe Manana <[email protected]>
fs: allow deduplication of eof block into the end of the destination file
Herbert Xu <[email protected]>
padata: Remove broken queue flushing
Gilad Ben-Yossef <[email protected]>
crypto: ccree - fix PM race condition
Ofir Drang <[email protected]>
crypto: ccree - fix FDE descriptor sequence
Gilad Ben-Yossef <[email protected]>
crypto: ccree - fix pm wrongful error reporting
Gilad Ben-Yossef <[email protected]>
crypto: ccree - fix AEAD decrypt auth fail
Gilad Ben-Yossef <[email protected]>
crypto: ccree - fix backlog memory leak
Herbert Xu <[email protected]>
crypto: api - Check spawn->alg under lock in crypto_drop_spawn
Bitan Biswas <[email protected]>
nvmem: core: fix memory abort in cleanup path
Samuel Holland <[email protected]>
mfd: axp20x: Mark AXP20X_VBUS_IPSOUT_MGMT as volatile
Tianyu Lan <[email protected]>
hv_balloon: Balloon up according to request page number
Pierre-Louis Bossart <[email protected]>
ASoC: SOF: core: free trace on errors
Michał Mirosław <[email protected]>
mmc: sdhci-of-at91: fix memleak on clk_get failure
Zhihao Cheng <[email protected]>
ubifs: Fix deadlock in concurrent bulk-read and writepage
Eric Biggers <[email protected]>
ubifs: Fix FS_IOC_SETFLAGS unexpectedly clearing encrypt flag
Sascha Hauer <[email protected]>
ubifs: Fix wrong memory allocation
Eric Biggers <[email protected]>
ubifs: don't trigger assertion on invalid no-key filename
Eric Biggers <[email protected]>
fscrypt: don't print name of busy file when removing key
Stephen Boyd <[email protected]>
alarmtimer: Unregister wakeup source when module get fails
Hans de Goede <[email protected]>
ACPI / battery: Deal better with neither design nor full capacity not being reported
Hans de Goede <[email protected]>
ACPI / battery: Use design-cap for capacity calculations if full-cap is not available
Hans de Goede <[email protected]>
ACPI / battery: Deal with design or full capacity being reported as -1
Hans de Goede <[email protected]>
ACPI: video: Do not export a non working backlight interface on MSI MS-7721 boards
Linus Walleij <[email protected]>
mmc: spi: Toggle SPI polarity, do not hardcode it
Kishon Vijay Abraham I <[email protected]>
PCI: keystone: Fix error handling when "num-viewport" DT property is not populated
Yurii Monakov <[email protected]>
PCI: keystone: Fix link training retries initiation
Yurii Monakov <[email protected]>
PCI: keystone: Fix outbound region mapping
David Engraf <[email protected]>
PCI: tegra: Fix return value check of pm_runtime_get_sync()
Tom Zanussi <[email protected]>
tracing: Fix now invalid var_ref_vals assumption in trace action
Christophe Leroy <[email protected]>
powerpc/32s: Fix CPU wake-up from sleep mode
Christophe Leroy <[email protected]>
powerpc/32s: Fix bad_kuap_fault()
Pingfan Liu <[email protected]>
powerpc/pseries: Advance pfn if section is not present in lmb_is_removable()
Sukadev Bhattiprolu <[email protected]>
powerpc/xmon: don't access ASDR in VMs
Christophe Leroy <[email protected]>
powerpc/ptdump: Fix W+X verification
Aneesh Kumar K.V <[email protected]>
powerpc/mmu_gather: enable RCU_TABLE_FREE even for !SMP case
Gerald Schaefer <[email protected]>
s390/mm: fix dynamic pagetable upgrade for hugetlbfs
Alexander Lobakin <[email protected]>
MIPS: boot: fix typo in 'vmlinux.lzma.its' target
Alexander Lobakin <[email protected]>
MIPS: fix indentation of the 'RELOCS' message
Alexander Lobakin <[email protected]>
MIPS: syscalls: fix indentation of the 'SYSNR' message
Christoffer Dall <[email protected]>
KVM: arm64: Only sign-extend MMIO up to register width
Mark Rutland <[email protected]>
KVM: arm/arm64: Correct AArch32 SPSR on exception entry
Mark Rutland <[email protected]>
KVM: arm/arm64: Correct CPSR on exception entry
Mark Rutland <[email protected]>
KVM: arm64: Correct PSTATE on exception entry
Mark Rutland <[email protected]>
arm64: acpi: fix DAIF manipulation with pNMI
Yong Zhi <[email protected]>
ALSA: hda: Add JasperLake PCI ID and codec vid
Hans de Goede <[email protected]>
ALSA: hda: Add Clevo W65_67SB the power_save blacklist
Takashi Iwai <[email protected]>
ALSA: hda: Apply aligned MMIO access only conditionally
Mika Westerberg <[email protected]>
platform/x86: intel_scu_ipc: Fix interrupt support
Pawan Gupta <[email protected]>
x86/cpu: Update cached HLE state on write to TSX_CTRL_CPUID_CLEAR
Kevin Hao <[email protected]>
irqdomain: Fix a memory leak in irq_domain_push_irq()
Gustavo A. R. Silva <[email protected]>
lib/test_kasan.c: fix memory leak in kmalloc_oob_krealloc_more()
Helen Koike <[email protected]>
media: v4l2-rect.h: fix v4l2_rect_map_inside() top/left adjustments
Arnd Bergmann <[email protected]>
media: v4l2-core: compat: ignore native command codes
John Hubbard <[email protected]>
media/v4l2-core: set pages dirty upon releasing DMA buffers
Yang Shi <[email protected]>
mm: move_pages: report the number of non-attempted pages
Wei Yang <[email protected]>
mm: thp: don't need care deferred split queue in memcg charge move path
Dan Williams <[email protected]>
mm/memory_hotplug: fix remove_memory() lockdep splat
Amir Goldstein <[email protected]>
utimes: Clamp the timestamps in notify_change()
zhengbin <[email protected]>
mmc: sdhci-pci: Make function amd_sdhci_reset static
Pingfan Liu <[email protected]>
mm/sparse.c: reset section's mem_map when fully deactivated
Theodore Ts'o <[email protected]>
memcg: fix a crash in wb_workfn when a device disappears
Takashi Iwai <[email protected]>
ALSA: dummy: Fix PCM format loop in proc output
Takashi Iwai <[email protected]>
ALSA: usb-audio: Annotate endianess in Scarlett gen2 quirk
Takashi Iwai <[email protected]>
ALSA: usb-audio: Fix endianess in descriptor validation
Bryan O'Donoghue <[email protected]>
usb: gadget: f_ecm: Use atomic_t to track in-flight request
Bryan O'Donoghue <[email protected]>
usb: gadget: f_ncm: Use atomic_t to track in-flight request
Roger Quadros <[email protected]>
usb: gadget: legacy: set max_speed to super-speed
Peter Chen <[email protected]>
usb: gadget: f_fs: set req->num_sgs as 0 for non-sg transfer
Olof Johansson <[email protected]>
objtool: Silence build output
Jun Li <[email protected]>
usb: typec: tcpci: mask event interrupts when remove driver
Thinh Nguyen <[email protected]>
usb: dwc3: gadget: Delay starting transfer
Thinh Nguyen <[email protected]>
usb: dwc3: gadget: Check END_TRANSFER completion
Navid Emamdoost <[email protected]>
brcmfmac: Fix memory leak in brcmf_usbdev_qinit
Kai-Heng Feng <[email protected]>
Bluetooth: btusb: Disable runtime suspend on Realtek devices
Colin Ian King <[email protected]>
Bluetooth: btusb: fix memory leak on fw
Israel Rukshin <[email protected]>
nvmet: Fix controller use after free
Israel Rukshin <[email protected]>
nvmet: Fix error print message at nvmet_install_queue function
Paul E. McKenney <[email protected]>
rcu: Use READ_ONCE() for ->expmask in rcu_read_unlock_special()
Paul E. McKenney <[email protected]>
srcu: Apply *_ONCE() to ->srcu_last_gp_end
Eric Dumazet <[email protected]>
rcu: Avoid data-race in rcu_gp_fqs_check_wake()
Paul E. McKenney <[email protected]>
rcu: Use *_ONCE() to protect lockless ->expmask accesses
Mathieu Desnoyers <[email protected]>
tracing: Fix sched switch start/stop refcount racy updates
Steven Rostedt (VMware) <[email protected]>
tracing/kprobes: Have uname use __get_str() in print_fmt
Lu Shuaibing <[email protected]>
ipc/msg.c: consolidate all xxxctl_down() functions
Kadlecsik József <[email protected]>
netfilter: ipset: fix suspicious RCU usage in find_set_and_id
Oliver Neukum <[email protected]>
mfd: dln2: More sanity checking for endpoints
Will Deacon <[email protected]>
media: uvcvideo: Avoid cyclic entity chains due to malformed USB descriptors
Vasundhara Volam <[email protected]>
bnxt_en: Fix logic that disables Bus Master during firmware reset.
Taehee Yoo <[email protected]>
netdevsim: fix stack-out-of-bounds in nsim_dev_debugfs_init()
Lukas Bulwahn <[email protected]>
MAINTAINERS: correct entries for ISDN/mISDN section
Shannon Nelson <[email protected]>
ionic: fix rxq comp packet type mask
Eric Dumazet <[email protected]>
tcp: clear tp->segs_{in|out} in tcp_disconnect()Eric Dumazet <[email protected]>
tcp: clear tp->data_segs{in|out} in tcp_disconnect()Eric Dumazet <[email protected]>
tcp: clear tp->delivered in tcp_disconnect()
Eric Dumazet <[email protected]>
tcp: clear tp->total_retrans in tcp_disconnect()
David Howells <[email protected]>
rxrpc: Fix NULL pointer deref due to call->conn being cleared on disconnect
David Howells <[email protected]>
rxrpc: Fix missing active use pinning of rxrpc_local object
David Howells <[email protected]>
rxrpc: Fix insufficient receive notification generation
David Howells <[email protected]>
rxrpc: Fix use-after-free in rxrpc_put_local()
Michael Chan <[email protected]>
bnxt_en: Fix TC queue mapping.
Nicolin Chen <[email protected]>
net: stmmac: Delete txtimer in suspend()
Cong Wang <[email protected]>
net_sched: fix an OOB access in cls_tcindex
Eric Dumazet <[email protected]>
net: hsr: fix possible NULL deref in hsr_handle_frame()
Ridge Kennedy <[email protected]>
l2tp: Allow duplicate session creation with UDP
Taehee Yoo <[email protected]>
gtp: use __GFP_NOWARN to avoid memalloc warning
Eric Dumazet <[email protected]>
cls_rsvp: fix rsvp_policy
Vasundhara Volam <[email protected]>
bnxt_en: Move devlink_register before registering netdev
Arnd Bergmann <[email protected]>
sparc32: fix struct ipc64_perm type definition
-------------
Diffstat:
MAINTAINERS | 6 +- Makefile | 4 +- arch/Kconfig | 3 - arch/arm/include/asm/kvm_emulate.h | 22 ++ arch/arm/include/asm/kvm_mmio.h | 2 + arch/arm/mach-tegra/sleep-tegra30.S | 11 + arch/arm/mm/dma-mapping.c | 2 +- arch/arm64/boot/dts/qcom/qcs404-evb.dtsi | 1 + arch/arm64/crypto/ghash-ce-glue.c | 2 +- arch/arm64/include/asm/daifflags.h | 11 +- arch/arm64/include/asm/kvm_emulate.h | 37 ++ arch/arm64/include/asm/kvm_mmio.h | 6 +- arch/arm64/include/asm/ptrace.h | 1 + arch/arm64/include/uapi/asm/ptrace.h | 1 + arch/arm64/kernel/acpi.c | 2 +- arch/arm64/kvm/inject_fault.c | 70 +++- arch/mips/Makefile.postlink | 2 +- arch/mips/boot/Makefile | 2 +- arch/mips/kernel/syscalls/Makefile | 2 +- arch/powerpc/Kconfig | 4 +- arch/powerpc/boot/4xx.c | 2 +- arch/powerpc/include/asm/book3s/32/kup.h | 22 +- arch/powerpc/include/asm/book3s/32/pgalloc.h | 8 - arch/powerpc/include/asm/book3s/64/kup-radix.h | 14 +- arch/powerpc/include/asm/book3s/64/pgalloc.h | 2 - arch/powerpc/include/asm/futex.h | 10 +- arch/powerpc/include/asm/kup.h | 36 +- arch/powerpc/include/asm/nohash/32/kup-8xx.h | 7 +- arch/powerpc/include/asm/nohash/pgalloc.h | 8 - arch/powerpc/include/asm/tlb.h | 11 + arch/powerpc/include/asm/uaccess.h | 4 +- arch/powerpc/kernel/entry_32.S | 3 +- arch/powerpc/kvm/book3s_hv.c | 4 +- arch/powerpc/kvm/book3s_pr.c | 4 +- arch/powerpc/kvm/book3s_xive_native.c | 2 +- arch/powerpc/mm/book3s64/pgtable.c | 7 - arch/powerpc/mm/fault.c | 2 +- arch/powerpc/mm/ptdump/ptdump.c | 4 +- arch/powerpc/platforms/pseries/hotplug-memory.c | 4 +- arch/powerpc/xmon/xmon.c | 9 +- arch/riscv/net/bpf_jit_comp.c | 13 +- arch/s390/include/asm/page.h | 2 + arch/s390/kvm/kvm-s390.c | 6 +- arch/s390/mm/hugetlbpage.c | 100 ++++- arch/sparc/Kconfig | 1 - arch/sparc/include/asm/tlb_64.h | 9 + arch/sparc/include/uapi/asm/ipcbuf.h | 22 +- arch/x86/include/asm/apic.h | 10 + arch/x86/include/asm/kvm_host.h | 13 +- arch/x86/include/asm/x86_init.h | 2 + arch/x86/kernel/apic/apic.c | 23 +- arch/x86/kernel/apic/msi.c | 128 +++++- arch/x86/kernel/cpu/tsx.c | 13 +- arch/x86/kernel/time.c | 12 +- arch/x86/kernel/x86_init.c | 1 + arch/x86/kvm/cpuid.c | 4 +- arch/x86/kvm/emulate.c | 66 +++- arch/x86/kvm/hyperv.c | 10 +- arch/x86/kvm/i8259.c | 6 +- arch/x86/kvm/ioapic.c | 15 +- arch/x86/kvm/lapic.c | 13 +- arch/x86/kvm/mmu.c | 107 ++--- arch/x86/kvm/mmutrace.h | 12 +- arch/x86/kvm/mtrr.c | 8 +- arch/x86/kvm/paging_tmpl.h | 25 +- arch/x86/kvm/pmu.h | 18 +- arch/x86/kvm/svm.c | 6 + arch/x86/kvm/vmx/capabilities.h | 5 + arch/x86/kvm/vmx/nested.c | 4 +- arch/x86/kvm/vmx/pmu_intel.c | 24 +- arch/x86/kvm/vmx/vmx.c | 3 + arch/x86/kvm/x86.c | 196 +++++++--- arch/x86/kvm/x86.h | 2 +- arch/x86/xen/enlighten_pv.c | 1 + crypto/algapi.c | 46 ++- crypto/api.c | 7 +- crypto/internal.h | 1 - crypto/pcrypt.c | 37 +- drivers/acpi/battery.c | 75 +++- drivers/acpi/video_detect.c | 13 + drivers/base/power/main.c | 42 +- drivers/bluetooth/btusb.c | 6 +- drivers/clk/tegra/clk-tegra-periph.c | 6 +- drivers/cpufreq/cppc_cpufreq.c | 2 +- drivers/cpufreq/cpufreq-nforce2.c | 2 +- drivers/cpufreq/cpufreq.c | 147 ++++--- drivers/cpufreq/freq_table.c | 4 +- drivers/cpufreq/gx-suspmod.c | 2 +- drivers/cpufreq/intel_pstate.c | 38 +- drivers/cpufreq/longrun.c | 6 +- drivers/cpufreq/pcc-cpufreq.c | 2 +- drivers/cpufreq/sh-cpufreq.c | 2 +- drivers/cpufreq/unicore2-cpufreq.c | 2 +- drivers/crypto/atmel-aes.c | 37 +- drivers/crypto/ccp/ccp-dev-v3.c | 1 + drivers/crypto/ccree/cc_aead.c | 2 +- drivers/crypto/ccree/cc_cipher.c | 48 ++- drivers/crypto/ccree/cc_driver.h | 1 + drivers/crypto/ccree/cc_pm.c | 30 +- drivers/crypto/ccree/cc_request_mgr.c | 51 +-- drivers/crypto/ccree/cc_request_mgr.h | 8 - drivers/crypto/hisilicon/Kconfig | 1 - drivers/crypto/hisilicon/zip/zip.h | 4 + drivers/crypto/hisilicon/zip/zip_crypto.c | 92 ++--- drivers/crypto/picoxcell_crypto.c | 15 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 13 +- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 18 +- drivers/gpu/drm/drm_dp_mst_topology.c | 12 + drivers/gpu/drm/drm_rect.c | 7 +- drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c | 2 +- drivers/hv/hv_balloon.c | 13 +- drivers/infiniband/core/umem_odp.c | 2 +- drivers/infiniband/hw/mlx5/gsi.c | 3 +- drivers/md/bcache/bcache.h | 3 + drivers/md/bcache/request.c | 17 +- drivers/md/bcache/sysfs.c | 22 ++ drivers/md/dm-crypt.c | 12 +- drivers/md/dm-thin-metadata.c | 10 +- drivers/md/dm-writecache.c | 42 +- drivers/md/dm-zoned-metadata.c | 23 +- drivers/md/dm.c | 9 +- drivers/md/persistent-data/dm-space-map-common.c | 27 ++ drivers/md/persistent-data/dm-space-map-common.h | 2 + drivers/md/persistent-data/dm-space-map-disk.c | 6 +- drivers/md/persistent-data/dm-space-map-metadata.c | 5 +- drivers/media/rc/iguanair.c | 2 +- drivers/media/rc/rc-main.c | 27 +- drivers/media/usb/uvc/uvc_driver.c | 12 + drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 148 +++---- drivers/media/v4l2-core/videobuf-dma-sg.c | 5 +- drivers/mfd/axp20x.c | 2 +- drivers/mfd/da9062-core.c | 2 +- drivers/mfd/dln2.c | 13 +- drivers/mfd/rn5t618.c | 1 + drivers/mmc/host/mmc_spi.c | 11 +- drivers/mmc/host/sdhci-of-at91.c | 9 +- drivers/mmc/host/sdhci-pci-core.c | 2 +- drivers/mtd/spi-nor/spi-nor.c | 9 +- drivers/mtd/ubi/fastmap.c | 23 +- drivers/net/bonding/bond_alb.c | 44 ++- drivers/net/dsa/b53/b53_common.c | 2 +- drivers/net/dsa/bcm_sf2.c | 4 +- drivers/net/dsa/microchip/ksz9477_spi.c | 6 + drivers/net/ethernet/broadcom/bcmsysport.c | 3 + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 25 +- drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 1 - drivers/net/ethernet/cadence/macb_main.c | 14 +- drivers/net/ethernet/dec/tulip/dmfe.c | 7 +- drivers/net/ethernet/dec/tulip/uli526x.c | 4 +- drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 14 +- drivers/net/ethernet/marvell/mvneta.c | 27 +- .../net/ethernet/mellanox/mlx5/core/accel/tls.h | 2 +- .../mellanox/mlx5/core/en_accel/tls_rxtx.c | 2 +- .../net/ethernet/mellanox/mlx5/core/fpga/ipsec.c | 3 +- drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 15 +- drivers/net/ethernet/mellanox/mlx5/core/fw.c | 2 +- drivers/net/ethernet/pensando/ionic/ionic_if.h | 2 +- drivers/net/ethernet/qlogic/qed/qed_ptp.c | 4 +- drivers/net/ethernet/smsc/smc911x.c | 2 +- .../ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 1 + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 + drivers/net/gtp.c | 4 +- drivers/net/netdevsim/dev.c | 2 +- drivers/net/ppp/ppp_async.c | 18 +- .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 1 + drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 10 +- drivers/net/wireless/marvell/mwifiex/sta_ioctl.c | 1 + drivers/nfc/pn544/pn544.c | 2 +- drivers/nvme/target/fabrics-cmd.c | 15 +- drivers/nvmem/core.c | 8 +- drivers/of/Kconfig | 4 + drivers/of/address.c | 6 +- drivers/pci/controller/dwc/pci-keystone.c | 6 +- drivers/pci/controller/pci-tegra.c | 2 +- drivers/phy/qualcomm/phy-qcom-apq8064-sata.c | 2 +- drivers/platform/x86/intel_scu_ipc.c | 21 +- drivers/power/supply/axp20x_ac_power.c | 31 +- drivers/power/supply/ltc2941-battery-gauge.c | 2 +- drivers/regulator/helpers.c | 14 + drivers/scsi/csiostor/csio_scsi.c | 2 +- drivers/scsi/megaraid/megaraid_sas_base.c | 3 +- drivers/scsi/megaraid/megaraid_sas_fusion.c | 3 +- drivers/scsi/megaraid/megaraid_sas_fusion.h | 1 + drivers/scsi/qla2xxx/qla_dbg.c | 6 - drivers/scsi/qla2xxx/qla_dbg.h | 6 + drivers/scsi/qla2xxx/qla_def.h | 5 + drivers/scsi/qla2xxx/qla_init.c | 34 +- drivers/scsi/qla2xxx/qla_isr.c | 12 + drivers/scsi/qla2xxx/qla_mbx.c | 3 +- drivers/scsi/qla2xxx/qla_nx.c | 7 +- drivers/scsi/qla2xxx/qla_target.c | 1 + drivers/scsi/qla4xxx/ql4_os.c | 2 +- drivers/scsi/ufs/ufshcd.c | 3 + drivers/usb/dwc3/core.h | 2 + drivers/usb/dwc3/ep0.c | 4 +- drivers/usb/dwc3/gadget.c | 17 +- drivers/usb/gadget/function/f_ecm.c | 16 +- drivers/usb/gadget/function/f_fs.c | 2 + drivers/usb/gadget/function/f_ncm.c | 17 +- drivers/usb/gadget/legacy/cdc2.c | 2 +- drivers/usb/gadget/legacy/g_ffs.c | 2 +- drivers/usb/gadget/legacy/multi.c | 2 +- drivers/usb/gadget/legacy/ncm.c | 2 +- drivers/usb/typec/tcpm/tcpci.c | 6 + drivers/virtio/virtio_balloon.c | 19 +- drivers/virtio/virtio_pci_common.c | 2 +- drivers/watchdog/watchdog_core.c | 35 ++ drivers/watchdog/watchdog_dev.c | 36 +- drivers/xen/xen-balloon.c | 2 +- fs/aio.c | 20 +- fs/attr.c | 23 +- fs/btrfs/ctree.c | 8 +- fs/btrfs/ctree.h | 6 +- fs/btrfs/delayed-ref.c | 8 +- fs/btrfs/disk-io.c | 22 +- fs/btrfs/extent_io.c | 55 ++- fs/btrfs/ioctl.c | 3 +- fs/btrfs/tests/btrfs-tests.c | 1 - fs/btrfs/tests/extent-io-tests.c | 9 + fs/btrfs/transaction.c | 30 +- fs/btrfs/tree-log.c | 432 +++++++-------------- fs/btrfs/volumes.c | 17 +- fs/cifs/readdir.c | 3 +- fs/cifs/smb2pdu.c | 10 +- fs/configfs/inode.c | 9 +- fs/crypto/keyring.c | 15 +- fs/erofs/decompressor.c | 22 +- fs/eventfd.c | 15 + fs/ext2/super.c | 6 +- fs/ext4/dir.c | 9 +- fs/ext4/page-io.c | 19 +- fs/f2fs/dir.c | 11 +- fs/f2fs/file.c | 18 +- fs/f2fs/super.c | 14 +- fs/fs-writeback.c | 2 +- fs/fuse/file.c | 5 +- fs/gfs2/file.c | 72 ++-- fs/gfs2/lops.c | 2 +- fs/jbd2/journal.c | 1 + fs/nfs/dir.c | 47 ++- fs/nfsd/filecache.c | 6 + fs/nfsd/nfs4layouts.c | 2 +- fs/nfsd/nfs4state.c | 2 +- fs/nfsd/state.h | 2 +- fs/nfsd/vfs.c | 1 + fs/ntfs/inode.c | 18 +- fs/ocfs2/file.c | 14 +- fs/overlayfs/file.c | 2 +- fs/overlayfs/readdir.c | 8 +- fs/read_write.c | 10 +- fs/ubifs/dir.c | 2 + fs/ubifs/file.c | 22 +- fs/ubifs/ioctl.c | 3 +- fs/ubifs/sb.c | 2 +- fs/ubifs/super.c | 2 + fs/utimes.c | 4 +- include/asm-generic/tlb.h | 22 +- include/linux/backing-dev.h | 10 + include/linux/cpufreq.h | 32 +- include/linux/eventfd.h | 14 + include/linux/irq.h | 18 + include/linux/irqdomain.h | 7 + include/linux/kvm_host.h | 13 +- include/linux/kvm_types.h | 9 +- include/linux/mfd/rohm-bd70528.h | 2 +- include/linux/mlx5/mlx5_ifc.h | 7 +- include/linux/padata.h | 34 +- include/linux/percpu-defs.h | 3 +- include/linux/regulator/consumer.h | 7 + include/media/v4l2-rect.h | 8 +- include/net/ipx.h | 5 - include/sound/hdaudio.h | 77 ++-- include/trace/events/writeback.h | 37 +- ipc/msg.c | 19 +- kernel/bpf/devmap.c | 3 +- kernel/events/core.c | 10 +- kernel/irq/debugfs.c | 1 + kernel/irq/irqdomain.c | 1 + kernel/irq/msi.c | 5 +- kernel/padata.c | 275 ++++++++----- kernel/rcu/srcutree.c | 7 +- kernel/rcu/tree_exp.h | 19 +- kernel/rcu/tree_plugin.h | 13 +- kernel/time/alarmtimer.c | 8 +- kernel/time/clocksource.c | 11 +- kernel/trace/ftrace.c | 15 +- kernel/trace/trace.h | 29 +- kernel/trace/trace_events_hist.c | 53 ++- kernel/trace/trace_probe.c | 6 +- kernel/trace/trace_sched_switch.c | 4 +- lib/test_kasan.c | 1 + mm/backing-dev.c | 1 + mm/memcontrol.c | 18 - mm/memory_hotplug.c | 9 +- mm/migrate.c | 25 +- mm/mmu_gather.c | 16 +- mm/page_alloc.c | 14 +- mm/sparse.c | 2 +- net/core/devlink.c | 6 + net/core/drop_monitor.c | 4 +- net/hsr/hsr_slave.c | 2 + net/ipv4/tcp.c | 6 + net/ipv6/addrconf.c | 3 + net/l2tp/l2tp_core.c | 7 +- net/netfilter/ipset/ip_set_core.c | 41 +- net/rxrpc/af_rxrpc.c | 2 + net/rxrpc/ar-internal.h | 11 + net/rxrpc/call_object.c | 4 +- net/rxrpc/conn_client.c | 3 +- net/rxrpc/conn_event.c | 30 +- net/rxrpc/conn_object.c | 3 +- net/rxrpc/input.c | 6 +- net/rxrpc/local_object.c | 23 +- net/rxrpc/output.c | 27 +- net/rxrpc/peer_event.c | 42 +- net/sched/cls_rsvp.h | 6 +- net/sched/cls_tcindex.c | 43 +- net/sched/sch_taprio.c | 92 +++-- net/sunrpc/auth_gss/svcauth_gss.c | 4 + samples/bpf/Makefile | 2 +- samples/bpf/xdp_redirect_cpu_user.c | 59 ++- scripts/find-unused-docs.sh | 2 +- security/smack/smack_lsm.c | 41 +- sound/drivers/dummy.c | 2 +- sound/pci/hda/hda_intel.c | 4 + sound/pci/hda/hda_tegra.c | 1 + sound/pci/hda/patch_hdmi.c | 1 + sound/soc/codecs/sgtl5000.c | 3 +- sound/soc/intel/boards/skl_hda_dsp_common.c | 21 +- sound/soc/meson/axg-fifo.c | 27 +- sound/soc/meson/axg-fifo.h | 6 +- sound/soc/meson/axg-frddr.c | 24 +- sound/soc/meson/axg-toddr.c | 21 +- sound/soc/sof/core.c | 87 +++-- sound/soc/sof/intel/hda-loader.c | 1 - sound/soc/sof/intel/hda.c | 4 +- sound/soc/sof/ipc.c | 17 +- sound/soc/sof/loader.c | 19 +- sound/soc/sof/pm.c | 25 +- sound/soc/sof/sof-priv.h | 11 +- sound/usb/mixer_scarlett_gen2.c | 46 +-- sound/usb/validate.c | 6 +- tools/kvm/kvm_stat/kvm_stat | 8 +- tools/lib/bpf/libbpf.c | 4 +- tools/objtool/sync-check.sh | 2 - tools/power/cpupower/lib/cpufreq.c | 78 +++- tools/power/cpupower/lib/cpufreq.h | 20 +- tools/power/cpupower/utils/cpufreq-info.c | 12 +- .../selftests/bpf/prog_tests/attach_probe.c | 7 +- .../testing/selftests/bpf/prog_tests/perf_buffer.c | 29 +- .../bpf/prog_tests/stacktrace_build_id_nmi.c | 8 +- .../bpf/progs/test_select_reuseport_kern.c | 6 + tools/testing/selftests/bpf/test_sockmap.c | 15 +- .../tc-testing/plugin-lib/buildebpfPlugin.py | 2 +- virt/kvm/arm/aarch32.c | 117 +++++- virt/kvm/arm/mmio.c | 6 + virt/kvm/async_pf.c | 10 +- virt/kvm/kvm_main.c | 117 +++++- 358 files changed, 3990 insertions(+), 2199 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/309 sparc32: fix struct ipc64_perm type definition
From: Arnd Bergmann <[email protected]>
[ Upstream commit 34ca70ef7d3a9fa7e89151597db5e37ae1d429b4 ]
As discussed in the strace issue tracker, it appears that the sparc32 sysvipc support has been broken for the past 11 years. It was however working in compat mode, which is how it must have escaped most of the regular testing.
The problem is that a cleanup patch inadvertently changed the uid/gid fields in struct ipc64_perm from 32-bit types to 16-bit types in uapi headers.
Both glibc and uclibc-ng still use the original types, so they should work fine with compat mode, but not natively. Change the definitions to use __kernel_uid32_t and __kernel_gid32_t again.
--- arch/sparc/include/uapi/asm/ipcbuf.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
arch/sparc/include/uapi/asm/ipcbuf.h +11 -11
@@ -15,19 +15,19 @@struct ipc64_perm { -__kernel_key_t key; -__kernel_uid_t uid; -__kernel_gid_t gid; -__kernel_uid_t cuid; -__kernel_gid_t cgid; +__kernel_key_t key; +__kernel_uid32_t uid; +__kernel_gid32_t gid; +__kernel_uid32_t cuid; +__kernel_gid32_t cgid;#ifndef __arch64__ -unsigned short __pad0; +unsigned short __pad0;#endif -__kernel_mode_t mode; -unsigned short __pad1; -unsigned short seq; -unsigned long long __unused1; -unsigned long long __unused2; +__kernel_mode_t mode; +unsigned short __pad1; +unsigned short seq; +unsigned long long __unused1; +unsigned long long __unused2; };#endif /* __SPARC_IPCBUF_H */
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 2/309 bnxt_en: Move devlink_register before registering netdev
In reply to Greg Kroah-HartmanFrom: Vasundhara Volam <[email protected]>
[ Upstream commit cda2cab0771183932d6ba73c5ac63bb63decdadf ]
Latest kernels get the phys_port_name via devlink, if ndo_get_phys_port_name is not defined. To provide the phys_port_name correctly, register devlink before registering netdev.
Also call devlink_port_type_eth_set() after registering netdev as devlink port updates the netdev structure and notifies user.
--- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 12 ++++++++---- drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 1 - 2 files changed, 8 insertions(+), 5 deletions(-)
drivers/net/ethernet/broadcom/bnxt/bnxt.c +8 -4
@@ -11359,9 +11359,9 @@ static void bnxt_remove_one(struct pci_dbnxt_sriov_disable (bp);bnxt_dl_fw_reporters_destroy (bp, true); -bnxt_dl_unregister (bp);pci_disable_pcie_error_reporting (pdev);unregister_netdev (dev); +bnxt_dl_unregister (bp);bnxt_shutdown_tc (bp);bnxt_cancel_sp_work (bp); bp->sp_event =0 ;
@@ -11850,11 +11850,14 @@ static int bnxt_init_one(struct pci_devbnxt_init_tc (bp); } +bnxt_dl_register (bp); + rc =register_netdev (dev);if (rc) - goto init_err_cleanup_tc; + goto init_err_cleanup; -bnxt_dl_register (bp); +if (BNXT_PF (bp)) +devlink_port_type_eth_set (&bp->dl_port, bp->dev);bnxt_dl_fw_reporters_create (bp); netdev_info(dev, "%s found at mem %lx, node addr %pM\n",
@@ -11864,7 +11867,8 @@ static int bnxt_init_one(struct pci_devreturn 0 ; -init_err_cleanup_tc: +init_err_cleanup: +bnxt_dl_unregister (bp);bnxt_shutdown_tc (bp);bnxt_clear_int_mode (bp);
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c +0 -1
@@ -482,7 +482,6 @@ int bnxt_dl_register(struct bnxt *bp)netdev_err (bp->dev,"devlink_port_register failed" ); goto err_dl_param_unreg; } -devlink_port_type_eth_set (&bp->dl_port, bp->dev); rc =devlink_port_params_register (&bp->dl_port, bnxt_dl_port_params,ARRAY_SIZE (bnxt_dl_port_params));
Greg Kroah-Hartman
maintainerPATCH 3/309 cls_rsvp: fix rsvp_policy
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
[ Upstream commit cb3c0e6bdf64d0d124e94ce43cbe4ccbb9b37f51 ]
NLA_BINARY can be confusing, since .len value represents the max size of the blob.
cls_rsvp really wants user space to provide long enough data for TCA_RSVP_DST and TCA_RSVP_SRC attributes.
BUG: KMSAN: uninit-value in rsvp_get net/sched/cls_rsvp.h:258 [inline] BUG: KMSAN: uninit-value in gen_handle net/sched/cls_rsvp.h:402 [inline] BUG: KMSAN: uninit-value in rsvp_change+0x1ae9/0x4220 net/sched/cls_rsvp.h:572 CPU: 1 PID: 13228 Comm: syz-executor.1 Not tainted 5.5.0-rc5-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x1c9/0x220 lib/dump_stack.c:118 kmsan_report+0xf7/0x1e0 mm/kmsan/kmsan_report.c:118 __msan_warning+0x58/0xa0 mm/kmsan/kmsan_instr.c:215 rsvp_get net/sched/cls_rsvp.h:258 [inline] gen_handle net/sched/cls_rsvp.h:402 [inline] rsvp_change+0x1ae9/0x4220 net/sched/cls_rsvp.h:572 tc_new_tfilter+0x31fe/0x5010 net/sched/cls_api.c:2104 rtnetlink_rcv_msg+0xcb7/0x1570 net/core/rtnetlink.c:5415 netlink_rcv_skb+0x451/0x650 net/netlink/af_netlink.c:2477 rtnetlink_rcv+0x50/0x60 net/core/rtnetlink.c:5442 netlink_unicast_kernel net/netlink/af_netlink.c:1302 [inline] netlink_unicast+0xf9e/0x1100 net/netlink/af_netlink.c:1328 netlink_sendmsg+0x1248/0x14d0 net/netlink/af_netlink.c:1917 sock_sendmsg_nosec net/socket.c:639 [inline] sock_sendmsg net/socket.c:659 [inline] ____sys_sendmsg+0x12b6/0x1350 net/socket.c:2330 ___sys_sendmsg net/socket.c:2384 [inline] __sys_sendmsg+0x451/0x5f0 net/socket.c:2417 __do_sys_sendmsg net/socket.c:2426 [inline] __se_sys_sendmsg+0x97/0xb0 net/socket.c:2424 __x64_sys_sendmsg+0x4a/0x70 net/socket.c:2424 do_syscall_64+0xb8/0x160 arch/x86/entry/common.c:296 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x45b349 Code: ad b6 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 7b b6 fb ff c3 66 2e 0f 1f 84 00 00 00 00 RSP: 002b:00007f269d43dc78 EFLAGS: 00000246 ORIG_RAX: 000000000000002e RAX: ffffffffffffffda RBX: 00007f269d43e6d4 RCX: 000000000045b349 RDX: 0000000000000000 RSI: 00000000200001c0 RDI: 0000000000000003 RBP: 000000000075bfc8 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 00000000ffffffff R13: 00000000000009c2 R14: 00000000004cb338 R15: 000000000075bfd4
Uninit was created at:
kmsan_save_stack_with_flags mm/kmsan/kmsan.c:144 [inline] kmsan_internal_poison_shadow+0x66/0xd0 mm/kmsan/kmsan.c:127 kmsan_slab_alloc+0x8a/0xe0 mm/kmsan/kmsan_hooks.c:82 slab_alloc_node mm/slub.c:2774 [inline] __kmalloc_node_track_caller+0xb40/0x1200 mm/slub.c:4382 __kmalloc_reserve net/core/skbuff.c:141 [inline] __alloc_skb+0x2fd/0xac0 net/core/skbuff.c:209 alloc_skb include/linux/skbuff.h:1049 [inline] netlink_alloc_large_skb net/netlink/af_netlink.c:1174 [inline] netlink_sendmsg+0x7d3/0x14d0 net/netlink/af_netlink.c:1892 sock_sendmsg_nosec net/socket.c:639 [inline] sock_sendmsg net/socket.c:659 [inline] ____sys_sendmsg+0x12b6/0x1350 net/socket.c:2330 ___sys_sendmsg net/socket.c:2384 [inline] __sys_sendmsg+0x451/0x5f0 net/socket.c:2417 __do_sys_sendmsg net/socket.c:2426 [inline] __se_sys_sendmsg+0x97/0xb0 net/socket.c:2424 __x64_sys_sendmsg+0x4a/0x70 net/socket.c:2424 do_syscall_64+0xb8/0x160 arch/x86/entry/common.c:296 entry_SYSCALL_64_after_hwframe+0x44/0xa9
--- net/sched/cls_rsvp.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
net/sched/cls_rsvp.h +2 -4
@@ -463,10 +463,8 @@ static u32 gen_tunnel(struct rsvp_head *static const struct nla_policy rsvp_policy[TCA_RSVP_MAX +1 ] = { [TCA_RSVP_CLASSID ] = { .type =NLA_U32 }, - [TCA_RSVP_DST ] = { .type =NLA_BINARY , - .len =RSVP_DST_LEN *sizeof (u32) }, - [TCA_RSVP_SRC ] = { .type =NLA_BINARY , - .len =RSVP_DST_LEN *sizeof (u32) }, + [TCA_RSVP_DST ] = { .len =RSVP_DST_LEN *sizeof (u32) }, + [TCA_RSVP_SRC ] = { .len =RSVP_DST_LEN *sizeof (u32) }, [TCA_RSVP_PINFO ] = { .len =sizeof (struct tc_rsvp_pinfo ) }, };
Greg Kroah-Hartman
maintainerPATCH 4/309 gtp: use __GFP_NOWARN to avoid memalloc warning
In reply to Greg Kroah-HartmanFrom: Taehee Yoo <[email protected]>
[ Upstream commit bd5cd35b782abf5437fbd01dfaee12437d20e832 ]
gtp hashtable size is received by user-space.
So, this hashtable size could be too large. If so, kmalloc will internally print a warning message.
This warning message is actually not necessary for the gtp module. So, this patch adds __GFP_NOWARN to avoid this message.
Splat looks like:
[ 2171.200049][ T1860] WARNING: CPU: 1 PID: 1860 at mm/page_alloc.c:4713 __alloc_pages_nodemask+0x2f3/0x740 [ 2171.238885][ T1860] Modules linked in: gtp veth openvswitch nsh nf_conncount nf_nat nf_conntrack nf_defrag_ipv] [ 2171.262680][ T1860] CPU: 1 PID: 1860 Comm: gtp-link Not tainted 5.5.0+ #321 [ 2171.263567][ T1860] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 [ 2171.264681][ T1860] RIP: 0010:__alloc_pages_nodemask+0x2f3/0x740 [ 2171.265332][ T1860] Code: 64 fe ff ff 65 48 8b 04 25 c0 0f 02 00 48 05 f0 12 00 00 41 be 01 00 00 00 49 89 47 0 [ 2171.267301][ T1860] RSP: 0018:ffff8880b51af1f0 EFLAGS: 00010246 [ 2171.268320][ T1860] RAX: ffffed1016a35e43 RBX: 0000000000000000 RCX: 0000000000000000 [ 2171.269517][ T1860] RDX: 0000000000000000 RSI: 000000000000000b RDI: 0000000000000000 [ 2171.270305][ T1860] RBP: 0000000000040cc0 R08: ffffed1018893109 R09: dffffc0000000000 [ 2171.275973][ T1860] R10: 0000000000000001 R11: ffffed1018893108 R12: 1ffff11016a35e43 [ 2171.291039][ T1860] R13: 000000000000000b R14: 000000000000000b R15: 00000000000f4240 [ 2171.292328][ T1860] FS: 00007f53cbc83740(0000) GS:ffff8880da000000(0000) knlGS:0000000000000000 [ 2171.293409][ T1860] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 2171.294586][ T1860] CR2: 000055f540014508 CR3: 00000000b49f2004 CR4: 00000000000606e0 [ 2171.295424][ T1860] Call Trace: [ 2171.295756][ T1860] ? mark_held_locks+0xa5/0xe0 [ 2171.296659][ T1860] ? __alloc_pages_slowpath+0x21b0/0x21b0 [ 2171.298283][ T1860] ? gtp_encap_enable_socket+0x13e/0x400 [gtp] [ 2171.298962][ T1860] ? alloc_pages_current+0xc1/0x1a0 [ 2171.299475][ T1860] kmalloc_order+0x22/0x80 [ 2171.299936][ T1860] kmalloc_order_trace+0x1d/0x140 [ 2171.300437][ T1860] __kmalloc+0x302/0x3a0 [ 2171.300896][ T1860] gtp_newlink+0x293/0xba0 [gtp]
[ ... ]
--- drivers/net/gtp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/gtp.c +2 -2
@@ -767,12 +767,12 @@ static int gtp_hashtable_new(struct gtp_int i; gtp->addr_hash =kmalloc_array (hsize,sizeof (struct hlist_head ), -GFP_KERNEL ); +GFP_KERNEL | __GFP_NOWARN);if (gtp->addr_hash ==NULL )return -ENOMEM ; gtp->tid_hash =kmalloc_array (hsize,sizeof (struct hlist_head ), -GFP_KERNEL ); +GFP_KERNEL | __GFP_NOWARN);if (gtp->tid_hash ==NULL ) goto err1;
Greg Kroah-Hartman
maintainerPATCH 5/309 l2tp: Allow duplicate session creation with UDP
In reply to Greg Kroah-HartmanFrom: Ridge Kennedy <[email protected]>
[ Upstream commit 0d0d9a388a858e271bb70e71e99e7fe2a6fd6f64 ]
In the past it was possible to create multiple L2TPv3 sessions with the same session id as long as the sessions belonged to different tunnels. The resulting sessions had issues when used with IP encapsulated tunnels, but worked fine with UDP encapsulated ones. Some applications began to rely on this behaviour to avoid having to negotiate unique session ids.
Some time ago a change was made to require session ids to be unique across all tunnels, breaking the applications making use of this "feature".
This change relaxes the duplicate session id check to allow duplicates if both of the colliding sessions belong to UDP encapsulated tunnels.
--- net/l2tp/l2tp_core.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
net/l2tp/l2tp_core.c +6 -1
@@ -322,8 +322,13 @@ int l2tp_session_register(struct l2tp_sespin_lock_bh (&pn->l2tp_session_hlist_lock); +/* IP encap expects session IDs to be globally unique, while +* UDP encap doesn't. +*/ hlist_for_each_entry (session_walk, g_head, global_hlist) -if (session_walk->session_id == session->session_id) { +if (session_walk->session_id == session->session_id && + (session_walk->tunnel->encap ==L2TP_ENCAPTYPE_IP || + tunnel->encap ==L2TP_ENCAPTYPE_IP )) { err = -EEXIST ; goto err_tlock_pnlock; }
Greg Kroah-Hartman
maintainerPATCH 6/309 net: hsr: fix possible NULL deref in hsr_handle_frame()
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
[ Upstream commit 2b5b8251bc9fe2f9118411f037862ee17cf81e97 ]
hsr_port_get_rcu() can return NULL, so we need to be careful.
general protection fault, probably for non-canonical address 0xdffffc0000000006: 0000 [#1] PREEMPT SMP KASAN KASAN: null-ptr-deref in range [0x0000000000000030-0x0000000000000037] CPU: 1 PID: 10249 Comm: syz-executor.5 Not tainted 5.5.0-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 RIP: 0010:__read_once_size include/linux/compiler.h:199 [inline] RIP: 0010:hsr_addr_is_self+0x86/0x330 net/hsr/hsr_framereg.c:44 Code: 04 00 f3 f3 f3 65 48 8b 04 25 28 00 00 00 48 89 45 d0 31 c0 e8 6b ff 94 f9 4c 89 f2 48 b8 00 00 00 00 00 fc ff df 48 c1 ea 03 <80> 3c 02 00 0f 85 75 02 00 00 48 8b 43 30 49 39 c6 49 89 47 c0 0f RSP: 0018:ffffc90000da8a90 EFLAGS: 00010206 RAX: dffffc0000000000 RBX: 0000000000000000 RCX: ffffffff87e0cc33 RDX: 0000000000000006 RSI: ffffffff87e035d5 RDI: 0000000000000000 RBP: ffffc90000da8b20 R08: ffff88808e7de040 R09: ffffed1015d2707c R10: ffffed1015d2707b R11: ffff8880ae9383db R12: ffff8880a689bc5e R13: 1ffff920001b5153 R14: 0000000000000030 R15: ffffc90000da8af8 FS: 00007fd7a42be700(0000) GS:ffff8880ae900000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000001b32338000 CR3: 00000000a928c000 CR4: 00000000001406e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: <IRQ> hsr_handle_frame+0x1c5/0x630 net/hsr/hsr_slave.c:31 __netif_receive_skb_core+0xfbc/0x30b0 net/core/dev.c:5099 __netif_receive_skb_one_core+0xa8/0x1a0 net/core/dev.c:5196 __netif_receive_skb+0x2c/0x1d0 net/core/dev.c:5312 process_backlog+0x206/0x750 net/core/dev.c:6144 napi_poll net/core/dev.c:6582 [inline] net_rx_action+0x508/0x1120 net/core/dev.c:6650 __do_softirq+0x262/0x98c kernel/softirq.c:292 do_softirq_own_stack+0x2a/0x40 arch/x86/entry/entry_64.S:1082 </IRQ>
--- net/hsr/hsr_slave.c | 2 ++ 1 file changed, 2 insertions(+)
net/hsr/hsr_slave.c +2 -0
@@ -27,6 +27,8 @@ static rx_handler_result_t hsr_handle_frrcu_read_lock ();/* hsr->node_db, hsr->ports */ port =hsr_port_get_rcu (skb->dev); +if (!port) + goto finish_pass;if (hsr_addr_is_self (port->hsr,eth_hdr (skb)->h_source)) {/* Directly kill frames sent by ourselves */
Greg Kroah-Hartman
maintainerPATCH 7/309 net_sched: fix an OOB access in cls_tcindex
In reply to Greg Kroah-HartmanFrom: Cong Wang <[email protected]>
[ Upstream commit 599be01ee567b61f4471ee8078870847d0a11e8e ]
As Eric noticed, tcindex_alloc_perfect_hash() uses cp->hash to compute the size of memory allocation, but cp->hash is set again after the allocation, this caused an out-of-bound access.
So we have to move all cp->hash initialization and computation before the memory allocation. Move cp->mask and cp->shift together as cp->hash may need them for computation too.
--- net/sched/cls_tcindex.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-)
net/sched/cls_tcindex.c +20 -20
@@ -333,12 +333,31 @@ tcindex_set_parms(struct net *net, struc cp->fall_through = p->fall_through; cp->tp = tp; +if (tb[TCA_TCINDEX_HASH ]) + cp->hash =nla_get_u32 (tb[TCA_TCINDEX_HASH ]); + +if (tb[TCA_TCINDEX_MASK ]) + cp->mask =nla_get_u16 (tb[TCA_TCINDEX_MASK ]); + +if (tb[TCA_TCINDEX_SHIFT ]) + cp->shift =nla_get_u32 (tb[TCA_TCINDEX_SHIFT ]); + +if (!cp->hash) { +/* Hash not specified, use perfect hash if the upper limit +* of the hashing index is below the threshold. +*/ +if ((cp->mask >> cp->shift) <PERFECT_HASH_THRESHOLD ) + cp->hash = (cp->mask >> cp->shift) +1 ; +else + cp->hash =DEFAULT_HASH_SIZE ; + } +if (p->perfect) {int i;if (tcindex_alloc_perfect_hash (net, cp) <0 ) goto errout; -for (i =0 ; i < cp->hash; i++) +for (i =0 ; i <min (cp->hash, p->hash); i++) cp->perfect[i].res = p->perfect[i].res; balloc =1 ; }
@@ -350,15 +369,6 @@ tcindex_set_parms(struct net *net, strucif (old_r) cr = r->res; -if (tb[TCA_TCINDEX_HASH ]) - cp->hash =nla_get_u32 (tb[TCA_TCINDEX_HASH ]); - -if (tb[TCA_TCINDEX_MASK ]) - cp->mask =nla_get_u16 (tb[TCA_TCINDEX_MASK ]); - -if (tb[TCA_TCINDEX_SHIFT ]) - cp->shift =nla_get_u32 (tb[TCA_TCINDEX_SHIFT ]); - err = -EBUSY ;/* Hash already allocated, make sure that we still meet the
@@ -376,16 +386,6 @@ tcindex_set_parms(struct net *net, strucif (tb[TCA_TCINDEX_FALL_THROUGH ]) cp->fall_through =nla_get_u32 (tb[TCA_TCINDEX_FALL_THROUGH ]); -if (!cp->hash) { -/* Hash not specified, use perfect hash if the upper limit -* of the hashing index is below the threshold. -*/ -if ((cp->mask >> cp->shift) <PERFECT_HASH_THRESHOLD ) - cp->hash = (cp->mask >> cp->shift) +1 ; -else - cp->hash =DEFAULT_HASH_SIZE ; - } -if (!cp->perfect && !cp->h) cp->alloc_hash = cp->hash;
Greg Kroah-Hartman
maintainerPATCH 8/309 net: stmmac: Delete txtimer in suspend()
In reply to Greg Kroah-HartmanFrom: Nicolin Chen <[email protected]>
[ Upstream commit 14b41a2959fbaa50932699d32ceefd6643abacc6 ]
When running v5.5 with a rootfs on NFS, memory abort may happen in the system resume stage:
Unable to handle kernel paging request at virtual address dead00000000012a [dead00000000012a] address between user and kernel address ranges pc : run_timer_softirq+0x334/0x3d8 lr : run_timer_softirq+0x244/0x3d8 x1 : ffff800011cafe80 x0 : dead000000000122 Call trace: run_timer_softirq+0x334/0x3d8 efi_header_end+0x114/0x234 irq_exit+0xd0/0xd8 __handle_domain_irq+0x60/0xb0 gic_handle_irq+0x58/0xa8 el1_irq+0xb8/0x180 arch_cpu_idle+0x10/0x18 do_idle+0x1d8/0x2b0 cpu_startup_entry+0x24/0x40 secondary_start_kernel+0x1b4/0x208 Code: f9000693 a9400660 f9000020 b4000040 (f9000401) ---[ end trace bb83ceeb4c482071 ]--- Kernel panic - not syncing: Fatal exception in interrupt SMP: stopping secondary CPUs SMP: failed to stop secondary CPUs 2-3 Kernel Offset: disabled CPU features: 0x00002,2300aa30 Memory Limit: none ---[ end Kernel panic - not syncing: Fatal exception in interrupt ]---
It's found that stmmac_xmit() and stmmac_resume() sometimes might run concurrently, possibly resulting in a race condition between mod_timer() and setup_timer(), being called by stmmac_xmit() and stmmac_resume() respectively.
Since the resume() runs setup_timer() every time, it'd be safer to have del_timer_sync() in the suspend() as the counterpart.
--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +4 -0
@@ -4763,6 +4763,7 @@ int stmmac_suspend(struct device *dev) {struct net_device *ndev =dev_get_drvdata (dev);struct stmmac_priv *priv =netdev_priv (ndev); +u32 chan;if (!ndev || !netif_running (ndev))return 0 ;
@@ -4776,6 +4777,9 @@ int stmmac_suspend(struct device *dev)stmmac_disable_all_queues (priv); +for (chan =0 ; chan < priv->plat->tx_queues_to_use; chan++) +del_timer_sync (&priv->tx_queue[chan].txtimer); +/* Stop TX/RX DMA */ stmmac_stop_all_dma (priv);
Greg Kroah-Hartman
maintainerPATCH 9/309 bnxt_en: Fix TC queue mapping.
In reply to Greg Kroah-HartmanFrom: Michael Chan <[email protected]>
[ Upstream commit 18e4960c18f484ac288f41b43d0e6c4c88e6ea78 ]
The driver currently only calls netdev_set_tc_queue when the number of TCs is greater than 1. Instead, the comparison should be greater than or equal to 1. Even with 1 TC, we need to set the queue mapping.
This bug can cause warnings when the number of TCs is changed back to 1.
--- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/broadcom/bnxt/bnxt.c +1 -1
@@ -7873,7 +7873,7 @@ static void bnxt_setup_msix(struct bnxtint tcs, i; tcs =netdev_get_num_tc (dev); -if (tcs >1 ) { +if (tcs) {int i, off, count;for (i =0 ; i < tcs; i++) {
Greg Kroah-Hartman
maintainerPATCH 10/309 rxrpc: Fix use-after-free in rxrpc_put_local()
In reply to Greg Kroah-HartmanFrom: David Howells <[email protected]>
[ Upstream commit fac20b9e738523fc884ee3ea5be360a321cd8bad ]
Fix rxrpc_put_local() to not access local->debug_id after calling atomic_dec_return() as, unless that returned n==0, we no longer have the right to access the object.
--- net/rxrpc/local_object.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
net/rxrpc/local_object.c +4 -1
@@ -364,11 +364,14 @@ void rxrpc_queue_local(struct rxrpc_locavoid rxrpc_put_local (struct rxrpc_local *local) {const void *here =__builtin_return_address (0 ); +unsigned int debug_id;int n;if (local) { + debug_id = local->debug_id; + n =atomic_dec_return (&local->usage); -trace_rxrpc_local (local->debug_id, rxrpc_local_put, n, here); +trace_rxrpc_local (debug_id, rxrpc_local_put, n, here);if (n ==0 )call_rcu (&local->rcu, rxrpc_local_rcu);
Greg Kroah-Hartman
maintainerPATCH 11/309 rxrpc: Fix insufficient receive notification generation
In reply to Greg Kroah-HartmanFrom: David Howells <[email protected]>
[ Upstream commit f71dbf2fb28489a79bde0dca1c8adfb9cdb20a6b ]
In rxrpc_input_data(), rxrpc_notify_socket() is called if the base sequence number of the packet is immediately following the hard-ack point at the end of the function. However, this isn't sufficient, since the recvmsg side may have been advancing the window and then overrun the position in which we're adding - at which point rx_hard_ack >= seq0 and no notification is generated.
Fix this by always generating a notification at the end of the input function.
Without this, a long call may stall, possibly indefinitely.
--- net/rxrpc/input.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
net/rxrpc/input.c +2 -4
@@ -599,10 +599,8 @@ ack: false, true, rxrpc_propose_ack_input_data); -if (seq0 ==READ_ONCE (call->rx_hard_ack) +1 ) { -trace_rxrpc_notify_socket (call->debug_id, serial); -rxrpc_notify_socket (call); - } +trace_rxrpc_notify_socket (call->debug_id, serial); +rxrpc_notify_socket (call); unlock:spin_unlock (&call->input_lock);
Greg Kroah-Hartman
maintainerPATCH 12/309 rxrpc: Fix missing active use pinning of rxrpc_local object
In reply to Greg Kroah-HartmanFrom: David Howells <[email protected]>
[ Upstream commit 04d36d748fac349b068ef621611f454010054c58 ]
The introduction of a split between the reference count on rxrpc_local objects and the usage count didn't quite go far enough. A number of kernel work items need to make use of the socket to perform transmission. These also need to get an active count on the local object to prevent the socket from being closed.
Fix this by getting the active count in those places.
Also split out the raw active count get/put functions as these places tend to hold refs on the rxrpc_local object already, so getting and putting an extra object ref is just a waste of time.
The problem can lead to symptoms like:
BUG: kernel NULL pointer dereference, address: 0000000000000018
..
CPU: 2 PID: 818 Comm: kworker/u9:0 Not tainted 5.5.0-fscache+ #51
...
RIP: 0010:selinux_socket_sendmsg+0x5/0x13
...
Call Trace:
security_socket_sendmsg+0x2c/0x3e
sock_sendmsg+0x1a/0x46
rxrpc_send_keepalive+0x131/0x1ae
rxrpc_peer_keepalive_worker+0x219/0x34b
process_one_work+0x18e/0x271
worker_thread+0x1a3/0x247
kthread+0xe6/0xeb
ret_from_fork+0x1f/0x30--- net/rxrpc/af_rxrpc.c | 2 ++ net/rxrpc/ar-internal.h | 10 ++++++++++ net/rxrpc/conn_event.c | 30 ++++++++++++++++++++---------- net/rxrpc/local_object.c | 18 +++++++----------- net/rxrpc/peer_event.c | 40 ++++++++++++++++++++++------------------ 5 files changed, 61 insertions(+), 39 deletions(-)
net/rxrpc/af_rxrpc.c +2 -0
@@ -194,6 +194,7 @@ static int rxrpc_bind(struct socket *soc service_in_use:write_unlock (&local->services_lock);rxrpc_unuse_local (local); +rxrpc_put_local (local); ret = -EADDRINUSE ; error_unlock:release_sock (&rx->sk);
@@ -899,6 +900,7 @@ static int rxrpc_release_sock(struct socrxrpc_purge_queue (&sk->sk_receive_queue);rxrpc_unuse_local (rx->local); +rxrpc_put_local (rx->local); rx->local =NULL ;key_put (rx->key); rx->key =NULL ;
net/rxrpc/ar-internal.h +10 -0
@@ -1021,6 +1021,16 @@ void rxrpc_unuse_local(struct rxrpc_locavoid rxrpc_queue_local (struct rxrpc_local *);void rxrpc_destroy_all_locals (struct rxrpc_net *); +static inline bool __rxrpc_unuse_local (struct rxrpc_local *local) +{ +return atomic_dec_return (&local->active_users) ==0 ; +} + +static inline bool __rxrpc_use_local (struct rxrpc_local *local) +{ +return atomic_fetch_add_unless (&local->active_users,1 ,0 ) !=0 ; +} +/* * misc.c */
net/rxrpc/conn_event.c +20 -10
@@ -438,16 +438,12 @@ again:/* * connection-level event processor */ -void rxrpc_process_connection (struct work_struct *work) +static void rxrpc_do_process_connection (struct rxrpc_connection *conn) { -struct rxrpc_connection *conn = - container_of(work, struct rxrpc_connection, processor);struct sk_buff *skb;u32 abort_code =RX_PROTOCOL_ERROR ;int ret; -rxrpc_see_connection (conn); -if (test_and_clear_bit (RXRPC_CONN_EV_CHALLENGE , &conn->events))rxrpc_secure_connection (conn);
@@ -475,18 +471,32 @@ void rxrpc_process_connection(struct wor } } -out: -rxrpc_put_connection (conn); -_leave ("" );return ; requeue_and_leave:skb_queue_head (&conn->rx_queue, skb); - goto out; +return ; protocol_error:if (rxrpc_abort_connection (conn, ret, abort_code) <0 ) goto requeue_and_leave;rxrpc_free_skb (skb, rxrpc_skb_freed); - goto out; +return ; +} + +void rxrpc_process_connection (struct work_struct *work) +{ +struct rxrpc_connection *conn = + container_of(work, struct rxrpc_connection, processor); + +rxrpc_see_connection (conn); + +if (__rxrpc_use_local (conn->params.local)) { +rxrpc_do_process_connection (conn); +rxrpc_unuse_local (conn->params.local); + } + +rxrpc_put_connection (conn); +_leave ("" ); +return ; }
net/rxrpc/local_object.c +7 -11
@@ -383,14 +383,11 @@ void rxrpc_put_local(struct rxrpc_local*/ struct rxrpc_local *rxrpc_use_local (struct rxrpc_local *local) { -unsigned int au; - local =rxrpc_get_local_maybe (local);if (!local)return NULL ; - au =atomic_fetch_add_unless (&local->active_users,1 ,0 ); -if (au ==0 ) { +if (!__rxrpc_use_local (local)) {rxrpc_put_local (local);return NULL ; }
@@ -404,14 +401,11 @@ struct rxrpc_local *rxrpc_use_local(stru*/ void rxrpc_unuse_local (struct rxrpc_local *local) { -unsigned int au; -if (local) { - au =atomic_dec_return (&local->active_users); -if (au ==0 ) +if (__rxrpc_unuse_local (local)) { +rxrpc_get_local (local);rxrpc_queue_local (local); -else -rxrpc_put_local (local); + } } }
@@ -468,7 +462,7 @@ static void rxrpc_local_processor(struct do { again = false; - if (atomic_read(&local->active_users) == 0) { + if (!__rxrpc_use_local(local)) { rxrpc_local_destroyer(local); break; }
@@ -482,6 +476,8 @@ static void rxrpc_local_processor(structrxrpc_process_local_events (local); again = true; } + +__rxrpc_unuse_local (local); }while (again);rxrpc_put_local (local);
net/rxrpc/peer_event.c +22 -18
@@ -364,27 +364,31 @@ static void rxrpc_peer_keepalive_dispatcif (!rxrpc_get_peer_maybe (peer))continue ; -spin_unlock_bh (&rxnet->peer_hash_lock); +if (__rxrpc_use_local (peer->local)) { +spin_unlock_bh (&rxnet->peer_hash_lock); - keepalive_at = peer->last_tx_at +RXRPC_KEEPALIVE_TIME ; - slot = keepalive_at - base; -_debug ("%02x peer %u t=%d {%pISp}" , - cursor, peer->debug_id, slot, &peer->srx.transport); + keepalive_at = peer->last_tx_at +RXRPC_KEEPALIVE_TIME ; + slot = keepalive_at - base; +_debug ("%02x peer %u t=%d {%pISp}" , + cursor, peer->debug_id, slot, &peer->srx.transport); -if (keepalive_at <= base || - keepalive_at > base +RXRPC_KEEPALIVE_TIME ) { -rxrpc_send_keepalive (peer); - slot =RXRPC_KEEPALIVE_TIME ; - } +if (keepalive_at <= base || + keepalive_at > base +RXRPC_KEEPALIVE_TIME ) { +rxrpc_send_keepalive (peer); + slot =RXRPC_KEEPALIVE_TIME ; + } -/* A transmission to this peer occurred since last we examined -* it so put it into the appropriate future bucket. -*/ - slot += cursor; - slot &= mask; -spin_lock_bh (&rxnet->peer_hash_lock); -list_add_tail (&peer->keepalive_link, - &rxnet->peer_keepalive[slot & mask]); +/* A transmission to this peer occurred since last we +* examined it so put it into the appropriate future +* bucket. +*/ + slot += cursor; + slot &= mask; +spin_lock_bh (&rxnet->peer_hash_lock); +list_add_tail (&peer->keepalive_link, + &rxnet->peer_keepalive[slot & mask]); +rxrpc_unuse_local (peer->local); + }rxrpc_put_peer_locked (peer); }
Greg Kroah-Hartman
maintainerPATCH 13/309 rxrpc: Fix NULL pointer deref due to call->conn being cleared on disconnect
In reply to Greg Kroah-HartmanFrom: David Howells <[email protected]>
[ Upstream commit 5273a191dca65a675dc0bcf3909e59c6933e2831 ]
When a call is disconnected, the connection pointer from the call is cleared to make sure it isn't used again and to prevent further attempted transmission for the call. Unfortunately, there might be a daemon trying to use it at the same time to transmit a packet.
Fix this by keeping call->conn set, but setting a flag on the call to indicate disconnection instead.
Remove also the bits in the transmission functions where the conn pointer is checked and a ref taken under spinlock as this is now redundant.
--- net/rxrpc/ar-internal.h | 1 + net/rxrpc/call_object.c | 4 ++-- net/rxrpc/conn_client.c | 3 +-- net/rxrpc/conn_object.c | 4 ++-- net/rxrpc/output.c | 27 +++++++++------------------ 5 files changed, 15 insertions(+), 24 deletions(-)
net/rxrpc/ar-internal.h +1 -0
@@ -490,6 +490,7 @@ enum rxrpc_call_flag {RXRPC_CALL_RX_HEARD ,/* The peer responded at least once to this call */ RXRPC_CALL_RX_UNDERRUN ,/* Got data underrun */ RXRPC_CALL_IS_INTR ,/* The call is interruptible */ + RXRPC_CALL_DISCONNECTED, /* The call has been disconnected */ };/*
net/rxrpc/call_object.c +2 -2
@@ -493,7 +493,7 @@ void rxrpc_release_call(struct rxrpc_soc_debug ("RELEASE CALL %p (%d CONN %p)" , call, call->debug_id, conn); -if (conn) +if (conn && !test_bit (RXRPC_CALL_DISCONNECTED , &call->flags))rxrpc_disconnect_call (call);if (call->security) call->security->free_call_crypto (call);
@@ -569,6 +569,7 @@ static void rxrpc_rcu_destroy_call(struc struct rxrpc_call *call = container_of(rcu, struct rxrpc_call, rcu);struct rxrpc_net *rxnet = call->rxnet; +rxrpc_put_connection (call->conn);rxrpc_put_peer (call->peer);kfree (call->rxtx_buffer);kfree (call->rxtx_annotations);
@@ -590,7 +591,6 @@ void rxrpc_cleanup_call(struct rxrpc_cal ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE);ASSERT (test_bit (RXRPC_CALL_RELEASED , &call->flags)); - ASSERTCMP(call->conn, ==, NULL);rxrpc_cleanup_ring (call);rxrpc_free_skb (call->tx_pending, rxrpc_skb_cleaned);
net/rxrpc/conn_client.c +1 -2
@@ -785,6 +785,7 @@ void rxrpc_disconnect_client_call(structu32 cid;spin_lock (&conn->channel_lock); +set_bit (RXRPC_CALL_DISCONNECTED , &call->flags); cid = call->cid;if (cid) {
@@ -792,7 +793,6 @@ void rxrpc_disconnect_client_call(struct chan = &conn->channels[channel]; }trace_rxrpc_client (conn, channel, rxrpc_client_chan_disconnect); - call->conn =NULL ;/* Calls that have never actually been assigned a channel can simply be * discarded. If the conn didn't get used either, it will follow
@@ -908,7 +908,6 @@ out:spin_unlock (&rxnet->client_conn_cache_lock); out_2:spin_unlock (&conn->channel_lock); -rxrpc_put_connection (conn);_leave ("" );return ;
net/rxrpc/conn_object.c +2 -2
@@ -171,6 +171,8 @@ void __rxrpc_disconnect_call(struct rxrp_enter ("%d,%x" , conn->debug_id, call->cid); +set_bit (RXRPC_CALL_DISCONNECTED , &call->flags); +if (rcu_access_pointer (chan->call) == call) {/* Save the result of the call so that we can repeat it if necessary * through the channel, whilst disposing of the actual call record.
@@ -223,9 +225,7 @@ void rxrpc_disconnect_call(struct rxrpc___rxrpc_disconnect_call (conn, call);spin_unlock (&conn->channel_lock); - call->conn =NULL ; conn->idle_timestamp = jiffies; -rxrpc_put_connection (conn); }/*
net/rxrpc/output.c +9 -18
@@ -129,7 +129,7 @@ static size_t rxrpc_fill_out_ack(structint rxrpc_send_ack_packet (struct rxrpc_call *call,bool ping,rxrpc_serial_t *_serial) { -struct rxrpc_connection *conn =NULL ; +struct rxrpc_connection *conn;struct rxrpc_ack_buffer *pkt;struct msghdr msg;struct kvec iov[2 ];
@@ -139,18 +139,14 @@ int rxrpc_send_ack_packet(struct rxrpc_cint ret;u8 reason; -spin_lock_bh (&call->lock); -if (call->conn) - conn =rxrpc_get_connection_maybe (call->conn); -spin_unlock_bh (&call->lock); -if (!conn) +if (test_bit (RXRPC_CALL_DISCONNECTED , &call->flags))return -ECONNRESET ; pkt =kzalloc (sizeof (*pkt),GFP_KERNEL ); -if (!pkt) { -rxrpc_put_connection (conn); +if (!pkt)return -ENOMEM ; - } + + conn = call->conn; msg.msg_name = &call->peer->srx.transport; msg.msg_namelen = call->peer->srx.transport_len;
@@ -244,7 +240,6 @@ int rxrpc_send_ack_packet(struct rxrpc_c } out: -rxrpc_put_connection (conn);kfree (pkt);return ret; }
@@ -254,7 +249,7 @@ out:*/ int rxrpc_send_abort_packet (struct rxrpc_call *call) { -struct rxrpc_connection *conn =NULL ; +struct rxrpc_connection *conn;struct rxrpc_abort_buffer pkt;struct msghdr msg;struct kvec iov[1 ];
@@ -271,13 +266,11 @@ int rxrpc_send_abort_packet(struct rxrpc test_bit(RXRPC_CALL_TX_LAST, &call->flags))return 0 ; -spin_lock_bh (&call->lock); -if (call->conn) - conn =rxrpc_get_connection_maybe (call->conn); -spin_unlock_bh (&call->lock); -if (!conn) +if (test_bit (RXRPC_CALL_DISCONNECTED , &call->flags))return -ECONNRESET ; + conn = call->conn; + msg.msg_name = &call->peer->srx.transport; msg.msg_namelen = call->peer->srx.transport_len; msg.msg_control =NULL ;
@@ -312,8 +305,6 @@ int rxrpc_send_abort_packet(struct rxrpctrace_rxrpc_tx_packet (call->debug_id, &pkt.whdr, rxrpc_tx_point_call_abort);rxrpc_tx_backoff (call, ret); - -rxrpc_put_connection (conn);return ret; }
Greg Kroah-Hartman
maintainerPATCH 14/309 tcp: clear tp->total_retrans in tcp_disconnect()
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
[ Upstream commit c13c48c00a6bc1febc73902505bdec0967bd7095 ]
total_retrans needs to be cleared in tcp_disconnect().
tcp_disconnect() is rarely used, but it is worth fixing it.
--- net/ipv4/tcp.c | 1 + 1 file changed, 1 insertion(+)
net/ipv4/tcp.c +1 -0
@@ -2622,6 +2622,7 @@ int tcp_disconnect(struct sock *sk, inttcp_set_ca_state (sk, TCP_CA_Open); tp->is_sack_reneg =0 ;tcp_clear_retrans (tp); + tp->total_retrans =0 ;inet_csk_delack_init (sk);/* Initialize rcv_mss to TCP_MIN_MSS to avoid division by 0 * issue in __tcp_select_window()
Greg Kroah-Hartman
maintainerPATCH 15/309 tcp: clear tp->delivered in tcp_disconnect()
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
[ Upstream commit 2fbdd56251b5c62f96589f39eded277260de7267 ]
tp->delivered needs to be cleared in tcp_disconnect().
tcp_disconnect() is rarely used, but it is worth fixing it.
--- net/ipv4/tcp.c | 1 + 1 file changed, 1 insertion(+)
net/ipv4/tcp.c +1 -0
@@ -2618,6 +2618,7 @@ int tcp_disconnect(struct sock *sk, int tp->snd_cwnd =TCP_INIT_CWND ; tp->snd_cwnd_cnt =0 ; tp->window_clamp =0 ; + tp->delivered =0 ; tp->delivered_ce =0 ;tcp_set_ca_state (sk, TCP_CA_Open); tp->is_sack_reneg =0 ;
Greg Kroah-Hartman
maintainerPATCH 16/309 tcp: clear tp->data_segs{in|out} in tcp_disconnect()
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
[ Upstream commit db7ffee6f3eb3683cdcaeddecc0a630a14546fe3 ]
tp->data_segs_in and tp->data_segs_out need to be cleared in tcp_disconnect().
tcp_disconnect() is rarely used, but it is worth fixing it.
--- net/ipv4/tcp.c | 2 ++ 1 file changed, 2 insertions(+)
net/ipv4/tcp.c +2 -0
@@ -2639,6 +2639,8 @@ int tcp_disconnect(struct sock *sk, int tp->bytes_acked =0 ; tp->bytes_received =0 ; tp->bytes_retrans =0 ; + tp->data_segs_in =0 ; + tp->data_segs_out =0 ; tp->duplicate_sack[0 ].start_seq =0 ; tp->duplicate_sack[0 ].end_seq =0 ; tp->dsack_dups =0 ;
Greg Kroah-Hartman
maintainerPATCH 17/309 tcp: clear tp->segs_{in|out} in tcp_disconnect()
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
[ Upstream commit 784f8344de750a41344f4bbbebb8507a730fc99c ]
tp->segs_in and tp->segs_out need to be cleared in tcp_disconnect().
tcp_disconnect() is rarely used, but it is worth fixing it.
--- net/ipv4/tcp.c | 2 ++ 1 file changed, 2 insertions(+)
net/ipv4/tcp.c +2 -0
@@ -2635,6 +2635,8 @@ int tcp_disconnect(struct sock *sk, int sk->sk_rx_dst =NULL ;tcp_saved_syn_free (tp); tp->compressed_ack =0 ; + tp->segs_in =0 ; + tp->segs_out =0 ; tp->bytes_sent =0 ; tp->bytes_acked =0 ; tp->bytes_received =0 ;
Greg Kroah-Hartman
maintainerPATCH 18/309 ionic: fix rxq comp packet type mask
In reply to Greg Kroah-HartmanFrom: Shannon Nelson <[email protected]>
[ Upstream commit b5ce31b5e11b768b7d685b2bab7db09ad5549493 ]
Be sure to include all the packet type bits in the mask.
--- drivers/net/ethernet/pensando/ionic/ionic_if.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/pensando/ionic/ionic_if.h +1 -1
@@ -862,7 +862,7 @@ struct ionic_rxq_comp {#define IONIC_RXQ_COMP_CSUM_F_VLAN 0x40#define IONIC_RXQ_COMP_CSUM_F_CALC 0x80u8 pkt_type_color; -#define IONIC_RXQ_COMP_PKT_TYPE_MASK 0x0f +#define IONIC_RXQ_COMP_PKT_TYPE_MASK 0x7f };enum ionic_pkt_type {
Greg Kroah-Hartman
maintainerPATCH 19/309 MAINTAINERS: correct entries for ISDN/mISDN section
In reply to Greg Kroah-HartmanFrom: Lukas Bulwahn <[email protected]>
[ Upstream commit dff6bc1bfd462b76dc13ec19dedc2c134a62ac59 ]
Commit 6d97985072dc ("isdn: move capi drivers to staging") cleaned up the isdn drivers and split the MAINTAINERS section for ISDN, but missed to add the terminal slash for the two directories mISDN and hardware. Hence, all files in those directories were not part of the new ISDN/mISDN SUBSYSTEM, but were considered to be part of "THE REST".
Rectify the situation, and while at it, also complete the section with two further build files that belong to that subsystem.
This was identified with a small script that finds all files belonging to "THE REST" according to the current MAINTAINERS file, and I investigated upon its output.
--- MAINTAINERS | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
MAINTAINERS +4 -2
@@ -8704,8 +8704,10 @@ L: [email protected] (su L: [email protected] W: http://www.isdn4linux.de S: Maintained -F: drivers/isdn/mISDN -F: drivers/isdn/hardware +F: drivers/isdn/mISDN/ +F: drivers/isdn/hardware/ +F: drivers/isdn/Kconfig +F: drivers/isdn/Makefile ISDN/CAPI SUBSYSTEM M: Karsten Keil <[email protected]>
Greg Kroah-Hartman
maintainerPATCH 20/309 netdevsim: fix stack-out-of-bounds in nsim_dev_debugfs_init()
In reply to Greg Kroah-HartmanFrom: Taehee Yoo <[email protected]>
[ Upstream commit 6fb8852b1298200da39bd85788bc5755d1d56f32 ]
When netdevsim dev is being created, a debugfs directory is created. The variable "dev_ddir_name" is 16bytes device name pointer and device name is "netdevsim<dev id>".
The maximum dev id length is 10.
So, 16bytes for device name isn't enough.
Test commands:
modprobe netdevsim
echo "1000000000 0" > /sys/bus/netdevsim/new_deviceSplat looks like:
[ 249.622710][ T900] BUG: KASAN: stack-out-of-bounds in number+0x824/0x880 [ 249.623658][ T900] Write of size 1 at addr ffff88804c527988 by task bash/900 [ 249.624521][ T900] [ 249.624830][ T900] CPU: 1 PID: 900 Comm: bash Not tainted 5.5.0+ #322 [ 249.625691][ T900] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 [ 249.626712][ T900] Call Trace: [ 249.627103][ T900] dump_stack+0x96/0xdb [ 249.627639][ T900] ? number+0x824/0x880 [ 249.628173][ T900] print_address_description.constprop.5+0x1be/0x360 [ 249.629022][ T900] ? number+0x824/0x880 [ 249.629569][ T900] ? number+0x824/0x880 [ 249.630105][ T900] __kasan_report+0x12a/0x170 [ 249.630717][ T900] ? number+0x824/0x880 [ 249.631201][ T900] kasan_report+0xe/0x20 [ 249.631723][ T900] number+0x824/0x880 [ 249.632235][ T900] ? put_dec+0xa0/0xa0 [ 249.632716][ T900] ? rcu_read_lock_sched_held+0x90/0xc0 [ 249.633392][ T900] vsnprintf+0x63c/0x10b0 [ 249.633983][ T900] ? pointer+0x5b0/0x5b0 [ 249.634543][ T900] ? mark_lock+0x11d/0xc40 [ 249.635200][ T900] sprintf+0x9b/0xd0 [ 249.635750][ T900] ? scnprintf+0xe0/0xe0 [ 249.636370][ T900] nsim_dev_probe+0x63c/0xbf0 [netdevsim]
[ ... ]
--- drivers/net/netdevsim/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/netdevsim/dev.c +1 -1
@@ -73,7 +73,7 @@ static const struct file_operations nsimstatic int nsim_dev_debugfs_init (struct nsim_dev *nsim_dev) { -char dev_ddir_name[16 ]; +char dev_ddir_name[sizeof (DRV_NAME ) +10 ];sprintf (dev_ddir_name,DRV_NAME "%u" , nsim_dev->nsim_bus_dev->dev.id); nsim_dev->ddir =debugfs_create_dir (dev_ddir_name, nsim_dev_ddir);
Greg Kroah-Hartman
maintainerPATCH 21/309 bnxt_en: Fix logic that disables Bus Master during firmware reset.
In reply to Greg Kroah-HartmanFrom: Vasundhara Volam <[email protected]>
[ Upstream commit d407302895d3f3ca3a333c711744a95e0b1b0150 ]
The current logic that calls pci_disable_device() in __bnxt_close_nic() during firmware reset is flawed. If firmware is still alive, we're disabling the device too early, causing some firmware commands to not reach the firmware.
Fix it by moving the logic to bnxt_reset_close(). If firmware is in fatal condition, we call pci_disable_device() before we free any of the rings to prevent DMA corruption of the freed rings. If firmware is still alive, we call pci_disable_device() after the last firmware message has been sent.
--- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
drivers/net/ethernet/broadcom/bnxt/bnxt.c +7 -4
@@ -9273,10 +9273,6 @@ static void __bnxt_close_nic(struct bnxtbnxt_debug_dev_exit (bp);bnxt_disable_napi (bp);del_timer_sync (&bp->timer); -if (test_bit (BNXT_STATE_IN_FW_RESET , &bp->state) && -pci_is_enabled (bp->pdev)) -pci_disable_device (bp->pdev); -bnxt_free_skbs (bp);/* Save ring stats before shutdown */
@@ -10052,8 +10048,15 @@ static void bnxt_fw_reset_close(struct b {__bnxt_close_nic (bp, true, false);bnxt_ulp_irq_stop (bp); +/* When firmware is fatal state, disable PCI device to prevent +* any potential bad DMAs before freeing kernel memory. +*/ +if (test_bit (BNXT_STATE_FW_FATAL_COND , &bp->state)) +pci_disable_device (bp->pdev);bnxt_clear_int_mode (bp);bnxt_hwrm_func_drv_unrgtr (bp); +if (pci_is_enabled (bp->pdev)) +pci_disable_device (bp->pdev);bnxt_free_ctx_mem (bp);kfree (bp->ctx); bp->ctx =NULL ;
Greg Kroah-Hartman
maintainerPATCH 22/309 media: uvcvideo: Avoid cyclic entity chains due to malformed USB descriptors
In reply to Greg Kroah-HartmanFrom: Will Deacon <[email protected]>
commit 68035c80e129c4cfec659aac4180354530b26527 upstream.
Way back in 2017, fuzzing the 4.14-rc2 USB stack with syzkaller kicked up the following WARNING from the UVC chain scanning code:
| list_add double add: new=ffff880069084010, prev=ffff880069084010, | next=ffff880067d22298. | ------------[ cut here ]------------ | WARNING: CPU: 1 PID: 1846 at lib/list_debug.c:31 __list_add_valid+0xbd/0xf0 | Modules linked in: | CPU: 1 PID: 1846 Comm: kworker/1:2 Not tainted | 4.14.0-rc2-42613-g1488251d1a98 #238 | Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 | Workqueue: usb_hub_wq hub_event | task: ffff88006b01ca40 task.stack: ffff880064358000 | RIP: 0010:__list_add_valid+0xbd/0xf0 lib/list_debug.c:29 | RSP: 0018:ffff88006435ddd0 EFLAGS: 00010286 | RAX: 0000000000000058 RBX: ffff880067d22298 RCX: 0000000000000000 | RDX: 0000000000000058 RSI: ffffffff85a58800 RDI: ffffed000c86bbac | RBP: ffff88006435dde8 R08: 1ffff1000c86ba52 R09: 0000000000000000 | R10: 0000000000000002 R11: 0000000000000000 R12: ffff880069084010 | R13: ffff880067d22298 R14: ffff880069084010 R15: ffff880067d222a0 | FS: 0000000000000000(0000) GS:ffff88006c900000(0000) knlGS:0000000000000000 | CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 | CR2: 0000000020004ff2 CR3: 000000006b447000 CR4: 00000000000006e0 | Call Trace: | __list_add ./include/linux/list.h:59 | list_add_tail+0x8c/0x1b0 ./include/linux/list.h:92 | uvc_scan_chain_forward.isra.8+0x373/0x416 | drivers/media/usb/uvc/uvc_driver.c:1471 | uvc_scan_chain drivers/media/usb/uvc/uvc_driver.c:1585 | uvc_scan_device drivers/media/usb/uvc/uvc_driver.c:1769 | uvc_probe+0x77f2/0x8f00 drivers/media/usb/uvc/uvc_driver.c:2104
Looking into the output from usbmon, the interesting part is the following data packet:
ffff880069c63e00 30710169 C Ci:1:002:0 0 143 = 09028f00 01030080 00090403 00000e01 00000924 03000103 7c003328 010204db
If we drop the lead configuration and interface descriptors, we're left with an output terminal descriptor describing a generic display:
/* Output terminal descriptor */
buf[0] 09
buf[1] 24
buf[2] 03 /* UVC_VC_OUTPUT_TERMINAL */
buf[3] 00 /* ID */
buf[4] 01 /* type == 0x0301 (UVC_OTT_DISPLAY) */
buf[5] 03
buf[6] 7c
buf[7] 00 /* source ID refers to self! */
buf[8] 33
The problem with this descriptor is that it is self-referential: the source ID of 0 matches itself! This causes the 'struct uvc_entity' representing the display to be added to its chain list twice during 'uvc_scan_chain()': once via 'uvc_scan_chain_entity()' when it is processed directly from the 'dev->entities' list and then again immediately afterwards when trying to follow the source ID in 'uvc_scan_chain_forward()'
Add a check before adding an entity to a chain list to ensure that the entity is not already part of a chain.
--- drivers/media/usb/uvc/uvc_driver.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
drivers/media/usb/uvc/uvc_driver.c +12 -0
@@ -1493,6 +1493,11 @@ static int uvc_scan_chain_forward(structbreak ;if (forward == prev)continue ; +if (forward->chain.next || forward->chain.prev) { +uvc_trace (UVC_TRACE_DESCR ,"Found reference to " +"entity %d already in chain.\n" , forward->id); +return -EINVAL ; + }switch (UVC_ENTITY_TYPE (forward)) {case UVC_VC_EXTENSION_UNIT :
@@ -1574,6 +1579,13 @@ static int uvc_scan_chain_backward(strucreturn -1 ; } +if (term->chain.next || term->chain.prev) { +uvc_trace (UVC_TRACE_DESCR ,"Found reference to " +"entity %d already in chain.\n" , + term->id); +return -EINVAL ; + } +if (uvc_trace_param &UVC_TRACE_PROBE )printk (KERN_CONT " %d" , term->id);
Greg Kroah-Hartman
maintainerPATCH 23/309 mfd: dln2: More sanity checking for endpoints
In reply to Greg Kroah-HartmanFrom: Oliver Neukum <[email protected]>
commit 2b8bd606b1e60ca28c765f69c1eedd7d2a2e9dca upstream.
It is not enough to check for the number of endpoints. The types must also be correct.
--- drivers/mfd/dln2.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/mfd/dln2.c +11 -2
@@ -722,6 +722,8 @@ static int dln2_probe(struct usb_interfa const struct usb_device_id *usb_id) {struct usb_host_interface *hostif = interface->cur_altsetting; +struct usb_endpoint_descriptor *epin; +struct usb_endpoint_descriptor *epout;struct device *dev = &interface->dev;struct dln2_dev *dln2;int ret;
@@ -731,12 +733,19 @@ static int dln2_probe(struct usb_interfa hostif->desc.bNumEndpoints < 2)return -ENODEV ; + epin = &hostif->endpoint[0 ].desc; + epout = &hostif->endpoint[1 ].desc; +if (!usb_endpoint_is_bulk_out (epout)) +return -ENODEV ; +if (!usb_endpoint_is_bulk_in (epin)) +return -ENODEV ; + dln2 =kzalloc (sizeof (*dln2),GFP_KERNEL );if (!dln2)return -ENOMEM ; - dln2->ep_out = hostif->endpoint[0 ].desc.bEndpointAddress; - dln2->ep_in = hostif->endpoint[1 ].desc.bEndpointAddress; + dln2->ep_out = epout->bEndpointAddress; + dln2->ep_in = epin->bEndpointAddress; dln2->usb_dev =usb_get_dev (interface_to_usbdev (interface)); dln2->interface = interface;usb_set_intfdata (interface, dln2);
Greg Kroah-Hartman
maintainerPATCH 24/309 netfilter: ipset: fix suspicious RCU usage in find_set_and_id
In reply to Greg Kroah-HartmanFrom: Kadlecsik József <[email protected]>
commit 5038517119d50ed0240059b1d7fc2faa92371c08 upstream.
find_set_and_id() is called when the NFNL_SUBSYS_IPSET mutex is held. However, in the error path there can be a follow-up recvmsg() without the mutex held. Use the start() function of struct netlink_dump_control instead of dump() to verify and report if the specified set does not exist.
Thanks to Pablo Neira Ayuso for helping me to understand the subleties of the netlink protocol.
--- net/netfilter/ipset/ip_set_core.c | 41 +++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 20 deletions(-)
net/netfilter/ipset/ip_set_core.c +21 -20
@@ -1293,31 +1293,34 @@ ip_set_dump_policy[IPSET_ATTR_CMD_MAX + };static int -dump_init (struct netlink_callback *cb,struct ip_set_net *inst) +ip_set_dump_start (struct netlink_callback *cb) {struct nlmsghdr *nlh =nlmsg_hdr (cb->skb);int min_len =nlmsg_total_size (sizeof (struct nfgenmsg ));struct nlattr *cda[IPSET_ATTR_CMD_MAX +1 ];struct nlattr *attr = (void *)nlh + min_len; +struct sk_buff *skb = cb->skb; +struct ip_set_net *inst =ip_set_pernet (sock_net (skb->sk));u32 dump_type; -ip_set_id_t index;int ret; ret =nla_parse (cda,IPSET_ATTR_CMD_MAX , attr, nlh->nlmsg_len - min_len, ip_set_dump_policy,NULL );if (ret) -return ret; + goto error; cb->args[IPSET_CB_PROTO ] =nla_get_u8 (cda[IPSET_ATTR_PROTOCOL ]);if (cda[IPSET_ATTR_SETNAME ]) { +ip_set_id_t index;struct ip_set *set; set =find_set_and_id (inst,nla_data (cda[IPSET_ATTR_SETNAME ]), &index); -if (!set) -return -ENOENT ; - +if (!set) { + ret = -ENOENT ; + goto error; + } dump_type =DUMP_ONE ; cb->args[IPSET_CB_INDEX ] = index; }else {
@@ -1333,10 +1336,17 @@ dump_init(struct netlink_callback *cb, s cb->args[IPSET_CB_DUMP ] = dump_type;return 0 ; + +error: +/* We have to create and send the error message manually :-( */ +if (nlh->nlmsg_flags &NLM_F_ACK ) { +netlink_ack (cb->skb, nlh, ret,NULL ); + } +return ret; }static int -ip_set_dump_start (struct sk_buff *skb,struct netlink_callback *cb) +ip_set_dump_do (struct sk_buff *skb,struct netlink_callback *cb) {ip_set_id_t index =IPSET_INVALID_ID , max;struct ip_set *set =NULL ;
@@ -1347,18 +1357,8 @@ ip_set_dump_start(struct sk_buff *skb, sbool is_destroyed;int ret =0 ; -if (!cb->args[IPSET_CB_DUMP ]) { - ret =dump_init (cb, inst); -if (ret <0 ) { - nlh =nlmsg_hdr (cb->skb); -/* We have to create and send the error message -* manually :-( -*/ -if (nlh->nlmsg_flags &NLM_F_ACK ) -netlink_ack (cb->skb, nlh, ret,NULL ); -return ret; - } - } +if (!cb->args[IPSET_CB_DUMP ]) +return -EINVAL ;if (cb->args[IPSET_CB_INDEX ] >= inst->ip_set_max) goto out;
@@ -1494,7 +1494,8 @@ static int ip_set_dump(struct net *net, {struct netlink_dump_control c = { - .dump = ip_set_dump_start, + .start = ip_set_dump_start, + .dump = ip_set_dump_do, .done = ip_set_dump_done, };return netlink_dump_start (ctnl, skb, nlh, &c);
Greg Kroah-Hartman
maintainerPATCH 25/309 ipc/msg.c: consolidate all xxxctl_down() functions
In reply to Greg Kroah-HartmanFrom: Lu Shuaibing <[email protected]>
commit 889b331724c82c11e15ba0a60979cf7bded0a26c upstream.
A use of uninitialized memory in msgctl_down() because msqid64 in ksys_msgctl hasn't been initialized. The local | msqid64 | is created in ksys_msgctl() and then passed into msgctl_down(). Along the way msqid64 is never initialized before msgctl_down() checks msqid64->msg_qbytes.
KUMSAN(KernelUninitializedMemorySantizer, a new error detection tool) reports:
==================================================================
BUG: KUMSAN: use of uninitialized memory in msgctl_down+0x94/0x300 Read of size 8 at addr ffff88806bb97eb8 by task syz-executor707/2022 CPU: 0 PID: 2022 Comm: syz-executor707 Not tainted 5.2.0-rc4+ #63 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014 Call Trace: dump_stack+0x75/0xae __kumsan_report+0x17c/0x3e6 kumsan_report+0xe/0x20 msgctl_down+0x94/0x300 ksys_msgctl.constprop.14+0xef/0x260 do_syscall_64+0x7e/0x1f0 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x4400e9 Code: 18 89 d0 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 fb 13 fc ff c3 66 2e 0f 1f 84 00 00 00 00 RSP: 002b:00007ffd869e0598 EFLAGS: 00000246 ORIG_RAX: 0000000000000047 RAX: ffffffffffffffda RBX: 00000000004002c8 RCX: 00000000004400e9 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 RBP: 00000000006ca018 R08: 0000000000000000 R09: 0000000000000000 R10: 00000000ffffffff R11: 0000000000000246 R12: 0000000000401970 R13: 0000000000401a00 R14: 0000000000000000 R15: 0000000000000000 The buggy address belongs to the page: page:ffffea0001aee5c0 refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 flags: 0x100000000000000() raw: 0100000000000000 0000000000000000 ffffffff01ae0101 0000000000000000 raw: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000 page dumped because: kumsan: bad access detected ==================================================================
Syzkaller reproducer:
msgctl$IPC_RMID(0x0, 0x0)
C reproducer:
// autogenerated by syzkaller (https://github.com/google/syzkaller)
int main(void)
{
syscall(__NR_mmap, 0x20000000, 0x1000000, 3, 0x32, -1, 0); syscall(__NR_msgctl, 0, 0, 0);
return 0;
}
From: Andrew Morton <[email protected]>
Subject: [PATCH 5.4 025/309] ipc/msg.c: consolidate all xxxctl_down() functions
Each line here overflows 80 cols by exactly one character. Delete one tab per line to fix.
--- ipc/msg.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
ipc/msg.c +10 -9
@@ -377,7 +377,7 @@ copy_msqid_from_user(struct msqid64_ds ** NOTE: no locks must be held, the rwsem is taken inside this function. */ static int msgctl_down (struct ipc_namespace *ns,int msqid,int cmd, -struct msqid64_ds *msqid64) +struct ipc64_perm *perm,int msg_qbytes) {struct kern_ipc_perm *ipcp;struct msg_queue *msq;
@@ -387,7 +387,7 @@ static int msgctl_down(struct ipc_namesprcu_read_lock (); ipcp =ipcctl_obtain_check (ns, &msg_ids (ns), msqid, cmd, - &msqid64->msg_perm, msqid64->msg_qbytes); + perm, msg_qbytes);if (IS_ERR (ipcp)) { err =PTR_ERR (ipcp); goto out_unlock1;
@@ -409,18 +409,18 @@ static int msgctl_down(struct ipc_namesp {DEFINE_WAKE_Q (wake_q); -if (msqid64->msg_qbytes > ns->msg_ctlmnb && +if (msg_qbytes > ns->msg_ctlmnb && !capable (CAP_SYS_RESOURCE )) { err = -EPERM ; goto out_unlock1; }ipc_lock_object (&msq->q_perm); - err =ipc_update_perm (&msqid64->msg_perm, ipcp); + err =ipc_update_perm (perm, ipcp);if (err) goto out_unlock0; - msq->q_qbytes = msqid64->msg_qbytes; + msq->q_qbytes = msg_qbytes; msq->q_ctime =ktime_get_real_seconds ();/*
@@ -601,9 +601,10 @@ static long ksys_msgctl(int msqid, int ccase IPC_SET :if (copy_msqid_from_user (&msqid64, buf, version))return -EFAULT ; -/* fallthru */ +return msgctl_down (ns, msqid, cmd, &msqid64.msg_perm, + msqid64.msg_qbytes);case IPC_RMID : -return msgctl_down (ns, msqid, cmd, &msqid64); +return msgctl_down (ns, msqid, cmd,NULL ,0 );default :return -EINVAL ; }
@@ -735,9 +736,9 @@ static long compat_ksys_msgctl(int msqidcase IPC_SET :if (copy_compat_msqid_from_user (&msqid64, uptr, version))return -EFAULT ; -/* fallthru */ +return msgctl_down (ns, msqid, cmd, &msqid64.msg_perm, msqid64.msg_qbytes);case IPC_RMID : -return msgctl_down (ns, msqid, cmd, &msqid64); +return msgctl_down (ns, msqid, cmd,NULL ,0 );default :return -EINVAL ; }
Greg Kroah-Hartman
maintainerPATCH 26/309 tracing/kprobes: Have uname use __get_str() in print_fmt
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (VMware) <[email protected]>
commit 20279420ae3a8ef4c5d9fedc360a2c37a1dbdf1b upstream.
Thomas Richter reported:
Quoted 8 lines
Test case 66 'Use
vfs_getnameprobe to get syscall args filenames' is broken on s390, but works on x86. The test case fails with:[root@m35lp76 perf]# perf test -F 66
66: Usevfs_getnameprobe to get syscall args filenames
:Recording open file:
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.004 MB /tmp/__perf_test.perf.data.TCdYj\
Quoted 4 lines
(20 samples) ]Looking at perf.data file for
vfs_getnamerecords for the file we touched:
FAILED!
[root@m35lp76 perf]#
The root cause was the print_fmt of the kprobe event that referenced the "ustring"
Quoted 10 lines
Setting up the kprobe event using perf command:
# ./perf probe "vfs_getname=getname_flags:72 pathname=filename:ustring"generates this format file:
[root@m35lp76 perf]# cat /sys/kernel/debug/tracing/events/probe/\
vfs_getname/format
name:vfs_getname
ID: 1172
format:
Quoted 9 lines
field:unsigned short common_type; offset:0; size:2; signed:0;
field:unsigned char common_flags; offset:2; size:1; signed:0;
field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
field:int common_pid; offset:4; size:4; signed:1;
field:unsigned long __probe_ip; offset:8; size:8; signed:0;
field:__data_loc char[] pathname; offset:16; size:4; signed:1;
print fmt: "(%lx) pathname=\"%s\"", REC->__probe_ip, REC->pathnameInstead of using "__get_str(pathname)" it referenced it directly.
--- kernel/trace/trace_probe.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
kernel/trace/trace_probe.c +4 -2
@@ -876,7 +876,8 @@ static int __set_print_fmt(struct trace_for (i =0 ; i < tp->nr_args; i++) { parg = tp->args + i;if (parg->count) { -if (strcmp (parg->type->name,"string" ) ==0 ) +if ((strcmp (parg->type->name,"string" ) ==0 ) || + (strcmp (parg->type->name,"ustring" ) ==0 )) fmt =", __get_str(%s[%d])" ;else fmt =", REC->%s[%d]" ;
@@ -884,7 +885,8 @@ static int __set_print_fmt(struct trace_ pos +=snprintf (buf + pos,LEN_OR_ZERO , fmt, parg->name, j); }else { -if (strcmp (parg->type->name,"string" ) ==0 ) +if ((strcmp (parg->type->name,"string" ) ==0 ) || + (strcmp (parg->type->name,"ustring" ) ==0 )) fmt =", __get_str(%s)" ;else fmt =", REC->%s" ;
Greg Kroah-Hartman
maintainerPATCH 27/309 tracing: Fix sched switch start/stop refcount racy updates
In reply to Greg Kroah-HartmanFrom: Mathieu Desnoyers <[email protected]>
commit 64ae572bc7d0060429e40e1c8d803ce5eb31a0d6 upstream.
Reading the sched_cmdline_ref and sched_tgid_ref initial state within tracing_start_sched_switch without holding the sched_register_mutex is racy against concurrent updates, which can lead to tracepoint probes being registered more than once (and thus trigger warnings within tracepoint.c).
--- kernel/trace/trace_sched_switch.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
kernel/trace/trace_sched_switch.c +3 -1
@@ -89,8 +89,10 @@ static void tracing_sched_unregister(voistatic void tracing_start_sched_switch (int ops) { -bool sched_register = (!sched_cmdline_ref && !sched_tgid_ref); +bool sched_register; +mutex_lock (&sched_register_mutex); + sched_register = (!sched_cmdline_ref && !sched_tgid_ref);switch (ops) {case RECORD_CMDLINE :
Greg Kroah-Hartman
maintainerPATCH 28/309 rcu: Use *_ONCE() to protect lockless ->expmask accesses
In reply to Greg Kroah-HartmanFrom: Paul E. McKenney <[email protected]>
commit 15c7c972cd26d89a26788e609c53b5a465324a6c upstream.
The rcu_node structure's ->expmask field is accessed locklessly when starting a new expedited grace period and when reporting an expedited RCU CPU stall warning. This commit therefore handles the former by taking a snapshot of ->expmask while the lock is held and the latter by applying READ_ONCE() to lockless reads and WRITE_ONCE() to the corresponding updates.
--- kernel/rcu/tree_exp.h | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-)
kernel/rcu/tree_exp.h +9 -10
@@ -134,7 +134,7 @@ static void __maybe_unused sync_exp_resercu_for_each_node_breadth_first (rnp) {raw_spin_lock_irqsave_rcu_node (rnp, flags);WARN_ON_ONCE (rnp->expmask); - rnp->expmask = rnp->expmaskinit; +WRITE_ONCE (rnp->expmask, rnp->expmaskinit);raw_spin_unlock_irqrestore_rcu_node (rnp, flags); } }
@@ -211,7 +211,7 @@ static void __rcu_report_exp_rnp(struct rnp = rnp->parent;raw_spin_lock_rcu_node (rnp);/* irqs already disabled */ WARN_ON_ONCE (!(rnp->expmask & mask)); - rnp->expmask &= ~mask; +WRITE_ONCE (rnp->expmask, rnp->expmask & ~mask); } }
@@ -241,7 +241,7 @@ static void rcu_report_exp_cpu_mult(struraw_spin_unlock_irqrestore_rcu_node (rnp, flags);return ; } - rnp->expmask &= ~mask; +WRITE_ONCE (rnp->expmask, rnp->expmask & ~mask);__rcu_report_exp_rnp (rnp, wake, flags);/* Releases rnp->lock. */ }
@@ -372,12 +372,10 @@ static void sync_rcu_exp_select_node_cpuraw_spin_unlock_irqrestore_rcu_node (rnp, flags);/* IPI the remaining CPUs for expedited quiescent state. */ -for_each_leaf_node_cpu_mask (rnp, cpu, rnp->expmask) { +for_each_leaf_node_cpu_mask (rnp, cpu, mask_ofl_ipi) {unsigned long mask =leaf_node_cpu_bit (rnp, cpu);struct rcu_data *rdp =per_cpu_ptr (&rcu_data, cpu); -if (!(mask_ofl_ipi & mask)) -continue ; retry_ipi:if (rcu_dynticks_in_eqs_since (rdp, rdp->exp_dynticks_snap)) { mask_ofl_test |= mask;
@@ -491,7 +489,7 @@ static void synchronize_sched_expedited_struct rcu_data *rdp; mask =leaf_node_cpu_bit (rnp, cpu); -if (!(rnp->expmask & mask)) +if (!(READ_ONCE (rnp->expmask) & mask))continue ; ndetected++; rdp =per_cpu_ptr (&rcu_data, cpu);
@@ -503,7 +501,8 @@ static void synchronize_sched_expedited_ }pr_cont (" } %lu jiffies s: %lu root: %#lx/%c\n" , jiffies - jiffies_start, rcu_state.expedited_sequence, - rnp_root->expmask,".T" [!!rnp_root->exp_tasks]); +READ_ONCE (rnp_root->expmask), +".T" [!!rnp_root->exp_tasks]);if (ndetected) {pr_err ("blocking rcu_node structures:" );rcu_for_each_node_breadth_first (rnp) {
@@ -513,7 +512,7 @@ static void synchronize_sched_expedited_continue ;pr_cont (" l=%u:%d-%d:%#lx/%c" , rnp->level, rnp->grplo, rnp->grphi, - rnp->expmask, +READ_ONCE (rnp->expmask),".T" [!!rnp->exp_tasks]); }pr_cont ("\n" );
@@ -521,7 +520,7 @@ static void synchronize_sched_expedited_rcu_for_each_leaf_node (rnp) {for_each_leaf_node_possible_cpu (rnp, cpu) { mask =leaf_node_cpu_bit (rnp, cpu); -if (!(rnp->expmask & mask)) +if (!(READ_ONCE (rnp->expmask) & mask))continue ;dump_cpu_task (cpu); }
Greg Kroah-Hartman
maintainerPATCH 29/309 rcu: Avoid data-race in rcu_gp_fqs_check_wake()
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
commit 6935c3983b246d5fbfebd3b891c825e65c118f2d upstream.
The rcu_gp_fqs_check_wake() function uses rcu_preempt_blocked_readers_cgp() to read ->gp_tasks while other cpus might overwrite this field.
We need READ_ONCE()/WRITE_ONCE() pairs to avoid compiler tricks and KCSAN splats like the following :
BUG: KCSAN: data-race in rcu_gp_fqs_check_wake / rcu_preempt_deferred_qs_irqrestore
write to 0xffffffff85a7f190 of 8 bytes by task 7317 on cpu 0:
rcu_preempt_deferred_qs_irqrestore+0x43d/0x580 kernel/rcu/tree_plugin.h:507 rcu_read_unlock_special+0xec/0x370 kernel/rcu/tree_plugin.h:659 __rcu_read_unlock+0xcf/0xe0 kernel/rcu/tree_plugin.h:394 rcu_read_unlock include/linux/rcupdate.h:645 [inline] __ip_queue_xmit+0x3b0/0xa40 net/ipv4/ip_output.c:533 ip_queue_xmit+0x45/0x60 include/net/ip.h:236 __tcp_transmit_skb+0xdeb/0x1cd0 net/ipv4/tcp_output.c:1158 __tcp_send_ack+0x246/0x300 net/ipv4/tcp_output.c:3685 tcp_send_ack+0x34/0x40 net/ipv4/tcp_output.c:3691 tcp_cleanup_rbuf+0x130/0x360 net/ipv4/tcp.c:1575 tcp_recvmsg+0x633/0x1a30 net/ipv4/tcp.c:2179 inet_recvmsg+0xbb/0x250 net/ipv4/af_inet.c:838 sock_recvmsg_nosec net/socket.c:871 [inline] sock_recvmsg net/socket.c:889 [inline] sock_recvmsg+0x92/0xb0 net/socket.c:885 sock_read_iter+0x15f/0x1e0 net/socket.c:967 call_read_iter include/linux/fs.h:1864 [inline] new_sync_read+0x389/0x4f0 fs/read_write.c:414
read to 0xffffffff85a7f190 of 8 bytes by task 10 on cpu 1:
rcu_gp_fqs_check_wake kernel/rcu/tree.c:1556 [inline] rcu_gp_fqs_check_wake+0x93/0xd0 kernel/rcu/tree.c:1546 rcu_gp_fqs_loop+0x36c/0x580 kernel/rcu/tree.c:1611 rcu_gp_kthread+0x143/0x220 kernel/rcu/tree.c:1768 kthread+0x1d4/0x200 drivers/block/aoe/aoecmd.c:1253 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:352
Reported by Kernel Concurrency Sanitizer on:
CPU: 1 PID: 10 Comm: rcu_preempt Not tainted 5.3.0+ #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
--- kernel/rcu/tree_plugin.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
kernel/rcu/tree_plugin.h +6 -5
@@ -220,7 +220,7 @@ static void rcu_preempt_ctxt_queue(struc* blocked tasks. */ if (!rnp->gp_tasks && (blkd_state &RCU_GP_BLKD )) { - rnp->gp_tasks = &t->rcu_node_entry; +WRITE_ONCE (rnp->gp_tasks, &t->rcu_node_entry);WARN_ON_ONCE (rnp->completedqs == rnp->gp_seq); }if (!rnp->exp_tasks && (blkd_state &RCU_EXP_BLKD ))
@@ -340,7 +340,7 @@ EXPORT_SYMBOL_GPL(rcu_note_context_switc*/ static int rcu_preempt_blocked_readers_cgp (struct rcu_node *rnp) { -return rnp->gp_tasks !=NULL ; +return READ_ONCE (rnp->gp_tasks) !=NULL ; }/* Bias and limit values for ->rcu_read_lock_nesting. */
@@ -493,7 +493,7 @@ rcu_preempt_deferred_qs_irqrestore(structrace_rcu_unlock_preempted_task (TPS ("rcu_preempt" ), rnp->gp_seq, t->pid);if (&t->rcu_node_entry == rnp->gp_tasks) - rnp->gp_tasks = np; +WRITE_ONCE (rnp->gp_tasks, np);if (&t->rcu_node_entry == rnp->exp_tasks) rnp->exp_tasks = np;if (IS_ENABLED (CONFIG_RCU_BOOST )) {
@@ -663,7 +663,7 @@ static void rcu_preempt_check_blocked_tadump_blkd_tasks (rnp,10 );if (rcu_preempt_has_tasks (rnp) && (rnp->qsmaskinit || rnp->wait_blkd_tasks)) { - rnp->gp_tasks = rnp->blkd_tasks.next; +WRITE_ONCE (rnp->gp_tasks, rnp->blkd_tasks.next); t = container_of(rnp->gp_tasks, struct task_struct, rcu_node_entry); trace_rcu_unlock_preempted_task(TPS("rcu_preempt-GPS"),
@@ -757,7 +757,8 @@ dump_blkd_tasks(struct rcu_node *rnp, inpr_info ("%s: %d:%d ->qsmask %#lx ->qsmaskinit %#lx ->qsmaskinitnext %#lx\n" , __func__, rnp1->grplo, rnp1->grphi, rnp1->qsmask, rnp1->qsmaskinit, rnp1->qsmaskinitnext);pr_info ("%s: ->gp_tasks %p ->boost_tasks %p ->exp_tasks %p\n" , - __func__, rnp->gp_tasks, rnp->boost_tasks, rnp->exp_tasks); + __func__,READ_ONCE (rnp->gp_tasks), rnp->boost_tasks, + rnp->exp_tasks);pr_info ("%s: ->blkd_tasks" , __func__); i =0 ;list_for_each (lhp, &rnp->blkd_tasks) {
Greg Kroah-Hartman
maintainerPATCH 30/309 srcu: Apply *_ONCE() to ->srcu_last_gp_end
In reply to Greg Kroah-HartmanFrom: Paul E. McKenney <[email protected]>
commit 844a378de3372c923909681706d62336d702531e upstream.
The ->srcu_last_gp_end field is accessed from any CPU at any time by synchronize_srcu(), so non-initialization references need to use READ_ONCE() and WRITE_ONCE(). This commit therefore makes that change.
--- kernel/rcu/srcutree.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
kernel/rcu/srcutree.c +4 -3
@@ -530,7 +530,7 @@ static void srcu_gp_end(struct srcu_stru idx =rcu_seq_state (ssp->srcu_gp_seq);WARN_ON_ONCE (idx !=SRCU_STATE_SCAN2 ); cbdelay =srcu_get_delay (ssp); - ssp->srcu_last_gp_end =ktime_get_mono_fast_ns (); +WRITE_ONCE (ssp->srcu_last_gp_end,ktime_get_mono_fast_ns ());rcu_seq_end (&ssp->srcu_gp_seq); gpseq =rcu_seq_current (&ssp->srcu_gp_seq);if (ULONG_CMP_LT (ssp->srcu_gp_seq_needed_exp, gpseq))
@@ -762,6 +762,7 @@ static bool srcu_might_be_idle(struct srunsigned long flags;struct srcu_data *sdp;unsigned long t; +unsigned long tlast;/* If the local srcu_data structure has callbacks, not idle. */ local_irq_save (flags);
@@ -780,9 +781,9 @@ static bool srcu_might_be_idle(struct sr/* First, see if enough time has passed since the last GP. */ t =ktime_get_mono_fast_ns (); + tlast =READ_ONCE (ssp->srcu_last_gp_end);if (exp_holdoff ==0 || -time_in_range_open (t, ssp->srcu_last_gp_end, - ssp->srcu_last_gp_end + exp_holdoff)) +time_in_range_open (t, tlast, tlast + exp_holdoff))return false;/* Too soon after last GP. */ /* Next, check for probable idleness. */
Greg Kroah-Hartman
maintainerPATCH 31/309 rcu: Use READ_ONCE() for ->expmask in rcu_read_unlock_special()
In reply to Greg Kroah-HartmanFrom: Paul E. McKenney <[email protected]>
commit c51f83c315c392d9776c33eb16a2fe1349d65c7f upstream.
The rcu_node structure's ->expmask field is updated only when holding the ->lock, but is also accessed locklessly. This means that all ->expmask updates must use WRITE_ONCE() and all reads carried out without holding ->lock must use READ_ONCE(). This commit therefore changes the lockless ->expmask read in rcu_read_unlock_special() to use READ_ONCE().
--- kernel/rcu/tree_plugin.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/rcu/tree_plugin.h +1 -1
@@ -612,7 +612,7 @@ static void rcu_read_unlock_special(stru t->rcu_read_unlock_special.b.exp_hint = false; exp = (t->rcu_blocked_node && t->rcu_blocked_node->exp_tasks) || - (rdp->grpmask & rnp->expmask) || + (rdp->grpmask &READ_ONCE (rnp->expmask)) ||tick_nohz_full_cpu (rdp->cpu);// Need to defer quiescent state until everything is enabled. if (irqs_were_disabled && use_softirq &&
Greg Kroah-Hartman
maintainerPATCH 32/309 nvmet: Fix error print message at nvmet_install_queue function
In reply to Greg Kroah-HartmanFrom: Israel Rukshin <[email protected]>
commit 0b87a2b795d66be7b54779848ef0f3901c5e46fc upstream.
Place the arguments in the correct order.
--- drivers/nvme/target/fabrics-cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/nvme/target/fabrics-cmd.c +1 -1
@@ -132,7 +132,7 @@ static u16 nvmet_install_queue(struct nvif (ret) {pr_err ("failed to install queue %d cntlid %d ret %x\n" , - qid, ret, ctrl->cntlid); + qid, ctrl->cntlid, ret);return ret; } }
Greg Kroah-Hartman
maintainerPATCH 33/309 nvmet: Fix controller use after free
In reply to Greg Kroah-HartmanFrom: Israel Rukshin <[email protected]>
commit 1a3f540d63152b8db0a12de508bfa03776217d83 upstream.
After nvmet_install_queue() sets sq->ctrl calling to nvmet_sq_destroy() reduces the controller refcount. In case nvmet_install_queue() fails, calling to nvmet_ctrl_put() is done twice (at nvmet_sq_destroy and nvmet_execute_io_connect/nvmet_execute_admin_connect) instead of once for the queue which leads to use after free of the controller. Fix this by set NULL at sq->ctrl in case of a failure at nvmet_install_queue().
The bug leads to the following Call Trace:
[65857.994862] refcount_t: underflow; use-after-free. [65858.108304] Workqueue: events nvmet_rdma_release_queue_work [nvmet_rdma] [65858.115557] RIP: 0010:refcount_warn_saturate+0xe5/0xf0 [65858.208141] Call Trace: [65858.211203] nvmet_sq_destroy+0xe1/0xf0 [nvmet] [65858.216383] nvmet_rdma_release_queue_work+0x37/0xf0 [nvmet_rdma] [65858.223117] process_one_work+0x167/0x370 [65858.227776] worker_thread+0x49/0x3e0 [65858.232089] kthread+0xf5/0x130 [65858.235895] ? max_active_store+0x80/0x80 [65858.240504] ? kthread_bind+0x10/0x10 [65858.244832] ret_from_fork+0x1f/0x30 [65858.249074] ---[ end trace f82d59250b54beb7 ]---
--- drivers/nvme/target/fabrics-cmd.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/nvme/target/fabrics-cmd.c +9 -4
@@ -105,6 +105,7 @@ static u16 nvmet_install_queue(struct nvu16 qid =le16_to_cpu (c->qid);u16 sqsize =le16_to_cpu (c->sqsize);struct nvmet_ctrl *old; +u16 ret; old =cmpxchg (&req->sq->ctrl,NULL , ctrl);if (old) {
@@ -115,7 +116,8 @@ static u16 nvmet_install_queue(struct nvif (!sqsize) {pr_warn ("queue size zero!\n" ); req->error_loc = offsetof(struct nvmf_connect_command , sqsize); -return NVME_SC_CONNECT_INVALID_PARAM |NVME_SC_DNR ; + ret =NVME_SC_CONNECT_INVALID_PARAM |NVME_SC_DNR ; + goto err; }/* note: convert queue size from 0's-based value to 1's-based value */
@@ -128,16 +130,19 @@ static u16 nvmet_install_queue(struct nv }if (ctrl->ops->install_queue) { -u16 ret = ctrl->ops->install_queue (req->sq); - + ret = ctrl->ops->install_queue (req->sq);if (ret) {pr_err ("failed to install queue %d cntlid %d ret %x\n" , qid, ctrl->cntlid, ret); -return ret; + goto err; } }return 0 ; + +err: + req->sq->ctrl =NULL ; +return ret; }static void nvmet_execute_admin_connect (struct nvmet_req *req)
Greg Kroah-Hartman
maintainerPATCH 34/309 Bluetooth: btusb: fix memory leak on fw
In reply to Greg Kroah-HartmanFrom: Colin Ian King <[email protected]>
commit 3168c19d7eb17a0108a3b60ad8e8c1b18ea05c63 upstream.
Currently the error return path when the call to btusb_mtk_hci_wmt_sync fails does not free fw. Fix this by returning via the error_release_fw label that performs the free'ing.
Addresses-Coverity: ("Resource leak")
--- drivers/bluetooth/btusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/bluetooth/btusb.c +1 -1
@@ -2850,7 +2850,7 @@ static int btusb_mtk_setup_firmware(stru err =btusb_mtk_hci_wmt_sync (hdev, &wmt_params);if (err <0 ) {bt_dev_err (hdev,"Failed to send wmt rst (%d)" , err); -return err; + goto err_release_fw; }/* Wait a few moments for firmware activation done */
Greg Kroah-Hartman
maintainerPATCH 35/309 Bluetooth: btusb: Disable runtime suspend on Realtek devices
In reply to Greg Kroah-HartmanFrom: Kai-Heng Feng <[email protected]>
commit 7ecacafc240638148567742cca41aa7144b4fe1e upstream.
After commit 9e45524a0111 ("Bluetooth: btusb: Fix suspend issue for Realtek devices") both WiFi and Bluetooth stop working after reboot:
[ 34.322617] usb 1-8: reset full-speed USB device number 3 using xhci_hcd [ 34.450401] usb 1-8: device descriptor read/64, error -71 [ 34.694375] usb 1-8: device descriptor read/64, error -71 ... [ 44.599111] rtw_pci 0000:02:00.0: failed to poll offset=0x5 mask=0x3 value=0x0 [ 44.599113] rtw_pci 0000:02:00.0: mac power on failed [ 44.599114] rtw_pci 0000:02:00.0: failed to power on mac [ 44.599114] rtw_pci 0000:02:00.0: leave idle state failed [ 44.599492] rtw_pci 0000:02:00.0: failed to leave ips state [ 44.599493] rtw_pci 0000:02:00.0: failed to leave idle state
That commit removed USB_QUIRK_RESET_RESUME, which not only resets the USB device after resume, it also prevents the device from being runtime suspended by USB core. My experiment shows if the Realtek btusb device ever runtime suspends once, the entire wireless module becomes useless after reboot.
So let's explicitly disable runtime suspend on Realtek btusb device for now.
--- drivers/bluetooth/btusb.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/bluetooth/btusb.c +4 -0
@@ -3819,6 +3819,10 @@ static int btusb_probe(struct usb_interf* (DEVICE_REMOTE_WAKEUP) */ set_bit (BTUSB_WAKEUP_DISABLE , &data->flags); + + err =usb_autopm_get_interface (intf); +if (err <0 ) + goto out_free_dev; }if (id->driver_info &BTUSB_AMP ) {
Greg Kroah-Hartman
maintainerPATCH 36/309 brcmfmac: Fix memory leak in brcmf_usbdev_qinit
In reply to Greg Kroah-HartmanFrom: Navid Emamdoost <[email protected]>
commit 4282dc057d750c6a7dd92953564b15c26b54c22c upstream.
In the implementation of brcmf_usbdev_qinit() the allocated memory for reqs is leaking if usb_alloc_urb() fails. Release reqs in the error handling path.
--- drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +1 -0
@@ -430,6 +430,7 @@ fail:usb_free_urb (req->urb);list_del (q->next); } +kfree (reqs);return NULL ; }
Greg Kroah-Hartman
maintainerPATCH 37/309 usb: dwc3: gadget: Check END_TRANSFER completion
In reply to Greg Kroah-HartmanFrom: Thinh Nguyen <[email protected]>
commit c58d8bfc77a2c7f6ff6339b58c9fca7ae6f57e70 upstream.
While the END_TRANSFER command is sent but not completed, any request dequeue during this time will cause the driver to issue the END_TRANSFER command. The driver needs to submit the command only once to stop the controller from processing further. The controller may take more time to process the same command multiple times unnecessarily. Let's add a flag DWC3_EP_END_TRANSFER_PENDING to check for this condition.
--- drivers/usb/dwc3/core.h | 1 + drivers/usb/dwc3/ep0.c | 4 +++- drivers/usb/dwc3/gadget.c | 6 +++++- 3 files changed, 9 insertions(+), 2 deletions(-)
drivers/usb/dwc3/core.h +1 -0
@@ -688,6 +688,7 @@ struct dwc3_ep {#define DWC3_EP_STALL BIT(1)#define DWC3_EP_WEDGE BIT(2)#define DWC3_EP_TRANSFER_STARTED BIT(3) +#define DWC3_EP_END_TRANSFER_PENDING BIT(4)#define DWC3_EP_PENDING_REQUEST BIT(5)/* This last one is specific to EP0 */
drivers/usb/dwc3/ep0.c +3 -1
@@ -1136,8 +1136,10 @@ void dwc3_ep0_interrupt(struct dwc3 *dwccase DWC3_DEPEVT_EPCMDCMPLT : cmd =DEPEVT_PARAMETER_CMD (event->parameters); -if (cmd ==DWC3_DEPCMD_ENDTRANSFER ) +if (cmd ==DWC3_DEPCMD_ENDTRANSFER ) { + dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING ; dep->flags &= ~DWC3_EP_TRANSFER_STARTED ; + }break ; } }
drivers/usb/dwc3/gadget.c +5 -1
@@ -2625,6 +2625,7 @@ static void dwc3_endpoint_interrupt(stru cmd =DEPEVT_PARAMETER_CMD (event->parameters);if (cmd ==DWC3_DEPCMD_ENDTRANSFER ) { + dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING ; dep->flags &= ~DWC3_EP_TRANSFER_STARTED ;dwc3_gadget_ep_cleanup_cancelled_requests (dep); }
@@ -2683,7 +2684,8 @@ static void dwc3_stop_active_transfer(stu32 cmd;int ret; -if (!(dep->flags &DWC3_EP_TRANSFER_STARTED )) +if (!(dep->flags &DWC3_EP_TRANSFER_STARTED ) || + (dep->flags &DWC3_EP_END_TRANSFER_PENDING ))return ;/*
@@ -2728,6 +2730,8 @@ static void dwc3_stop_active_transfer(stif (!interrupt) dep->flags &= ~DWC3_EP_TRANSFER_STARTED ; +else + dep->flags |=DWC3_EP_END_TRANSFER_PENDING ;if (dwc3_is_usb31 (dwc) || dwc->revision <DWC3_REVISION_310A )udelay (100 );
Greg Kroah-Hartman
maintainerPATCH 38/309 usb: dwc3: gadget: Delay starting transfer
In reply to Greg Kroah-HartmanFrom: Thinh Nguyen <[email protected]>
commit da10bcdd6f70dc9977f2cf18f4783cf78520623a upstream.
If the END_TRANSFER command hasn't completed yet, then don't send the START_TRANSFER command. The controller may not be able to start if that's the case. Some controller revisions depend on this. See commit 76a638f8ac0d ("usb: dwc3: gadget: wait for End Transfer to complete"). Let's only send START_TRANSFER command after the END_TRANSFER command had completed.
--- drivers/usb/dwc3/core.h | 1 + drivers/usb/dwc3/gadget.c | 11 +++++++++++ 2 files changed, 12 insertions(+)
drivers/usb/dwc3/core.h +1 -0
@@ -690,6 +690,7 @@ struct dwc3_ep {#define DWC3_EP_TRANSFER_STARTED BIT(3)#define DWC3_EP_END_TRANSFER_PENDING BIT(4)#define DWC3_EP_PENDING_REQUEST BIT(5) +#define DWC3_EP_DELAY_START BIT(6)/* This last one is specific to EP0 */ #define DWC3_EP0_DIR_IN BIT(31)
drivers/usb/dwc3/gadget.c +11 -0
@@ -1447,6 +1447,12 @@ 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 ) { + dep->flags |=DWC3_EP_DELAY_START ; +return 0 ; + } +/* * NOTICE: Isochronous endpoints should NEVER be prestarted. We must * wait for a XferNotReady event so we will know what's the current
@@ -2628,6 +2634,11 @@ 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_DELAY_START ) && + !usb_endpoint_xfer_isoc (dep->endpoint.desc)) +__dwc3_gadget_kick_transfer (dep); + + dep->flags &= ~DWC3_EP_DELAY_START ; }break ;case DWC3_DEPEVT_STREAMEVT :
Greg Kroah-Hartman
maintainerPATCH 39/309 usb: typec: tcpci: mask event interrupts when remove driver
In reply to Greg Kroah-HartmanFrom: Jun Li <[email protected]>
commit 3ba76256fc4e2a0d7fb26cc95459041ea0e88972 upstream.
This is to prevent any possible events generated while unregister tpcm port.
--- drivers/usb/typec/tcpm/tcpci.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/usb/typec/tcpm/tcpci.c +6 -0
@@ -591,6 +591,12 @@ static int tcpci_probe(struct i2c_clientstatic int tcpci_remove (struct i2c_client *client) {struct tcpci_chip *chip =i2c_get_clientdata (client); +int err; + +/* Disable chip interrupts before unregistering port */ + err =tcpci_write16 (chip->tcpci,TCPC_ALERT_MASK ,0 ); +if (err <0 ) +return err;tcpci_unregister_port (chip->tcpci);
Greg Kroah-Hartman
maintainerPATCH 40/309 objtool: Silence build output
In reply to Greg Kroah-HartmanFrom: Olof Johansson <[email protected]>
commit 6ec14aa7a58a1c2fb303692f8cb1ff82d9abd10a upstream.
The sync-check.sh script prints out the path due to a "cd -" at the end of the script, even on silent builds. This isn't even needed, since the script is executed in our build instead of sourced (so it won't change the working directory of the surrounding build anyway).
Just remove the cd to make the build silent.
--- tools/objtool/sync-check.sh | 2 -- 1 file changed, 2 deletions(-)
tools/objtool/sync-check.sh +0 -2
@@ -47,5 +47,3 @@ check arch/x86/include/asm/inat.h '- check arch/x86/include/asm/insn.h '-I "^#include [\"<]\(asm/\)*inat.h[\">]"' check arch/x86/lib/inat.c '-I "^#include [\"<]\(../include/\)*asm/insn.h[\">]"' check arch/x86/lib/insn.c '-I "^#include [\"<]\(../include/\)*asm/in\(at\|sn\).h[\">]"' - -cd -
Greg Kroah-Hartman
maintainerPATCH 41/309 usb: gadget: f_fs: set req->num_sgs as 0 for non-sg transfer
In reply to Greg Kroah-HartmanFrom: Peter Chen <[email protected]>
commit d2450c6937018d40d4111fe830fa48d4ddceb8d0 upstream.
The UDC core uses req->num_sgs to judge if scatter buffer list is used.
Eg: usb_gadget_map_request_by_dev. For f_fs sync io mode, the request is re-used for each request, so if the 1st request->length > PAGE_SIZE, and the 2nd request->length is <= PAGE_SIZE, the f_fs uses the 1st req->num_sgs for the 2nd request, it causes the UDC core get the wrong req->num_sgs value (The 2nd request doesn't use sg). For f_fs async io mode, it is not harm to initialize req->num_sgs as 0 either, in case, the UDC driver doesn't zeroed request structure.
--- drivers/usb/gadget/function/f_fs.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/usb/gadget/function/f_fs.c +2 -0
@@ -1062,6 +1062,7 @@ static ssize_t ffs_epfile_io(struct file req->num_sgs = io_data->sgt.nents; }else { req->buf = data; + req->num_sgs =0 ; } req->length = data_len;
@@ -1105,6 +1106,7 @@ static ssize_t ffs_epfile_io(struct file req->num_sgs = io_data->sgt.nents; }else { req->buf = data; + req->num_sgs =0 ; } req->length = data_len;
Greg Kroah-Hartman
maintainerPATCH 42/309 usb: gadget: legacy: set max_speed to super-speed
In reply to Greg Kroah-HartmanFrom: Roger Quadros <[email protected]>
commit 463f67aec2837f981b0a0ce8617721ff59685c00 upstream.
These interfaces do support super-speed so let's not limit maximum speed to high-speed.
--- drivers/usb/gadget/legacy/cdc2.c | 2 +- drivers/usb/gadget/legacy/g_ffs.c | 2 +- drivers/usb/gadget/legacy/multi.c | 2 +- drivers/usb/gadget/legacy/ncm.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-)
drivers/usb/gadget/legacy/cdc2.c +1 -1
@@ -225,7 +225,7 @@ static struct usb_composite_driver cdc_d .name = "g_cdc", .dev = &device_desc, .strings = dev_strings, - .max_speed = USB_SPEED_HIGH, + .max_speed = USB_SPEED_SUPER, .bind = cdc_bind, .unbind = cdc_unbind, };
drivers/usb/gadget/legacy/g_ffs.c +1 -1
@@ -149,7 +149,7 @@ static struct usb_composite_driver gfs_d .name = DRIVER_NAME, .dev = &gfs_dev_desc, .strings = gfs_dev_strings, - .max_speed = USB_SPEED_HIGH, + .max_speed = USB_SPEED_SUPER, .bind = gfs_bind, .unbind = gfs_unbind, };
drivers/usb/gadget/legacy/multi.c +1 -1
@@ -482,7 +482,7 @@ static struct usb_composite_driver multi .name = "g_multi", .dev = &device_desc, .strings = dev_strings, - .max_speed = USB_SPEED_HIGH, + .max_speed = USB_SPEED_SUPER, .bind = multi_bind, .unbind = multi_unbind, .needs_serial = 1,
drivers/usb/gadget/legacy/ncm.c +1 -1
@@ -197,7 +197,7 @@ static struct usb_composite_driver ncm_d .name = "g_ncm", .dev = &device_desc, .strings = dev_strings, - .max_speed = USB_SPEED_HIGH, + .max_speed = USB_SPEED_SUPER, .bind = gncm_bind, .unbind = gncm_unbind, };
Greg Kroah-Hartman
maintainerPATCH 43/309 usb: gadget: f_ncm: Use atomic_t to track in-flight request
In reply to Greg Kroah-HartmanFrom: Bryan O'Donoghue <[email protected]>
commit 5b24c28cfe136597dc3913e1c00b119307a20c7e upstream.
Currently ncm->notify_req is used to flag when a request is in-flight. ncm->notify_req is set to NULL and when a request completes it is subsequently reset.
This is fundamentally buggy in that the unbind logic of the NCM driver will unconditionally free ncm->notify_req leading to a NULL pointer dereference.
--- drivers/usb/gadget/function/f_ncm.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
drivers/usb/gadget/function/f_ncm.c +13 -4
@@ -53,6 +53,7 @@ struct f_ncm {struct usb_ep *notify;struct usb_request *notify_req;u8 notify_state; +atomic_t notify_count;bool is_open;const struct ndp_parser_opts *parser_opts;
@@ -547,7 +548,7 @@ static void ncm_do_notify(struct f_ncm *int status;/* notification already in flight? */ -if (!req) +if (atomic_read (&ncm->notify_count))return ; event = req->buf;
@@ -587,7 +588,8 @@ static void ncm_do_notify(struct f_ncm * event->bmRequestType =0xA1 ; event->wIndex =cpu_to_le16 (ncm->ctrl_id); - ncm->notify_req =NULL ; +atomic_inc (&ncm->notify_count); +/* * In double buffering if there is a space in FIFO, * completion callback can be called right after the call,
@@ -597,7 +599,7 @@ static void ncm_do_notify(struct f_ncm * status =usb_ep_queue (ncm->notify, req,GFP_ATOMIC );spin_lock (&ncm->lock);if (status <0 ) { - ncm->notify_req = req; +atomic_dec (&ncm->notify_count);DBG (cdev,"notify --> %d\n" , status); } }
@@ -632,17 +634,19 @@ static void ncm_notify_complete(struct ucase 0 :VDBG (cdev,"Notification %02x sent\n" , event->bNotificationType); +atomic_dec (&ncm->notify_count);break ;case -ECONNRESET :case -ESHUTDOWN : +atomic_set (&ncm->notify_count,0 ); ncm->notify_state =NCM_NOTIFY_NONE ;break ;default :DBG (cdev,"event %02x --> %d\n" , event->bNotificationType, req->status); +atomic_dec (&ncm->notify_count);break ; } - ncm->notify_req = req;ncm_do_notify (ncm);spin_unlock (&ncm->lock); }
@@ -1649,6 +1653,11 @@ static void ncm_unbind(struct usb_config ncm_string_defs[0 ].id =0 ;usb_free_all_descriptors (f); +if (atomic_read (&ncm->notify_count)) { +usb_ep_dequeue (ncm->notify, ncm->notify_req); +atomic_set (&ncm->notify_count,0 ); + } +kfree (ncm->notify_req->buf);usb_ep_free_request (ncm->notify, ncm->notify_req); }
Greg Kroah-Hartman
maintainerPATCH 44/309 usb: gadget: f_ecm: Use atomic_t to track in-flight request
In reply to Greg Kroah-HartmanFrom: Bryan O'Donoghue <[email protected]>
commit d710562e01c48d59be3f60d58b7a85958b39aeda upstream.
Currently ecm->notify_req is used to flag when a request is in-flight. ecm->notify_req is set to NULL and when a request completes it is subsequently reset.
This is fundamentally buggy in that the unbind logic of the ECM driver will unconditionally free ecm->notify_req leading to a NULL pointer dereference.
--- drivers/usb/gadget/function/f_ecm.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
drivers/usb/gadget/function/f_ecm.c +12 -4
@@ -52,6 +52,7 @@ struct f_ecm {struct usb_ep *notify;struct usb_request *notify_req;u8 notify_state; +atomic_t notify_count;bool is_open;/* FIXME is_open needs some irq-ish locking
@@ -380,7 +381,7 @@ static void ecm_do_notify(struct f_ecm *int status;/* notification already in flight? */ -if (!req) +if (atomic_read (&ecm->notify_count))return ; event = req->buf;
@@ -420,10 +421,10 @@ static void ecm_do_notify(struct f_ecm * event->bmRequestType =0xA1 ; event->wIndex =cpu_to_le16 (ecm->ctrl_id); - ecm->notify_req =NULL ; +atomic_inc (&ecm->notify_count); status =usb_ep_queue (ecm->notify, req,GFP_ATOMIC );if (status <0 ) { - ecm->notify_req = req; +atomic_dec (&ecm->notify_count);DBG (cdev,"notify --> %d\n" , status); } }
@@ -448,17 +449,19 @@ static void ecm_notify_complete(struct uswitch (req->status) {case 0 :/* no fault */ +atomic_dec (&ecm->notify_count);break ;case -ECONNRESET :case -ESHUTDOWN : +atomic_set (&ecm->notify_count,0 ); ecm->notify_state =ECM_NOTIFY_NONE ;break ;default :DBG (cdev,"event %02x --> %d\n" , event->bNotificationType, req->status); +atomic_dec (&ecm->notify_count);break ; } - ecm->notify_req = req;ecm_do_notify (ecm); }
@@ -907,6 +910,11 @@ static void ecm_unbind(struct usb_configusb_free_all_descriptors (f); +if (atomic_read (&ecm->notify_count)) { +usb_ep_dequeue (ecm->notify, ecm->notify_req); +atomic_set (&ecm->notify_count,0 ); + } +kfree (ecm->notify_req->buf);usb_ep_free_request (ecm->notify, ecm->notify_req); }
Greg Kroah-Hartman
maintainerPATCH 45/309 ALSA: usb-audio: Fix endianess in descriptor validation
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit f8e5f90b3a53bb75f05124ed19156388379a337d upstream.
I overlooked that some fields are words and need the converts from LE in the recently added USB descriptor validation code. This patch fixes those with the proper macro usages.
--- sound/usb/validate.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
sound/usb/validate.c +3 -3
@@ -110,7 +110,7 @@ static bool validate_processing_unit(condefault :if (v->type ==UAC1_EXTENSION_UNIT )return true;/* OK */ -switch (d->wProcessType) { +switch (le16_to_cpu (d->wProcessType)) {case UAC_PROCESS_UP_DOWNMIX :case UAC_PROCESS_DOLBY_PROLOGIC :if (d->bLength < len +1 )/* bNrModes */
@@ -125,7 +125,7 @@ static bool validate_processing_unit(concase UAC_VERSION_2 :if (v->type ==UAC2_EXTENSION_UNIT_V2 )return true;/* OK */ -switch (d->wProcessType) { +switch (le16_to_cpu (d->wProcessType)) {case UAC2_PROCESS_UP_DOWNMIX :case UAC2_PROCESS_DOLBY_PROLOCIC :/* SiC! */ if (d->bLength < len +1 )/* bNrModes */
@@ -142,7 +142,7 @@ static bool validate_processing_unit(con len +=2 ;/* wClusterDescrID */ break ; } -switch (d->wProcessType) { +switch (le16_to_cpu (d->wProcessType)) {case UAC3_PROCESS_UP_DOWNMIX :if (d->bLength < len +1 )/* bNrModes */ return false;
Greg Kroah-Hartman
maintainerPATCH 46/309 ALSA: usb-audio: Annotate endianess in Scarlett gen2 quirk
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit d8f489355cff55b30731354317739a00cf1238bd upstream.
The Scarlett gen2 mixer quirk code defines a few record types to communicate via USB hub, and those must be all little-endian. This patch changes the field types to LE to annotate endianess properly. It also fixes the incorrect usage of leXX_to_cpu() in a couple of places, which was caught by sparse after this change.
--- sound/usb/mixer_scarlett_gen2.c | 46 ++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-)
sound/usb/mixer_scarlett_gen2.c +23 -23
@@ -558,11 +558,11 @@ static const struct scarlett2_config/* proprietary request/response format */ struct scarlett2_usb_packet { -u32 cmd; -u16 size; -u16 seq; -u32 error; -u32 pad; +__le32 cmd; +__le16 size; +__le16 seq; +__le32 error; +__le32 pad;u8 data[]; };
@@ -664,11 +664,11 @@ static int scarlett2_usb("Scarlett Gen 2 USB invalid response; " "cmd tx/rx %d/%d seq %d/%d size %d/%d " "error %d pad %d\n" , -le16_to_cpu (req->cmd),le16_to_cpu (resp->cmd), +le32_to_cpu (req->cmd),le32_to_cpu (resp->cmd),le16_to_cpu (req->seq),le16_to_cpu (resp->seq), resp_size,le16_to_cpu (resp->size), -le16_to_cpu (resp->error), - le16_to_cpu(resp->pad)); +le32_to_cpu (resp->error), + le32_to_cpu(resp->pad)); err = -EINVAL ; goto unlock; }
@@ -687,7 +687,7 @@ error:/* Send SCARLETT2_USB_DATA_CMD SCARLETT2_USB_CONFIG_SAVE */ static void scarlett2_config_save (struct usb_mixer_interface *mixer) { -u32 req =cpu_to_le32 (SCARLETT2_USB_CONFIG_SAVE ); +__le32 req =cpu_to_le32 (SCARLETT2_USB_CONFIG_SAVE ); scarlett2_usb(mixer, SCARLETT2_USB_DATA_CMD, &req, sizeof(u32),
@@ -713,11 +713,11 @@ static int scarlett2_usb_set_config(const struct scarlett2_config config_item = scarlett2_config_items[config_item_num];struct { -u32 offset; -u32 bytes; -s32 value; +__le32 offset; +__le32 bytes; +__le32 value; } __packed req; -u32 req2; +__le32 req2;int err;struct scarlett2_mixer_data *private = mixer->private_data;
@@ -753,8 +753,8 @@ static int scarlett2_usb_get( int offset, void *buf, int size) { struct { - u32 offset; -u32 size; + __le32 offset; +__le32 size; }__packed req; req.offset =cpu_to_le32 (offset);
@@ -794,8 +794,8 @@ static int scarlett2_usb_set_mix(structconst struct scarlett2_device_info *info = private->info;struct { -u16 mix_num; -u16 data[SCARLETT2_INPUT_MIX_MAX ]; +__le16 mix_num; +__le16 data[SCARLETT2_INPUT_MIX_MAX ]; } __packed req;int i, j;
@@ -850,9 +850,9 @@ static int scarlett2_usb_set_mux(struct };struct { -u16 pad; -u16 num; -u32 data[SCARLETT2_MUX_MAX ]; +__le16 pad; +__le16 num; +__le32 data[SCARLETT2_MUX_MAX ]; } __packed req; req.pad =0 ;
@@ -911,9 +911,9 @@ static int scarlett2_usb_get_meter_level u16 *levels) {struct { -u16 pad; -u16 num_meters; -u32 magic; +__le16 pad; +__le16 num_meters; +__le32 magic; } __packed req;u32 resp[SCARLETT2_NUM_METERS ];int i, err;
Greg Kroah-Hartman
maintainerPATCH 47/309 ALSA: dummy: Fix PCM format loop in proc output
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit 2acf25f13ebe8beb40e97a1bbe76f36277c64f1e upstream.
The loop termination for iterating over all formats should contain SNDRV_PCM_FORMAT_LAST, not less than it.
--- sound/drivers/dummy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/drivers/dummy.c +1 -1
@@ -915,7 +915,7 @@ static void print_formats(struct snd_dum {int i; -for (i =0 ; i <SNDRV_PCM_FORMAT_LAST ; i++) { +for (i =0 ; i <=SNDRV_PCM_FORMAT_LAST ; i++) {if (dummy->pcm_hw.formats & (1ULL << i))snd_iprintf (buffer," %s" ,snd_pcm_format_name (i)); }
Greg Kroah-Hartman
maintainerPATCH 48/309 memcg: fix a crash in wb_workfn when a device disappears
In reply to Greg Kroah-HartmanFrom: Theodore Ts'o <[email protected]>
commit 68f23b89067fdf187763e75a56087550624fdbee upstream.
Without memcg, there is a one-to-one mapping between the bdi and bdi_writeback structures. In this world, things are fairly straightforward; the first thing bdi_unregister() does is to shutdown the bdi_writeback structure (or wb), and part of that writeback ensures that no other work queued against the wb, and that the wb is fully drained.
With memcg, however, there is a one-to-many relationship between the bdi and bdi_writeback structures; that is, there are multiple wb objects which can all point to a single bdi. There is a refcount which prevents the bdi object from being released (and hence, unregistered). So in theory, the bdi_unregister() *should* only get called once its refcount goes to zero (bdi_put will drop the refcount, and when it is zero, release_bdi gets called, which calls bdi_unregister).
Unfortunately, del_gendisk() in block/gen_hd.c never got the memo about the Brave New memcg World, and calls bdi_unregister directly. It does this without informing the file system, or the memcg code, or anything else. This causes the root wb associated with the bdi to be unregistered, but none of the memcg-specific wb's are shutdown. So when one of these wb's are woken up to do delayed work, they try to dereference their wb->bdi->dev to fetch the device name, but unfortunately bdi->dev is now NULL, thanks to the bdi_unregister() called by del_gendisk(). As a result, *boom*.
Fortunately, it looks like the rest of the writeback path is perfectly happy with bdi->dev and bdi->owner being NULL, so the simplest fix is to create a bdi_dev_name() function which can handle bdi->dev being NULL. This also allows us to bulletproof the writeback tracepoints to prevent them from dereferencing a NULL pointer and crashing the kernel if one is tracing with memcg's enabled, and an iSCSI device dies or a USB storage stick is pulled.
The most common way of triggering this will be hotremoval of a device while writeback with memcg enabled is going on. It was triggering several times a day in a heavily loaded production environment.
Google Bug Id: 145475544
--- fs/fs-writeback.c | 2 +- include/linux/backing-dev.h | 10 ++++++++++ include/trace/events/writeback.h | 37 +++++++++++++++++-------------------- mm/backing-dev.c | 1 + 4 files changed, 29 insertions(+), 21 deletions(-)
fs/fs-writeback.c +1 -1
@@ -2063,7 +2063,7 @@ void wb_workfn(struct work_struct *work) struct bdi_writeback, dwork);long pages_written; -set_worker_desc ("flush-%s" ,dev_name (wb->bdi->dev)); +set_worker_desc ("flush-%s" ,bdi_dev_name (wb->bdi)); current->flags |=PF_SWAPWRITE ; if (likely(!current_is_workqueue_rescuer() ||
include/linux/backing-dev.h +10 -0
@@ -13,6 +13,7 @@#include <linux/fs.h> #include <linux/sched.h> #include <linux/blkdev.h> +#include <linux/device.h> #include <linux/writeback.h> #include <linux/blk-cgroup.h> #include <linux/backing-dev-defs.h>
@@ -504,4 +505,13 @@ static inline int bdi_rw_congested(struc (1 << WB_async_congested)); } +extern const char *bdi_unknown_name; + +static inline const char *bdi_dev_name (struct backing_dev_info *bdi) +{ +if (!bdi || !bdi->dev) +return bdi_unknown_name; +return dev_name (bdi->dev); +} +#endif /* _LINUX_BACKING_DEV_H */
include/trace/events/writeback.h +17 -20
@@ -67,8 +67,8 @@ DECLARE_EVENT_CLASS(writeback_page_templTP_fast_assign (strscpy_pad (__entry->name, - mapping ?dev_name (inode_to_bdi (mapping->host)->dev) :"(unknown)" , - 32); +bdi_dev_name (mapping ?inode_to_bdi (mapping->host) : + NULL), 32); __entry->ino = mapping ? mapping->host->i_ino :0 ; __entry->index = page->index; ),
@@ -111,8 +111,7 @@ DECLARE_EVENT_CLASS(writeback_dirty_inodstruct backing_dev_info *bdi =inode_to_bdi (inode);/* may be called for files on pseudo FSes w/ unregistered bdi */ -strscpy_pad (__entry->name, - bdi->dev ?dev_name (bdi->dev) :"(unknown)" ,32 ); +strscpy_pad (__entry->name,bdi_dev_name (bdi),32 ); __entry->ino = inode->i_ino; __entry->state = inode->i_state; __entry->flags = flags;
@@ -193,7 +192,7 @@ TRACE_EVENT(inode_foreign_history, ),TP_fast_assign ( - strncpy(__entry->name, dev_name(inode_to_bdi(inode)->dev), 32); + strncpy(__entry->name, bdi_dev_name(inode_to_bdi(inode)), 32); __entry->ino = inode->i_ino; __entry->cgroup_ino =__trace_wbc_assign_cgroup (wbc); __entry->history = history;
@@ -222,7 +221,7 @@ TRACE_EVENT(inode_switch_wbs, ),TP_fast_assign ( - strncpy(__entry->name, dev_name(old_wb->bdi->dev), 32); + strncpy(__entry->name, bdi_dev_name(old_wb->bdi), 32); __entry->ino = inode->i_ino; __entry->old_cgroup_ino =__trace_wb_assign_cgroup (old_wb); __entry->new_cgroup_ino =__trace_wb_assign_cgroup (new_wb);
@@ -255,7 +254,7 @@ TRACE_EVENT(track_foreign_dirty,struct address_space *mapping =page_mapping (page);struct inode *inode = mapping ? mapping->host :NULL ; -strncpy (__entry->name,dev_name (wb->bdi->dev),32 ); +strncpy (__entry->name,bdi_dev_name (wb->bdi),32 ); __entry->bdi_id = wb->bdi->id; __entry->ino = inode ? inode->i_ino :0 ; __entry->memcg_id = wb->memcg_css->id;
@@ -288,7 +287,7 @@ TRACE_EVENT(flush_foreign, ), TP_fast_assign( - strncpy(__entry->name, dev_name(wb->bdi->dev), 32); + strncpy(__entry->name, bdi_dev_name(wb->bdi), 32); __entry->cgroup_ino =__trace_wb_assign_cgroup (wb); __entry->frn_bdi_id = frn_bdi_id; __entry->frn_memcg_id = frn_memcg_id;
@@ -318,7 +317,7 @@ DECLARE_EVENT_CLASS(writeback_write_inodTP_fast_assign (strscpy_pad (__entry->name, - dev_name(inode_to_bdi(inode)->dev), 32); + bdi_dev_name(inode_to_bdi(inode)), 32); __entry->ino = inode->i_ino; __entry->sync_mode = wbc->sync_mode; __entry->cgroup_ino =__trace_wbc_assign_cgroup (wbc);
@@ -361,9 +360,7 @@ DECLARE_EVENT_CLASS(writeback_work_class __field(unsigned int, cgroup_ino) ),TP_fast_assign ( - strscpy_pad(__entry->name, - wb->bdi->dev ? dev_name(wb->bdi->dev) : - "(unknown)", 32); + strscpy_pad(__entry->name, bdi_dev_name(wb->bdi), 32); __entry->nr_pages = work->nr_pages; __entry->sb_dev = work->sb ? work->sb->s_dev :0 ; __entry->sync_mode = work->sync_mode;
@@ -416,7 +413,7 @@ DECLARE_EVENT_CLASS(writeback_class, __field(unsigned int, cgroup_ino) ),TP_fast_assign ( - strscpy_pad(__entry->name, dev_name(wb->bdi->dev), 32); + strscpy_pad(__entry->name, bdi_dev_name(wb->bdi), 32); __entry->cgroup_ino =__trace_wb_assign_cgroup (wb); ), TP_printk("bdi %s: cgroup_ino=%u",
@@ -438,7 +435,7 @@ TRACE_EVENT(writeback_bdi_register,__array (char, name,32 ) ),TP_fast_assign ( - strscpy_pad(__entry->name, dev_name(bdi->dev), 32); + strscpy_pad(__entry->name, bdi_dev_name(bdi), 32); ),TP_printk ("bdi %s" , __entry->name
@@ -463,7 +460,7 @@ DECLARE_EVENT_CLASS(wbc_class, ), TP_fast_assign( - strscpy_pad(__entry->name, dev_name(bdi->dev), 32); + strscpy_pad(__entry->name, bdi_dev_name(bdi), 32); __entry->nr_to_write = wbc->nr_to_write; __entry->pages_skipped = wbc->pages_skipped; __entry->sync_mode = wbc->sync_mode;
@@ -514,7 +511,7 @@ TRACE_EVENT(writeback_queue_io, ),TP_fast_assign ( unsigned long *older_than_this = work->older_than_this; -strscpy_pad (__entry->name,dev_name (wb->bdi->dev),32 ); +strscpy_pad (__entry->name,bdi_dev_name (wb->bdi),32 ); __entry->older = older_than_this ? *older_than_this :0 ; __entry->age = older_than_this ? (jiffies - *older_than_this) *1000 /HZ :-1 ;
@@ -600,7 +597,7 @@ TRACE_EVENT(bdi_dirty_ratelimit, ),TP_fast_assign ( - strscpy_pad(__entry->bdi, dev_name(wb->bdi->dev), 32); + strscpy_pad(__entry->bdi, bdi_dev_name(wb->bdi), 32); __entry->write_bw =KBps (wb->write_bandwidth); __entry->avg_write_bw =KBps (wb->avg_write_bandwidth); __entry->dirty_rate =KBps (dirty_rate);
@@ -665,7 +662,7 @@ TRACE_EVENT(balance_dirty_pages, TP_fast_assign( unsigned long freerun = (thresh + bg_thresh) / 2; -strscpy_pad (__entry->bdi,dev_name (wb->bdi->dev),32 ); +strscpy_pad (__entry->bdi,bdi_dev_name (wb->bdi),32 ); __entry->limit = global_wb_domain.dirty_limit; __entry->setpoint = (global_wb_domain.dirty_limit +
@@ -726,7 +723,7 @@ TRACE_EVENT(writeback_sb_inodes_requeue,TP_fast_assign (strscpy_pad (__entry->name, - dev_name(inode_to_bdi(inode)->dev), 32); + bdi_dev_name(inode_to_bdi(inode)), 32); __entry->ino = inode->i_ino; __entry->state = inode->i_state; __entry->dirtied_when = inode->dirtied_when;
@@ -800,7 +797,7 @@ DECLARE_EVENT_CLASS(writeback_single_inoTP_fast_assign (strscpy_pad (__entry->name, - dev_name(inode_to_bdi(inode)->dev), 32); + bdi_dev_name(inode_to_bdi(inode)), 32); __entry->ino = inode->i_ino; __entry->state = inode->i_state; __entry->dirtied_when = inode->dirtied_when;
mm/backing-dev.c +1 -0
@@ -21,6 +21,7 @@ struct backing_dev_info noop_backing_devEXPORT_SYMBOL_GPL (noop_backing_dev_info);static struct class *bdi_class; +const char *bdi_unknown_name ="(unknown)" ;/* * bdi_lock protects bdi_tree and updates to bdi_list. bdi_list has RCU
Greg Kroah-Hartman
maintainerPATCH 49/309 mm/sparse.c: reset sections mem_map when fully deactivated
In reply to Greg Kroah-HartmanFrom: Pingfan Liu <[email protected]>
commit 1f503443e7df8dc8366608b4d810ce2d6669827c upstream.
After commit ba72b4c8cf60 ("mm/sparsemem: support sub-section hotplug"), when a mem section is fully deactivated, section_mem_map still records the section's start pfn, which is not used any more and will be reassigned during re-addition.
In analogy with alloc/free pattern, it is better to clear all fields of section_mem_map.
Beside this, it breaks the user space tool "makedumpfile" [1], which makes assumption that a hot-removed section has mem_map as NULL, instead of checking directly against SECTION_MARKED_PRESENT bit. (makedumpfile will be better to change the assumption, and need a patch)
The bug can be reproduced on IBM POWERVM by "drmgr -c mem -r -q 5" , trigger a crash, and save vmcore by makedumpfile
[1]: makedumpfile, commit e73016540293 ("[v1.6.7] Update version")
--- mm/sparse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/sparse.c +1 -1
@@ -787,7 +787,7 @@ static void section_deactivate(unsigned ms->usage =NULL ; } memmap =sparse_decode_mem_map (ms->section_mem_map, section_nr); - ms->section_mem_map =sparse_encode_mem_map (NULL , section_nr); + ms->section_mem_map = (unsigned long )NULL ; }if (section_is_early && memmap)
Greg Kroah-Hartman
maintainerPATCH 50/309 mmc: sdhci-pci: Make function amd_sdhci_reset static
In reply to Greg Kroah-HartmanFrom: zhengbin <[email protected]>
commit 38413ce39a4bd908c02257cd2f9e0c92b27886f4 upstream.
Fix sparse warnings:
drivers/mmc/host/sdhci-pci-core.c:1599:6: warning: symbol 'amd_sdhci_reset' was not declared. Should it be static?
--- drivers/mmc/host/sdhci-pci-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/mmc/host/sdhci-pci-core.c +1 -1
@@ -1604,7 +1604,7 @@ static u32 sdhci_read_present_state(strureturn sdhci_readl (host,SDHCI_PRESENT_STATE ); } -void amd_sdhci_reset (struct sdhci_host *host,u8 mask) +static void amd_sdhci_reset (struct sdhci_host *host,u8 mask) {struct sdhci_pci_slot *slot =sdhci_priv (host);struct pci_dev *pdev = slot->chip->pdev;
Greg Kroah-Hartman
maintainerPATCH 51/309 utimes: Clamp the timestamps in notify_change()
In reply to Greg Kroah-HartmanFrom: Amir Goldstein <[email protected]>
commit eb31e2f63d85d1bec4f7b136f317e03c03db5503 upstream.
Push clamping timestamps into notify_change(), so in-kernel callers like nfsd and overlayfs will get similar timestamp set behavior as utimes.
AV: get rid of clamping in ->setattr() instances; we don't need to bother with that there, with notify_change() doing normalization in all cases now (it already did for implicit case, since current_time() clamps).
--- fs/attr.c | 23 +++++++++++------------ fs/configfs/inode.c | 9 +++------ fs/f2fs/file.c | 18 ++++++------------ fs/ntfs/inode.c | 18 ++++++------------ fs/ubifs/file.c | 18 ++++++------------ fs/utimes.c | 4 ++-- 6 files changed, 34 insertions(+), 56 deletions(-)
fs/attr.c +11 -12
@@ -183,18 +183,12 @@ void setattr_copy(struct inode *inode, c inode->i_uid = attr->ia_uid;if (ia_valid &ATTR_GID ) inode->i_gid = attr->ia_gid; -if (ia_valid &ATTR_ATIME ) { - inode->i_atime =timestamp_truncate (attr->ia_atime, - inode); - } -if (ia_valid &ATTR_MTIME ) { - inode->i_mtime =timestamp_truncate (attr->ia_mtime, - inode); - } -if (ia_valid &ATTR_CTIME ) { - inode->i_ctime =timestamp_truncate (attr->ia_ctime, - inode); - } +if (ia_valid &ATTR_ATIME ) + inode->i_atime = attr->ia_atime; +if (ia_valid &ATTR_MTIME ) + inode->i_mtime = attr->ia_mtime; +if (ia_valid &ATTR_CTIME ) + inode->i_ctime = attr->ia_ctime;if (ia_valid &ATTR_MODE ) {umode_t mode = attr->ia_mode;
@@ -268,8 +262,13 @@ int notify_change(struct dentry * dentry attr->ia_ctime = now;if (!(ia_valid &ATTR_ATIME_SET )) attr->ia_atime = now; +else + attr->ia_atime =timestamp_truncate (attr->ia_atime, inode);if (!(ia_valid &ATTR_MTIME_SET )) attr->ia_mtime = now; +else + attr->ia_mtime =timestamp_truncate (attr->ia_mtime, inode); +if (ia_valid &ATTR_KILL_PRIV ) { error =security_inode_need_killpriv (dentry);if (error <0 )
fs/configfs/inode.c +3 -6
@@ -76,14 +76,11 @@ int configfs_setattr(struct dentry * denif (ia_valid &ATTR_GID ) sd_iattr->ia_gid = iattr->ia_gid;if (ia_valid &ATTR_ATIME ) - sd_iattr->ia_atime =timestamp_truncate (iattr->ia_atime, - inode); + sd_iattr->ia_atime = iattr->ia_atime;if (ia_valid &ATTR_MTIME ) - sd_iattr->ia_mtime =timestamp_truncate (iattr->ia_mtime, - inode); + sd_iattr->ia_mtime = iattr->ia_mtime;if (ia_valid &ATTR_CTIME ) - sd_iattr->ia_ctime =timestamp_truncate (iattr->ia_ctime, - inode); + sd_iattr->ia_ctime = iattr->ia_ctime;if (ia_valid &ATTR_MODE ) {umode_t mode = iattr->ia_mode;
fs/f2fs/file.c +6 -12
@@ -751,18 +751,12 @@ static void __setattr_copy(struct inode inode->i_uid = attr->ia_uid;if (ia_valid &ATTR_GID ) inode->i_gid = attr->ia_gid; -if (ia_valid &ATTR_ATIME ) { - inode->i_atime =timestamp_truncate (attr->ia_atime, - inode); - } -if (ia_valid &ATTR_MTIME ) { - inode->i_mtime =timestamp_truncate (attr->ia_mtime, - inode); - } -if (ia_valid &ATTR_CTIME ) { - inode->i_ctime =timestamp_truncate (attr->ia_ctime, - inode); - } +if (ia_valid &ATTR_ATIME ) + inode->i_atime = attr->ia_atime; +if (ia_valid &ATTR_MTIME ) + inode->i_mtime = attr->ia_mtime; +if (ia_valid &ATTR_CTIME ) + inode->i_ctime = attr->ia_ctime;if (ia_valid &ATTR_MODE ) {umode_t mode = attr->ia_mode;
fs/ntfs/inode.c +6 -12
@@ -2899,18 +2899,12 @@ int ntfs_setattr(struct dentry *dentry, ia_valid |=ATTR_MTIME |ATTR_CTIME ; } } -if (ia_valid &ATTR_ATIME ) { - vi->i_atime =timestamp_truncate (attr->ia_atime, - vi); - } -if (ia_valid &ATTR_MTIME ) { - vi->i_mtime =timestamp_truncate (attr->ia_mtime, - vi); - } -if (ia_valid &ATTR_CTIME ) { - vi->i_ctime =timestamp_truncate (attr->ia_ctime, - vi); - } +if (ia_valid &ATTR_ATIME ) + vi->i_atime = attr->ia_atime; +if (ia_valid &ATTR_MTIME ) + vi->i_mtime = attr->ia_mtime; +if (ia_valid &ATTR_CTIME ) + vi->i_ctime = attr->ia_ctime;mark_inode_dirty (vi); out:return err;
fs/ubifs/file.c +6 -12
@@ -1078,18 +1078,12 @@ static void do_attr_changes(struct inode inode->i_uid = attr->ia_uid;if (attr->ia_valid &ATTR_GID ) inode->i_gid = attr->ia_gid; -if (attr->ia_valid &ATTR_ATIME ) { - inode->i_atime =timestamp_truncate (attr->ia_atime, - inode); - } -if (attr->ia_valid &ATTR_MTIME ) { - inode->i_mtime =timestamp_truncate (attr->ia_mtime, - inode); - } -if (attr->ia_valid &ATTR_CTIME ) { - inode->i_ctime =timestamp_truncate (attr->ia_ctime, - inode); - } +if (attr->ia_valid &ATTR_ATIME ) + inode->i_atime = attr->ia_atime; +if (attr->ia_valid &ATTR_MTIME ) + inode->i_mtime = attr->ia_mtime; +if (attr->ia_valid &ATTR_CTIME ) + inode->i_ctime = attr->ia_ctime;if (attr->ia_valid &ATTR_MODE ) {umode_t mode = attr->ia_mode;
fs/utimes.c +2 -2
@@ -36,14 +36,14 @@ static int utimes_common(const struct paif (times[0 ].tv_nsec ==UTIME_OMIT ) newattrs.ia_valid &= ~ATTR_ATIME ;else if (times[0 ].tv_nsec !=UTIME_NOW ) { - newattrs.ia_atime =timestamp_truncate (times[0 ], inode); + newattrs.ia_atime = times[0 ]; newattrs.ia_valid |=ATTR_ATIME_SET ; }if (times[1 ].tv_nsec ==UTIME_OMIT ) newattrs.ia_valid &= ~ATTR_MTIME ;else if (times[1 ].tv_nsec !=UTIME_NOW ) { - newattrs.ia_mtime =timestamp_truncate (times[1 ], inode); + newattrs.ia_mtime = times[1 ]; newattrs.ia_valid |=ATTR_MTIME_SET ; }/*
Greg Kroah-Hartman
maintainerPATCH 52/309 mm/memory_hotplug: fix remove_memory() lockdep splat
In reply to Greg Kroah-HartmanFrom: Dan Williams <[email protected]>
commit f1037ec0cc8ac1a450974ad9754e991f72884f48 upstream.
The daxctl unit test for the dax_kmem driver currently triggers the (false positive) lockdep splat below. It results from the fact that remove_memory_block_devices() is invoked under the mem_hotplug_lock() causing lockdep entanglements with cpu_hotplug_lock() and sysfs (kernfs active state tracking). It is a false positive because the sysfs attribute path triggering the memory remove is not the same attribute path associated with memory-block device.
sysfs_break_active_protection() is not applicable since there is no real deadlock conflict, instead move memory-block device removal outside the lock. The mem_hotplug_lock() is not needed to synchronize the memory-block device removal vs the page online state, that is already handled by lock_device_hotplug(). Specifically, lock_device_hotplug() is sufficient to allow try_remove_memory() to check the offline state of the memblocks and be assured that any in progress online attempts are flushed / blocked by kernfs_drain() / attribute removal.
The add_memory() path safely creates memblock devices under the mem_hotplug_lock(). There is no kernfs active state synchronization in the memblock device_register() path, so nothing to fix there.
This change is only possible thanks to the recent change that refactored memory block device removal out of arch_remove_memory() (commit 4c4b7f9ba948 "mm/memory_hotplug: remove memory block devices before arch_remove_memory()"), and David's due diligence tracking down the guarantees afforded by kernfs_drain(). Not flagged for -stable since this only impacts ongoing development and lockdep validation, not a runtime issue.
======================================================
WARNING: possible circular locking dependency detected
5.5.0-rc3+ #230 Tainted: G OE
------------------------------------------------------
lt-daxctl/6459 is trying to acquire lock:
ffff99c7f0003510 (kn->count#241){++++}, at: kernfs_remove_by_name_ns+0x41/0x80
but task is already holding lock:
ffffffffa76a5450 (mem_hotplug_lock.rw_sem){++++}, at: percpu_down_write+0x20/0xe0
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #2 (mem_hotplug_lock.rw_sem){++++}:
__lock_acquire+0x39c/0x790
lock_acquire+0xa2/0x1b0
get_online_mems+0x3e/0xb0
kmem_cache_create_usercopy+0x2e/0x260
kmem_cache_create+0x12/0x20
ptlock_cache_init+0x20/0x28
start_kernel+0x243/0x547
secondary_startup_64+0xb6/0xc0
-> #1 (cpu_hotplug_lock.rw_sem){++++}:
__lock_acquire+0x39c/0x790
lock_acquire+0xa2/0x1b0
cpus_read_lock+0x3e/0xb0
online_pages+0x37/0x300
memory_subsys_online+0x17d/0x1c0
device_online+0x60/0x80
state_store+0x65/0xd0
kernfs_fop_write+0xcf/0x1c0
vfs_write+0xdb/0x1d0
ksys_write+0x65/0xe0
do_syscall_64+0x5c/0xa0
entry_SYSCALL_64_after_hwframe+0x49/0xbe
-> #0 (kn->count#241){++++}:
check_prev_add+0x98/0xa40
validate_chain+0x576/0x860
__lock_acquire+0x39c/0x790
lock_acquire+0xa2/0x1b0
__kernfs_remove+0x25f/0x2e0
kernfs_remove_by_name_ns+0x41/0x80
remove_files.isra.0+0x30/0x70
sysfs_remove_group+0x3d/0x80
sysfs_remove_groups+0x29/0x40
device_remove_attrs+0x39/0x70
device_del+0x16a/0x3f0
device_unregister+0x16/0x60
remove_memory_block_devices+0x82/0xb0
try_remove_memory+0xb5/0x130
remove_memory+0x26/0x40
dev_dax_kmem_remove+0x44/0x6a [kmem]
device_release_driver_internal+0xe4/0x1c0
unbind_store+0xef/0x120
kernfs_fop_write+0xcf/0x1c0
vfs_write+0xdb/0x1d0
ksys_write+0x65/0xe0
do_syscall_64+0x5c/0xa0
entry_SYSCALL_64_after_hwframe+0x49/0xbe
other info that might help us debug this:
Chain exists of:
kn->count#241 --> cpu_hotplug_lock.rw_sem --> mem_hotplug_lock.rw_sem
Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(mem_hotplug_lock.rw_sem);
lock(cpu_hotplug_lock.rw_sem);
lock(mem_hotplug_lock.rw_sem);
lock(kn->count#241);
*** DEADLOCK ***No fixes tag as this has been a long standing issue that predated the addition of kernfs lockdep annotations.
--- mm/memory_hotplug.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
mm/memory_hotplug.c +6 -3
@@ -1738,8 +1738,6 @@ static int __ref try_remove_memory(int nBUG_ON (check_hotplug_memory_range (start, size)); -mem_hotplug_begin (); -/* * All memory blocks must be offlined before removing memory. Check * whether all memory blocks in question are offline and return error
@@ -1754,9 +1752,14 @@ static int __ref try_remove_memory(int nmemblock_free (start, size);memblock_remove (start, size); -/* remove memory block devices before removing memory */ +/* +* Memory block device removal under the device_hotplug_lock is +* a barrier against racing online attempts. +*/ remove_memory_block_devices (start, size); +mem_hotplug_begin (); +arch_remove_memory (nid, start, size,NULL );__release_memory_resource (start, size);
Greg Kroah-Hartman
maintainerPATCH 53/309 mm: thp: dont need care deferred split queue in memcg charge move path
In reply to Greg Kroah-HartmanFrom: Wei Yang <[email protected]>
commit fac0516b5534897bf4c4a88daa06a8cfa5611b23 upstream.
If compound is true, this means it is a PMD mapped THP. Which implies the page is not linked to any defer list. So the first code chunk will not be executed.
Also with this reason, it would not be proper to add this page to a defer list. So the second code chunk is not correct.
Based on this, we should remove the defer list related code.
--- mm/memcontrol.c | 18 ------------------ 1 file changed, 18 deletions(-)
mm/memcontrol.c +0 -18
@@ -5465,14 +5465,6 @@ static int mem_cgroup_move_account(struc__mod_lruvec_state (to_vec,NR_WRITEBACK , nr_pages); } -#ifdef CONFIG_TRANSPARENT_HUGEPAGE -if (compound && !list_empty (page_deferred_list (page))) { -spin_lock (&from->deferred_split_queue.split_queue_lock); -list_del_init (page_deferred_list (page)); - from->deferred_split_queue.split_queue_len--; -spin_unlock (&from->deferred_split_queue.split_queue_lock); - } -#endif /* * It is safe to change page->mem_cgroup here because the page * is referenced, charged, and isolated - we can't race with
@@ -5482,16 +5474,6 @@ static int mem_cgroup_move_account(struc/* caller should have done css_get */ page->mem_cgroup = to; -#ifdef CONFIG_TRANSPARENT_HUGEPAGE -if (compound &&list_empty (page_deferred_list (page))) { -spin_lock (&to->deferred_split_queue.split_queue_lock); -list_add_tail (page_deferred_list (page), - &to->deferred_split_queue.split_queue); - to->deferred_split_queue.split_queue_len++; -spin_unlock (&to->deferred_split_queue.split_queue_lock); - } -#endif -spin_unlock_irqrestore (&from->move_lock, flags); ret =0 ;
Greg Kroah-Hartman
maintainerPATCH 54/309 mm: move_pages: report the number of non-attempted pages
In reply to Greg Kroah-HartmanFrom: Yang Shi <[email protected]>
commit 5984fabb6e82d9ab4e6305cb99694c85d46de8ae upstream.
Since commit a49bd4d71637 ("mm, numa: rework do_pages_move"), the semantic of move_pages() has changed to return the number of non-migrated pages if they were result of a non-fatal reasons (usually a busy page).
This was an unintentional change that hasn't been noticed except for LTP tests which checked for the documented behavior.
There are two ways to go around this change. We can even get back to the original behavior and return -EAGAIN whenever migrate_pages is not able to migrate pages due to non-fatal reasons. Another option would be to simply continue with the changed semantic and extend move_pages documentation to clarify that -errno is returned on an invalid input or when migration simply cannot succeed (e.g. -ENOMEM, -EBUSY) or the number of pages that couldn't have been migrated due to ephemeral reasons (e.g. page is pinned or locked for other reasons).
This patch implements the second option because this behavior is in place for some time without anybody complaining and possibly new users depending on it. Also it allows to have a slightly easier error handling as the caller knows that it is worth to retry when err > 0.
But since the new semantic would be aborted immediately if migration is failed due to ephemeral reasons, need include the number of non-attempted pages in the return value too.
--- mm/migrate.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-)
mm/migrate.c +23 -2
@@ -1631,8 +1631,19 @@ static int do_pages_move(struct mm_struc start = i; }else if (node != current_node) { err =do_move_pages_to_node (mm, &pagelist, current_node); -if (err) +if (err) { +/* +* Positive err means the number of failed +* pages to migrate. Since we are going to +* abort and return the number of non-migrated +* pages, so need to incude the rest of the +* nr_pages that have not been attempted as +* well. +*/ +if (err >0 ) + err += nr_pages - i -1 ; goto out; + } err =store_status (status, start, current_node, i - start);if (err) goto out;
@@ -1663,8 +1674,11 @@ static int do_pages_move(struct mm_struc goto out_flush; err =do_move_pages_to_node (mm, &pagelist, current_node); -if (err) +if (err) { +if (err >0 ) + err += nr_pages - i -1 ; goto out; + }if (i > start) { err =store_status (status, start, current_node, i - start);if (err)
@@ -1678,6 +1692,13 @@ out_flush:/* Make sure we do not overwrite the existing error */ err1 =do_move_pages_to_node (mm, &pagelist, current_node); +/* +* Don't have to report non-attempted pages here since: +* - If the above loop is done gracefully all pages have been +* attempted. +* - If the above loop is aborted it means a fatal error +* happened, should return ret. +*/ if (!err1) err1 =store_status (status, start, current_node, i - start);if (err >=0 )
Greg Kroah-Hartman
maintainerPATCH 55/309 media/v4l2-core: set pages dirty upon releasing DMA buffers
In reply to Greg Kroah-HartmanFrom: John Hubbard <[email protected]>
commit 3c7470b6f68434acae459482ab920d1e3fabd1c7 upstream.
After DMA is complete, and the device and CPU caches are synchronized, it's still required to mark the CPU pages as dirty, if the data was coming from the device. However, this driver was just issuing a bare put_page() call, without any set_page_dirty*() call.
Fix the problem, by calling set_page_dirty_lock() if the CPU pages were potentially receiving data from the device.
--- drivers/media/v4l2-core/videobuf-dma-sg.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/media/v4l2-core/videobuf-dma-sg.c +4 -1
@@ -349,8 +349,11 @@ int videobuf_dma_free(struct videobuf_dmBUG_ON (dma->sglen);if (dma->pages) { -for (i =0 ; i < dma->nr_pages; i++) +for (i =0 ; i < dma->nr_pages; i++) { +if (dma->direction ==DMA_FROM_DEVICE ) +set_page_dirty_lock (dma->pages[i]);put_page (dma->pages[i]); + }kfree (dma->pages); dma->pages =NULL ; }
Greg Kroah-Hartman
maintainerPATCH 56/309 media: v4l2-core: compat: ignore native command codes
In reply to Greg Kroah-HartmanFrom: Arnd Bergmann <[email protected]>
commit 4a873f3fa5d6ca52e446d306dd7194dd86a09422 upstream.
The do_video_ioctl() compat handler converts the compat command codes into the native ones before processing further, but this causes problems for 32-bit user applications that pass a command code that matches a 64-bit native number, which will then be handled the same way.
Specifically, this breaks VIDIOC_DQEVENT_TIME from user space applications with 64-bit time_t, as the structure layout is the same as the native 64-bit layout on many architectures (x86 being the notable exception).
Change the handler to use the converted command code only for passing into the native ioctl handler, not for deciding on the conversion, in order to make the compat behavior match the native behavior.
Actual support for the 64-bit time_t version of VIDIOC_DQEVENT_TIME and other commands still needs to be added in a separate patch.
--- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 148 +++++++++++++------------- 1 file changed, 75 insertions(+), 73 deletions(-)
drivers/media/v4l2-core/v4l2-compat-ioctl32.c +75 -73
@@ -1183,36 +1183,38 @@ static long do_video_ioctl(struct file *u32 aux_space;int compatible_arg =1 ;long err =0 ; +unsigned int ncmd;/* * 1. When struct size is different, converts the command. */ switch (cmd) { -case VIDIOC_G_FMT32 : cmd =VIDIOC_G_FMT ;break ; -case VIDIOC_S_FMT32 : cmd =VIDIOC_S_FMT ;break ; -case VIDIOC_QUERYBUF32 : cmd =VIDIOC_QUERYBUF ;break ; -case VIDIOC_G_FBUF32 : cmd =VIDIOC_G_FBUF ;break ; -case VIDIOC_S_FBUF32 : cmd =VIDIOC_S_FBUF ;break ; -case VIDIOC_QBUF32 : cmd =VIDIOC_QBUF ;break ; -case VIDIOC_DQBUF32 : cmd =VIDIOC_DQBUF ;break ; -case VIDIOC_ENUMSTD32 : cmd =VIDIOC_ENUMSTD ;break ; -case VIDIOC_ENUMINPUT32 : cmd =VIDIOC_ENUMINPUT ;break ; -case VIDIOC_TRY_FMT32 : cmd =VIDIOC_TRY_FMT ;break ; -case VIDIOC_G_EXT_CTRLS32 : cmd =VIDIOC_G_EXT_CTRLS ;break ; -case VIDIOC_S_EXT_CTRLS32 : cmd =VIDIOC_S_EXT_CTRLS ;break ; -case VIDIOC_TRY_EXT_CTRLS32 : cmd =VIDIOC_TRY_EXT_CTRLS ;break ; -case VIDIOC_DQEVENT32 : cmd =VIDIOC_DQEVENT ;break ; -case VIDIOC_OVERLAY32 : cmd =VIDIOC_OVERLAY ;break ; -case VIDIOC_STREAMON32 : cmd =VIDIOC_STREAMON ;break ; -case VIDIOC_STREAMOFF32 : cmd =VIDIOC_STREAMOFF ;break ; -case VIDIOC_G_INPUT32 : cmd =VIDIOC_G_INPUT ;break ; -case VIDIOC_S_INPUT32 : cmd =VIDIOC_S_INPUT ;break ; -case VIDIOC_G_OUTPUT32 : cmd =VIDIOC_G_OUTPUT ;break ; -case VIDIOC_S_OUTPUT32 : cmd =VIDIOC_S_OUTPUT ;break ; -case VIDIOC_CREATE_BUFS32 : cmd =VIDIOC_CREATE_BUFS ;break ; -case VIDIOC_PREPARE_BUF32 : cmd =VIDIOC_PREPARE_BUF ;break ; -case VIDIOC_G_EDID32 : cmd =VIDIOC_G_EDID ;break ; -case VIDIOC_S_EDID32 : cmd =VIDIOC_S_EDID ;break ; +case VIDIOC_G_FMT32 : ncmd =VIDIOC_G_FMT ;break ; +case VIDIOC_S_FMT32 : ncmd =VIDIOC_S_FMT ;break ; +case VIDIOC_QUERYBUF32 : ncmd =VIDIOC_QUERYBUF ;break ; +case VIDIOC_G_FBUF32 : ncmd =VIDIOC_G_FBUF ;break ; +case VIDIOC_S_FBUF32 : ncmd =VIDIOC_S_FBUF ;break ; +case VIDIOC_QBUF32 : ncmd =VIDIOC_QBUF ;break ; +case VIDIOC_DQBUF32 : ncmd =VIDIOC_DQBUF ;break ; +case VIDIOC_ENUMSTD32 : ncmd =VIDIOC_ENUMSTD ;break ; +case VIDIOC_ENUMINPUT32 : ncmd =VIDIOC_ENUMINPUT ;break ; +case VIDIOC_TRY_FMT32 : ncmd =VIDIOC_TRY_FMT ;break ; +case VIDIOC_G_EXT_CTRLS32 : ncmd =VIDIOC_G_EXT_CTRLS ;break ; +case VIDIOC_S_EXT_CTRLS32 : ncmd =VIDIOC_S_EXT_CTRLS ;break ; +case VIDIOC_TRY_EXT_CTRLS32 : ncmd =VIDIOC_TRY_EXT_CTRLS ;break ; +case VIDIOC_DQEVENT32 : ncmd =VIDIOC_DQEVENT ;break ; +case VIDIOC_OVERLAY32 : ncmd =VIDIOC_OVERLAY ;break ; +case VIDIOC_STREAMON32 : ncmd =VIDIOC_STREAMON ;break ; +case VIDIOC_STREAMOFF32 : ncmd =VIDIOC_STREAMOFF ;break ; +case VIDIOC_G_INPUT32 : ncmd =VIDIOC_G_INPUT ;break ; +case VIDIOC_S_INPUT32 : ncmd =VIDIOC_S_INPUT ;break ; +case VIDIOC_G_OUTPUT32 : ncmd =VIDIOC_G_OUTPUT ;break ; +case VIDIOC_S_OUTPUT32 : ncmd =VIDIOC_S_OUTPUT ;break ; +case VIDIOC_CREATE_BUFS32 : ncmd =VIDIOC_CREATE_BUFS ;break ; +case VIDIOC_PREPARE_BUF32 : ncmd =VIDIOC_PREPARE_BUF ;break ; +case VIDIOC_G_EDID32 : ncmd =VIDIOC_G_EDID ;break ; +case VIDIOC_S_EDID32 : ncmd =VIDIOC_S_EDID ;break ; +default : ncmd = cmd;break ; }/*
@@ -1221,11 +1223,11 @@ static long do_video_ioctl(struct file ** argument into it. */ switch (cmd) { -case VIDIOC_OVERLAY : -case VIDIOC_STREAMON : -case VIDIOC_STREAMOFF : -case VIDIOC_S_INPUT : -case VIDIOC_S_OUTPUT : +case VIDIOC_OVERLAY32 : +case VIDIOC_STREAMON32 : +case VIDIOC_STREAMOFF32 : +case VIDIOC_S_INPUT32 : +case VIDIOC_S_OUTPUT32 : err =alloc_userspace (sizeof (unsigned int ),0 , &new_p64);if (!err &&assign_in_user ((unsigned int __user *)new_p64, (compat_uint_t __user *)p32))
@@ -1233,23 +1235,23 @@ static long do_video_ioctl(struct file * compatible_arg =0 ;break ; -case VIDIOC_G_INPUT : -case VIDIOC_G_OUTPUT : +case VIDIOC_G_INPUT32 : +case VIDIOC_G_OUTPUT32 : err =alloc_userspace (sizeof (unsigned int ),0 , &new_p64); compatible_arg =0 ;break ; -case VIDIOC_G_EDID : -case VIDIOC_S_EDID : +case VIDIOC_G_EDID32 : +case VIDIOC_S_EDID32 : err =alloc_userspace (sizeof (struct v4l2_edid ),0 , &new_p64);if (!err) err =get_v4l2_edid32 (new_p64, p32); compatible_arg =0 ;break ; -case VIDIOC_G_FMT : -case VIDIOC_S_FMT : -case VIDIOC_TRY_FMT : +case VIDIOC_G_FMT32 : +case VIDIOC_S_FMT32 : +case VIDIOC_TRY_FMT32 : err =bufsize_v4l2_format (p32, &aux_space);if (!err) err = alloc_userspace(sizeof(struct v4l2_format),
@@ -1262,7 +1264,7 @@ static long do_video_ioctl(struct file * compatible_arg =0 ;break ; -case VIDIOC_CREATE_BUFS : +case VIDIOC_CREATE_BUFS32 : err =bufsize_v4l2_create (p32, &aux_space);if (!err) err = alloc_userspace(sizeof(struct v4l2_create_buffers),
@@ -1275,10 +1277,10 @@ static long do_video_ioctl(struct file * compatible_arg =0 ;break ; -case VIDIOC_PREPARE_BUF : -case VIDIOC_QUERYBUF : -case VIDIOC_QBUF : -case VIDIOC_DQBUF : +case VIDIOC_PREPARE_BUF32 : +case VIDIOC_QUERYBUF32 : +case VIDIOC_QBUF32 : +case VIDIOC_DQBUF32 : err =bufsize_v4l2_buffer (p32, &aux_space);if (!err) err = alloc_userspace(sizeof(struct v4l2_buffer),
@@ -1291,7 +1293,7 @@ static long do_video_ioctl(struct file * compatible_arg =0 ;break ; -case VIDIOC_S_FBUF : +case VIDIOC_S_FBUF32 : err =alloc_userspace (sizeof (struct v4l2_framebuffer ),0 , &new_p64);if (!err)
@@ -1299,13 +1301,13 @@ static long do_video_ioctl(struct file * compatible_arg =0 ;break ; -case VIDIOC_G_FBUF : +case VIDIOC_G_FBUF32 : err =alloc_userspace (sizeof (struct v4l2_framebuffer ),0 , &new_p64); compatible_arg =0 ;break ; -case VIDIOC_ENUMSTD : +case VIDIOC_ENUMSTD32 : err =alloc_userspace (sizeof (struct v4l2_standard ),0 , &new_p64);if (!err)
@@ -1313,16 +1315,16 @@ static long do_video_ioctl(struct file * compatible_arg =0 ;break ; -case VIDIOC_ENUMINPUT : +case VIDIOC_ENUMINPUT32 : err =alloc_userspace (sizeof (struct v4l2_input ),0 , &new_p64);if (!err) err =get_v4l2_input32 (new_p64, p32); compatible_arg =0 ;break ; -case VIDIOC_G_EXT_CTRLS : -case VIDIOC_S_EXT_CTRLS : -case VIDIOC_TRY_EXT_CTRLS : +case VIDIOC_G_EXT_CTRLS32 : +case VIDIOC_S_EXT_CTRLS32 : +case VIDIOC_TRY_EXT_CTRLS32 : err =bufsize_v4l2_ext_controls (p32, &aux_space);if (!err) err = alloc_userspace(sizeof(struct v4l2_ext_controls),
@@ -1334,7 +1336,7 @@ static long do_video_ioctl(struct file * } compatible_arg =0 ;break ; -case VIDIOC_DQEVENT : +case VIDIOC_DQEVENT32 : err =alloc_userspace (sizeof (struct v4l2_event ),0 , &new_p64); compatible_arg =0 ;break ;
@@ -1352,9 +1354,9 @@ static long do_video_ioctl(struct file ** Otherwise, it will pass the newly allocated @new_p64 argument. */ if (compatible_arg) - err =native_ioctl (file, cmd, (unsigned long )p32); + err =native_ioctl (file, ncmd, (unsigned long )p32);else - err =native_ioctl (file, cmd, (unsigned long )new_p64); + err =native_ioctl (file, ncmd, (unsigned long )new_p64);if (err == -ENOTTY )return err;
@@ -1370,13 +1372,13 @@ static long do_video_ioctl(struct file ** the blocks to maximum allowed value. */ switch (cmd) { -case VIDIOC_G_EXT_CTRLS : -case VIDIOC_S_EXT_CTRLS : -case VIDIOC_TRY_EXT_CTRLS : +case VIDIOC_G_EXT_CTRLS32 : +case VIDIOC_S_EXT_CTRLS32 : +case VIDIOC_TRY_EXT_CTRLS32 :if (put_v4l2_ext_controls32 (file, new_p64, p32)) err = -EFAULT ;break ; -case VIDIOC_S_EDID : +case VIDIOC_S_EDID32 :if (put_v4l2_edid32 (new_p64, p32)) err = -EFAULT ;break ;
@@ -1389,49 +1391,49 @@ static long do_video_ioctl(struct file ** the original 32 bits structure. */ switch (cmd) { -case VIDIOC_S_INPUT : -case VIDIOC_S_OUTPUT : -case VIDIOC_G_INPUT : -case VIDIOC_G_OUTPUT : +case VIDIOC_S_INPUT32 : +case VIDIOC_S_OUTPUT32 : +case VIDIOC_G_INPUT32 : +case VIDIOC_G_OUTPUT32 :if (assign_in_user ((compat_uint_t __user *)p32, ((unsigned int __user *)new_p64))) err = -EFAULT ;break ; -case VIDIOC_G_FBUF : +case VIDIOC_G_FBUF32 : err =put_v4l2_framebuffer32 (new_p64, p32);break ; -case VIDIOC_DQEVENT : +case VIDIOC_DQEVENT32 : err =put_v4l2_event32 (new_p64, p32);break ; -case VIDIOC_G_EDID : +case VIDIOC_G_EDID32 : err =put_v4l2_edid32 (new_p64, p32);break ; -case VIDIOC_G_FMT : -case VIDIOC_S_FMT : -case VIDIOC_TRY_FMT : +case VIDIOC_G_FMT32 : +case VIDIOC_S_FMT32 : +case VIDIOC_TRY_FMT32 : err =put_v4l2_format32 (new_p64, p32);break ; -case VIDIOC_CREATE_BUFS : +case VIDIOC_CREATE_BUFS32 : err =put_v4l2_create32 (new_p64, p32);break ; -case VIDIOC_PREPARE_BUF : -case VIDIOC_QUERYBUF : -case VIDIOC_QBUF : -case VIDIOC_DQBUF : +case VIDIOC_PREPARE_BUF32 : +case VIDIOC_QUERYBUF32 : +case VIDIOC_QBUF32 : +case VIDIOC_DQBUF32 : err =put_v4l2_buffer32 (new_p64, p32);break ; -case VIDIOC_ENUMSTD : +case VIDIOC_ENUMSTD32 : err =put_v4l2_standard32 (new_p64, p32);break ; -case VIDIOC_ENUMINPUT : +case VIDIOC_ENUMINPUT32 : err =put_v4l2_input32 (new_p64, p32);break ; }
Greg Kroah-Hartman
maintainerPATCH 57/309 media: v4l2-rect.h: fix v4l2_rect_map_inside() top/left adjustments
In reply to Greg Kroah-HartmanFrom: Helen Koike <[email protected]>
commit f51e50db4c20d46930b33be3f208851265694f3e upstream.
boundary->width and boundary->height are sizes relative to boundary->left and boundary->top coordinates, but they were not being taken into consideration to adjust r->left and r->top, leading to the following error:
Consider the follow as initial values for boundary and r:
struct v4l2_rect boundary = {
.left = 100,
.top = 100,
.width = 800,
.height = 600,
}struct v4l2_rect r = {
.left = 0,
.top = 0,
.width = 1920,
.height = 960,
}calling v4l2_rect_map_inside(&r, &boundary) was modifying r to:
r = {
.left = 0,
.top = 0,
.width = 800,
.height = 600,
}Which is wrongly outside the boundary rectangle, because:
v4l2_rect_set_max_size(r, boundary); // r->width = 800, r->height = 600 ... if (r->left + r->width > boundary->width) // true r->left = boundary->width - r->width; // r->left = 800 - 800 if (r->top + r->height > boundary->height) // true r->top = boundary->height - r->height; // r->height = 600 - 600
Fix this by considering top/left coordinates from boundary.
--- include/media/v4l2-rect.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
include/media/v4l2-rect.h +4 -4
@@ -63,10 +63,10 @@ static inline void v4l2_rect_map_inside( r->left = boundary->left;if (r->top < boundary->top) r->top = boundary->top; -if (r->left + r->width > boundary->width) - r->left = boundary->width - r->width; -if (r->top + r->height > boundary->height) - r->top = boundary->height - r->height; +if (r->left + r->width > boundary->left + boundary->width) + r->left = boundary->left + boundary->width - r->width; +if (r->top + r->height > boundary->top + boundary->height) + r->top = boundary->top + boundary->height - r->height; }/**
Greg Kroah-Hartman
maintainerPATCH 58/309 lib/test_kasan.c: fix memory leak in kmalloc_oob_krealloc_more()
In reply to Greg Kroah-HartmanFrom: Gustavo A. R. Silva <[email protected]>
commit 3e21d9a501bf99aee2e5835d7f34d8c823f115b5 upstream.
In case memory resources for _ptr2_ were allocated, release them before return.
Notice that in case _ptr1_ happens to be NULL, krealloc() behaves exactly like kmalloc().
Addresses-Coverity-ID: 1490594 ("Resource leak")
--- lib/test_kasan.c | 1 + 1 file changed, 1 insertion(+)
lib/test_kasan.c +1 -0
@@ -157,6 +157,7 @@ static noinline void __init kmalloc_oob_if (!ptr1 || !ptr2) {pr_err ("Allocation failed\n" );kfree (ptr1); +kfree (ptr2);return ; }
Greg Kroah-Hartman
maintainerPATCH 59/309 irqdomain: Fix a memory leak in irq_domain_push_irq()
In reply to Greg Kroah-HartmanFrom: Kevin Hao <[email protected]>
commit 0f394daef89b38d58c91118a2b08b8a1b316703b upstream.
Fix a memory leak reported by kmemleak:
unreferenced object 0xffff000bc6f50e80 (size 128):
comm "kworker/23:2", pid 201, jiffies 4294894947 (age 942.132s) hex dump (first 32 bytes):
00 00 00 00 41 00 00 00 86 c0 03 00 00 00 00 00 ....A...........
00 a0 b2 c6 0b 00 ff ff 40 51 fd 10 00 80 ff ff ........@Q......
backtrace:
[<00000000e62d2240>] kmem_cache_alloc_trace+0x1a4/0x320
[<00000000279143c9>] irq_domain_push_irq+0x7c/0x188
[<00000000d9f4c154>] thunderx_gpio_probe+0x3ac/0x438
[<00000000fd09ec22>] pci_device_probe+0xe4/0x198
[<00000000d43eca75>] really_probe+0xdc/0x320
[<00000000d3ebab09>] driver_probe_device+0x5c/0xf0
[<000000005b3ecaa0>] __device_attach_driver+0x88/0xc0
[<000000004e5915f5>] bus_for_each_drv+0x7c/0xc8
[<0000000079d4db41>] __device_attach+0xe4/0x140
[<00000000883bbda9>] device_initial_probe+0x18/0x20
[<000000003be59ef6>] bus_probe_device+0x98/0xa0
[<0000000039b03d3f>] deferred_probe_work_func+0x74/0xa8
[<00000000870934ce>] process_one_work+0x1c8/0x470
[<00000000e3cce570>] worker_thread+0x1f8/0x428
[<000000005d64975e>] kthread+0xfc/0x128
[<00000000f0eaa764>] ret_from_fork+0x10/0x18--- kernel/irq/irqdomain.c | 1 + 1 file changed, 1 insertion(+)
kernel/irq/irqdomain.c +1 -0
@@ -1459,6 +1459,7 @@ int irq_domain_push_irq(struct irq_domaiif (rv) {/* Restore the original irq_data. */ *root_irq_data = *child_irq_data; +kfree (child_irq_data); goto error; }
Greg Kroah-Hartman
maintainerPATCH 60/309 x86/cpu: Update cached HLE state on write to TSX_CTRL_CPUID_CLEAR
In reply to Greg Kroah-HartmanFrom: Pawan Gupta <[email protected]>
commit 5efc6fa9044c3356d6046c6e1da6d02572dbed6b upstream.
/proc/cpuinfo currently reports Hardware Lock Elision (HLE) feature to be present on boot cpu even if it was disabled during the bootup. This is because cpuinfo_x86->x86_capability HLE bit is not updated after TSX state is changed via the new MSR IA32_TSX_CTRL.
Update the cached HLE bit also since it is expected to change after an update to CPUID_CLEAR bit in MSR IA32_TSX_CTRL.
--- arch/x86/kernel/cpu/tsx.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
arch/x86/kernel/cpu/tsx.c +7 -6
@@ -115,11 +115,12 @@ void __init tsx_init(void)tsx_disable ();/* -* tsx_disable() will change the state of the -* RTM CPUID bit. Clear it here since it is now -* expected to be not set. +* tsx_disable() will change the state of the RTM and HLE CPUID +* bits. Clear them here since they are now expected to be not +* set. */ setup_clear_cpu_cap (X86_FEATURE_RTM ); +setup_clear_cpu_cap (X86_FEATURE_HLE ); }else if (tsx_ctrl_state ==TSX_CTRL_ENABLE ) {/*
@@ -131,10 +132,10 @@ void __init tsx_init(void)tsx_enable ();/* -* tsx_enable() will change the state of the -* RTM CPUID bit. Force it here since it is now -* expected to be set. +* tsx_enable() will change the state of the RTM and HLE CPUID +* bits. Force them here since they are now expected to be set. */ setup_force_cpu_cap (X86_FEATURE_RTM ); +setup_force_cpu_cap (X86_FEATURE_HLE ); } }
Greg Kroah-Hartman
maintainerPATCH 61/309 platform/x86: intel_scu_ipc: Fix interrupt support
In reply to Greg Kroah-HartmanFrom: Mika Westerberg <[email protected]>
commit e48b72a568bbd641c91dad354138d3c17d03ee6f upstream.
Currently the driver has disabled interrupt support for Tangier but actually interrupt works just fine if the command is not written twice in a row. Also we need to ack the interrupt in the handler.
--- drivers/platform/x86/intel_scu_ipc.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-)
drivers/platform/x86/intel_scu_ipc.c +8 -13
@@ -67,26 +67,22 @@struct intel_scu_ipc_pdata_t {u32 i2c_base;u32 i2c_len; -u8 irq_mode; };static const struct intel_scu_ipc_pdata_t intel_scu_ipc_lincroft_pdata = { .i2c_base =0xff12b000 , .i2c_len =0x10 , - .irq_mode =0 , };/* Penwell and Cloverview */ static const struct intel_scu_ipc_pdata_t intel_scu_ipc_penwell_pdata = { .i2c_base =0xff12b000 , .i2c_len =0x10 , - .irq_mode =1 , };static const struct intel_scu_ipc_pdata_t intel_scu_ipc_tangier_pdata = { .i2c_base =0xff00d000 , .i2c_len =0x10 , - .irq_mode =0 , };struct intel_scu_ipc_dev {
@@ -99,6 +95,9 @@ struct intel_scu_ipc_dev {static struct intel_scu_ipc_dev ipcdev;/* Only one for now */ +#define IPC_STATUS 0x04 +#define IPC_STATUS_IRQ BIT(2) +/* * IPC Read Buffer (Read Only): * 16 byte buffer for receiving data from SCU, if IPC command
@@ -120,11 +119,8 @@ static DEFINE_MUTEX(ipclock); /* lock us*/ static inline void ipc_command (struct intel_scu_ipc_dev *scu,u32 cmd) { -if (scu->irq_mode) { -reinit_completion (&scu->cmd_complete); -writel (cmd |IPC_IOC , scu->ipc_base); - } -writel (cmd, scu->ipc_base); +reinit_completion (&scu->cmd_complete); +writel (cmd |IPC_IOC , scu->ipc_base); }/*
@@ -610,9 +606,10 @@ EXPORT_SYMBOL(intel_scu_ipc_i2c_cntrl);static irqreturn_t ioc (int irq,void *dev_id) {struct intel_scu_ipc_dev *scu = dev_id; +int status =ipc_read_status (scu); -if (scu->irq_mode) -complete (&scu->cmd_complete); +writel (status |IPC_STATUS_IRQ , scu->ipc_base +IPC_STATUS ); +complete (&scu->cmd_complete);return IRQ_HANDLED ; }
@@ -638,8 +635,6 @@ static int ipc_probe(struct pci_dev *pdeif (!pdata)return -ENODEV ; - scu->irq_mode = pdata->irq_mode; - err =pcim_enable_device (pdev);if (err)return err;
Greg Kroah-Hartman
maintainerPATCH 62/309 ALSA: hda: Apply aligned MMIO access only conditionally
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit 4d024fe8f806e20e577cc934204c5784c7063293 upstream.
It turned out that the recent simplification of HD-audio bus access helpers caused a regression on the virtual HD-audio device on QEMU with ARM platforms. The driver got a CORB/RIRB timeout and couldn't probe any codecs.
The essential difference that caused a problem was the enforced aligned MMIO accesses by simplification. Since snd-hda-tegra driver is enabled on ARM, it enables CONFIG_SND_HDA_ALIGNED_MMIO, which makes the all HD-audio drivers using the aligned MMIO accesses. While this is mandatory for snd-hda-tegra, it seems that snd-hda-intel on ARM gets broken by this access pattern.
For addressing the regression, this patch introduces a new flag, aligned_mmio, to hdac_bus object, and applies the aligned MMIO only when this flag is set. This change affects only platforms with CONFIG_SND_HDA_ALIGNED_MMIO set, i.e. mostly only for ARM platforms.
Unfortunately the patch became a big bigger than it should be, just because the former calls didn't take hdac_bus object in the argument, hence we had to extend the call patterns.
--- include/sound/hdaudio.h | 77 +++++++++++++++++++++++++++++++--------------- sound/pci/hda/hda_tegra.c | 1 2 files changed, 54 insertions(+), 24 deletions(-)
include/sound/hdaudio.h +53 -24
@@ -8,6 +8,7 @@#include <linux/device.h> #include <linux/interrupt.h> +#include <linux/io.h> #include <linux/pm_runtime.h> #include <linux/timecounter.h> #include <sound/core.h>
@@ -330,6 +331,7 @@ struct hdac_bus { bool chip_init:1; /* h/w initialized *//* behavior flags */ + bool aligned_mmio:1; /* aligned MMIO access */ bool sync_write:1; /* sync after verb write */ bool use_posbuf:1; /* use position buffer */ bool snoop:1; /* enable snooping */
@@ -405,34 +407,61 @@ void snd_hdac_bus_free_stream_pages(struunsigned int snd_hdac_aligned_read (void __iomem *addr,unsigned int mask);void snd_hdac_aligned_write (unsigned int val,void __iomem *addr,unsigned int mask); -#define snd_hdac_reg_writeb (v, addr) snd_hdac_aligned_write(v, addr, 0xff) -#define snd_hdac_reg_writew (v, addr) snd_hdac_aligned_write(v, addr, 0xffff) -#define snd_hdac_reg_readb (addr) snd_hdac_aligned_read(addr, 0xff) -#define snd_hdac_reg_readw (addr) snd_hdac_aligned_read(addr, 0xffff) -#else /* CONFIG_SND_HDA_ALIGNED_MMIO */ -#define snd_hdac_reg_writeb (val, addr) writeb(val, addr) -#define snd_hdac_reg_writew (val, addr) writew(val, addr) -#define snd_hdac_reg_readb (addr) readb(addr) -#define snd_hdac_reg_readw (addr) readw(addr) -#endif /* CONFIG_SND_HDA_ALIGNED_MMIO */ -#define snd_hdac_reg_writel (val, addr) writel(val, addr) -#define snd_hdac_reg_readl (addr) readl(addr) +#define snd_hdac_aligned_mmio (bus) (bus)->aligned_mmio +#else +#define snd_hdac_aligned_mmio (bus) false +#define snd_hdac_aligned_read (addr, mask) 0 +#define snd_hdac_aligned_write (val, addr, mask) do {} while (0) +#endif + +static inline void snd_hdac_reg_writeb (struct hdac_bus *bus,void __iomem *addr, +u8 val) +{ +if (snd_hdac_aligned_mmio (bus)) +snd_hdac_aligned_write (val, addr,0xff ); +else +writeb (val, addr); +} + +static inline void snd_hdac_reg_writew (struct hdac_bus *bus,void __iomem *addr, +u16 val) +{ +if (snd_hdac_aligned_mmio (bus)) +snd_hdac_aligned_write (val, addr,0xffff ); +else +writew (val, addr); +} + +static inline u8 snd_hdac_reg_readb (struct hdac_bus *bus,void __iomem *addr) +{ +return snd_hdac_aligned_mmio (bus) ? +snd_hdac_aligned_read (addr,0xff ) :readb (addr); +} + +static inline u16 snd_hdac_reg_readw (struct hdac_bus *bus,void __iomem *addr) +{ +return snd_hdac_aligned_mmio (bus) ? +snd_hdac_aligned_read (addr,0xffff ) :readw (addr); +} + +#define snd_hdac_reg_writel (bus, addr, val) writel(val, addr) +#define snd_hdac_reg_readl (bus, addr) readl(addr)/* * macros for easy use */ #define _snd_hdac_chip_writeb (chip, reg, value) \ - snd_hdac_reg_writeb(value, (chip)->remap_addr + (reg)) + snd_hdac_reg_writeb(chip, (chip)->remap_addr + (reg), value)#define _snd_hdac_chip_readb (chip, reg) \ - snd_hdac_reg_readb((chip)->remap_addr + (reg)) + snd_hdac_reg_readb(chip, (chip)->remap_addr + (reg))#define _snd_hdac_chip_writew (chip, reg, value) \ - snd_hdac_reg_writew(value, (chip)->remap_addr + (reg)) + snd_hdac_reg_writew(chip, (chip)->remap_addr + (reg), value)#define _snd_hdac_chip_readw (chip, reg) \ - snd_hdac_reg_readw((chip)->remap_addr + (reg)) + snd_hdac_reg_readw(chip, (chip)->remap_addr + (reg))#define _snd_hdac_chip_writel (chip, reg, value) \ - snd_hdac_reg_writel(value, (chip)->remap_addr + (reg)) + snd_hdac_reg_writel(chip, (chip)->remap_addr + (reg), value)#define _snd_hdac_chip_readl (chip, reg) \ - snd_hdac_reg_readl((chip)->remap_addr + (reg)) + snd_hdac_reg_readl(chip, (chip)->remap_addr + (reg))/* read/write a register, pass without AZX_REG_ prefix */ #define snd_hdac_chip_writel (chip, reg, value) \
@@ -540,17 +569,17 @@ int snd_hdac_get_stream_stripe_ctl(struc*/ /* read/write a register, pass without AZX_REG_ prefix */ #define snd_hdac_stream_writel (dev, reg, value) \ - snd_hdac_reg_writel(value, (dev)->sd_addr + AZX_REG_ ## reg) + snd_hdac_reg_writel((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg, value)#define snd_hdac_stream_writew (dev, reg, value) \ - snd_hdac_reg_writew(value, (dev)->sd_addr + AZX_REG_ ## reg) + snd_hdac_reg_writew((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg, value)#define snd_hdac_stream_writeb (dev, reg, value) \ - snd_hdac_reg_writeb(value, (dev)->sd_addr + AZX_REG_ ## reg) + snd_hdac_reg_writeb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg, value)#define snd_hdac_stream_readl (dev, reg) \ - snd_hdac_reg_readl((dev)->sd_addr + AZX_REG_ ## reg) + snd_hdac_reg_readl((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)#define snd_hdac_stream_readw (dev, reg) \ - snd_hdac_reg_readw((dev)->sd_addr + AZX_REG_ ## reg) + snd_hdac_reg_readw((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)#define snd_hdac_stream_readb (dev, reg) \ - snd_hdac_reg_readb((dev)->sd_addr + AZX_REG_ ## reg) + snd_hdac_reg_readb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)/* update a register, pass without AZX_REG_ prefix */ #define snd_hdac_stream_updatel (dev, reg, mask, val) \
sound/pci/hda/hda_tegra.c +1 -0
@@ -398,6 +398,7 @@ static int hda_tegra_create(struct snd_creturn err; chip->bus.needs_damn_long_delay =1 ; + chip->bus.core.aligned_mmio =1 ; err =snd_device_new (card,SNDRV_DEV_LOWLEVEL , chip, &ops);if (err <0 ) {
Greg Kroah-Hartman
maintainerPATCH 63/309 ALSA: hda: Add Clevo W65_67SB the power_save blacklist
In reply to Greg Kroah-HartmanFrom: Hans de Goede <[email protected]>
commit d8feb6080bb0c9f4d799a423d9453048fdd06990 upstream.
Using HDA power-saving on the Clevo W65_67SB causes the first 0.5 seconds of audio to be missing every time audio starts playing.
This commit adds the Clevo W65_67SB the power_save blacklist to avoid this issue.
--- sound/pci/hda/hda_intel.c | 2 ++ 1 file changed, 2 insertions(+)
sound/pci/hda/hda_intel.c +2 -0
@@ -2156,6 +2156,8 @@ static struct snd_pci_quirk power_save_b/* https://bugzilla.redhat.com/show_bug.cgi?id=1581607 */ SND_PCI_QUIRK (0x1558 ,0x3501 ,"Clevo W35xSS_370SS" ,0 ),/* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ +SND_PCI_QUIRK (0x1558 ,0x6504 ,"Clevo W65_67SB" ,0 ), +/* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ SND_PCI_QUIRK(0x1028, 0x0497, "Dell Precision T3600", 0),/* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ /* Note the P55A-UD3 and Z87-D3HP share the subsys id for the HDA dev */
Greg Kroah-Hartman
maintainerPATCH 64/309 ALSA: hda: Add JasperLake PCI ID and codec vid
In reply to Greg Kroah-HartmanFrom: Yong Zhi <[email protected]>
commit 78be2228c15dd45865b102b29d72e721f0ace9b1 upstream.
Add HD Audio Device PCI ID and codec vendor_id for the Intel JasperLake REV2/A0 silicon.
--- sound/pci/hda/hda_intel.c | 2 ++ sound/pci/hda/patch_hdmi.c | 1 + 2 files changed, 3 insertions(+)
sound/pci/hda/hda_intel.c +2 -0
@@ -2417,6 +2417,8 @@ static const struct pci_device_id azx_id/* Jasperlake */ { PCI_DEVICE(0x8086, 0x38c8), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, + { PCI_DEVICE(0x8086, 0x4dc8), + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, /* Tigerlake */ { PCI_DEVICE(0x8086, 0xa0c8), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
sound/pci/hda/patch_hdmi.c +1 -0
@@ -4153,6 +4153,7 @@ HDA_CODEC_ENTRY(0x8086280c, "CannonlakeHDA_CODEC_ENTRY (0x8086280d ,"Geminilake HDMI" , patch_i915_glk_hdmi),HDA_CODEC_ENTRY (0x8086280f ,"Icelake HDMI" , patch_i915_icl_hdmi),HDA_CODEC_ENTRY (0x80862812 ,"Tigerlake HDMI" , patch_i915_tgl_hdmi), +HDA_CODEC_ENTRY (0x8086281a ,"Jasperlake HDMI" , patch_i915_icl_hdmi),HDA_CODEC_ENTRY (0x80862880 ,"CedarTrail HDMI" , patch_generic_hdmi),HDA_CODEC_ENTRY (0x80862882 ,"Valleyview2 HDMI" , patch_i915_byt_hdmi), HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_i915_byt_hdmi),
Greg Kroah-Hartman
maintainerPATCH 65/309 arm64: acpi: fix DAIF manipulation with pNMI
In reply to Greg Kroah-HartmanFrom: Mark Rutland <[email protected]>
commit e533dbe9dcb199bb637a2c465f3a6e70564994fe upstream.
Since commit:
d44f1b8dd7e66d80 ("arm64: KVM/mm: Move SEA handling behind a single 'claim' interface")
... the top-level APEI SEA handler has the shape:
1. current_flags = arch_local_save_flags()
2. local_daif_restore(DAIF_ERRCTX)
3. <GHES handler>
4. local_daif_restore(current_flags)
However, since commit:
4a503217ce37e1f4 ("arm64: irqflags: Use ICC_PMR_EL1 for interrupt masking")
... when pseudo-NMIs (pNMIs) are in use, arch_local_save_flags() will save the PMR value rather than the DAIF flags.
The combination of these two commits means that the APEI SEA handler will erroneously attempt to restore the PMR value into DAIF. Fix this by factoring local_daif_save_flags() out of local_daif_save(), so that we can consistently save DAIF in step #1, regardless of whether pNMIs are in use.
Both commits were introduced concurrently in v5.0.
--- arch/arm64/include/asm/daifflags.h | 11 ++++++++++- arch/arm64/kernel/acpi.c | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-)
arch/arm64/include/asm/daifflags.h +10 -1
@@ -36,7 +36,7 @@ static inline void local_daif_mask(void)trace_hardirqs_off (); } -static inline unsigned long local_daif_save (void ) +static inline unsigned long local_daif_save_flags (void ) {unsigned long flags;
@@ -48,6 +48,15 @@ static inline unsigned long local_daif_s flags |=PSR_I_BIT ; } +return flags; +} + +static inline unsigned long local_daif_save (void ) +{ +unsigned long flags; + + flags =local_daif_save_flags (); +local_daif_mask ();return flags;
arch/arm64/kernel/acpi.c +1 -1
@@ -274,7 +274,7 @@ int apei_claim_sea(struct pt_regs *regs)if (!IS_ENABLED (CONFIG_ACPI_APEI_GHES ))return err; - current_flags =arch_local_save_flags (); + current_flags =local_daif_save_flags ();/* * SEA can interrupt SError, mask it and describe this as an NMI so
Greg Kroah-Hartman
maintainerPATCH 66/309 KVM: arm64: Correct PSTATE on exception entry
In reply to Greg Kroah-HartmanFrom: Mark Rutland <[email protected]>
commit a425372e733177eb0779748956bc16c85167af48 upstream.
When KVM injects an exception into a guest, it generates the PSTATE value from scratch, configuring PSTATE.{M[4:0],DAIF}, and setting all other bits to zero.
This isn't correct, as the architecture specifies that some PSTATE bits are (conditionally) cleared or set upon an exception, and others are unchanged from the original context.
This patch adds logic to match the architectural behaviour. To make this simple to follow/audit/extend, documentation references are provided, and bits are configured in order of their layout in SPSR_EL2. This layout can be seen in the diagram on ARM DDI 0487E.a page C5-429.
--- arch/arm64/include/uapi/asm/ptrace.h | 1 arch/arm64/kvm/inject_fault.c | 70 ++++++++++++++++++++++++++++++++--- 2 files changed, 66 insertions(+), 5 deletions(-)
arch/arm64/include/uapi/asm/ptrace.h +1 -0
@@ -49,6 +49,7 @@#define PSR_SSBS_BIT 0x00001000#define PSR_PAN_BIT 0x00400000#define PSR_UAO_BIT 0x00800000 +#define PSR_DIT_BIT 0x01000000#define PSR_V_BIT 0x10000000#define PSR_C_BIT 0x20000000#define PSR_Z_BIT 0x40000000
arch/arm64/kvm/inject_fault.c +65 -5
94 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 67/309 KVM: arm/arm64: Correct CPSR on exception entry
In reply to Greg Kroah-HartmanFrom: Mark Rutland <[email protected]>
commit 3c2483f15499b877ccb53250d88addb8c91da147 upstream.
When KVM injects an exception into a guest, it generates the CPSR value from scratch, configuring CPSR.{M,A,I,T,E}, and setting all other bits to zero.
This isn't correct, as the architecture specifies that some CPSR bits are (conditionally) cleared or set upon an exception, and others are unchanged from the original context.
This patch adds logic to match the architectural behaviour. To make this simple to follow/audit/extend, documentation references are provided, and bits are configured in order of their layout in SPSR_EL2. This layout can be seen in the diagram on ARM DDI 0487E.a page C5-426.
Note that this code is used by both arm and arm64, and is intended to fuction with the SPSR_EL2 and SPSR_HYP layouts.
--- arch/arm/include/asm/kvm_emulate.h | 12 ++++ arch/arm64/include/asm/ptrace.h | 1 virt/kvm/arm/aarch32.c | 111 +++++++++++++++++++++++++++++++++---- 3 files changed, 114 insertions(+), 10 deletions(-)
arch/arm/include/asm/kvm_emulate.h +12 -0
@@ -14,13 +14,25 @@#include <asm/cputype.h> /* arm64 compatibility macros */ +#define PSR_AA32_MODE_FIQ FIQ_MODE +#define PSR_AA32_MODE_SVC SVC_MODE#define PSR_AA32_MODE_ABT ABT_MODE#define PSR_AA32_MODE_UND UND_MODE#define PSR_AA32_T_BIT PSR_T_BIT +#define PSR_AA32_F_BIT PSR_F_BIT#define PSR_AA32_I_BIT PSR_I_BIT#define PSR_AA32_A_BIT PSR_A_BIT#define PSR_AA32_E_BIT PSR_E_BIT#define PSR_AA32_IT_MASK PSR_IT_MASK +#define PSR_AA32_GE_MASK 0x000f0000 +#define PSR_AA32_DIT_BIT 0x00200000 +#define PSR_AA32_PAN_BIT 0x00400000 +#define PSR_AA32_SSBS_BIT 0x00800000 +#define PSR_AA32_Q_BIT PSR_Q_BIT +#define PSR_AA32_V_BIT PSR_V_BIT +#define PSR_AA32_C_BIT PSR_C_BIT +#define PSR_AA32_Z_BIT PSR_Z_BIT +#define PSR_AA32_N_BIT PSR_N_BITunsigned long *vcpu_reg (struct kvm_vcpu *vcpu,u8 reg_num);
arch/arm64/include/asm/ptrace.h +1 -0
@@ -62,6 +62,7 @@#define PSR_AA32_I_BIT 0x00000080#define PSR_AA32_A_BIT 0x00000100#define PSR_AA32_E_BIT 0x00000200 +#define PSR_AA32_PAN_BIT 0x00400000#define PSR_AA32_SSBS_BIT 0x00800000#define PSR_AA32_DIT_BIT 0x01000000#define PSR_AA32_Q_BIT 0x08000000
virt/kvm/arm/aarch32.c +101 -10
136 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 68/309 KVM: arm/arm64: Correct AArch32 SPSR on exception entry
In reply to Greg Kroah-HartmanFrom: Mark Rutland <[email protected]>
commit 1cfbb484de158e378e8971ac40f3082e53ecca55 upstream.
Confusingly, there are three SPSR layouts that a kernel may need to deal with:
(1) An AArch64 SPSR_ELx view of an AArch64 pstate
(2) An AArch64 SPSR_ELx view of an AArch32 pstate
(3) An AArch32 SPSR_* view of an AArch32 pstate
When the KVM AArch32 support code deals with SPSR_{EL2,HYP}, it's either dealing with #2 or #3 consistently. On arm64 the PSR_AA32_* definitions match the AArch64 SPSR_ELx view, and on arm the PSR_AA32_* definitions match the AArch32 SPSR_* view.
However, when we inject an exception into an AArch32 guest, we have to synthesize the AArch32 SPSR_* that the guest will see. Thus, an AArch64 host needs to synthesize layout #3 from layout #2.
This patch adds a new host_spsr_to_spsr32() helper for this, and makes use of it in the KVM AArch32 support code. For arm64 we need to shuffle the DIT bit around, and remove the SS bit, while for arm we can use the value as-is.
I've open-coded the bit manipulation for now to avoid having to rework the existing PSR_* definitions into PSR64_AA32_* and PSR32_AA32_* definitions. I hope to perform a more thorough refactoring in future so that we can handle pstate view manipulation more consistently across the kernel tree.
--- arch/arm/include/asm/kvm_emulate.h | 5 +++++ arch/arm64/include/asm/kvm_emulate.h | 32 ++++++++++++++++++++++++++++++++ virt/kvm/arm/aarch32.c | 6 +++--- 3 files changed, 40 insertions(+), 3 deletions(-)
arch/arm/include/asm/kvm_emulate.h +5 -0
@@ -53,6 +53,11 @@ static inline void vcpu_write_spsr(struc *__vcpu_spsr (vcpu) = v; } +static inline unsigned long host_spsr_to_spsr32 (unsigned long spsr) +{ +return spsr; +} +static inline unsigned long vcpu_get_reg (struct kvm_vcpu *vcpu,u8 reg_num) {
arch/arm64/include/asm/kvm_emulate.h +32 -0
@@ -204,6 +204,38 @@ static inline void vcpu_write_spsr(strucvcpu_gp_regs (vcpu)->spsr[KVM_SPSR_EL1 ] = v; } +/* +* The layout of SPSR for an AArch32 state is different when observed from an +* AArch64 SPSR_ELx or an AArch32 SPSR_*. This function generates the AArch32 +* view given an AArch64 view. +* +* In ARM DDI 0487E.a see: +* +* - The AArch64 view (SPSR_EL2) in section C5.2.18, page C5-426 +* - The AArch32 view (SPSR_abt) in section G8.2.126, page G8-6256 +* - The AArch32 view (SPSR_und) in section G8.2.132, page G8-6280 +* +* Which show the following differences: +* +* | Bit | AA64 | AA32 | Notes | +* +-----+------+------+-----------------------------| +* | 24 | DIT | J | J is RES0 in ARMv8 | +* | 21 | SS | DIT | SS doesn't exist in AArch32 | +* +* ... and all other bits are (currently) common. +*/ +static inline unsigned long host_spsr_to_spsr32 (unsigned long spsr) +{ +const unsigned long overlap =BIT (24 ) |BIT (21 ); +unsigned long dit = !!(spsr &PSR_AA32_DIT_BIT ); + + spsr &= ~overlap; + + spsr |= dit <<21 ; + +return spsr; +} +static inline bool vcpu_mode_priv (const struct kvm_vcpu *vcpu) {u32 mode;
virt/kvm/arm/aarch32.c +3 -3
@@ -129,15 +129,15 @@ static unsigned long get_except32_cpsr(sstatic void prepare_fault32 (struct kvm_vcpu *vcpu,u32 mode,u32 vect_offset) { -unsigned long new_spsr_value = *vcpu_cpsr (vcpu); -bool is_thumb = (new_spsr_value &PSR_AA32_T_BIT ); +unsigned long spsr = *vcpu_cpsr (vcpu); +bool is_thumb = (spsr &PSR_AA32_T_BIT );u32 return_offset = return_offsets[vect_offset >>2 ][is_thumb];u32 sctlr =vcpu_cp15 (vcpu, c1_SCTLR); *vcpu_cpsr (vcpu) =get_except32_cpsr (vcpu, mode);/* Note: These now point to the banked copies */ -vcpu_write_spsr (vcpu, new_spsr_value); +vcpu_write_spsr (vcpu,host_spsr_to_spsr32 (spsr)); *vcpu_reg32 (vcpu,14 ) = *vcpu_pc (vcpu) + return_offset;/* Branch to exception vector */
Greg Kroah-Hartman
maintainerPATCH 69/309 KVM: arm64: Only sign-extend MMIO up to register width
In reply to Greg Kroah-HartmanFrom: Christoffer Dall <[email protected]>
commit b6ae256afd32f96bec0117175b329d0dd617655e upstream.
On AArch64 you can do a sign-extended load to either a 32-bit or 64-bit register, and we should only sign extend the register up to the width of the register as specified in the operation (by using the 32-bit Wn or 64-bit Xn register specifier).
As it turns out, the architecture provides this decoding information in the SF ("Sixty-Four" -- how cute...) bit.
Let's take advantage of this with the usual 32-bit/64-bit header file dance and do the right thing on AArch64 hosts.
--- arch/arm/include/asm/kvm_emulate.h | 5 +++++ arch/arm/include/asm/kvm_mmio.h | 2 ++ arch/arm64/include/asm/kvm_emulate.h | 5 +++++ arch/arm64/include/asm/kvm_mmio.h | 6 ++---- virt/kvm/arm/mmio.c | 6 ++++++ 5 files changed, 20 insertions(+), 4 deletions(-)
arch/arm/include/asm/kvm_emulate.h +5 -0
@@ -194,6 +194,11 @@ static inline bool kvm_vcpu_dabt_issext(return kvm_vcpu_get_hsr (vcpu) &HSR_SSE ; } +static inline bool kvm_vcpu_dabt_issf (const struct kvm_vcpu *vcpu) +{ +return false; +} +static inline int kvm_vcpu_dabt_get_rd (struct kvm_vcpu *vcpu) {return (kvm_vcpu_get_hsr (vcpu) &HSR_SRT_MASK ) >>HSR_SRT_SHIFT ;
arch/arm/include/asm/kvm_mmio.h +2 -0
@@ -14,6 +14,8 @@struct kvm_decode {unsigned long rt;bool sign_extend; +/* Not used on 32-bit arm */ +bool sixty_four; };void kvm_mmio_write_buf (void *buf,unsigned int len,unsigned long data);
arch/arm64/include/asm/kvm_emulate.h +5 -0
@@ -295,6 +295,11 @@ static inline bool kvm_vcpu_dabt_issext(return !!(kvm_vcpu_get_hsr (vcpu) & ESR_ELx_SSE); } +static inline bool kvm_vcpu_dabt_issf (const struct kvm_vcpu *vcpu) +{ +return !!(kvm_vcpu_get_hsr (vcpu) & ESR_ELx_SF); +} +static inline int kvm_vcpu_dabt_get_rd (const struct kvm_vcpu *vcpu) {return (kvm_vcpu_get_hsr (vcpu) & ESR_ELx_SRT_MASK) >> ESR_ELx_SRT_SHIFT;
arch/arm64/include/asm/kvm_mmio.h +2 -4
@@ -10,13 +10,11 @@#include <linux/kvm_host.h> #include <asm/kvm_arm.h> -/* -* This is annoying. The mmio code requires this, even if we don't -* need any decoding. To be fixed. -*/ struct kvm_decode {unsigned long rt;bool sign_extend; +/* Witdth of the register accessed by the faulting instruction is 64-bits */ +bool sixty_four; };void kvm_mmio_write_buf (void *buf,unsigned int len,unsigned long data);
virt/kvm/arm/mmio.c +6 -0
@@ -105,6 +105,9 @@ int kvm_handle_mmio_return(struct kvm_vc data = (data ^ mask) - mask; } +if (!vcpu->arch.mmio_decode.sixty_four) + data = data &0xffffffff ; +trace_kvm_mmio (KVM_TRACE_MMIO_READ , len, run->mmio.phys_addr, &data); data =vcpu_data_host_to_guest (vcpu, data, len);
@@ -125,6 +128,7 @@ static int decode_hsr(struct kvm_vcpu *vunsigned long rt;int access_size;bool sign_extend; +bool sixty_four;if (kvm_vcpu_dabt_iss1tw (vcpu)) {/* page table accesses IO mem: tell guest to fix its TTBR */
@@ -138,11 +142,13 @@ static int decode_hsr(struct kvm_vcpu *v *is_write =kvm_vcpu_dabt_iswrite (vcpu); sign_extend =kvm_vcpu_dabt_issext (vcpu); + sixty_four =kvm_vcpu_dabt_issf (vcpu); rt =kvm_vcpu_dabt_get_rd (vcpu); *len = access_size; vcpu->arch.mmio_decode.sign_extend = sign_extend; vcpu->arch.mmio_decode.rt = rt; + vcpu->arch.mmio_decode.sixty_four = sixty_four;return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 70/309 MIPS: syscalls: fix indentation of the SYSNR message
In reply to Greg Kroah-HartmanFrom: Alexander Lobakin <[email protected]>
commit 4f29ad200f7b40fbcf73cd65f95087535ba78380 upstream.
It also lacks a whitespace (copy'n'paste error?) and also messes up the output:
SYSHDR arch/mips/include/generated/uapi/asm/unistd_n32.h SYSHDR arch/mips/include/generated/uapi/asm/unistd_n64.h SYSHDR arch/mips/include/generated/uapi/asm/unistd_o32.h SYSNR arch/mips/include/generated/uapi/asm/unistd_nr_n32.h SYSNR arch/mips/include/generated/uapi/asm/unistd_nr_n64.h SYSNR arch/mips/include/generated/uapi/asm/unistd_nr_o32.h
WRAP arch/mips/include/generated/uapi/asm/bpf_perf_event.h
WRAP arch/mips/include/generated/uapi/asm/ipcbuf.h
After:
SYSHDR arch/mips/include/generated/uapi/asm/unistd_n32.h SYSHDR arch/mips/include/generated/uapi/asm/unistd_n64.h SYSHDR arch/mips/include/generated/uapi/asm/unistd_o32.h SYSNR arch/mips/include/generated/uapi/asm/unistd_nr_n32.h SYSNR arch/mips/include/generated/uapi/asm/unistd_nr_n64.h SYSNR arch/mips/include/generated/uapi/asm/unistd_nr_o32.h WRAP arch/mips/include/generated/uapi/asm/bpf_perf_event.h WRAP arch/mips/include/generated/uapi/asm/ipcbuf.h
Present since day 0 of syscall table generation introduction for MIPS.
--- arch/mips/kernel/syscalls/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/mips/kernel/syscalls/Makefile +1 -1
@@ -18,7 +18,7 @@ quiet_cmd_syshdr = SYSHDR $@ '$(syshdr_pfx_$(basetarget))' \ '$(syshdr_offset_$(basetarget))' -quiet_cmd_sysnr = SYSNR $@ +quiet_cmd_sysnr = SYSNR $@ cmd_sysnr = $(CONFIG_SHELL) '$(sysnr)' '$<' '$@' \ '$(sysnr_abis_$(basetarget))' \ '$(sysnr_pfx_$(basetarget))' \
Greg Kroah-Hartman
maintainerPATCH 71/309 MIPS: fix indentation of the RELOCS message
In reply to Greg Kroah-HartmanFrom: Alexander Lobakin <[email protected]>
commit a53998802e178451701d59d38e36f551422977ba upstream.
quiet_cmd_relocs lacks a whitespace which results in:
LD vmlinux SORTEX vmlinux SYSMAP System.map
RELOCS vmlinux
Building modules, stage 2.
MODPOST 64 modules
After this patch:
LD vmlinux SORTEX vmlinux SYSMAP System.map RELOCS vmlinux
Building modules, stage 2.
MODPOST 64 modules
Typo is present in kernel tree since the introduction of relocatable kernel support in commit e818fac595ab ("MIPS: Generate relocation table when CONFIG_RELOCATABLE"), but the relocation scripts were moved to Makefile.postlink later with commit 44079d3509ae ("MIPS: Use Makefile.postlink to insert relocations into vmlinux").
--- arch/mips/Makefile.postlink | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/mips/Makefile.postlink +1 -1
@@ -12,7 +12,7 @@ __archpost: include scripts/Kbuild.include CMD_RELOCS = arch/mips/boot/tools/relocs -quiet_cmd_relocs = RELOCS $@ +quiet_cmd_relocs = RELOCS $@ cmd_relocs = $(CMD_RELOCS) $@ # `@true` prevents complaint when there is nothing to be done
Greg Kroah-Hartman
maintainerPATCH 72/309 MIPS: boot: fix typo in vmlinux.lzma.its target
In reply to Greg Kroah-HartmanFrom: Alexander Lobakin <[email protected]>
commit 16202c09577f3d0c533274c0410b7de05fb0d458 upstream.
Commit 92b34a976348 ("MIPS: boot: add missing targets for vmlinux.*.its") fixed constant rebuild of *.its files on every make invocation, but due to typo ("lzmo") it made no sense for vmlinux.lzma.its.
--- arch/mips/boot/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/mips/boot/Makefile +1 -1
@@ -123,7 +123,7 @@ $(obj)/vmlinux.its.S: $(addprefix $(srct targets += vmlinux.its targets += vmlinux.gz.its targets += vmlinux.bz2.its -targets += vmlinux.lzmo.its +targets += vmlinux.lzma.its targets += vmlinux.lzo.its quiet_cmd_cpp_its_S = ITS $@
Greg Kroah-Hartman
maintainerPATCH 73/309 s390/mm: fix dynamic pagetable upgrade for hugetlbfs
In reply to Greg Kroah-HartmanFrom: Gerald Schaefer <[email protected]>
commit 5f490a520bcb393389a4d44bec90afcb332eb112 upstream.
Commit ee71d16d22bb ("s390/mm: make TASK_SIZE independent from the number of page table levels") changed the logic of TASK_SIZE and also removed the arch_mmap_check() implementation for s390. This combination has a subtle effect on how get_unmapped_area() for hugetlbfs pages works. It is now possible that a user process establishes a hugetlbfs mapping at an address above 4 TB, without triggering a dynamic pagetable upgrade from 3 to 4 levels.
This is because hugetlbfs mappings will not use mm->get_unmapped_area, but rather file->f_op->get_unmapped_area, which currently is the generic implementation of hugetlb_get_unmapped_area() that does not know about s390 dynamic pagetable upgrades, but with the new definition of TASK_SIZE, it will now allow mappings above 4 TB.
Subsequent access to such a mapped address above 4 TB will result in a page fault loop, because the CPU cannot translate such a large address with 3 pagetable levels. The fault handler will try to map in a hugepage at the address, but due to the folded pagetable logic it will end up with creating entries in the 3 level pagetable, possibly overwriting existing mappings, and then it all repeats when the access is retried.
Apart from the page fault loop, this can have various nasty effects, e.g. kernel panic from one of the BUG_ON() checks in memory management code, or even data loss if an existing mapping gets overwritten.
Fix this by implementing HAVE_ARCH_HUGETLB_UNMAPPED_AREA support for s390, providing an s390 version for hugetlb_get_unmapped_area() with pagetable upgrade support similar to arch_get_unmapped_area(), which will then be used instead of the generic version.
--- arch/s390/include/asm/page.h | 2 arch/s390/mm/hugetlbpage.c | 100 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 1 deletion(-)
arch/s390/include/asm/page.h +2 -0
@@ -33,6 +33,8 @@#define ARCH_HAS_PREPARE_HUGEPAGE #define ARCH_HAS_HUGEPAGE_CLEAR_FLUSH +#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA +#include <asm/setup.h> #ifndef __ASSEMBLY__
arch/s390/mm/hugetlbpage.c +99 -1
115 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 74/309 powerpc/mmu_gather: enable RCU_TABLE_FREE even for !SMP case
In reply to Greg Kroah-HartmanFrom: Aneesh Kumar K.V <[email protected]>
commit 12e4d53f3f04e81f9e83d6fc10edc7314ab9f6b9 upstream.
Patch series "Fixup page directory freeing", v4.
This is a repost of patch series from Peter with the arch specific changes except ppc64 dropped. ppc64 changes are added here because we are redoing the patch series on top of ppc64 changes. This makes it easy to backport these changes. Only the first 2 patches need to be backported to stable.
The thing is, on anything SMP, freeing page directories should observe the exact same order as normal page freeing:
1) unhook page/directory
2) TLB invalidate
3) free page/directory
Without this, any concurrent page-table walk could end up with a Use-after-Free. This is esp. trivial for anything that has software page-table walkers (HAVE_FAST_GUP / software TLB fill) or the hardware caches partial page-walks (ie. caches page directories).
Even on UP this might give issues since mmu_gather is preemptible these days. An interrupt or preempted task accessing user pages might stumble into the free page if the hardware caches page directories.
This patch series fixes ppc64 and add generic MMU_GATHER changes to support the conversion of other architectures. I haven't added patches w.r.t other architecture because they are yet to be acked.
This patch (of 9):
A followup patch is going to make sure we correctly invalidate page walk cache before we free page table pages. In order to keep things simple enable RCU_TABLE_FREE even for !SMP so that we don't have to fixup the !SMP case differently in the followup patch
!SMP case is right now broken for radix translation w.r.t page walk cache flush. We can get interrupted in between page table free and that would imply we have page walk cache entries pointing to tables which got freed already. Michael said "both our platforms that run on Power9 force SMP on in Kconfig, so the !SMP case is unlikely to be a problem for anyone in practice, unless they've hacked their kernel to build it !SMP."
--- arch/powerpc/Kconfig | 2 +- arch/powerpc/include/asm/book3s/32/pgalloc.h | 8 -------- arch/powerpc/include/asm/book3s/64/pgalloc.h | 2 -- arch/powerpc/include/asm/nohash/pgalloc.h | 8 -------- arch/powerpc/mm/book3s64/pgtable.c | 7 ------- 5 files changed, 1 insertion(+), 26 deletions(-)
arch/powerpc/Kconfig +1 -1
@@ -221,7 +221,7 @@ config PPC select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && HAVE_PERF_EVENTS_NMI && !HAVE_HARDLOCKUP_DETECTOR_ARCH select HAVE_PERF_REGS select HAVE_PERF_USER_STACK_DUMP - select HAVE_RCU_TABLE_FREE if SMP + select HAVE_RCU_TABLE_FREE select HAVE_RCU_TABLE_NO_INVALIDATE if HAVE_RCU_TABLE_FREE select HAVE_MMU_GATHER_PAGE_SIZE select HAVE_REGS_AND_STACK_ACCESS_API
arch/powerpc/include/asm/book3s/32/pgalloc.h +0 -8
@@ -49,7 +49,6 @@ static inline void pgtable_free(void *ta#define get_hugepd_cache_index (x) (x) -#ifdef CONFIG_SMP static inline void pgtable_free_tlb (struct mmu_gather *tlb,void *table,int shift) {
@@ -66,13 +65,6 @@ static inline void __tlb_remove_table(vopgtable_free (table, shift); } -#else -static inline void pgtable_free_tlb (struct mmu_gather *tlb, -void *table,int shift) -{ -pgtable_free (table, shift); -} -#endif static inline void __pte_free_tlb (struct mmu_gather *tlb,pgtable_t table,unsigned long address)
arch/powerpc/include/asm/book3s/64/pgalloc.h +0 -2
@@ -19,9 +19,7 @@ extern struct vmemmap_backing *vmemmap_lextern pmd_t *pmd_fragment_alloc (struct mm_struct *,unsigned long );extern void pmd_fragment_free (unsigned long *);extern void pgtable_free_tlb (struct mmu_gather *tlb,void *table,int shift); -#ifdef CONFIG_SMP extern void __tlb_remove_table (void *_table); -#endif void pte_frag_destroy (void *pte_frag);static inline pgd_t *radix__pgd_alloc (struct mm_struct *mm)
arch/powerpc/include/asm/nohash/pgalloc.h +0 -8
@@ -46,7 +46,6 @@ static inline void pgtable_free(void *ta#define get_hugepd_cache_index (x) (x) -#ifdef CONFIG_SMP static inline void pgtable_free_tlb (struct mmu_gather *tlb,void *table,int shift) {unsigned long pgf = (unsigned long )table;
@@ -64,13 +63,6 @@ static inline void __tlb_remove_table(vopgtable_free (table, shift); } -#else -static inline void pgtable_free_tlb (struct mmu_gather *tlb,void *table,int shift) -{ -pgtable_free (table, shift); -} -#endif -static inline void __pte_free_tlb (struct mmu_gather *tlb,pgtable_t table,unsigned long address) {
arch/powerpc/mm/book3s64/pgtable.c +0 -7
@@ -378,7 +378,6 @@ static inline void pgtable_free(void *ta } } -#ifdef CONFIG_SMP void pgtable_free_tlb (struct mmu_gather *tlb,void *table,int index) {unsigned long pgf = (unsigned long )table;
@@ -395,12 +394,6 @@ void __tlb_remove_table(void *_table)return pgtable_free (table, index); } -#else -void pgtable_free_tlb (struct mmu_gather *tlb,void *table,int index) -{ -return pgtable_free (table, index); -} -#endif #ifdef CONFIG_PROC_FS atomic_long_t direct_pages_count[MMU_PAGE_COUNT ];
Greg Kroah-Hartman
maintainerPATCH 75/309 powerpc/ptdump: Fix W+X verification
In reply to Greg Kroah-HartmanFrom: Christophe Leroy <[email protected]>
commit d80ae83f1f932ab7af47b54d0d3bef4f4dba489f upstream.
Verification cannot rely on simple bit checking because on some platforms PAGE_RW is 0, checking that a page is not W means checking that PAGE_RO is set instead of checking that PAGE_RW is not set.
Use pte helpers instead of checking bits.
--- arch/powerpc/mm/ptdump/ptdump.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/powerpc/mm/ptdump/ptdump.c +3 -1
@@ -173,10 +173,12 @@ static void dump_addr(struct pg_state *sstatic void note_prot_wx (struct pg_state *st,unsigned long addr) { +pte_t pte =__pte (st->current_flags); +if (!IS_ENABLED (CONFIG_PPC_DEBUG_WX ) || !st->check_wx)return ; -if (!((st->current_flags &pgprot_val (PAGE_KERNEL_X )) ==pgprot_val (PAGE_KERNEL_X ))) +if (!pte_write (pte) || !pte_exec (pte))return ; WARN_ONCE(1, "powerpc/mm: Found insecure W+X mapping at address %p/%pS\n",
Greg Kroah-Hartman
maintainerPATCH 76/309 powerpc/xmon: dont access ASDR in VMs
In reply to Greg Kroah-HartmanFrom: Sukadev Bhattiprolu <[email protected]>
commit c2a20711fc181e7f22ee5c16c28cb9578af84729 upstream.
ASDR is HV-privileged and must only be accessed in HV-mode. Fixes a Program Check (0x700) when xmon in a VM dumps SPRs.
--- arch/powerpc/xmon/xmon.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
arch/powerpc/xmon/xmon.c +4 -5
@@ -1894,15 +1894,14 @@ static void dump_300_sprs(void)printf ("pidr = %.16lx tidr = %.16lx\n" ,mfspr (SPRN_PID ),mfspr (SPRN_TIDR )); -printf ("asdr = %.16lx psscr = %.16lx\n" , -mfspr (SPRN_ASDR ), hv ?mfspr (SPRN_PSSCR ) - :mfspr (SPRN_PSSCR_PR )); +printf ("psscr = %.16lx\n" , + hv ?mfspr (SPRN_PSSCR ) :mfspr (SPRN_PSSCR_PR ));if (!hv)return ; -printf ("ptcr = %.16lx\n" , -mfspr (SPRN_PTCR )); +printf ("ptcr = %.16lx asdr = %.16lx\n" , +mfspr (SPRN_PTCR ),mfspr (SPRN_ASDR ));#endif }
Greg Kroah-Hartman
maintainerPATCH 77/309 powerpc/pseries: Advance pfn if section is not present in lmb_is_removable()
In reply to Greg Kroah-HartmanFrom: Pingfan Liu <[email protected]>
commit fbee6ba2dca30d302efe6bddb3a886f5e964a257 upstream.
In lmb_is_removable(), if a section is not present, it should continue to test the rest of the sections in the block. But the current code fails to do so.
--- arch/powerpc/platforms/pseries/hotplug-memory.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/powerpc/platforms/pseries/hotplug-memory.c +3 -1
@@ -360,8 +360,10 @@ static bool lmb_is_removable(struct drmefor (i =0 ; i < scns_per_block; i++) { pfn =PFN_DOWN (phys_addr); -if (!pfn_present (pfn)) +if (!pfn_present (pfn)) { + phys_addr +=MIN_MEMORY_BLOCK_SIZE ;continue ; + } rc &=is_mem_section_removable (pfn,PAGES_PER_SECTION ); phys_addr +=MIN_MEMORY_BLOCK_SIZE ;
Greg Kroah-Hartman
maintainerPATCH 78/309 powerpc/32s: Fix bad_kuap_fault()
In reply to Greg Kroah-HartmanFrom: Christophe Leroy <[email protected]>
commit 6ec20aa2e510b6297906c45f009aa08b2d97269a upstream.
At the moment, bad_kuap_fault() reports a fault only if a bad access to userspace occurred while access to userspace was not granted.
But if a fault occurs for a write outside the allowed userspace segment(s) that have been unlocked, bad_kuap_fault() fails to detect it and the kernel loops forever in do_page_fault().
Fix it by checking that the accessed address is within the allowed range.
--- arch/powerpc/include/asm/book3s/32/kup.h | 9 +++++++-- arch/powerpc/include/asm/book3s/64/kup-radix.h | 3 ++- arch/powerpc/include/asm/kup.h | 6 +++++- arch/powerpc/include/asm/nohash/32/kup-8xx.h | 3 ++- arch/powerpc/mm/fault.c | 2 +- 5 files changed, 17 insertions(+), 6 deletions(-)
arch/powerpc/include/asm/book3s/32/kup.h +7 -2
@@ -131,12 +131,17 @@ static inline void prevent_user_access(v kuap_update_sr(mfsrin(addr) | SR_KS, addr, end); /* set Ks */ } -static inline bool bad_kuap_fault (struct pt_regs *regs,bool is_write) +static inline bool +bad_kuap_fault (struct pt_regs *regs,unsigned long address,bool is_write) { +unsigned long begin = regs->kuap &0xf0000000 ; +unsigned long end = regs->kuap <<28 ; +if (!is_write)return false; -return WARN (!regs->kuap,"Bug: write fault blocked by segment registers !" ); +return WARN (address < begin || address >= end, +"Bug: write fault blocked by segment registers !" ); }#endif /* CONFIG_PPC_KUAP */
arch/powerpc/include/asm/book3s/64/kup-radix.h +2 -1
@@ -95,7 +95,8 @@ static inline void prevent_user_access(vset_kuap (AMR_KUAP_BLOCKED ); } -static inline bool bad_kuap_fault (struct pt_regs *regs,bool is_write) +static inline bool +bad_kuap_fault (struct pt_regs *regs,unsigned long address,bool is_write) { return WARN(mmu_has_feature(MMU_FTR_RADIX_KUAP) && (regs->kuap & (is_write ? AMR_KUAP_BLOCK_WRITE : AMR_KUAP_BLOCK_READ)),
arch/powerpc/include/asm/kup.h +5 -1
@@ -45,7 +45,11 @@ static inline void allow_user_access(voi unsigned long size) { }static inline void prevent_user_access (void __user *to,const void __user *from,unsigned long size) { } -static inline bool bad_kuap_fault (struct pt_regs *regs,bool is_write) {return false; } +static inline bool +bad_kuap_fault (struct pt_regs *regs,unsigned long address,bool is_write) +{ +return false; +}#endif /* CONFIG_PPC_KUAP */ static inline void allow_read_from_user (const void __user *from,unsigned long size)
arch/powerpc/include/asm/nohash/32/kup-8xx.h +2 -1
@@ -45,7 +45,8 @@ static inline void prevent_user_access(vmtspr (SPRN_MD_AP ,MD_APG_KUAP ); } -static inline bool bad_kuap_fault (struct pt_regs *regs,bool is_write) +static inline bool +bad_kuap_fault (struct pt_regs *regs,unsigned long address,bool is_write) {return WARN (!((regs->kuap ^MD_APG_KUAP ) &0xf0000000 ),"Bug: fault blocked by AP register !" );
arch/powerpc/mm/fault.c +1 -1
@@ -233,7 +233,7 @@ static bool bad_kernel_fault(struct pt_r// Read/write fault in a valid region (the exception table search passed // above), but blocked by KUAP is bad, it can never succeed. -if (bad_kuap_fault (regs, is_write)) +if (bad_kuap_fault (regs, address, is_write))return true;// What's left? Kernel fault on user in well defined regions (extable
Greg Kroah-Hartman
maintainerPATCH 79/309 powerpc/32s: Fix CPU wake-up from sleep mode
In reply to Greg Kroah-HartmanFrom: Christophe Leroy <[email protected]>
commit 9933819099c4600b41a042f27a074470a43cf6b9 upstream.
Commit f7354ccac844 ("powerpc/32: Remove CURRENT_THREAD_INFO and rename TI_CPU") broke the CPU wake-up from sleep mode (i.e. when _TLF_SLEEPING is set) by delaying the tovirt(r2, r2).
This is because r2 is not restored by fast_exception_return. It used to work (by chance ?) because CPU wake-up interrupt never comes from user, so r2 is expected to point to 'current' on return.
Commit e2fb9f544431 ("powerpc/32: Prepare for Kernel Userspace Access Protection") broke it even more by clobbering r0 which is not restored by fast_exception_return either.
Use r6 instead of r0. This is possible because r3-r6 are restored by fast_exception_return and only r3-r5 are used for exception arguments.
For r2 it could be converted back to virtual address, but stay on the safe side and restore it from the stack instead. It should be live in the cache at that moment, so loading from the stack should make no difference compared to converting it from phys to virt.
--- arch/powerpc/kernel/entry_32.S | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/powerpc/kernel/entry_32.S +2 -1
@@ -179,7 +179,7 @@ transfer_to_handler: 2: /* if from kernel, check interrupted DOZE/NAP mode and * check for stack overflow */ - kuap_save_and_lock r11, r12, r9, r2, r0 + kuap_save_and_lock r11, r12, r9, r2, r6 addi r2, r12, -THREAD lwz r9,KSP_LIMIT(r12) cmplw r1,r9 /* if r1 <= ksp_limit */
@@ -284,6 +284,7 @@ reenable_mmu: rlwinm r9,r9,0,~MSR_EE lwz r12,_LINK(r11) /* and return to address in LR */ kuap_restore r11, r2, r3, r4, r5 + lwz r2, GPR2(r11) b fast_exception_return #endif
Greg Kroah-Hartman
maintainerPATCH 80/309 tracing: Fix now invalid var_ref_vals assumption in trace action
In reply to Greg Kroah-HartmanFrom: Tom Zanussi <[email protected]>
[ Upstream commit d380dcde9a07ca5de4805dee11f58a98ec0ad6ff ]
The patch 'tracing: Fix histogram code when expression has same var as value' added code to return an existing variable reference when creating a new variable reference, which resulted in var_ref_vals slots being reused instead of being duplicated.
The implementation of the trace action assumes that the end of the var_ref_vals array starting at action_data.var_ref_idx corresponds to the values that will be assigned to the trace params. The patch mentioned above invalidates that assumption, which means that each param needs to explicitly specify its index into var_ref_vals.
This fix changes action_data.var_ref_idx to an array of var ref indexes to account for that.
--- kernel/trace/trace_events_hist.c | 53 +++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 15 deletions(-)
kernel/trace/trace_events_hist.c +38 -15
@@ -470,11 +470,12 @@ struct action_data {* When a histogram trigger is hit, the values of any * references to variables, including variables being passed * as parameters to synthetic events, are collected into a -* var_ref_vals array. This var_ref_idx is the index of the -* first param in the array to be passed to the synthetic -* event invocation. +* var_ref_vals array. This var_ref_idx array is an array of +* indices into the var_ref_vals array, one for each synthetic +* event param, and is passed to the synthetic event +* invocation. */ -unsigned int var_ref_idx; +unsigned int var_ref_idx[TRACING_MAP_VARS_MAX ];struct synth_event *synth_event;bool use_trace_keyword;char *synth_event_name;
@@ -875,14 +876,14 @@ static struct trace_event_functions synt static notrace void trace_event_raw_event_synth(void *__data,u64 *var_ref_vals, -unsigned int var_ref_idx) +unsigned int *var_ref_idx) {struct trace_event_file *trace_file = __data;struct synth_trace_event *entry;struct trace_event_buffer fbuffer;struct ring_buffer *buffer;struct synth_event *event; -unsigned int i, n_u64; +unsigned int i, n_u64, val_idx;int fields_size =0 ; event = trace_file->event_call->data;
@@ -905,15 +906,16 @@ static notrace void trace_event_raw_even goto out;for (i =0 , n_u64 =0 ; i < event->n_fields; i++) { + val_idx = var_ref_idx[i];if (event->fields[i]->is_string) { -char *str_val = (char *)(long )var_ref_vals[var_ref_idx + i]; +char *str_val = (char *)(long )var_ref_vals[val_idx];char *str_field = (char *)&entry->fields[n_u64];strscpy (str_field, str_val,STR_VAR_LEN_MAX ); n_u64 +=STR_VAR_LEN_MAX /sizeof (u64); }else {struct synth_field *field = event->fields[i]; -u64 val = var_ref_vals[var_ref_idx + i]; +u64 val = var_ref_vals[val_idx];switch (field->size) {case 1 :
@@ -1113,10 +1115,10 @@ static struct tracepoint *alloc_synth_tr }typedef void (*synth_probe_func_t ) (void *__data,u64 *var_ref_vals, -unsigned int var_ref_idx); +unsigned int *var_ref_idx);static inline void trace_synth (struct synth_event *event,u64 *var_ref_vals, -unsigned int var_ref_idx) +unsigned int *var_ref_idx) {struct tracepoint *tp = event->tp;
@@ -2655,6 +2657,22 @@ static int init_var_ref(struct hist_fiel goto out; } +static int find_var_ref_idx (struct hist_trigger_data *hist_data, +struct hist_field *var_field) +{ +struct hist_field *ref_field; +int i; + +for (i =0 ; i < hist_data->n_var_refs; i++) { + ref_field = hist_data->var_refs[i]; +if (ref_field->var.idx == var_field->var.idx && + ref_field->var.hist_data == var_field->hist_data) +return i; + } + +return -ENOENT ; +} +/** * create_var_ref - Create a variable reference and attach it to trigger * @hist_data: The trigger that will be referencing the variable
@@ -4228,11 +4246,11 @@ static int trace_action_create(struct histruct trace_array *tr = hist_data->event_file->tr;char *event_name, *param, *system =NULL ;struct hist_field *hist_field, *var_ref; -unsigned int i, var_ref_idx; +unsigned int i;unsigned int field_pos =0 ;struct synth_event *event;char *synth_event_name; -int ret =0 ; +int var_ref_idx, ret =0 ;lockdep_assert_held (&event_mutex);
@@ -4249,8 +4267,6 @@ static int trace_action_create(struct hi event->ref++; - var_ref_idx = hist_data->n_var_refs; -for (i =0 ; i < data->n_params; i++) {char *p;
@@ -4299,6 +4315,14 @@ static int trace_action_create(struct hi goto err; } + var_ref_idx =find_var_ref_idx (hist_data, var_ref); +if (WARN_ON (var_ref_idx <0 )) { + ret = var_ref_idx; + goto err; + } + + data->var_ref_idx[i] = var_ref_idx; + field_pos++;kfree (p);continue ;
@@ -4317,7 +4341,6 @@ static int trace_action_create(struct hi } data->synth_event = event; - data->var_ref_idx = var_ref_idx; out:return ret; err:
Greg Kroah-Hartman
maintainerPATCH 81/309 PCI: tegra: Fix return value check of pm_runtime_get_sync()
In reply to Greg Kroah-HartmanFrom: David Engraf <[email protected]>
commit 885199148442f56b880995d703d2ed03b6481a3c upstream.
pm_runtime_get_sync() returns the device's usage counter. This might be >0 if the device is already powered up or CONFIG_PM is disabled.
Abort probe function on real error only.
--- drivers/pci/controller/pci-tegra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pci/controller/pci-tegra.c +1 -1
@@ -2798,7 +2798,7 @@ static int tegra_pcie_probe(struct platfpm_runtime_enable (pcie->dev); err =pm_runtime_get_sync (pcie->dev); -if (err) { +if (err <0 ) {dev_err (dev,"fail to enable pcie controller: %d\n" , err); goto teardown_msi; }
Greg Kroah-Hartman
maintainerPATCH 82/309 PCI: keystone: Fix outbound region mapping
In reply to Greg Kroah-HartmanFrom: Yurii Monakov <[email protected]>
commit 2d0c3fbe43fa0e6fcb7a6c755c5f4cd702c0d2f4 upstream.
The Keystone outbound Address Translation Unit (ATU) maps PCI MMIO space in 8 MB windows. When programming the ATU windows, we previously incremented the starting address by 8, not 8 MB, so all the windows were mapped to the first 8 MB. Therefore, only 8 MB of MMIO space was accessible.
Update the loop so it increments the starting address by 8 MB, not 8, so more MMIO space is accessible.
--- drivers/pci/controller/dwc/pci-keystone.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pci/controller/dwc/pci-keystone.c +1 -1
@@ -422,7 +422,7 @@ static void ks_pcie_setup_rc_app_regs(st lower_32_bits(start) | OB_ENABLEN);ks_pcie_app_writel (ks_pcie,OB_OFFSET_HI (i),upper_32_bits (start)); - start +=OB_WIN_SIZE ; + start +=OB_WIN_SIZE *SZ_1M ; } val =ks_pcie_app_readl (ks_pcie,CMD_STATUS );
Greg Kroah-Hartman
maintainerPATCH 83/309 PCI: keystone: Fix link training retries initiation
In reply to Greg Kroah-HartmanFrom: Yurii Monakov <[email protected]>
commit 6df19872d881641e6394f93ef2938cffcbdae5bb upstream.
ks_pcie_stop_link() function does not clear LTSSM_EN_VAL bit so link training was not triggered more than once after startup. In configurations where link can be unstable during early boot, for example, under low temperature, it will never be established.
--- drivers/pci/controller/dwc/pci-keystone.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pci/controller/dwc/pci-keystone.c +1 -1
@@ -510,7 +510,7 @@ static void ks_pcie_stop_link(struct dw_/* Disable Link training */ val =ks_pcie_app_readl (ks_pcie,CMD_STATUS ); val &= ~LTSSM_EN_VAL ; -ks_pcie_app_writel (ks_pcie,CMD_STATUS ,LTSSM_EN_VAL | val); +ks_pcie_app_writel (ks_pcie,CMD_STATUS , val); }static int ks_pcie_start_link (struct dw_pcie *pci)
Greg Kroah-Hartman
maintainerPATCH 84/309 PCI: keystone: Fix error handling when "num-viewport" DT property is not populated
In reply to Greg Kroah-HartmanFrom: Kishon Vijay Abraham I <[email protected]>
commit b0de922af53eede340986a2d05b6cd4b6d6efa43 upstream.
Fix error handling when "num-viewport" DT property is not populated.
--- drivers/pci/controller/dwc/pci-keystone.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pci/controller/dwc/pci-keystone.c +1 -1
@@ -1354,7 +1354,7 @@ static int __init ks_pcie_probe(struct p ret =of_property_read_u32 (np,"num-viewport" , &num_viewport);if (ret <0 ) {dev_err (dev,"unable to read *num-viewport* property\n" ); -return ret; + goto err_get_sync; }/*
Greg Kroah-Hartman
maintainerPATCH 85/309 mmc: spi: Toggle SPI polarity, do not hardcode it
In reply to Greg Kroah-HartmanFrom: Linus Walleij <[email protected]>
commit af3ed119329cf9690598c5a562d95dfd128e91d6 upstream.
The code in mmc_spi_initsequence() tries to send a burst with high chipselect and for this reason hardcodes the device into SPI_CS_HIGH.
This is not good because the SPI_CS_HIGH flag indicates logical "asserted" CS not always the physical level. In some cases the signal is inverted in the GPIO library and in that case SPI_CS_HIGH is already set, and enforcing SPI_CS_HIGH again will actually drive it low.
Instead of hard-coding this, toggle the polarity so if the default is LOW it goes high to assert chipselect but if it is already high then toggle it low instead.
--- drivers/mmc/host/mmc_spi.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
drivers/mmc/host/mmc_spi.c +8 -3
@@ -1134,17 +1134,22 @@ static void mmc_spi_initsequence(struct* SPI protocol. Another is that when chipselect is released while * the card returns BUSY status, the clock must issue several cycles * with chipselect high before the card will stop driving its output. +* +* SPI_CS_HIGH means "asserted" here. In some cases like when using +* GPIOs for chip select, SPI_CS_HIGH is set but this will be logically +* inverted by gpiolib, so if we want to ascertain to drive it high +* we should toggle the default with an XOR as we do here. */ - host->spi->mode |=SPI_CS_HIGH ; + host->spi->mode ^=SPI_CS_HIGH ;if (spi_setup (host->spi) !=0 ) {/* Just warn; most cards work without it. */ dev_warn (&host->spi->dev,"can't change chip-select polarity\n" ); - host->spi->mode &= ~SPI_CS_HIGH ; + host->spi->mode ^=SPI_CS_HIGH ; }else {mmc_spi_readbytes (host,18 ); - host->spi->mode &= ~SPI_CS_HIGH ; + host->spi->mode ^=SPI_CS_HIGH ;if (spi_setup (host->spi) !=0 ) {/* Wot, we can't get the same setup we had before? */ dev_err(&host->spi->dev,
Greg Kroah-Hartman
maintainerPATCH 86/309 ACPI: video: Do not export a non working backlight interface on MSI MS-7721 boards
In reply to Greg Kroah-HartmanFrom: Hans de Goede <[email protected]>
commit d21a91629f4b8e794fc4c0e0c17c85cedf1d806c upstream.
Despite our heuristics to not wrongly export a non working ACPI backlight interface on desktop machines, we still end up exporting one on desktops using a motherboard from the MSI MS-7721 series.
I've looked at improving the heuristics, but in this case a quirk seems to be the only way to solve this.
While at it also add a comment to separate the video_detect_force_none entries in the video_detect_dmi_table from other type of entries, as we already do for the other entry types.
--- drivers/acpi/video_detect.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
drivers/acpi/video_detect.c +13 -0
@@ -336,6 +336,11 @@ static const struct dmi_system_id video_ DMI_MATCH(DMI_PRODUCT_NAME, "Precision 7510"), }, }, + +/* +* Desktops which falsely report a backlight and which our heuristics +* for this do not catch. +*/ { .callback = video_detect_force_none, .ident = "Dell OptiPlex 9020M",
@@ -344,6 +349,14 @@ static const struct dmi_system_id video_ DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 9020M"), }, }, + { + .callback = video_detect_force_none, + .ident = "MSI MS-7721", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MSI"), + DMI_MATCH(DMI_PRODUCT_NAME, "MS-7721"), + }, + }, { }, };
Greg Kroah-Hartman
maintainerPATCH 87/309 ACPI / battery: Deal with design or full capacity being reported as -1
In reply to Greg Kroah-HartmanFrom: Hans de Goede <[email protected]>
commit cc99f0ad52467028cb1251160f23ad4bb65baf20 upstream.
Commit b41901a2cf06 ("ACPI / battery: Do not export energy_full[_design] on devices without full_charge_capacity") added support for some (broken) devices which always report 0 for both design- and full_charge-capacity.
This assumes that if the capacity is not being reported it is 0. The ThunderSoft TS178 tablet's _BIX implementation falsifies this assumption. It reports ACPI_BATTERY_VALUE_UNKNOWN (-1) as full_charge_capacity, which we treat as a valid value which causes several problems.
This commit fixes this by adding a new ACPI_BATTERY_CAPACITY_VALID() helper which checks that the value is not 0 and not -1; and using this whenever we need to test if either design_capacity or full_charge_capacity is valid.
--- drivers/acpi/battery.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-)
drivers/acpi/battery.c +12 -7
@@ -38,6 +38,8 @@#define PREFIX "ACPI: "#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF +#define ACPI_BATTERY_CAPACITY_VALID (capacity) \ + ((capacity) != 0 && (capacity) != ACPI_BATTERY_VALUE_UNKNOWN)#define ACPI_BATTERY_DEVICE_NAME "Battery"
@@ -192,7 +194,8 @@ static int acpi_battery_is_charged(strucstatic bool acpi_battery_is_degraded (struct acpi_battery *battery) { -return battery->full_charge_capacity && battery->design_capacity && +return ACPI_BATTERY_CAPACITY_VALID (battery->full_charge_capacity) && +ACPI_BATTERY_CAPACITY_VALID (battery->design_capacity) && battery->full_charge_capacity < battery->design_capacity; }
@@ -263,14 +266,14 @@ static int acpi_battery_get_property(strbreak ;case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN :case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN : -if (battery->design_capacity ==ACPI_BATTERY_VALUE_UNKNOWN ) +if (!ACPI_BATTERY_CAPACITY_VALID (battery->design_capacity)) ret = -ENODEV ;else val->intval = battery->design_capacity *1000 ;break ;case POWER_SUPPLY_PROP_CHARGE_FULL :case POWER_SUPPLY_PROP_ENERGY_FULL : -if (battery->full_charge_capacity ==ACPI_BATTERY_VALUE_UNKNOWN ) +if (!ACPI_BATTERY_CAPACITY_VALID (battery->full_charge_capacity)) ret = -ENODEV ;else val->intval = battery->full_charge_capacity *1000 ;
@@ -283,11 +286,12 @@ static int acpi_battery_get_property(str val->intval = battery->capacity_now *1000 ;break ;case POWER_SUPPLY_PROP_CAPACITY : -if (battery->capacity_now && battery->full_charge_capacity) +if (battery->capacity_now ==ACPI_BATTERY_VALUE_UNKNOWN || + !ACPI_BATTERY_CAPACITY_VALID (battery->full_charge_capacity)) + ret = -ENODEV ; +else val->intval = battery->capacity_now *100 / battery->full_charge_capacity; -else - val->intval =0 ;break ;case POWER_SUPPLY_PROP_CAPACITY_LEVEL :if (battery->state &ACPI_BATTERY_STATE_CRITICAL )
@@ -799,7 +803,8 @@ static int sysfs_add_battery(struct acpi battery->bat_desc.properties = charge_battery_props; battery->bat_desc.num_properties =ARRAY_SIZE (charge_battery_props); - }else if (battery->full_charge_capacity ==0 ) { + }else if (!ACPI_BATTERY_CAPACITY_VALID ( + battery->full_charge_capacity)) { battery->bat_desc.properties = energy_battery_full_cap_broken_props; battery->bat_desc.num_properties =
Greg Kroah-Hartman
maintainerPATCH 88/309 ACPI / battery: Use design-cap for capacity calculations if full-cap is not available
In reply to Greg Kroah-HartmanFrom: Hans de Goede <[email protected]>
commit 5b74d1d16e2f5753fcbdecd6771b2d8370dda414 upstream.
The ThunderSoft TS178 tablet's _BIX implementation reports design_capacity but not full_charge_capacity.
Before this commit this would cause us to return -ENODEV for the capacity attribute, which userspace does not like. Specifically upower does this:
if (sysfs_file_exists (native_path, "capacity")) {
percentage = sysfs_get_double (native_path, "capacity");Where the sysfs_get_double() helper returns 0 when we return -ENODEV, so the battery always reads 0% if we return -ENODEV.
This commit fixes this by using the design-capacity instead of the full-charge-capacity when the full-charge-capacity is not available.
--- drivers/acpi/battery.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
drivers/acpi/battery.c +8 -3
@@ -217,7 +217,7 @@ static int acpi_battery_get_property(strenum power_supply_property psp, union power_supply_propval *val) { - int ret = 0; + int full_capacity = ACPI_BATTERY_VALUE_UNKNOWN, ret = 0;struct acpi_battery *battery =to_acpi_battery (psy);if (acpi_battery_present (battery)) {
@@ -286,12 +286,17 @@ static int acpi_battery_get_property(str val->intval = battery->capacity_now *1000 ;break ;case POWER_SUPPLY_PROP_CAPACITY : +if (ACPI_BATTERY_CAPACITY_VALID (battery->full_charge_capacity)) + full_capacity = battery->full_charge_capacity; +else if (ACPI_BATTERY_CAPACITY_VALID (battery->design_capacity)) + full_capacity = battery->design_capacity; +if (battery->capacity_now ==ACPI_BATTERY_VALUE_UNKNOWN || - !ACPI_BATTERY_CAPACITY_VALID (battery->full_charge_capacity)) + full_capacity ==ACPI_BATTERY_VALUE_UNKNOWN ) ret = -ENODEV ;else val->intval = battery->capacity_now *100 / - battery->full_charge_capacity; + full_capacity;break ;case POWER_SUPPLY_PROP_CAPACITY_LEVEL :if (battery->state &ACPI_BATTERY_STATE_CRITICAL )
Greg Kroah-Hartman
maintainerPATCH 89/309 ACPI / battery: Deal better with neither design nor full capacity not being reported
In reply to Greg Kroah-HartmanFrom: Hans de Goede <[email protected]>
commit ff3154d1d89a2343fd5f82e65bc0cf1d4e6659b3 upstream.
Commit b41901a2cf06 ("ACPI / battery: Do not export energy_full[_design] on devices without full_charge_capacity") added support for some (broken) devices which always report 0 for both design_capacity and full_charge_capacity.
Since the device that commit was written as a fix for is not reporting any form of "full" capacity we cannot calculate the value for the POWER_SUPPLY_PROP_CAPACITY, this is worked around by using an alternative array of available properties which does not contain this property.
This is necessary because userspace (upower) treats us returning -ENODEV as 0 and then typically will trigger an emergency shutdown because of that. Userspace does not do this if the capacity sysfs attribute is not present at all.
There are two potential problems with that commit:
1) It assumes that both full_charge- and design-capacity are broken at the same time and only checks if full_charge- is broken.
2) It assumes that this only ever happens for devices which report energy units rather then charge units.
This commit fixes both issues by only using the alternative array of available properties if both full_charge- and design-capacity are broken and by also adding an alternative array of available properties for devices using mA units.
--- drivers/acpi/battery.c | 51 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 12 deletions(-)
drivers/acpi/battery.c +39 -12
@@ -342,6 +342,20 @@ static enum power_supply_property charge POWER_SUPPLY_PROP_SERIAL_NUMBER, }; +static enum power_supply_property charge_battery_full_cap_broken_props[] = { +POWER_SUPPLY_PROP_STATUS , +POWER_SUPPLY_PROP_PRESENT , +POWER_SUPPLY_PROP_TECHNOLOGY , +POWER_SUPPLY_PROP_CYCLE_COUNT , +POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN , +POWER_SUPPLY_PROP_VOLTAGE_NOW , +POWER_SUPPLY_PROP_CURRENT_NOW , +POWER_SUPPLY_PROP_CHARGE_NOW , +POWER_SUPPLY_PROP_MODEL_NAME , +POWER_SUPPLY_PROP_MANUFACTURER , +POWER_SUPPLY_PROP_SERIAL_NUMBER , +}; +static enum power_supply_property energy_battery_props[] = {POWER_SUPPLY_PROP_STATUS ,POWER_SUPPLY_PROP_PRESENT ,
@@ -803,21 +817,34 @@ static void __exit battery_hook_exit(voistatic int sysfs_add_battery (struct acpi_battery *battery) {struct power_supply_config psy_cfg = { .drv_data = battery, }; +bool full_cap_broken = false; + +if (!ACPI_BATTERY_CAPACITY_VALID (battery->full_charge_capacity) && + !ACPI_BATTERY_CAPACITY_VALID (battery->design_capacity)) + full_cap_broken = true;if (battery->power_unit ==ACPI_BATTERY_POWER_UNIT_MA ) { - battery->bat_desc.properties = charge_battery_props; - battery->bat_desc.num_properties = -ARRAY_SIZE (charge_battery_props); - }else if (!ACPI_BATTERY_CAPACITY_VALID ( - battery->full_charge_capacity)) { - battery->bat_desc.properties = - energy_battery_full_cap_broken_props; - battery->bat_desc.num_properties = -ARRAY_SIZE (energy_battery_full_cap_broken_props); +if (full_cap_broken) { + battery->bat_desc.properties = + charge_battery_full_cap_broken_props; + battery->bat_desc.num_properties = +ARRAY_SIZE (charge_battery_full_cap_broken_props); + }else { + battery->bat_desc.properties = charge_battery_props; + battery->bat_desc.num_properties = +ARRAY_SIZE (charge_battery_props); + } }else { - battery->bat_desc.properties = energy_battery_props; - battery->bat_desc.num_properties = -ARRAY_SIZE (energy_battery_props); +if (full_cap_broken) { + battery->bat_desc.properties = + energy_battery_full_cap_broken_props; + battery->bat_desc.num_properties = +ARRAY_SIZE (energy_battery_full_cap_broken_props); + }else { + battery->bat_desc.properties = energy_battery_props; + battery->bat_desc.num_properties = +ARRAY_SIZE (energy_battery_props); + } } battery->bat_desc.name =acpi_device_bid (battery->device);
Greg Kroah-Hartman
maintainerPATCH 90/309 alarmtimer: Unregister wakeup source when module get fails
In reply to Greg Kroah-HartmanFrom: Stephen Boyd <[email protected]>
commit 6b6d188aae79a630957aefd88ff5c42af6553ee3 upstream.
The alarmtimer_rtc_add_device() function creates a wakeup source and then tries to grab a module reference. If that fails the function returns early with an error code, but fails to remove the wakeup source.
Cleanup this exit path so there is no dangling wakeup source, which is named 'alarmtime' left allocated which will conflict with another RTC device that may be registered later.
--- kernel/time/alarmtimer.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
kernel/time/alarmtimer.c +5 -3
@@ -88,6 +88,7 @@ static int alarmtimer_rtc_add_device(strunsigned long flags;struct rtc_device *rtc =to_rtc_device (dev);struct wakeup_source *__ws; +int ret =0 ;if (rtcdev)return -EBUSY ;
@@ -102,8 +103,8 @@ static int alarmtimer_rtc_add_device(strspin_lock_irqsave (&rtcdev_lock, flags);if (!rtcdev) {if (!try_module_get (rtc->owner)) { -spin_unlock_irqrestore (&rtcdev_lock, flags); -return -1 ; + ret =-1 ; + goto unlock; } rtcdev = rtc;
@@ -112,11 +113,12 @@ static int alarmtimer_rtc_add_device(str ws = __ws; __ws =NULL ; } +unlock:spin_unlock_irqrestore (&rtcdev_lock, flags);wakeup_source_unregister (__ws); -return 0 ; +return ret; }static inline void alarmtimer_rtc_timer_init (void )
Greg Kroah-Hartman
maintainerPATCH 91/309 fscrypt: dont print name of busy file when removing key
In reply to Greg Kroah-HartmanFrom: Eric Biggers <[email protected]>
commit 13a10da94615d81087e718517794f2868a8b3fab upstream.
When an encryption key can't be fully removed due to file(s) protected by it still being in-use, we shouldn't really print the path to one of these files to the kernel log, since parts of this path are likely to be encrypted on-disk, and (depending on how the system is set up) the confidentiality of this path might be lost by printing it to the log.
This is a trade-off: a single file path often doesn't matter at all, especially if it's a directory; the kernel log might still be protected in some way; and I had originally hoped that any "inode(s) still busy" bugs (which are security weaknesses in their own right) would be quickly fixed and that to do so it would be super helpful to always know the file path and not have to run 'find dir -inum $inum' after the fact.
But in practice, these bugs can be hard to fix (e.g. due to asynchronous process killing that is difficult to eliminate, for performance reasons), and also not tied to specific files, so knowing a file path doesn't necessarily help.
So to be safe, for now let's just show the inode number, not the path. If someone really wants to know a path they can use 'find -inum'.
--- fs/crypto/keyring.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-)
fs/crypto/keyring.c +2 -13
@@ -664,9 +664,6 @@ static int check_for_busy_inodes(structstruct list_head *pos;size_t busy_count =0 ;unsigned long ino; -struct dentry *dentry; -char _path[256 ]; -char *path =NULL ;spin_lock (&mk->mk_decrypted_inodes_lock);
@@ -685,22 +682,14 @@ static int check_for_busy_inodes(struct struct fscrypt_info, ci_master_key_link)->ci_inode; ino = inode->i_ino; - dentry =d_find_alias (inode); }spin_unlock (&mk->mk_decrypted_inodes_lock); -if (dentry) { - path =dentry_path (dentry, _path,sizeof (_path)); -dput (dentry); - } -if (IS_ERR_OR_NULL (path)) - path ="(unknown)" ; -fscrypt_warn (NULL , -"%s: %zu inode(s) still busy after removing key with %s %*phN, including ino %lu (%s)" , +"%s: %zu inode(s) still busy after removing key with %s %*phN, including ino %lu" , sb->s_id, busy_count,master_key_spec_type (&mk->mk_spec),master_key_spec_len (&mk->mk_spec), (u8 *)&mk->mk_spec.u, - ino, path); + ino);return -EBUSY ; }
Greg Kroah-Hartman
maintainerPATCH 92/309 ubifs: dont trigger assertion on invalid no-key filename
In reply to Greg Kroah-HartmanFrom: Eric Biggers <[email protected]>
commit f0d07a98a070bb5e443df19c3aa55693cbca9341 upstream.
If userspace provides an invalid fscrypt no-key filename which encodes a hash value with any of the UBIFS node type bits set (i.e. the high 3 bits), gracefully report ENOENT rather than triggering ubifs_assert().
Test case with kvm-xfstests shell:
. fs/ubifs/config
. ~/xfstests/common/encrypt dev=$(__blkdev_to_ubi_volume /dev/vdc) ubiupdatevol $dev -t
mount $dev /mnt -t ubifs
mkdir /mnt/edir
xfs_io -c set_encpolicy /mnt/edir
rm /mnt/edir/_,,,,,DAAAAAAAAAAAAAAAAAAAAAAAAAA
With the bug, the following assertion fails on the 'rm' command:
[ 19.066048] UBIFS error (ubi0:0 pid 379): ubifs_assert_failed: UBIFS assert failed: !(hash & ~UBIFS_S_KEY_HASH_MASK), in fs/ubifs/key.h:170
--- fs/ubifs/dir.c | 2 ++ 1 file changed, 2 insertions(+)
fs/ubifs/dir.c +2 -0
@@ -228,6 +228,8 @@ static struct dentry *ubifs_lookup(strucif (nm.hash) {ubifs_assert (c,fname_len (&nm) ==0 );ubifs_assert (c,fname_name (&nm) ==NULL ); +if (nm.hash & ~UBIFS_S_KEY_HASH_MASK ) + goto done;/* ENOENT */ dent_key_init_hash (c, &key, dir->i_ino, nm.hash); err =ubifs_tnc_lookup_dh (c, &key, dent, nm.minor_hash); }else {
Greg Kroah-Hartman
maintainerPATCH 93/309 ubifs: Fix wrong memory allocation
In reply to Greg Kroah-HartmanFrom: Sascha Hauer <[email protected]>
commit edec51374bce779f37fc209a228139c55d90ec8d upstream.
In create_default_filesystem() when we allocate the idx node we must use the idx_node_size we calculated just one line before, not tmp, which contains completely other data.
--- fs/ubifs/sb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ubifs/sb.c +1 -1
@@ -161,7 +161,7 @@ static int create_default_filesystem(str sup =kzalloc (ALIGN (UBIFS_SB_NODE_SZ , c->min_io_size),GFP_KERNEL ); mst =kzalloc (c->mst_node_alsz,GFP_KERNEL ); idx_node_size =ubifs_idx_node_sz (c,1 ); - idx =kzalloc (ALIGN (tmp, c->min_io_size),GFP_KERNEL ); + idx =kzalloc (ALIGN (idx_node_size, c->min_io_size),GFP_KERNEL ); ino =kzalloc (ALIGN (UBIFS_INO_NODE_SZ , c->min_io_size),GFP_KERNEL ); cs =kzalloc (ALIGN (UBIFS_CS_NODE_SZ , c->min_io_size),GFP_KERNEL );
Greg Kroah-Hartman
maintainerPATCH 94/309 ubifs: Fix FS_IOC_SETFLAGS unexpectedly clearing encrypt flag
In reply to Greg Kroah-HartmanFrom: Eric Biggers <[email protected]>
commit 2b57067a7778484c10892fa191997bfda29fea13 upstream.
UBIFS's implementation of FS_IOC_SETFLAGS fails to preserve existing inode flags that aren't settable by FS_IOC_SETFLAGS, namely the encrypt flag. This causes the encrypt flag to be unexpectedly cleared.
Fix it by preserving existing unsettable flags, like ext4 and f2fs do.
Test case with kvm-xfstests shell:
FSTYP=ubifs KEYCTL_PROG=keyctl
. fs/ubifs/config
. ~/xfstests/common/encrypt
dev=$(__blkdev_to_ubi_volume /dev/vdc)
ubiupdatevol -t $dev
mount $dev /mnt -t ubifs
k=$(_generate_session_encryption_key)
mkdir /mnt/edir
xfs_io -c "set_encpolicy $k" /mnt/edir
echo contents > /mnt/edir/file
chattr +i /mnt/edir/file
chattr -i /mnt/edir/file
With the bug, the following errors occur on the last command:
[ 18.081559] fscrypt (ubifs, inode 67): Inconsistent encryption context (parent directory: 65)
chattr: Operation not permitted while reading flags on /mnt/edir/file--- fs/ubifs/ioctl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/ubifs/ioctl.c +2 -1
@@ -113,7 +113,8 @@ static int setflags(struct inode *inode,if (err) goto out_unlock; - ui->flags =ioctl2ubifs (flags); + ui->flags &= ~ioctl2ubifs (UBIFS_SUPPORTED_IOCTL_FLAGS ); + ui->flags |=ioctl2ubifs (flags);ubifs_set_inode_flags (inode); inode->i_ctime =current_time (inode); release = ui->dirty;
Greg Kroah-Hartman
maintainerPATCH 95/309 ubifs: Fix deadlock in concurrent bulk-read and writepage
In reply to Greg Kroah-HartmanFrom: Zhihao Cheng <[email protected]>
commit f5de5b83303e61b1f3fb09bd77ce3ac2d7a475f2 upstream.
In ubifs, concurrent execution of writepage and bulk read on the same file may cause ABBA deadlock, for example (Reproduce method see Link):
Process A(Bulk-read starts from page4) Process B(write page4 back)
vfs_read wb_workfn or fsync ... ... generic_file_buffered_read write_cache_pages
ubifs_readpage LOCK(page4)
ubifs_bulk_read ubifs_writepage
LOCK(ui->ui_mutex) ubifs_write_inode
ubifs_do_bulk_read LOCK(ui->ui_mutex)
find_or_create_page(alloc page4) ↑
LOCK(page4) <-- ABBA deadlock occurs!
In order to ensure the serialization execution of bulk read, we can't remove the big lock 'ui->ui_mutex' in ubifs_bulk_read(). Instead, we allow ubifs_do_bulk_read() to lock page failed by replacing find_or_create_page(FGP_LOCK) with pagecache_get_page(FGP_LOCK | FGP_NOWAIT).
--- fs/ubifs/file.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/ubifs/file.c +3 -1
@@ -786,7 +786,9 @@ static int ubifs_do_bulk_read(struct ubiif (page_offset > end_index)break ; - page =find_or_create_page (mapping, page_offset, ra_gfp_mask); + page =pagecache_get_page (mapping, page_offset, +FGP_LOCK |FGP_ACCESSED |FGP_CREAT |FGP_NOWAIT , + ra_gfp_mask);if (!page)break ;if (!PageUptodate (page))
Greg Kroah-Hartman
maintainerPATCH 96/309 mmc: sdhci-of-at91: fix memleak on clk_get failure
In reply to Greg Kroah-HartmanFrom: Michał Mirosław <[email protected]>
[ Upstream commit a04184ce777b46e92c2b3c93c6dcb2754cb005e1 ]
sdhci_alloc_host() does its work not using managed infrastructure, so needs explicit free on error path. Add it where needed.
--- drivers/mmc/host/sdhci-of-at91.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
drivers/mmc/host/sdhci-of-at91.c +6 -3
@@ -324,19 +324,22 @@ static int sdhci_at91_probe(struct platform_device *pdev) priv->mainck =devm_clk_get (&pdev->dev,"baseclk" );if (IS_ERR (priv->mainck)) {dev_err (&pdev->dev,"failed to get baseclk\n" ); -return PTR_ERR (priv->mainck); + ret =PTR_ERR (priv->mainck); + goto sdhci_pltfm_free; } priv->hclock =devm_clk_get (&pdev->dev,"hclock" );if (IS_ERR (priv->hclock)) {dev_err (&pdev->dev,"failed to get hclock\n" ); -return PTR_ERR (priv->hclock); + ret =PTR_ERR (priv->hclock); + goto sdhci_pltfm_free; } priv->gck =devm_clk_get (&pdev->dev,"multclk" );if (IS_ERR (priv->gck)) {dev_err (&pdev->dev,"failed to get multclk\n" ); -return PTR_ERR (priv->gck); + ret =PTR_ERR (priv->gck); + goto sdhci_pltfm_free; } ret =sdhci_at91_set_clks_presets (&pdev->dev);
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 97/309 ASoC: SOF: core: free trace on errors
In reply to Greg Kroah-HartmanFrom: Pierre-Louis Bossart <[email protected]>
commit 37e97e6faeabda405d0c4319f8419dcc3da14b2b upstream.
free_trace() is not called on probe errors, fix
--- sound/soc/sof/core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
sound/soc/sof/core.c +5 -2
@@ -368,7 +368,7 @@ static int sof_probe_continue(struct sndif (ret <0 ) {dev_err (sdev->dev,"error: failed to register DSP DAI driver %d\n" , ret); - goto fw_run_err; + goto fw_trace_err; } drv_name = plat_data->machine->drv_name;
@@ -382,7 +382,7 @@ static int sof_probe_continue(struct sndif (IS_ERR (plat_data->pdev_mach)) { ret =PTR_ERR (plat_data->pdev_mach); - goto fw_run_err; + goto fw_trace_err; } dev_dbg(sdev->dev, "created machine %s\n",
@@ -394,6 +394,8 @@ static int sof_probe_continue(struct sndreturn 0 ;#if !IS_ENABLED (CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE ) +fw_trace_err: +snd_sof_free_trace (sdev); fw_run_err:snd_sof_fw_unload (sdev); fw_load_err:
@@ -411,6 +413,7 @@ dbg_err:* snd_sof_device_remove() when the PCI/ACPI device is removed */ +fw_trace_err: fw_run_err: fw_load_err: ipc_err:
Greg Kroah-Hartman
maintainerPATCH 98/309 hv_balloon: Balloon up according to request page number
In reply to Greg Kroah-HartmanFrom: Tianyu Lan <[email protected]>
commit d33c240d47dab4fd15123d9e73fc8810cbc6ed6a upstream.
Current code has assumption that balloon request memory size aligns with 2MB. But actually Hyper-V doesn't guarantee such alignment. When balloon driver receives non-aligned balloon request, it produces warning and balloon up more memory than requested in order to keep 2MB alignment. Remove the warning and balloon up memory according to actual requested memory size.
--- drivers/hv/hv_balloon.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-)
drivers/hv/hv_balloon.c +3 -10
@@ -1213,10 +1213,7 @@ static unsigned int alloc_balloon_pages(unsigned int i, j;struct page *pg; -if (num_pages < alloc_unit) -return 0 ; - -for (i =0 ; (i * alloc_unit) < num_pages; i++) { +for (i =0 ; i < num_pages / alloc_unit; i++) {if (bl_resp->hdr.size +sizeof (union dm_mem_page_range ) >PAGE_SIZE )return i * alloc_unit;
@@ -1254,7 +1251,7 @@ static unsigned int alloc_balloon_pages( } -return num_pages; +return i * alloc_unit; }static void balloon_up (struct work_struct *dummy)
@@ -1269,9 +1266,6 @@ static void balloon_up(struct work_struclong avail_pages;unsigned long floor; -/* The host balloons pages in 2M granularity. */ -WARN_ON_ONCE (num_pages %PAGES_IN_2M !=0 ); -/* * We will attempt 2M allocations. However, if we fail to * allocate 2M chunks, we will go back to 4k allocations.
@@ -1281,14 +1275,13 @@ static void balloon_up(struct work_struc avail_pages =si_mem_available (); floor =compute_balloon_floor (); -/* Refuse to balloon below the floor, keep the 2M granularity. */ +/* Refuse to balloon below the floor. */ if (avail_pages < num_pages || avail_pages - num_pages < floor) {pr_warn ("Balloon request will be partially fulfilled. %s\n" , avail_pages < num_pages ?"Not enough memory." :"Balloon floor reached." ); num_pages = avail_pages > floor ? (avail_pages - floor) :0 ; - num_pages -= num_pages %PAGES_IN_2M ; }while (!done) {
Greg Kroah-Hartman
maintainerPATCH 99/309 mfd: axp20x: Mark AXP20X_VBUS_IPSOUT_MGMT as volatile
In reply to Greg Kroah-HartmanFrom: Samuel Holland <[email protected]>
commit dc91c3b6fe66a13ac76f6cb3b2100c0779cd3350 upstream.
On AXP288 and newer PMICs, bit 7 of AXP20X_VBUS_IPSOUT_MGMT can be set to prevent using the VBUS input. However, when the VBUS unplugged and plugged back in, the bit automatically resets to zero.
We need to set the register as volatile to prevent regmap from caching that bit. Otherwise, regcache will think the bit is already set and not write the register.
--- drivers/mfd/axp20x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/mfd/axp20x.c +1 -1
@@ -126,7 +126,7 @@ static const struct regmap_range axp288_static const struct regmap_range axp288_volatile_ranges[] = {regmap_reg_range (AXP20X_PWR_INPUT_STATUS ,AXP288_POWER_REASON ),regmap_reg_range (AXP288_BC_GLOBAL ,AXP288_BC_GLOBAL ), -regmap_reg_range (AXP288_BC_DET_STAT ,AXP288_BC_DET_STAT ), +regmap_reg_range (AXP288_BC_DET_STAT ,AXP20X_VBUS_IPSOUT_MGMT ),regmap_reg_range (AXP20X_CHRG_BAK_CTRL ,AXP20X_CHRG_BAK_CTRL ),regmap_reg_range (AXP20X_IRQ1_EN ,AXP20X_IPSOUT_V_HIGH_L ),regmap_reg_range (AXP20X_TIMER_CTRL ,AXP20X_TIMER_CTRL ),
Greg Kroah-Hartman
maintainerPATCH 100/309 nvmem: core: fix memory abort in cleanup path
In reply to Greg Kroah-HartmanFrom: Bitan Biswas <[email protected]>
commit 16bb7abc4a6b9defffa294e4dc28383e62a1dbcf upstream.
nvmem_cell_info_to_nvmem_cell implementation has static allocation of name. nvmem_add_cells_from_of() call may return error and kfree name results in memory abort. Use kstrdup_const() and kfree_const calls for name alloc and free.
Unable to handle kernel paging request at virtual address ffffffffffe44888
Mem abort info:
ESR = 0x96000006
EC = 0x25: DABT (current EL), IL = 32 bits
SET = 0, FnV = 0
EA = 0, S1PTW = 0
Data abort info:
ISV = 0, ISS = 0x00000006
CM = 0, WnR = 0
swapper pgtable: 64k pages, 48-bit VAs, pgdp=00000000815d0000 [ffffffffffe44888] pgd=0000000081d30803, pud=0000000081d30803, pmd=0000000000000000
Internal error: Oops: 96000006 [#1] PREEMPT SMP Modules linked in: CPU: 2 PID: 43 Comm: kworker/2:1 Tainted Hardware name: quill (DT) Workqueue: events deferred_probe_work_func pstate: a0000005 (NzCv daif -PAN -UAO) pc : kfree+0x38/0x278 lr : nvmem_cell_drop+0x68/0x80
sp : ffff80001284f9d0
x29: ffff80001284f9d0 x28: ffff0001f677e830
x27: ffff800011b0b000 x26: ffff0001c36e1008
x25: ffff8000112ad000 x24: ffff8000112c9000
x23: ffffffffffffffea x22: ffff800010adc7f0
x21: ffffffffffe44880 x20: ffff800011b0b068
x19: ffff80001122d380 x18: ffffffffffffffff
x17: 00000000d5cb4756 x16: 0000000070b193b8
x15: ffff8000119538c8 x14: 0720072007200720
x13: 07200720076e0772 x12: 07750762072d0765
x11: 0773077507660765 x10: 072f073007300730
x9 : 0730073207380733 x8 : 0000000000000151
x7 : 07660765072f0720 x6 : ffff0001c00e0f00
x5 : 0000000000000000 x4 : ffff0001c0b43800
x3 : ffff800011b0b068 x2 : 0000000000000000
x1 : 0000000000000000 x0 : ffffffdfffe00000
Call trace: kfree+0x38/0x278 nvmem_cell_drop+0x68/0x80 nvmem_device_remove_all_cells+0x2c/0x50 nvmem_register.part.9+0x520/0x628 devm_nvmem_register+0x48/0xa0 tegra_fuse_probe+0x140/0x1f0 platform_drv_probe+0x50/0xa0 really_probe+0x108/0x348 driver_probe_device+0x58/0x100 __device_attach_driver+0x90/0xb0 bus_for_each_drv+0x64/0xc8 __device_attach+0xd8/0x138 device_initial_probe+0x10/0x18 bus_probe_device+0x90/0x98 deferred_probe_work_func+0x74/0xb0 process_one_work+0x1e0/0x358 worker_thread+0x208/0x488 kthread+0x118/0x120 ret_from_fork+0x10/0x18 Code: d350feb5 f2dffbe0 aa1e03f6 8b151815 (f94006a0) ---[ end trace 49b1303c6b83198e ]---
--- drivers/nvmem/core.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/nvmem/core.c +5 -3
@@ -110,7 +110,7 @@ static void nvmem_cell_drop(struct nvmemlist_del (&cell->node);mutex_unlock (&nvmem_mutex);of_node_put (cell->np); -kfree (cell->name); +kfree_const (cell->name);kfree (cell); }
@@ -137,7 +137,9 @@ static int nvmem_cell_info_to_nvmem_cell cell->nvmem = nvmem; cell->offset = info->offset; cell->bytes = info->bytes; - cell->name = info->name; + cell->name =kstrdup_const (info->name,GFP_KERNEL ); +if (!cell->name) +return -ENOMEM ; cell->bit_offset = info->bit_offset; cell->nbits = info->nbits;
@@ -327,7 +329,7 @@ static int nvmem_add_cells_from_of(strucdev_err (dev,"cell %s unaligned to nvmem stride %d\n" , cell->name, nvmem->stride);/* Cells already added will be freed later. */ -kfree (cell->name); +kfree_const (cell->name);kfree (cell);return -EINVAL ; }
Greg Kroah-Hartman
maintainerPATCH 101/309 crypto: api - Check spawn->alg under lock in crypto_drop_spawn
In reply to Greg Kroah-HartmanFrom: Herbert Xu <[email protected]>
commit 7db3b61b6bba4310f454588c2ca6faf2958ad79f upstream.
We need to check whether spawn->alg is NULL under lock as otherwise the algorithm could be removed from under us after we have checked it and found it to be non-NULL. This could cause us to remove the spawn from a non-existent list.
--- crypto/algapi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
crypto/algapi.c +2 -4
@@ -669,11 +669,9 @@ EXPORT_SYMBOL_GPL(crypto_grab_spawn);void crypto_drop_spawn (struct crypto_spawn *spawn) { -if (!spawn->alg) -return ; -down_write (&crypto_alg_sem); -list_del (&spawn->list); +if (spawn->alg) +list_del (&spawn->list);up_write (&crypto_alg_sem); }EXPORT_SYMBOL_GPL (crypto_drop_spawn);
Greg Kroah-Hartman
maintainerPATCH 102/309 crypto: ccree - fix backlog memory leak
In reply to Greg Kroah-HartmanFrom: Gilad Ben-Yossef <[email protected]>
commit 4df2ef25b3b3618fd708ab484fe6239abd130fec upstream.
Fix brown paper bag bug of not releasing backlog list item buffer when backlog was consumed causing a memory leak when backlog is used.
--- drivers/crypto/ccree/cc_request_mgr.c | 1 + 1 file changed, 1 insertion(+)
drivers/crypto/ccree/cc_request_mgr.c +1 -0
@@ -404,6 +404,7 @@ static void cc_proc_backlog(struct cc_drspin_lock (&mgr->bl_lock);list_del (&bli->list); --mgr->bl_len; +kfree (bli); }spin_unlock (&mgr->bl_lock);
Greg Kroah-Hartman
maintainerPATCH 103/309 crypto: ccree - fix AEAD decrypt auth fail
In reply to Greg Kroah-HartmanFrom: Gilad Ben-Yossef <[email protected]>
commit 2a6bc713f1cef32e39e3c4e6f2e1a9849da6379c upstream.
On AEAD decryption authentication failure we are suppose to zero out the output plaintext buffer. However, we've missed skipping the optional associated data that may prefix the ciphertext. This commit fixes this issue.
--- drivers/crypto/ccree/cc_aead.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/crypto/ccree/cc_aead.c +1 -1
@@ -237,7 +237,7 @@ static void cc_aead_complete(struct devi* revealed the decrypted message --> zero its memory. */ sg_zero_buffer (areq->dst,sg_nents (areq->dst), - areq->cryptlen,0 ); + areq->cryptlen, areq->assoclen); err = -EBADMSG ; }/*ENCRYPT*/
Greg Kroah-Hartman
maintainerPATCH 104/309 crypto: ccree - fix pm wrongful error reporting
In reply to Greg Kroah-HartmanFrom: Gilad Ben-Yossef <[email protected]>
commit cedca59fae5834af8445b403c66c9953754375d7 upstream.
pm_runtime_get_sync() can return 1 as a valid (none error) return code. Treat it as such.
--- drivers/crypto/ccree/cc_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/crypto/ccree/cc_pm.c +1 -1
@@ -85,7 +85,7 @@ int cc_pm_get(struct device *dev)else pm_runtime_get_noresume (dev); -return rc; +return (rc ==1 ?0 : rc); }int cc_pm_put_suspend (struct device *dev)
Greg Kroah-Hartman
maintainerPATCH 105/309 crypto: ccree - fix FDE descriptor sequence
In reply to Greg Kroah-HartmanFrom: Ofir Drang <[email protected]>
commit 5c83e8ec4d51ac4cc58482ed04297e6882b32a09 upstream.
In FDE mode (xts, essiv and bitlocker) the cryptocell hardware requires that the the XEX key will be loaded after Key1.
--- drivers/crypto/ccree/cc_cipher.c | 48 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-)
drivers/crypto/ccree/cc_cipher.c +45 -3
@@ -523,6 +523,7 @@ static void cc_setup_readiv_desc(struct } } + static void cc_setup_state_desc(struct crypto_tfm *tfm, struct cipher_req_ctx *req_ctx, unsigned int ivsize, unsigned int nbytes,
@@ -534,8 +535,6 @@ static void cc_setup_state_desc(struct cint cipher_mode = ctx_p->cipher_mode;int flow_mode = ctx_p->flow_mode;int direction = req_ctx->gen_ctx.op_type; -dma_addr_t key_dma_addr = ctx_p->user.key_dma_addr; -unsigned int key_len = ctx_p->keylen;dma_addr_t iv_dma_addr = req_ctx->gen_ctx.iv_dma_addr;unsigned int du_size = nbytes;
@@ -571,6 +570,47 @@ static void cc_setup_state_desc(struct ccase DRV_CIPHER_XTS :case DRV_CIPHER_ESSIV :case DRV_CIPHER_BITLOCKER : +break ; +default : +dev_err (dev,"Unsupported cipher mode (%d)\n" , cipher_mode); + } +} + + +static void cc_setup_xex_state_desc (struct crypto_tfm *tfm, +struct cipher_req_ctx *req_ctx, +unsigned int ivsize,unsigned int nbytes, +struct cc_hw_desc desc[], +unsigned int *seq_size) +{ +struct cc_cipher_ctx *ctx_p =crypto_tfm_ctx (tfm); +struct device *dev =drvdata_to_dev (ctx_p->drvdata); +int cipher_mode = ctx_p->cipher_mode; +int flow_mode = ctx_p->flow_mode; +int direction = req_ctx->gen_ctx.op_type; +dma_addr_t key_dma_addr = ctx_p->user.key_dma_addr; +unsigned int key_len = ctx_p->keylen; +dma_addr_t iv_dma_addr = req_ctx->gen_ctx.iv_dma_addr; +unsigned int du_size = nbytes; + +struct cc_crypto_alg *cc_alg = + container_of(tfm->__crt_alg, struct cc_crypto_alg, + skcipher_alg.base); + +if (cc_alg->data_unit) + du_size = cc_alg->data_unit; + +switch (cipher_mode) { +case DRV_CIPHER_ECB : +break ; +case DRV_CIPHER_CBC : +case DRV_CIPHER_CBC_CTS : +case DRV_CIPHER_CTR : +case DRV_CIPHER_OFB : +break ; +case DRV_CIPHER_XTS : +case DRV_CIPHER_ESSIV : +case DRV_CIPHER_BITLOCKER :/* load XEX key */ hw_desc_init (&desc[*seq_size]);set_cipher_mode (&desc[*seq_size], cipher_mode);
@@ -881,12 +921,14 @@ static int cc_cipher_process(struct skci/* STAT_PHASE_2: Create sequence */ -/* Setup IV and XEX key used */ +/* Setup state (IV) */ cc_setup_state_desc (tfm, req_ctx, ivsize, nbytes, desc, &seq_len);/* Setup MLLI line, if needed */ cc_setup_mlli_desc (tfm, req_ctx, dst, src, nbytes, req, desc, &seq_len);/* Setup key */ cc_setup_key_desc (tfm, req_ctx, nbytes, desc, &seq_len); +/* Setup state (IV and XEX key) */ +cc_setup_xex_state_desc (tfm, req_ctx, ivsize, nbytes, desc, &seq_len);/* Data processing */ cc_setup_flow_desc (tfm, req_ctx, dst, src, nbytes, desc, &seq_len);/* Read next IV */
Greg Kroah-Hartman
maintainerPATCH 106/309 crypto: ccree - fix PM race condition
In reply to Greg Kroah-HartmanFrom: Gilad Ben-Yossef <[email protected]>
commit 15fd2566bf54ee4d4781d8f170acfc9472a1541f upstream.
The PM code was racy, possibly causing the driver to submit requests to a powered down device. Fix the race and while at it simplify the PM code.
--- drivers/crypto/ccree/cc_driver.h | 1 drivers/crypto/ccree/cc_pm.c | 28 ++++--------------- drivers/crypto/ccree/cc_request_mgr.c | 50 ---------------------------------- drivers/crypto/ccree/cc_request_mgr.h | 8 ----- 4 files changed, 7 insertions(+), 80 deletions(-)
drivers/crypto/ccree/cc_driver.h +1 -0
@@ -161,6 +161,7 @@ struct cc_drvdata {int std_bodies;bool sec_disabled;u32 comp_mask; +bool pm_on; };struct cc_crypto_alg {
drivers/crypto/ccree/cc_pm.c +6 -22
@@ -22,14 +22,8 @@ const struct dev_pm_ops ccree_pm = {int cc_pm_suspend (struct device *dev) {struct cc_drvdata *drvdata =dev_get_drvdata (dev); -int rc;dev_dbg (dev,"set HOST_POWER_DOWN_EN\n" ); - rc =cc_suspend_req_queue (drvdata); -if (rc) { -dev_err (dev,"cc_suspend_req_queue (%x)\n" , rc); -return rc; - }fini_cc_regs (drvdata);cc_iowrite (drvdata,CC_REG (HOST_POWER_DOWN_EN ),POWER_DOWN_ENABLE );cc_clk_off (drvdata);
@@ -63,13 +57,6 @@ int cc_pm_resume(struct device *dev)/* check if tee fips error occurred during power down */ cc_tee_handle_fips_error (drvdata); - rc =cc_resume_req_queue (drvdata); -if (rc) { -dev_err (dev,"cc_resume_req_queue (%x)\n" , rc); -return rc; - } - -/* must be after the queue resuming as it uses the HW queue*/ cc_init_hash_sram (drvdata);return 0 ;
@@ -80,10 +67,8 @@ int cc_pm_get(struct device *dev)int rc =0 ;struct cc_drvdata *drvdata =dev_get_drvdata (dev); -if (cc_req_queue_suspended (drvdata)) +if (drvdata->pm_on) rc =pm_runtime_get_sync (dev); -else -pm_runtime_get_noresume (dev);return (rc ==1 ?0 : rc); }
@@ -93,14 +78,11 @@ int cc_pm_put_suspend(struct device *devint rc =0 ;struct cc_drvdata *drvdata =dev_get_drvdata (dev); -if (!cc_req_queue_suspended (drvdata)) { +if (drvdata->pm_on) {pm_runtime_mark_last_busy (dev); rc =pm_runtime_put_autosuspend (dev); - }else { -/* Something wrong happens*/ -dev_err (dev,"request to suspend already suspended queue" ); - rc = -EBUSY ; } +return rc; }
@@ -117,7 +99,7 @@ int cc_pm_init(struct cc_drvdata *drvdat/* must be before the enabling to avoid resdundent suspending */ pm_runtime_set_autosuspend_delay (dev,CC_SUSPEND_TIMEOUT );pm_runtime_use_autosuspend (dev); -/* activate the PM module */ +/* set us as active - note we won't do PM ops until cc_pm_go()! */ return pm_runtime_set_active (dev); }
@@ -125,9 +107,11 @@ int cc_pm_init(struct cc_drvdata *drvdatvoid cc_pm_go (struct cc_drvdata *drvdata) {pm_runtime_enable (drvdata_to_dev (drvdata)); + drvdata->pm_on = true; }void cc_pm_fini (struct cc_drvdata *drvdata) {pm_runtime_disable (drvdata_to_dev (drvdata)); + drvdata->pm_on = false; }
drivers/crypto/ccree/cc_request_mgr.c +0 -50
59 lines not on this page · raw message
drivers/crypto/ccree/cc_request_mgr.h +0 -8
@@ -40,12 +40,4 @@ void complete_request(struct cc_drvdatavoid cc_req_mgr_fini (struct cc_drvdata *drvdata); -#if defined(CONFIG_PM ) -int cc_resume_req_queue (struct cc_drvdata *drvdata); - -int cc_suspend_req_queue (struct cc_drvdata *drvdata); - -bool cc_req_queue_suspended (struct cc_drvdata *drvdata); -#endif -#endif /*__REQUEST_MGR_H__*/
Greg Kroah-Hartman
maintainerPATCH 107/309 padata: Remove broken queue flushing
In reply to Greg Kroah-HartmanFrom: Herbert Xu <[email protected]>
commit 07928d9bfc81640bab36f5190e8725894d93b659 upstream.
The function padata_flush_queues is fundamentally broken because it cannot force padata users to complete the request that is underway. IOW padata has to passively wait for the completion of any outstanding work.
As it stands flushing is used in two places. Its use in padata_stop is simply unnecessary because nothing depends on the queues to be flushed afterwards.
The other use in padata_replace is more substantial as we depend on it to free the old pd structure. This patch instead uses the pd->refcnt to dynamically free the pd structure once all requests are complete.
--- kernel/padata.c | 43 ++++++++++++------------------------------- 1 file changed, 12 insertions(+), 31 deletions(-)
kernel/padata.c +12 -31
@@ -35,6 +35,8 @@#define MAX_OBJ_NUM 1000 +static void padata_free_pd (struct parallel_data *pd); +static int padata_index_to_cpu (struct parallel_data *pd,int cpu_index) {int cpu, target_cpu;
@@ -283,6 +285,7 @@ static void padata_serial_worker(structstruct padata_serial_queue *squeue;struct parallel_data *pd;LIST_HEAD (local_list); +int cnt;local_bh_disable (); squeue = container_of(serial_work, struct padata_serial_queue, work);
@@ -292,6 +295,8 @@ static void padata_serial_worker(structlist_replace_init (&squeue->serial.list, &local_list);spin_unlock (&squeue->serial.lock); + cnt =0 ; +while (!list_empty (&local_list)) {struct padata_priv *padata;
@@ -301,9 +306,12 @@ static void padata_serial_worker(structlist_del_init (&padata->list); padata->serial (padata); -atomic_dec (&pd->refcnt); + cnt++; }local_bh_enable (); + +if (atomic_sub_and_test (cnt, &pd->refcnt)) +padata_free_pd (pd); }/**
@@ -440,7 +448,7 @@ static struct parallel_data *padata_allopadata_init_squeues (pd);atomic_set (&pd->seq_nr,-1 );atomic_set (&pd->reorder_objects,0 ); -atomic_set (&pd->refcnt,0 ); +atomic_set (&pd->refcnt,1 );spin_lock_init (&pd->lock); pd->cpu =cpumask_first (pd->cpumask.pcpu);INIT_WORK (&pd->reorder_work, invoke_padata_reorder);
@@ -466,29 +474,6 @@ static void padata_free_pd(struct parallkfree (pd); } -/* Flush all objects out of the padata queues. */ -static void padata_flush_queues (struct parallel_data *pd) -{ -int cpu; -struct padata_parallel_queue *pqueue; -struct padata_serial_queue *squeue; - -for_each_cpu (cpu, pd->cpumask.pcpu) { - pqueue =per_cpu_ptr (pd->pqueue, cpu); -flush_work (&pqueue->work); - } - -if (atomic_read (&pd->reorder_objects)) -padata_reorder (pd); - -for_each_cpu (cpu, pd->cpumask.cbcpu) { - squeue =per_cpu_ptr (pd->squeue, cpu); -flush_work (&squeue->work); - } - -BUG_ON (atomic_read (&pd->refcnt) !=0 ); -} -static void __padata_start (struct padata_instance *pinst) { pinst->flags |=PADATA_INIT ;
@@ -502,10 +487,6 @@ static void __padata_stop(struct padata_ pinst->flags &= ~PADATA_INIT ;synchronize_rcu (); - -get_online_cpus (); -padata_flush_queues (pinst->pd); -put_online_cpus (); }/* Replace the internal control structure with a new one. */
@@ -526,8 +507,8 @@ static void padata_replace(struct padataif (!cpumask_equal (pd_old->cpumask.cbcpu, pd_new->cpumask.cbcpu)) notification_mask |=PADATA_CPU_SERIAL ; -padata_flush_queues (pd_old); -padata_free_pd (pd_old); +if (atomic_dec_and_test (&pd_old->refcnt)) +padata_free_pd (pd_old);if (notification_mask) blocking_notifier_call_chain(&pinst->cpumask_change_notifier,
Greg Kroah-Hartman
maintainerPATCH 108/309 fs: allow deduplication of eof block into the end of the destination file
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
commit a5e6ea18e3d132be4716eb5fdd520c2c234e3003 upstream.
We always round down, to a multiple of the filesystem's block size, the length to deduplicate at generic_remap_check_len(). However this is only needed if an attempt to deduplicate the last block into the middle of the destination file is requested, since that leads into a corruption if the length of the source file is not block size aligned. When an attempt to deduplicate the last block into the end of the destination file is requested, we should allow it because it is safe to do it - there's no stale data exposure and we are prepared to compare the data ranges for a length not aligned to the block (or page) size - in fact we even do the data compare before adjusting the deduplication length.
After btrfs was updated to use the generic helpers from VFS (by commit 34a28e3d77535e ("Btrfs: use generic_remap_file_range_prep() for cloning and deduplication")) we started to have user reports of deduplication not reflinking the last block anymore, and whence users getting lower deduplication scores. The main use case is deduplication of entire files that have a size not aligned to the block size of the filesystem.
We already allow cloning the last block to the end (and beyond) of the destination file, so allow for deduplication as well.
--- fs/read_write.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
fs/read_write.c +4 -6
@@ -1777,10 +1777,9 @@ static int remap_verify_area(struct file* else. Assume that the offsets have already been checked for block * alignment. * -* For deduplication we always scale down to the previous block because we -* can't meaningfully compare post-EOF contents. -* -* For clone we only link a partial EOF block above the destination file's EOF. +* For clone we only link a partial EOF block above or at the destination file's +* EOF. For deduplication we accept a partial EOF block only if it ends at the +* destination file's EOF (can not link it into the middle of a file). * * Shorten the request if possible. */
@@ -1796,8 +1795,7 @@ static int generic_remap_check_len(strucif ((*len & blkmask) ==0 )return 0 ; -if ((remap_flags &REMAP_FILE_DEDUP ) || - pos_out + *len <i_size_read (inode_out)) +if (pos_out + *len <i_size_read (inode_out)) new_len &= ~blkmask;if (new_len == *len)
Greg Kroah-Hartman
maintainerPATCH 109/309 scripts/find-unused-docs: Fix massive false positives
In reply to Greg Kroah-HartmanFrom: Geert Uytterhoeven <[email protected]>
commit 1630146db2111412e7524d05d812ff8f2c75977e upstream.
scripts/find-unused-docs.sh invokes scripts/kernel-doc to find out if a source file contains kerneldoc or not.
However, as it passes the no longer supported "-text" option to scripts/kernel-doc, the latter prints out its help text, causing all files to be considered containing kerneldoc.
Get rid of these false positives by removing the no longer supported "-text" option from the scripts/kernel-doc invocation.
--- scripts/find-unused-docs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
scripts/find-unused-docs.sh +1 -1
@@ -54,7 +54,7 @@ for file in `find $1 -name '*.c'`; do if [[ ${FILES_INCLUDED[$file]+_} ]]; then continue; fi - str=$(scripts/kernel-doc -text -export "$file" 2>/dev/null) + str=$(scripts/kernel-doc -export "$file" 2>/dev/null) if [[ -n "$str" ]]; then echo "$file" fi
Greg Kroah-Hartman
maintainerPATCH 110/309 erofs: fix out-of-bound read for shifted uncompressed block
In reply to Greg Kroah-HartmanFrom: Gao Xiang <[email protected]>
commit 4d2024370d877f9ac8b98694bcff666da6a5d333 upstream.
rq->out[1] should be valid before accessing. Otherwise, in very rare cases, out-of-bound dirty onstack rq->out[1] can equal to *in and lead to unintended memmove behavior.
--- fs/erofs/decompressor.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-)
fs/erofs/decompressor.c +10 -12
@@ -306,24 +306,22 @@ static int z_erofs_shifted_transform(con } src =kmap_atomic (*rq->in); -if (!rq->out[0 ]) { - dst =NULL ; - }else { +if (rq->out[0 ]) { dst =kmap_atomic (rq->out[0 ]);memcpy (dst + rq->pageofs_out, src, righthalf); +kunmap_atomic (dst); } -if (rq->out[1 ] == *rq->in) { -memmove (src, src + righthalf, rq->pageofs_out); - }else if (nrpages_out ==2 ) { -if (dst) -kunmap_atomic (dst); +if (nrpages_out ==2 ) {DBG_BUGON (!rq->out[1 ]); - dst =kmap_atomic (rq->out[1 ]); -memcpy (dst, src + righthalf, rq->pageofs_out); +if (rq->out[1 ] == *rq->in) { +memmove (src, src + righthalf, rq->pageofs_out); + }else { + dst =kmap_atomic (rq->out[1 ]); +memcpy (dst, src + righthalf, rq->pageofs_out); +kunmap_atomic (dst); + } } -if (dst) -kunmap_atomic (dst);kunmap_atomic (src);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 111/309 scsi: megaraid_sas: Do not initiate OCR if controller is not in ready state
In reply to Greg Kroah-HartmanFrom: Anand Lodnoor <[email protected]>
commit 6d7537270e3283b92f9b327da9d58a4de40fe8d0 upstream.
Driver initiates OCR if a DCMD command times out. But there is a deadlock if the driver attempts to invoke another OCR before the mutex lock (reset_mutex) is released from the previous session of OCR.
This patch takes care of the above scenario using new flag MEGASAS_FUSION_OCR_NOT_POSSIBLE to indicate if OCR is possible.
--- drivers/scsi/megaraid/megaraid_sas_base.c | 3 ++- drivers/scsi/megaraid/megaraid_sas_fusion.c | 3 ++- drivers/scsi/megaraid/megaraid_sas_fusion.h | 1 + 3 files changed, 5 insertions(+), 2 deletions(-)
drivers/scsi/megaraid/megaraid_sas_base.c +2 -1
@@ -4392,7 +4392,8 @@ dcmd_timeout_ocr_possible(struct megasasif (instance->adapter_type ==MFI_SERIES )return KILL_ADAPTER ;else if (instance->unload || -test_bit (MEGASAS_FUSION_IN_RESET , &instance->reset_flags)) +test_bit (MEGASAS_FUSION_OCR_NOT_POSSIBLE , + &instance->reset_flags))return IGNORE_TIMEOUT ;else return INITIATE_OCR ;
drivers/scsi/megaraid/megaraid_sas_fusion.c +2 -1
@@ -4847,6 +4847,7 @@ int megasas_reset_fusion(struct Scsi_Hosif (instance->requestorId && !instance->skip_heartbeat_timer_del)del_timer_sync (&instance->sriov_heartbeat_timer);set_bit (MEGASAS_FUSION_IN_RESET , &instance->reset_flags); +set_bit (MEGASAS_FUSION_OCR_NOT_POSSIBLE , &instance->reset_flags);atomic_set (&instance->adprecovery,MEGASAS_ADPRESET_SM_POLLING ); instance->instancet->disable_intr (instance);megasas_sync_irqs ((unsigned long )instance);
@@ -5046,7 +5047,7 @@ kill_hba: instance->skip_heartbeat_timer_del =1 ; retval =FAILED ; out: -clear_bit (MEGASAS_FUSION_IN_RESET , &instance->reset_flags); +clear_bit (MEGASAS_FUSION_OCR_NOT_POSSIBLE , &instance->reset_flags);mutex_unlock (&instance->reset_mutex);return retval; }
drivers/scsi/megaraid/megaraid_sas_fusion.h +1 -0
@@ -89,6 +89,7 @@ enum MR_RAID_FLAGS_IO_SUB_TYPE {#define MEGASAS_FP_CMD_LEN 16#define MEGASAS_FUSION_IN_RESET 0 +#define MEGASAS_FUSION_OCR_NOT_POSSIBLE 1#define RAID_1_PEER_CMDS 2#define JBOD_MAPS_COUNT 2#define MEGASAS_REDUCE_QD_COUNT 64
Greg Kroah-Hartman
maintainerPATCH 112/309 scsi: qla2xxx: Fix mtcp dump collection failure
In reply to Greg Kroah-HartmanFrom: Quinn Tran <[email protected]>
commit 641e0efddcbde52461e017136acd3ce7f2ef0c14 upstream.
MTCP dump failed due to MB Reg 10 was picking garbage data from stack memory.
--- drivers/scsi/qla2xxx/qla_mbx.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/scsi/qla2xxx/qla_mbx.c +1 -2
@@ -6151,9 +6151,8 @@ qla2x00_dump_mctp_data(scsi_qla_host_t * mcp->mb[7 ] =LSW (MSD (req_dma)); mcp->mb[8 ] =MSW (addr);/* Setting RAM ID to valid */ - mcp->mb[10 ] |=BIT_7 ;/* For MCTP RAM ID is 0x40 */ - mcp->mb[10 ] |=0x40 ; + mcp->mb[10 ] =BIT_7 |0x40 ; mcp->out_mb |=MBX_10 |MBX_8 |MBX_7 |MBX_6 |MBX_5 |MBX_4 |MBX_3 |MBX_2 |MBX_1 |MBX_0 ;
Greg Kroah-Hartman
maintainerPATCH 113/309 cpupower: Revert library ABI changes from commit ae2917093fb60bdc1ed3e
In reply to Greg Kroah-HartmanFrom: Thomas Renninger <[email protected]>
commit 41ddb7e1f79693d904502ae9bea609837973eff8 upstream.
Commit ae2917093fb6 ("tools/power/cpupower: Display boost frequency separately") modified the library function:
struct cpufreq_available_frequencies *cpufreq_get_available_frequencies(unsigned int cpu)
to
struct cpufreq_frequencies *cpufreq_get_frequencies(const char *type, unsigned int cpu)
This patch recovers the old API and implements the new functionality in a newly introduce method:
struct cpufreq_boost_frequencies *cpufreq_get_available_frequencies(unsigned int cpu)
This one should get merged into stable kernels back to 5.0 when the above had been introduced.
--- tools/power/cpupower/lib/cpufreq.c | 78 ++++++++++++++++++++++++++---- tools/power/cpupower/lib/cpufreq.h | 20 +++++-- tools/power/cpupower/utils/cpufreq-info.c | 12 ++-- 3 files changed, 87 insertions(+), 23 deletions(-)
tools/power/cpupower/lib/cpufreq.c +68 -10
@@ -332,21 +332,74 @@ void cpufreq_put_available_governors(str } -struct cpufreq_frequencies -*cpufreq_get_frequencies (const char *type,unsigned int cpu) +struct cpufreq_available_frequencies +*cpufreq_get_available_frequencies (unsigned int cpu) { -struct cpufreq_frequencies *first =NULL ; -struct cpufreq_frequencies *current =NULL ; +struct cpufreq_available_frequencies *first =NULL ; +struct cpufreq_available_frequencies *current =NULL ;char one_value[SYSFS_PATH_MAX ];char linebuf[MAX_LINE_LEN ]; -char fname[MAX_LINE_LEN ];unsigned int pos, i;unsigned int len; -snprintf (fname,MAX_LINE_LEN ,"scaling_%s_frequencies" , type); + len =sysfs_cpufreq_read_file (cpu,"scaling_available_frequencies" , + linebuf,sizeof (linebuf)); +if (len ==0 ) +return NULL ; + + pos =0 ; +for (i =0 ; i < len; i++) { +if (linebuf[i] ==' ' || linebuf[i] =='\n' ) { +if (i - pos <2 ) +continue ; +if (i - pos >=SYSFS_PATH_MAX ) + goto error_out; +if (current) { + current->next =malloc (sizeof (*current)); +if (!current->next) + goto error_out; + current = current->next; + }else { + first =malloc (sizeof (*first)); +if (!first) + goto error_out; + current = first; + } + current->first = first; + current->next =NULL ; + +memcpy (one_value, linebuf + pos, i - pos); + one_value[i - pos] ='\0' ; +if (sscanf (one_value,"%lu" , ¤t->frequency) !=1 ) + goto error_out; + + pos = i +1 ; + } + } + +return first; + + error_out: +while (first) { + current = first->next; +free (first); + first = current; + } +return NULL ; +} - len =sysfs_cpufreq_read_file (cpu, fname, - linebuf,sizeof (linebuf)); +struct cpufreq_available_frequencies +*cpufreq_get_boost_frequencies (unsigned int cpu) +{ +struct cpufreq_available_frequencies *first =NULL ; +struct cpufreq_available_frequencies *current =NULL ; +char one_value[SYSFS_PATH_MAX ]; +char linebuf[MAX_LINE_LEN ]; +unsigned int pos, i; +unsigned int len; + + len =sysfs_cpufreq_read_file (cpu,"scaling_boost_frequencies" , + linebuf,sizeof (linebuf));if (len ==0 )return NULL ;
@@ -391,9 +444,9 @@ struct cpufreq_frequenciesreturn NULL ; } -void cpufreq_put_frequencies (struct cpufreq_frequencies *any) +void cpufreq_put_available_frequencies (struct cpufreq_available_frequencies *any) { -struct cpufreq_frequencies *tmp, *next; +struct cpufreq_available_frequencies *tmp, *next;if (!any)return ;
@@ -406,6 +459,11 @@ void cpufreq_put_frequencies(struct cpuf } } +void cpufreq_put_boost_frequencies (struct cpufreq_available_frequencies *any) +{ +cpufreq_put_available_frequencies (any); +} +static struct cpufreq_affected_cpus *sysfs_get_cpu_list (unsigned int cpu,const char *file) {
tools/power/cpupower/lib/cpufreq.h +13 -7
@@ -20,10 +20,10 @@ struct cpufreq_available_governors {struct cpufreq_available_governors *first; }; -struct cpufreq_frequencies { +struct cpufreq_available_frequencies {unsigned long frequency; -struct cpufreq_frequencies *next; -struct cpufreq_frequencies *first; +struct cpufreq_available_frequencies *next; +struct cpufreq_available_frequencies *first; };
@@ -124,11 +124,17 @@ void cpufreq_put_available_governors(* cpufreq_put_frequencies after use. */ -struct cpufreq_frequencies -*cpufreq_get_frequencies (const char *type,unsigned int cpu); +struct cpufreq_available_frequencies +*cpufreq_get_available_frequencies (unsigned int cpu); -void cpufreq_put_frequencies ( -struct cpufreq_frequencies *first); +void cpufreq_put_available_frequencies ( +struct cpufreq_available_frequencies *first); + +struct cpufreq_available_frequencies +*cpufreq_get_boost_frequencies (unsigned int cpu); + +void cpufreq_put_boost_frequencies ( +struct cpufreq_available_frequencies *first);/* determine affected CPUs
tools/power/cpupower/utils/cpufreq-info.c +6 -6
@@ -244,14 +244,14 @@ static int get_boost_mode_x86(unsigned istatic int get_boost_mode (unsigned int cpu) { -struct cpufreq_frequencies *freqs; +struct cpufreq_available_frequencies *freqs;if (cpupower_cpu_info.vendor ==X86_VENDOR_AMD || cpupower_cpu_info.vendor ==X86_VENDOR_HYGON || cpupower_cpu_info.vendor ==X86_VENDOR_INTEL )return get_boost_mode_x86 (cpu); - freqs =cpufreq_get_frequencies ("boost" , cpu); + freqs =cpufreq_get_boost_frequencies (cpu);if (freqs) {printf (_ (" boost frequency steps: " ));while (freqs->next) {
@@ -261,7 +261,7 @@ static int get_boost_mode(unsigned int c }print_speed (freqs->frequency);printf ("\n" ); -cpufreq_put_frequencies (freqs); +cpufreq_put_available_frequencies (freqs); }return 0 ;
@@ -475,7 +475,7 @@ static int get_latency(unsigned int cpu,static void debug_output_one (unsigned int cpu) { -struct cpufreq_frequencies *freqs; +struct cpufreq_available_frequencies *freqs;get_driver (cpu);get_related_cpus (cpu);
@@ -483,7 +483,7 @@ static void debug_output_one(unsigned inget_latency (cpu,1 );get_hardware_limits (cpu,1 ); - freqs =cpufreq_get_frequencies ("available" , cpu); + freqs =cpufreq_get_available_frequencies (cpu);if (freqs) {printf (_ (" available frequency steps: " ));while (freqs->next) {
@@ -493,7 +493,7 @@ static void debug_output_one(unsigned in }print_speed (freqs->frequency);printf ("\n" ); -cpufreq_put_frequencies (freqs); +cpufreq_put_available_frequencies (freqs); }get_available_governors (cpu);
Greg Kroah-Hartman
maintainerPATCH 114/309 power: supply: axp20x_ac_power: Fix reporting online status
In reply to Greg Kroah-HartmanFrom: Samuel Holland <[email protected]>
commit 1c51aad8475d670ad58ae60adc9d32342381df8d upstream.
AXP803/AXP813 have a flag that enables/disables the AC power supply input. This flag does not affect the status bits in PWR_INPUT_STATUS. Its effect can be verified by checking the battery charge/discharge state (bit 2 of PWR_INPUT_STATUS), or by examining the current draw on the AC input.
Take this flag into account when getting the ONLINE property of the AC input, on PMICs where this flag is present.
--- drivers/power/supply/axp20x_ac_power.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-)
drivers/power/supply/axp20x_ac_power.c +25 -6
@@ -23,6 +23,8 @@#define AXP20X_PWR_STATUS_ACIN_PRESENT BIT(7)#define AXP20X_PWR_STATUS_ACIN_AVAIL BIT(6) +#define AXP813_ACIN_PATH_SEL BIT(7) +#define AXP813_VHOLD_MASK GENMASK(5, 3)#define AXP813_VHOLD_UV_TO_BIT (x) ((((x) / 100000) - 40) << 3)#define AXP813_VHOLD_REG_TO_UV (x) \
@@ -40,6 +42,7 @@ struct axp20x_ac_power {struct power_supply *supply;struct iio_channel *acin_v;struct iio_channel *acin_i; +bool has_acin_path_sel; };static irqreturn_t axp20x_ac_power_irq (int irq,void *devid)
@@ -86,6 +89,17 @@ static int axp20x_ac_power_get_property(return ret; val->intval = !!(reg &AXP20X_PWR_STATUS_ACIN_AVAIL ); + +/* ACIN_PATH_SEL disables ACIN even if ACIN_AVAIL is set. */ +if (val->intval && power->has_acin_path_sel) { + ret =regmap_read (power->regmap,AXP813_ACIN_PATH_CTRL , + ®); +if (ret) +return ret; + + val->intval = !!(reg &AXP813_ACIN_PATH_SEL ); + } +return 0 ;case POWER_SUPPLY_PROP_VOLTAGE_NOW :
@@ -224,21 +238,25 @@ static const struct power_supply_desc axstruct axp_data {const struct power_supply_desc *power_desc;bool acin_adc; +bool acin_path_sel; };static const struct axp_data axp20x_data = { - .power_desc = &axp20x_ac_power_desc, - .acin_adc = true, + .power_desc = &axp20x_ac_power_desc, + .acin_adc = true, + .acin_path_sel = false, };static const struct axp_data axp22x_data = { - .power_desc = &axp22x_ac_power_desc, - .acin_adc = false, + .power_desc = &axp22x_ac_power_desc, + .acin_adc = false, + .acin_path_sel = false, };static const struct axp_data axp813_data = { - .power_desc = &axp813_ac_power_desc, - .acin_adc = false, + .power_desc = &axp813_ac_power_desc, + .acin_adc = false, + .acin_path_sel = true, };static int axp20x_ac_power_probe (struct platform_device *pdev)
@@ -282,6 +300,7 @@ static int axp20x_ac_power_probe(struct } power->regmap =dev_get_regmap (pdev->dev.parent,NULL ); + power->has_acin_path_sel = axp_data->acin_path_sel;platform_set_drvdata (pdev, power);
Greg Kroah-Hartman
maintainerPATCH 115/309 power: supply: ltc2941-battery-gauge: fix use-after-free
In reply to Greg Kroah-HartmanFrom: Sven Van Asbroeck <[email protected]>
commit a60ec78d306c6548d4adbc7918b587a723c555cc upstream.
This driver's remove path calls cancel_delayed_work(). However, that function does not wait until the work function finishes. This could mean that the work function is still running after the driver's remove function has finished, which would result in a use-after-free.
Fix by calling cancel_delayed_work_sync(), which ensures that that the work is properly cancelled, no longer running, and unable to re-schedule itself.
This issue was detected with the help of Coccinelle.
--- drivers/power/supply/ltc2941-battery-gauge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/power/supply/ltc2941-battery-gauge.c +1 -1
@@ -449,7 +449,7 @@ static int ltc294x_i2c_remove(struct i2c {struct ltc294x_info *info =i2c_get_clientdata (client); -cancel_delayed_work (&info->work); +cancel_delayed_work_sync (&info->work);power_supply_unregister (info->supply);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 116/309 ovl: fix wrong WARN_ON() in ovl_cache_update_ino()
In reply to Greg Kroah-HartmanFrom: Amir Goldstein <[email protected]>
commit 4c37e71b713ecffe81f8e6273c6835e54306d412 upstream.
The WARN_ON() that child entry is always on overlay st_dev became wrong when we allowed this function to update d_ino in non-samefs setup with xino enabled.
It is not true in case of xino bits overflow on a non-dir inode. Leave the WARN_ON() only for directories, where assertion is still true.
--- fs/overlayfs/readdir.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
fs/overlayfs/readdir.c +7 -1
@@ -504,7 +504,13 @@ get:if (err) goto fail; -WARN_ON_ONCE (dir->d_sb->s_dev != stat.dev); +/* +* Directory inode is always on overlay st_dev. +* Non-dir with ovl_same_dev() could be on pseudo st_dev in case +* of xino bits overflow. +*/ +WARN_ON_ONCE (S_ISDIR (stat.mode) && + dir->d_sb->s_dev != stat.dev); ino = stat.ino; }else if (xinobits && !OVL_TYPE_UPPER (type)) { ino = ovl_remap_lower_ino(ino, xinobits,
Greg Kroah-Hartman
maintainerPATCH 117/309 ovl: fix lseek overflow on 32bit
In reply to Greg Kroah-HartmanFrom: Miklos Szeredi <[email protected]>
commit a4ac9d45c0cd14a2adc872186431c79804b77dbf upstream.
ovl_lseek() is using ssize_t to return the value from vfs_llseek(). On a 32-bit kernel ssize_t is a 32-bit signed int, which overflows above 2 GB.
Assign the return value of vfs_llseek() to loff_t to fix this.
--- fs/overlayfs/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/overlayfs/file.c +1 -1
@@ -146,7 +146,7 @@ static loff_t ovl_llseek(struct file *fistruct inode *inode =file_inode (file);struct fd real;const struct cred *old_cred; -ssize_t ret; +loff_t ret;/* * The two special cases below do not need to involve real fs,
Greg Kroah-Hartman
maintainerPATCH 118/309 f2fs: choose hardlimit when softlimit is larger than hardlimit in f2fs_statfs_project()
In reply to Greg Kroah-HartmanFrom: Chengguang Xu <[email protected]>
commit 909110c060f22e65756659ec6fa957ae75777e00 upstream.
Setting softlimit larger than hardlimit seems meaningless for disk quota but currently it is allowed. In this case, there may be a bit of comfusion for users when they run df comamnd to directory which has project quota.
For example, we set 20M softlimit and 10M hardlimit of block usage limit for project quota of test_dir(project id 123).
[root@hades f2fs]# repquota -P -a
--- fs/f2fs/super.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-)
fs/f2fs/super.c +14 -6
@@ -1213,9 +1213,13 @@ static int f2fs_statfs_project(struct sureturn PTR_ERR (dquot);spin_lock (&dquot->dq_dqb_lock); - limit = (dquot->dq_dqb.dqb_bsoftlimit ? - dquot->dq_dqb.dqb_bsoftlimit : - dquot->dq_dqb.dqb_bhardlimit) >> sb->s_blocksize_bits; + limit =0 ; +if (dquot->dq_dqb.dqb_bsoftlimit) + limit = dquot->dq_dqb.dqb_bsoftlimit; +if (dquot->dq_dqb.dqb_bhardlimit && + (!limit || dquot->dq_dqb.dqb_bhardlimit < limit)) + limit = dquot->dq_dqb.dqb_bhardlimit; +if (limit && buf->f_blocks > limit) { curblock = dquot->dq_dqb.dqb_curspace >> sb->s_blocksize_bits; buf->f_blocks = limit;
@@ -1224,9 +1228,13 @@ static int f2fs_statfs_project(struct su (buf->f_blocks - curblock) : 0; } - limit = dquot->dq_dqb.dqb_isoftlimit ? - dquot->dq_dqb.dqb_isoftlimit : - dquot->dq_dqb.dqb_ihardlimit; + limit =0 ; +if (dquot->dq_dqb.dqb_isoftlimit) + limit = dquot->dq_dqb.dqb_isoftlimit; +if (dquot->dq_dqb.dqb_ihardlimit && + (!limit || dquot->dq_dqb.dqb_ihardlimit < limit)) + limit = dquot->dq_dqb.dqb_ihardlimit; +if (limit && buf->f_files > limit) { buf->f_files = limit; buf->f_ffree =
Greg Kroah-Hartman
maintainerPATCH 119/309 f2fs: fix miscounted block limit in f2fs_statfs_project()
In reply to Greg Kroah-HartmanFrom: Chengguang Xu <[email protected]>
commit acdf2172172a511f97fa21ed0ee7609a6d3b3a07 upstream.
statfs calculates Total/Used/Avail disk space in block unit, so we should translate soft/hard prjquota limit to block unit as well.
Below testing result shows the block/inode numbers of Total/Used/Avail from df command are all correct afer applying this patch.
[root@localhost quota-tools]\# ./repquota -P /dev/sdb1
--- fs/f2fs/super.c | 2 ++ 1 file changed, 2 insertions(+)
fs/f2fs/super.c +2 -0
@@ -1219,6 +1219,8 @@ static int f2fs_statfs_project(struct suif (dquot->dq_dqb.dqb_bhardlimit && (!limit || dquot->dq_dqb.dqb_bhardlimit < limit)) limit = dquot->dq_dqb.dqb_bhardlimit; +if (limit) + limit >>= sb->s_blocksize_bits;if (limit && buf->f_blocks > limit) { curblock = dquot->dq_dqb.dqb_curspace >> sb->s_blocksize_bits;
Greg Kroah-Hartman
maintainerPATCH 120/309 f2fs: code cleanup for f2fs_statfs_project()
In reply to Greg Kroah-HartmanFrom: Chengguang Xu <[email protected]>
commit bf2cbd3c57159c2b639ee8797b52ab5af180bf83 upstream.
Calling min_not_zero() to simplify complicated prjquota limit comparison in f2fs_statfs_project().
--- fs/f2fs/super.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-)
fs/f2fs/super.c +4 -12
@@ -1213,12 +1213,8 @@ static int f2fs_statfs_project(struct sureturn PTR_ERR (dquot);spin_lock (&dquot->dq_dqb_lock); - limit =0 ; -if (dquot->dq_dqb.dqb_bsoftlimit) - limit = dquot->dq_dqb.dqb_bsoftlimit; -if (dquot->dq_dqb.dqb_bhardlimit && - (!limit || dquot->dq_dqb.dqb_bhardlimit < limit)) - limit = dquot->dq_dqb.dqb_bhardlimit; + limit =min_not_zero (dquot->dq_dqb.dqb_bsoftlimit, + dquot->dq_dqb.dqb_bhardlimit);if (limit) limit >>= sb->s_blocksize_bits;
@@ -1230,12 +1226,8 @@ static int f2fs_statfs_project(struct su (buf->f_blocks - curblock) : 0; } - limit =0 ; -if (dquot->dq_dqb.dqb_isoftlimit) - limit = dquot->dq_dqb.dqb_isoftlimit; -if (dquot->dq_dqb.dqb_ihardlimit && - (!limit || dquot->dq_dqb.dqb_ihardlimit < limit)) - limit = dquot->dq_dqb.dqb_ihardlimit; + limit =min_not_zero (dquot->dq_dqb.dqb_isoftlimit, + dquot->dq_dqb.dqb_ihardlimit);if (limit && buf->f_files > limit) { buf->f_files = limit;
Greg Kroah-Hartman
maintainerPATCH 121/309 f2fs: fix dcache lookup of !casefolded directories
In reply to Greg Kroah-HartmanFrom: Eric Biggers <[email protected]>
commit 5515eae647426169e4b7969271fb207881eba7f6 upstream.
Do the name comparison for non-casefolded directories correctly.
This is analogous to ext4's commit 66883da1eee8 ("ext4: fix dcache lookup of !casefolded directories").
--- fs/f2fs/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/f2fs/dir.c +1 -1
@@ -1072,7 +1072,7 @@ static int f2fs_d_compare(const struct dif (!IS_CASEFOLDED (dentry->d_parent->d_inode)) {if (len != name->len)return -1 ; -return memcmp (str, name, len); +return memcmp (str, name->name, len); }return f2fs_ci_compare (dentry->d_parent->d_inode, name, &qstr, false);
Greg Kroah-Hartman
maintainerPATCH 122/309 f2fs: fix race conditions in ->d_compare() and ->d_hash()
In reply to Greg Kroah-HartmanFrom: Eric Biggers <[email protected]>
commit 80f2388afa6ef985f9c5c228e36705c4d4db4756 upstream.
Since ->d_compare() and ->d_hash() can be called in RCU-walk mode, ->d_parent and ->d_inode can be concurrently modified, and in particular, ->d_inode may be changed to NULL. For f2fs_d_hash() this resulted in a reproducible NULL dereference if a lookup is done in a directory being deleted, e.g. with:
int main()
{
if (fork()) {
for (;;) {
mkdir("subdir", 0700);
rmdir("subdir");
}
} else {
for (;;)
access("subdir/file", 0);
}
}... or by running the 't_encrypted_d_revalidate' program from xfstests. Both repros work in any directory on a filesystem with the encoding feature, even if the directory doesn't actually have the casefold flag.
I couldn't reproduce a crash in f2fs_d_compare(), but it appears that a similar crash is possible there.
Fix these bugs by reading ->d_parent and ->d_inode using READ_ONCE() and falling back to the case sensitive behavior if the inode is NULL.
--- fs/f2fs/dir.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
fs/f2fs/dir.c +6 -3
@@ -1068,24 +1068,27 @@ static int f2fs_d_compare(const struct d const char *str, const struct qstr *name) { struct qstr qstr = {.name = str, .len = len }; +const struct dentry *parent =READ_ONCE (dentry->d_parent); +const struct inode *inode =READ_ONCE (parent->d_inode); -if (!IS_CASEFOLDED (dentry->d_parent->d_inode)) { +if (!inode || !IS_CASEFOLDED (inode)) {if (len != name->len)return -1 ;return memcmp (str, name->name, len); } -return f2fs_ci_compare (dentry->d_parent->d_inode, name, &qstr, false); +return f2fs_ci_compare (inode, name, &qstr, false); }static int f2fs_d_hash (const struct dentry *dentry,struct qstr *str) {struct f2fs_sb_info *sbi =F2FS_SB (dentry->d_sb);const struct unicode_map *um = sbi->s_encoding; +const struct inode *inode =READ_ONCE (dentry->d_inode);unsigned char *norm;int len, ret =0 ; -if (!IS_CASEFOLDED (dentry->d_inode)) +if (!inode || !IS_CASEFOLDED (inode))return 0 ; norm =f2fs_kmalloc (sbi,PATH_MAX ,GFP_ATOMIC );
Greg Kroah-Hartman
maintainerPATCH 123/309 PM: core: Fix handling of devices deleted during system-wide resume
In reply to Greg Kroah-HartmanFrom: Rafael J. Wysocki <[email protected]>
commit 0552e05fdfea191a2cf3a0abd33574b5ef9ca818 upstream.
If a device is deleted by one of its system-wide resume callbacks (for example, because it does not appear to be present or accessible any more) along with its children, the resume of the children may continue leading to use-after-free errors and other issues (potentially).
Namely, if the device's children are resumed asynchronously, their resume may have been scheduled already before the device's callback runs and so the device may be deleted while dpm_wait_for_superior() is being executed for them. The memory taken up by the parent device object may be freed then while dpm_wait() is waiting for the parent's resume callback to complete, which leads to a use-after-free. Moreover, the resume of the children is really not expected to continue after they have been unregistered, so it must be terminated right away in that case.
To address this problem, modify dpm_wait_for_superior() to check if the target device is still there in the system-wide PM list of devices and if so, to increment its parent's reference counter, both under dpm_list_mtx which prevents device_del() running for the child from dropping the parent's reference counter prematurely.
If the device is not present in the system-wide PM list of devices any more, the resume of it cannot continue, so check that again after dpm_wait() returns, which means that the parent's callback has been completed, and pass the result of that check to the caller of dpm_wait_for_superior() to allow it to abort the device's resume if it is not there any more.
--- drivers/base/power/main.c | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-)
drivers/base/power/main.c +37 -5
@@ -273,10 +273,38 @@ static void dpm_wait_for_suppliers(strucdevice_links_read_unlock (idx); } -static void dpm_wait_for_superior (struct device *dev,bool async) +static bool dpm_wait_for_superior (struct device *dev,bool async) { -dpm_wait (dev->parent, async); +struct device *parent; + +/* +* If the device is resumed asynchronously and the parent's callback +* deletes both the device and the parent itself, the parent object may +* be freed while this function is running, so avoid that by reference +* counting the parent once more unless the device has been deleted +* already (in which case return right away). +*/ +mutex_lock (&dpm_list_mtx); + +if (!device_pm_initialized (dev)) { +mutex_unlock (&dpm_list_mtx); +return false; + } + + parent =get_device (dev->parent); + +mutex_unlock (&dpm_list_mtx); + +dpm_wait (parent, async); +put_device (parent); +dpm_wait_for_suppliers (dev, async); + +/* +* If the parent's callback has deleted the device, attempting to resume +* it would be invalid, so avoid doing that then. +*/ +return device_pm_initialized (dev); }static void dpm_wait_for_consumers (struct device *dev,bool async)
@@ -621,7 +649,8 @@ static int device_resume_noirq(struct deif (!dev->power.is_noirq_suspended) goto Out; -dpm_wait_for_superior (dev, async); +if (!dpm_wait_for_superior (dev, async)) + goto Out; skip_resume =dev_pm_may_skip_resume (dev);
@@ -829,7 +858,8 @@ static int device_resume_early(struct deif (!dev->power.is_late_suspended) goto Out; -dpm_wait_for_superior (dev, async); +if (!dpm_wait_for_superior (dev, async)) + goto Out; callback =dpm_subsys_resume_early_cb (dev, state, &info);
@@ -944,7 +974,9 @@ static int device_resume(struct device * goto Complete; } -dpm_wait_for_superior (dev, async); +if (!dpm_wait_for_superior (dev, async)) + goto Complete; +dpm_watchdog_set (&wd, dev);device_lock (dev);
Greg Kroah-Hartman
maintainerPATCH 124/309 cpufreq: Avoid creating excessively large stack frames
In reply to Greg Kroah-HartmanFrom: Rafael J. Wysocki <[email protected]>
commit 1e4f63aecb53e48468661e922fc2fa3b83e55722 upstream.
In the process of modifying a cpufreq policy, the cpufreq core makes a copy of it including all of the internals which is stored on the CPU stack. Because struct cpufreq_policy is relatively large, this may cause the size of the stack frame to exceed the 2 KB limit and so the GCC complains when -Wframe-larger-than= is used.
In fact, it is not necessary to copy the entire policy structure in order to modify it, however.
First, because cpufreq_set_policy() obtains the min and max policy limits from frequency QoS now, it is not necessary to pass the limits to it from the callers. The only things that need to be passed to it from there are the new governor pointer or (if there is a built-in governor in the driver) the "policy" value representing the governor choice. They both can be passed as individual arguments, though, so make cpufreq_set_policy() take them this way and rework its callers accordingly. This avoids making copies of cpufreq policies in the callers of cpufreq_set_policy().
Second, cpufreq_set_policy() still needs to pass the new policy data to the ->verify() callback of the cpufreq driver whose task is to sanitize the min and max policy limits. It still does not need to make a full copy of struct cpufreq_policy for this purpose, but it needs to pass a few items from it to the driver in case they are needed (different drivers have different needs in that respect and all of them have to be covered). For this reason, introduce struct cpufreq_policy_data to hold copies of the members of struct cpufreq_policy used by the existing ->verify() driver callbacks and pass a pointer to a temporary structure of that type to ->verify() (instead of passing a pointer to full struct cpufreq_policy to it).
While at it, notice that intel_pstate and longrun don't really need to verify the "policy" value in struct cpufreq_policy, so drop those check from them to avoid copying "policy" into struct cpufreq_policy_data (which allows it to be slightly smaller).
Also while at it fix up white space in a couple of places and make cpufreq_set_policy() static (as it can be so).
--- drivers/cpufreq/cppc_cpufreq.c | 2 drivers/cpufreq/cpufreq-nforce2.c | 2 drivers/cpufreq/cpufreq.c | 147 +++++++++++++++++-------------------- drivers/cpufreq/freq_table.c | 4 - drivers/cpufreq/gx-suspmod.c | 2 drivers/cpufreq/intel_pstate.c | 38 ++++----- drivers/cpufreq/longrun.c | 6 - drivers/cpufreq/pcc-cpufreq.c | 2 drivers/cpufreq/sh-cpufreq.c | 2 drivers/cpufreq/unicore2-cpufreq.c | 2 include/linux/cpufreq.h | 32 +++++--- 11 files changed, 119 insertions(+), 120 deletions(-)
drivers/cpufreq/cppc_cpufreq.c +1 -1
@@ -217,7 +217,7 @@ static int cppc_cpufreq_set_target(strucreturn ret; } -static int cppc_verify_policy (struct cpufreq_policy *policy) +static int cppc_verify_policy (struct cpufreq_policy_data *policy) {cpufreq_verify_within_cpu_limits (policy);return 0 ;
drivers/cpufreq/cpufreq-nforce2.c +1 -1
@@ -291,7 +291,7 @@ static int nforce2_target(struct cpufreq* nforce2_verify - verifies a new CPUFreq policy * @policy: new policy */ -static int nforce2_verify (struct cpufreq_policy *policy) +static int nforce2_verify (struct cpufreq_policy_data *policy) {unsigned int fsb_pol_max;
drivers/cpufreq/cpufreq.c +70 -77
263 lines not on this page · raw message
drivers/cpufreq/freq_table.c +2 -2
@@ -60,7 +60,7 @@ int cpufreq_frequency_table_cpuinfo(strureturn 0 ; } -int cpufreq_frequency_table_verify (struct cpufreq_policy *policy, +int cpufreq_frequency_table_verify (struct cpufreq_policy_data *policy,struct cpufreq_frequency_table *table) {struct cpufreq_frequency_table *pos;
@@ -100,7 +100,7 @@ EXPORT_SYMBOL_GPL(cpufreq_frequency_tabl* Generic routine to verify policy & frequency table, requires driver to set * policy->freq_table prior to it. */ -int cpufreq_generic_frequency_table_verify (struct cpufreq_policy *policy) +int cpufreq_generic_frequency_table_verify (struct cpufreq_policy_data *policy) {if (!policy->freq_table)return -ENODEV ;
drivers/cpufreq/gx-suspmod.c +1 -1
@@ -328,7 +328,7 @@ static void gx_set_cpuspeed(struct cpufr* for the hardware supported by the driver. */ -static int cpufreq_gx_verify (struct cpufreq_policy *policy) +static int cpufreq_gx_verify (struct cpufreq_policy_data *policy) {unsigned int tmp_freq =0 ;u8 tmp1, tmp2;
drivers/cpufreq/intel_pstate.c +17 -21
@@ -2036,8 +2036,9 @@ static int intel_pstate_get_max_freq(str cpu->pstate.max_freq : cpu->pstate.turbo_freq; } -static void intel_pstate_update_perf_limits (struct cpufreq_policy *policy, -struct cpudata *cpu) +static void intel_pstate_update_perf_limits (struct cpudata *cpu, +unsigned int policy_min, +unsigned int policy_max) {int max_freq =intel_pstate_get_max_freq (cpu);int32_t max_policy_perf, min_policy_perf;
@@ -2056,18 +2057,17 @@ static void intel_pstate_update_perf_lim turbo_max = cpu->pstate.turbo_pstate; } - max_policy_perf = max_state * policy->max / max_freq; -if (policy->max == policy->min) { + max_policy_perf = max_state * policy_max / max_freq; +if (policy_max == policy_min) { min_policy_perf = max_policy_perf; }else { - min_policy_perf = max_state * policy->min / max_freq; + min_policy_perf = max_state * policy_min / max_freq; min_policy_perf =clamp_t (int32_t, min_policy_perf,0 , max_policy_perf); }pr_debug ("cpu:%d max_state %d min_policy_perf:%d max_policy_perf:%d\n" , - policy->cpu, max_state, - min_policy_perf, max_policy_perf); + cpu->cpu, max_state, min_policy_perf, max_policy_perf);/* Normalize user input to [min_perf, max_perf] */ if (per_cpu_limits) {
@@ -2081,7 +2081,7 @@ static void intel_pstate_update_perf_lim global_min =DIV_ROUND_UP (turbo_max * global.min_perf_pct,100 ); global_min =clamp_t (int32_t, global_min,0 , global_max); -pr_debug ("cpu:%d global_min:%d global_max:%d\n" , policy->cpu, +pr_debug ("cpu:%d global_min:%d global_max:%d\n" , cpu->cpu, global_min, global_max); cpu->min_perf_ratio =max (min_policy_perf, global_min);
@@ -2094,7 +2094,7 @@ static void intel_pstate_update_perf_lim cpu->max_perf_ratio); } -pr_debug ("cpu:%d max_perf_ratio:%d min_perf_ratio:%d\n" , policy->cpu, +pr_debug ("cpu:%d max_perf_ratio:%d min_perf_ratio:%d\n" , cpu->cpu, cpu->max_perf_ratio, cpu->min_perf_ratio); }
@@ -2114,7 +2114,7 @@ static int intel_pstate_set_policy(strucmutex_lock (&intel_pstate_limits_lock); -intel_pstate_update_perf_limits (policy, cpu); +intel_pstate_update_perf_limits (cpu, policy->min, policy->max);if (cpu->policy ==CPUFREQ_POLICY_PERFORMANCE ) {/*
@@ -2143,8 +2143,8 @@ static int intel_pstate_set_policy(strucreturn 0 ; } -static void intel_pstate_adjust_policy_max (struct cpufreq_policy *policy, -struct cpudata *cpu) +static void intel_pstate_adjust_policy_max (struct cpudata *cpu, +struct cpufreq_policy_data *policy) { if (!hwp_active && cpu->pstate.max_pstate_physical > cpu->pstate.max_pstate &&
@@ -2155,7 +2155,7 @@ static void intel_pstate_adjust_policy_m } } -static int intel_pstate_verify_policy (struct cpufreq_policy *policy) +static int intel_pstate_verify_policy (struct cpufreq_policy_data *policy) {struct cpudata *cpu = all_cpu_data[policy->cpu];
@@ -2163,11 +2163,7 @@ static int intel_pstate_verify_policy(stcpufreq_verify_within_limits (policy, policy->cpuinfo.min_freq,intel_pstate_get_max_freq (cpu)); -if (policy->policy !=CPUFREQ_POLICY_POWERSAVE && - policy->policy !=CPUFREQ_POLICY_PERFORMANCE ) -return -EINVAL ; - -intel_pstate_adjust_policy_max (policy, cpu); +intel_pstate_adjust_policy_max (cpu, policy);return 0 ; }
@@ -2268,7 +2264,7 @@ static struct cpufreq_driver intel_pstat .name = "intel_pstate", }; -static int intel_cpufreq_verify_policy (struct cpufreq_policy *policy) +static int intel_cpufreq_verify_policy (struct cpufreq_policy_data *policy) {struct cpudata *cpu = all_cpu_data[policy->cpu];
@@ -2276,9 +2272,9 @@ static int intel_cpufreq_verify_policy(scpufreq_verify_within_limits (policy, policy->cpuinfo.min_freq,intel_pstate_get_max_freq (cpu)); -intel_pstate_adjust_policy_max (policy, cpu); +intel_pstate_adjust_policy_max (cpu, policy); -intel_pstate_update_perf_limits (policy, cpu); +intel_pstate_update_perf_limits (cpu, policy->min, policy->max);return 0 ; }
drivers/cpufreq/longrun.c +1 -5
@@ -122,7 +122,7 @@ static int longrun_set_policy(struct cpu* Validates a new CPUFreq policy. This function has to be called with * cpufreq_driver locked. */ -static int longrun_verify_policy (struct cpufreq_policy *policy) +static int longrun_verify_policy (struct cpufreq_policy_data *policy) {if (!policy)return -EINVAL ;
@@ -130,10 +130,6 @@ static int longrun_verify_policy(struct policy->cpu =0 ;cpufreq_verify_within_cpu_limits (policy); -if ((policy->policy !=CPUFREQ_POLICY_POWERSAVE ) && - (policy->policy !=CPUFREQ_POLICY_PERFORMANCE )) -return -EINVAL ; -return 0 ; }
drivers/cpufreq/pcc-cpufreq.c +1 -1
@@ -109,7 +109,7 @@ struct pcc_cpu {static struct pcc_cpu __percpu *pcc_cpu_info; -static int pcc_cpufreq_verify (struct cpufreq_policy *policy) +static int pcc_cpufreq_verify (struct cpufreq_policy_data *policy) {cpufreq_verify_within_cpu_limits (policy);return 0 ;
drivers/cpufreq/sh-cpufreq.c +1 -1
@@ -87,7 +87,7 @@ static int sh_cpufreq_target(struct cpufreturn work_on_cpu (policy->cpu, __sh_cpufreq_target, &data); } -static int sh_cpufreq_verify (struct cpufreq_policy *policy) +static int sh_cpufreq_verify (struct cpufreq_policy_data *policy) {struct clk *cpuclk = &per_cpu (sh_cpuclk, policy->cpu);struct cpufreq_frequency_table *freq_table;
drivers/cpufreq/unicore2-cpufreq.c +1 -1
@@ -22,7 +22,7 @@ static struct cpufreq_driver ucv2_driver/* make sure that only the "userspace" governor is run * -- anything else wouldn't make sense on this platform, anyway. */ -static int ucv2_verify_speed (struct cpufreq_policy *policy) +static int ucv2_verify_speed (struct cpufreq_policy_data *policy) {if (policy->cpu)return -EINVAL ;
include/linux/cpufreq.h +23 -9
@@ -148,6 +148,20 @@ struct cpufreq_policy {struct notifier_block nb_max; }; +/* +* Used for passing new cpufreq policy data to the cpufreq driver's ->verify() +* callback for sanitization. That callback is only expected to modify the min +* and max values, if necessary, and specifically it must not update the +* frequency table. +*/ +struct cpufreq_policy_data { +struct cpufreq_cpuinfo cpuinfo; +struct cpufreq_frequency_table *freq_table; +unsigned int cpu; +unsigned int min;/* in kHz */ +unsigned int max;/* in kHz */ +}; +struct cpufreq_freqs {struct cpufreq_policy *policy;unsigned int old;
@@ -201,8 +215,6 @@ u64 get_cpu_idle_time(unsigned int cpu,struct cpufreq_policy *cpufreq_cpu_acquire (unsigned int cpu);void cpufreq_cpu_release (struct cpufreq_policy *policy);int cpufreq_get_policy (struct cpufreq_policy *policy,unsigned int cpu); -int cpufreq_set_policy (struct cpufreq_policy *policy, -struct cpufreq_policy *new_policy);void refresh_frequency_limits (struct cpufreq_policy *policy);void cpufreq_update_policy (unsigned int cpu);void cpufreq_update_limits (unsigned int cpu);
@@ -284,7 +296,7 @@ struct cpufreq_driver {/* needed by all drivers */ int (*init)(struct cpufreq_policy *policy); -int (*verify)(struct cpufreq_policy *policy); +int (*verify)(struct cpufreq_policy_data *policy);/* define one out of two */ int (*setpolicy)(struct cpufreq_policy *policy);
@@ -415,8 +427,9 @@ static inline int cpufreq_thermal_contro (drv->flags &CPUFREQ_IS_COOLING_DEV ); } -static inline void cpufreq_verify_within_limits (struct cpufreq_policy *policy, -unsigned int min,unsigned int max) +static inline void cpufreq_verify_within_limits (struct cpufreq_policy_data *policy, +unsigned int min, +unsigned int max) {if (policy->min < min) policy->min = min;
@@ -432,10 +445,10 @@ static inline void cpufreq_verify_within }static inline void -cpufreq_verify_within_cpu_limits (struct cpufreq_policy *policy) +cpufreq_verify_within_cpu_limits (struct cpufreq_policy_data *policy) {cpufreq_verify_within_limits (policy, policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); + policy->cpuinfo.max_freq); }#ifdef CONFIG_CPU_FREQ
@@ -513,6 +526,7 @@ static inline unsigned long cpufreq_scal* CPUFREQ GOVERNORS * *********************************************************************/ +#define CPUFREQ_POLICY_UNKNOWN (0)/* * If (cpufreq_driver->target) exists, the ->governor decides what frequency * within the limits is used. If (cpufreq_driver->setpolicy> exists, these
@@ -684,9 +698,9 @@ static inline void dev_pm_opp_free_cpufrint cpufreq_frequency_table_cpuinfo (struct cpufreq_policy *policy,struct cpufreq_frequency_table *table); -int cpufreq_frequency_table_verify (struct cpufreq_policy *policy, +int cpufreq_frequency_table_verify (struct cpufreq_policy_data *policy,struct cpufreq_frequency_table *table); -int cpufreq_generic_frequency_table_verify (struct cpufreq_policy *policy); +int cpufreq_generic_frequency_table_verify (struct cpufreq_policy_data *policy); int cpufreq_table_index_unsorted(struct cpufreq_policy *policy, unsigned int target_freq,
Greg Kroah-Hartman
maintainerPATCH 125/309 of: Add OF_DMA_DEFAULT_COHERENT & select it on powerpc
In reply to Greg Kroah-HartmanFrom: Michael Ellerman <[email protected]>
commit dabf6b36b83a18d57e3d4b9d50544ed040d86255 upstream.
There's an OF helper called of_dma_is_coherent(), which checks if a device has a "dma-coherent" property to see if the device is coherent for DMA.
But on some platforms devices are coherent by default, and on some platforms it's not possible to update existing device trees to add the "dma-coherent" property.
So add a Kconfig symbol to allow arch code to tell of_dma_is_coherent() that devices are coherent by default, regardless of the presence of the property.
Select that symbol on powerpc when NOT_COHERENT_CACHE is not set, ie. when the system has a coherent cache.
--- arch/powerpc/Kconfig | 1 + drivers/of/Kconfig | 4 ++++ drivers/of/address.c | 6 +++++- 3 files changed, 10 insertions(+), 1 deletion(-)
arch/powerpc/Kconfig +1 -0
@@ -237,6 +237,7 @@ config PPC select NEED_DMA_MAP_STATE if PPC64 || NOT_COHERENT_CACHE select NEED_SG_DMA_LENGTH select OF + select OF_DMA_DEFAULT_COHERENT if !NOT_COHERENT_CACHE select OF_EARLY_FLATTREE select OLD_SIGACTION if PPC32 select OLD_SIGSUSPEND
drivers/of/Kconfig +4 -0
@@ -103,4 +103,8 @@ config OF_OVERLAY config OF_NUMA bool +config OF_DMA_DEFAULT_COHERENT + # arches should select this if DMA is coherent by default for OF devices + bool + endif # OF
drivers/of/address.c +5 -1
@@ -998,12 +998,16 @@ EXPORT_SYMBOL_GPL(of_dma_get_range);* @np: device node * * It returns true if "dma-coherent" property was found -* for this device in DT. +* for this device in the DT, or if DMA is coherent by +* default for OF devices on the current platform. */ bool of_dma_is_coherent (struct device_node *np) {struct device_node *node =of_node_get (np); +if (IS_ENABLED (CONFIG_OF_DMA_DEFAULT_COHERENT )) +return true; +while (node) {if (of_property_read_bool (node,"dma-coherent" )) {of_node_put (node);
Greg Kroah-Hartman
maintainerPATCH 126/309 ARM: dma-api: fix max_pfn off-by-one error in __dma_supported()
In reply to Greg Kroah-HartmanFrom: Chen-Yu Tsai <[email protected]>
commit f3cc4e1d44a813a0685f2e558b78ace3db559722 upstream.
max_pfn, as set in arch/arm/mm/init.c:
static void __init find_limits(unsigned long *min,
unsigned long *max_low,
unsigned long *max_high)
{
*max_low = PFN_DOWN(memblock_get_current_limit());
*min = PFN_UP(memblock_start_of_DRAM());
*max_high = PFN_DOWN(memblock_end_of_DRAM());
}with memblock_end_of_DRAM() pointing to the next byte after DRAM. As such, max_pfn points to the PFN after the end of DRAM.
Thus when using max_pfn to check DMA masks, we should subtract one when checking DMA ranges against it.
Commit 8bf1268f48ad ("ARM: dma-api: fix off-by-one error in __dma_supported()") fixed the same issue, but missed this spot.
This issue was found while working on the sun4i-csi v4l2 driver on the Allwinner R40 SoC. On Allwinner SoCs, DRAM is offset at 0x40000000, and we are starting to use of_dma_configure() with the "dma-ranges" property in the device tree to have the DMA API handle the offset.
In this particular instance, dma-ranges was set to the same range as the actual available (2 GiB) DRAM. The following error appeared when the driver attempted to allocate a buffer:
sun4i-csi 1c09000.csi: Coherent DMA mask 0x7fffffff (pfn 0x40000-0xc0000)
covers a smaller range of system memory than the DMA zone pfn 0x0-0xc0001
sun4i-csi 1c09000.csi: dma_alloc_coherent of size 307200 failedFixing the off-by-one error makes things work.
--- arch/arm/mm/dma-mapping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/mm/dma-mapping.c +1 -1
@@ -221,7 +221,7 @@ EXPORT_SYMBOL(arm_coherent_dma_ops);static int __dma_supported (struct device *dev,u64 mask,bool warn) { -unsigned long max_dma_pfn =min (max_pfn, arm_dma_pfn_limit); +unsigned long max_dma_pfn =min (max_pfn -1 , arm_dma_pfn_limit);/* * Translate the device's DMA mask to a PFN limit. This
Greg Kroah-Hartman
maintainerPATCH 127/309 dm zoned: support zone sizes smaller than 128MiB
In reply to Greg Kroah-HartmanFrom: Dmitry Fomichev <[email protected]>
commit b39962950339912978484cdac50069258545d753 upstream.
dm-zoned is observed to log failed kernel assertions and not work correctly when operating against a device with a zone size smaller than 128MiB (e.g. 32768 bits per 4K block). The reason is that the bitmap size per zone is calculated as zero with such a small zone size. Fix this problem and also make the code related to zone bitmap management be able to handle per zone bitmaps smaller than a single block.
A dm-zoned-tools patch is required to properly format dm-zoned devices with zone sizes smaller than 128MiB.
--- drivers/md/dm-zoned-metadata.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-)
drivers/md/dm-zoned-metadata.c +14 -9
@@ -134,6 +134,7 @@ struct dmz_metadata {sector_t zone_bitmap_size;unsigned int zone_nr_bitmap_blocks; +unsigned int zone_bits_per_mblk;unsigned int nr_bitmap_blocks;unsigned int nr_map_blocks;
@@ -1167,7 +1168,10 @@ static int dmz_init_zones(struct dmz_met/* Init */ zmd->zone_bitmap_size = dev->zone_nr_blocks >>3 ; - zmd->zone_nr_bitmap_blocks = zmd->zone_bitmap_size >>DMZ_BLOCK_SHIFT ; + zmd->zone_nr_bitmap_blocks = +max_t (sector_t,1 , zmd->zone_bitmap_size >>DMZ_BLOCK_SHIFT ); + zmd->zone_bits_per_mblk =min_t (sector_t, dev->zone_nr_blocks, +DMZ_BLOCK_SIZE_BITS );/* Allocate zone array */ zmd->zones =kcalloc (dev->nr_zones,sizeof (struct dm_zone ),GFP_KERNEL );
@@ -1991,7 +1995,7 @@ int dmz_copy_valid_blocks(struct dmz_metdmz_release_mblock (zmd, to_mblk);dmz_release_mblock (zmd, from_mblk); - chunk_block +=DMZ_BLOCK_SIZE_BITS ; + chunk_block += zmd->zone_bits_per_mblk; } to_zone->weight = from_zone->weight;
@@ -2052,7 +2056,7 @@ int dmz_validate_blocks(struct dmz_metad/* Set bits */ bit = chunk_block &DMZ_BLOCK_MASK_BITS ; - nr_bits =min (nr_blocks,DMZ_BLOCK_SIZE_BITS - bit); + nr_bits =min (nr_blocks, zmd->zone_bits_per_mblk - bit); count =dmz_set_bits ((unsigned long *)mblk->data, bit, nr_bits);if (count) {
@@ -2131,7 +2135,7 @@ int dmz_invalidate_blocks(struct dmz_met/* Clear bits */ bit = chunk_block &DMZ_BLOCK_MASK_BITS ; - nr_bits =min (nr_blocks,DMZ_BLOCK_SIZE_BITS - bit); + nr_bits =min (nr_blocks, zmd->zone_bits_per_mblk - bit); count =dmz_clear_bits ((unsigned long *)mblk->data, bit, nr_bits);
@@ -2191,6 +2195,7 @@ static int dmz_to_next_set_block(struct {struct dmz_mblock *mblk;unsigned int bit, set_bit, nr_bits; +unsigned int zone_bits = zmd->zone_bits_per_mblk;unsigned long *bitmap;int n =0 ;
@@ -2205,15 +2210,15 @@ static int dmz_to_next_set_block(struct/* Get offset */ bitmap = (unsigned long *) mblk->data; bit = chunk_block &DMZ_BLOCK_MASK_BITS ; - nr_bits =min (nr_blocks,DMZ_BLOCK_SIZE_BITS - bit); + nr_bits =min (nr_blocks, zone_bits - bit);if (set) - set_bit =find_next_bit (bitmap,DMZ_BLOCK_SIZE_BITS , bit); + set_bit =find_next_bit (bitmap, zone_bits, bit);else - set_bit =find_next_zero_bit (bitmap,DMZ_BLOCK_SIZE_BITS , bit); + set_bit =find_next_zero_bit (bitmap, zone_bits, bit);dmz_release_mblock (zmd, mblk); n += set_bit - bit; -if (set_bit <DMZ_BLOCK_SIZE_BITS ) +if (set_bit < zone_bits)break ; nr_blocks -= nr_bits;
@@ -2316,7 +2321,7 @@ static void dmz_get_zone_weight(struct d/* Count bits in this block */ bitmap = mblk->data; bit = chunk_block &DMZ_BLOCK_MASK_BITS ; - nr_bits =min (nr_blocks,DMZ_BLOCK_SIZE_BITS - bit); + nr_bits =min (nr_blocks, zmd->zone_bits_per_mblk - bit); n +=dmz_count_bits (bitmap, bit, nr_bits);dmz_release_mblock (zmd, mblk);
Greg Kroah-Hartman
maintainerPATCH 128/309 dm space map common: fix to ensure new block isnt already in use
In reply to Greg Kroah-HartmanFrom: Joe Thornber <[email protected]>
commit 4feaef830de7ffdd8352e1fe14ad3bf13c9688f8 upstream.
The space-maps track the reference counts for disk blocks allocated by both the thin-provisioning and cache targets. There are variants for tracking metadata blocks and data blocks.
Transactionality is implemented by never touching blocks from the previous transaction, so we can rollback in the event of a crash.
When allocating a new block we need to ensure the block is free (has reference count of 0) in both the current and previous transaction. Prior to this fix we were doing this by searching for a free block in the previous transaction, and relying on a 'begin' counter to track where the last allocation in the current transaction was. This 'begin' field was not being updated in all code paths (eg, increment of a data block reference count due to breaking sharing of a neighbour block in the same btree leaf).
This fix keeps the 'begin' field, but now it's just a hint to speed up the search. Instead the current transaction is searched for a free block, and then the old transaction is double checked to ensure it's free. Much simpler.
This fixes reports of sm_disk_new_block()'s BUG_ON() triggering when DM thin-provisioning's snapshots are heavily used.
--- drivers/md/persistent-data/dm-space-map-common.c | 27 +++++++++++++++++++++ drivers/md/persistent-data/dm-space-map-common.h | 2 + drivers/md/persistent-data/dm-space-map-disk.c | 6 +++- drivers/md/persistent-data/dm-space-map-metadata.c | 5 +++ 4 files changed, 37 insertions(+), 3 deletions(-)
drivers/md/persistent-data/dm-space-map-common.c +27 -0
@@ -380,6 +380,33 @@ int sm_ll_find_free_block(struct ll_diskreturn -ENOSPC ; } +int sm_ll_find_common_free_block (struct ll_disk *old_ll,struct ll_disk *new_ll, +dm_block_t begin,dm_block_t end,dm_block_t *b) +{ +int r; +uint32_t count; + +do { + r =sm_ll_find_free_block (new_ll, begin, new_ll->nr_blocks, b); +if (r) +break ; + +/* double check this block wasn't used in the old transaction */ +if (*b >= old_ll->nr_blocks) + count =0 ; +else { + r =sm_ll_lookup (old_ll, *b, &count); +if (r) +break ; + +if (count) + begin = *b +1 ; + } + }while (count); + +return r; +} +static int sm_ll_mutate (struct ll_disk *ll,dm_block_t b,int (*mutator)(void *context,uint32_t old,uint32_t *new),void *context,enum allocation_event *ev)
drivers/md/persistent-data/dm-space-map-common.h +2 -0
@@ -109,6 +109,8 @@ int sm_ll_lookup_bitmap(struct ll_disk *int sm_ll_lookup (struct ll_disk *ll,dm_block_t b,uint32_t *result);int sm_ll_find_free_block (struct ll_disk *ll,dm_block_t begin,dm_block_t end,dm_block_t *result); +int sm_ll_find_common_free_block (struct ll_disk *old_ll,struct ll_disk *new_ll, +dm_block_t begin,dm_block_t end,dm_block_t *result);int sm_ll_insert (struct ll_disk *ll,dm_block_t b,uint32_t ref_count,enum allocation_event *ev);int sm_ll_inc (struct ll_disk *ll,dm_block_t b,enum allocation_event *ev);int sm_ll_dec (struct ll_disk *ll,dm_block_t b,enum allocation_event *ev);
drivers/md/persistent-data/dm-space-map-disk.c +4 -2
@@ -167,8 +167,10 @@ static int sm_disk_new_block(struct dm_senum allocation_event ev; struct sm_disk *smd = container_of(sm, struct sm_disk, sm); -/* FIXME: we should loop round a couple of times */ - r =sm_ll_find_free_block (&smd->old_ll, smd->begin, smd->old_ll.nr_blocks, b); +/* +* Any block we allocate has to be free in both the old and current ll. +*/ + r =sm_ll_find_common_free_block (&smd->old_ll, &smd->ll, smd->begin, smd->ll.nr_blocks, b);if (r)return r;
drivers/md/persistent-data/dm-space-map-metadata.c +4 -1
@@ -448,7 +448,10 @@ static int sm_metadata_new_block_(structenum allocation_event ev; struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); - r =sm_ll_find_free_block (&smm->old_ll, smm->begin, smm->old_ll.nr_blocks, b); +/* +* Any block we allocate has to be free in both the old and current ll. +*/ + r =sm_ll_find_common_free_block (&smm->old_ll, &smm->ll, smm->begin, smm->ll.nr_blocks, b);if (r)return r;
Greg Kroah-Hartman
maintainerPATCH 129/309 dm writecache: fix incorrect flush sequence when doing SSD mode commit
In reply to Greg Kroah-HartmanFrom: Mikulas Patocka <[email protected]>
commit aa9509209c5ac2f0b35d01a922bf9ae072d0c2fc upstream.
When committing state, the function writecache_flush does the following:
1. write metadata (writecache_commit_flushed)
2. flush disk cache (writecache_commit_flushed)
3. wait for data writes to complete (writecache_wait_for_ios)
4. increase superblock seq_count
5. write the superblock
6. flush disk cache
It may happen that at step 3, when we wait for some write to finish, the disk may report the write as finished, but the write only hit the disk cache and it is not yet stored in persistent storage. At step 5 we write the superblock - it may happen that the superblock is written before the write that we waited for in step 3. If the machine crashes, it may result in incorrect data being returned after reboot.
In order to fix the bug, we must swap steps 2 and 3 in the above sequence, so that we first wait for writes to complete and then flush the disk cache.
--- drivers/md/dm-writecache.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-)
drivers/md/dm-writecache.c +21 -21
@@ -442,7 +442,13 @@ static void writecache_notify_io(unsignecomplete (&endio->c); } -static void ssd_commit_flushed (struct dm_writecache *wc) +static void writecache_wait_for_ios (struct dm_writecache *wc,int direction) +{ +wait_event (wc->bio_in_progress_wait[direction], + !atomic_read (&wc->bio_in_progress[direction])); +} + +static void ssd_commit_flushed (struct dm_writecache *wc,bool wait_for_ios) {struct dm_io_region region;struct dm_io_request req;
@@ -488,17 +494,20 @@ static void ssd_commit_flushed(struct dmwritecache_notify_io (0 , &endio);wait_for_completion_io (&endio.c); +if (wait_for_ios) +writecache_wait_for_ios (wc,WRITE ); +writecache_disk_flush (wc, wc->ssd_dev);memset (wc->dirty_bitmap,0 , wc->dirty_bitmap_size); } -static void writecache_commit_flushed (struct dm_writecache *wc) +static void writecache_commit_flushed (struct dm_writecache *wc,bool wait_for_ios) {if (WC_MODE_PMEM (wc))wmb ();else -ssd_commit_flushed (wc); +ssd_commit_flushed (wc, wait_for_ios); }static void writecache_disk_flush (struct dm_writecache *wc,struct dm_dev *dev)
@@ -522,12 +531,6 @@ static void writecache_disk_flush(structwritecache_error (wc, r,"error flushing metadata: %d" , r); } -static void writecache_wait_for_ios (struct dm_writecache *wc,int direction) -{ -wait_event (wc->bio_in_progress_wait[direction], - !atomic_read (&wc->bio_in_progress[direction])); -} -#define WFE_RETURN_FOLLOWING 1#define WFE_LOWEST_SEQ 2
@@ -724,15 +727,12 @@ static void writecache_flush(struct dm_w e = e2;cond_resched (); } -writecache_commit_flushed (wc); - -if (!WC_MODE_PMEM (wc)) -writecache_wait_for_ios (wc,WRITE ); +writecache_commit_flushed (wc, true); wc->seq_count++;pmem_assign (sb (wc)->seq_count,cpu_to_le64 (wc->seq_count));writecache_flush_region (wc, &sb (wc)->seq_count,sizeof sb (wc)->seq_count); -writecache_commit_flushed (wc); +writecache_commit_flushed (wc, false); wc->overwrote_committed = false;
@@ -756,7 +756,7 @@ static void writecache_flush(struct dm_w }if (need_flush_after_free) -writecache_commit_flushed (wc); +writecache_commit_flushed (wc, false); }static void writecache_flush_work (struct work_struct *work)
@@ -809,7 +809,7 @@ static void writecache_discard(struct dm }if (discarded_something) -writecache_commit_flushed (wc); +writecache_commit_flushed (wc, false); }static bool writecache_wait_for_writeback (struct dm_writecache *wc)
@@ -958,7 +958,7 @@ erase_this:if (need_flush) {writecache_flush_all_metadata (wc); -writecache_commit_flushed (wc); +writecache_commit_flushed (wc, false); }wc_unlock (wc);
@@ -1342,7 +1342,7 @@ static void __writecache_endio_pmem(stru wc->writeback_size--; n_walked++;if (unlikely (n_walked >=ENDIO_LATENCY )) { -writecache_commit_flushed (wc); +writecache_commit_flushed (wc, false);wc_unlock (wc);wc_lock (wc); n_walked =0 ;
@@ -1423,7 +1423,7 @@ pop_from_list:writecache_wait_for_ios (wc,READ ); } -writecache_commit_flushed (wc); +writecache_commit_flushed (wc, false);wc_unlock (wc); }
@@ -1766,10 +1766,10 @@ static int init_memory(struct dm_writecawrite_original_sector_seq_count (wc, &wc->entries[b],-1 ,-1 );writecache_flush_all_metadata (wc); -writecache_commit_flushed (wc); +writecache_commit_flushed (wc, false);pmem_assign (sb (wc)->magic,cpu_to_le32 (MEMORY_SUPERBLOCK_MAGIC ));writecache_flush_region (wc, &sb (wc)->magic,sizeof sb (wc)->magic); -writecache_commit_flushed (wc); +writecache_commit_flushed (wc, false);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 130/309 dm crypt: fix GFP flags passed to skcipher_request_alloc()
In reply to Greg Kroah-HartmanFrom: Mikulas Patocka <[email protected]>
commit 9402e959014a18b4ebf7558733076875808dd66c upstream.
GFP_KERNEL is not supposed to be or'd with GFP_NOFS (the result is equivalent to GFP_KERNEL). Also, we use GFP_NOIO instead of GFP_NOFS because we don't want any I/O being submitted in the direct reclaim path.
--- drivers/md/dm-crypt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/md/dm-crypt.c +1 -1
@@ -717,7 +717,7 @@ static int crypt_iv_eboiv_gen(struct crystruct crypto_wait wait;int err; - req =skcipher_request_alloc (any_tfm (cc),GFP_KERNEL |GFP_NOFS ); + req =skcipher_request_alloc (any_tfm (cc),GFP_NOIO );if (!req)return -ENOMEM ;
Greg Kroah-Hartman
maintainerPATCH 131/309 dm crypt: fix benbi IV constructor crash if used in authenticated mode
In reply to Greg Kroah-HartmanFrom: Milan Broz <[email protected]>
commit 4ea9471fbd1addb25a4d269991dc724e200ca5b5 upstream.
If benbi IV is used in AEAD construction, for example:
cryptsetup luksFormat <device> --cipher twofish-xts-benbi --key-size 512 --integrity=hmac-sha256
the constructor uses wrong skcipher function and crashes:
BUG: kernel NULL pointer dereference, address: 00000014 ... EIP: crypt_iv_benbi_ctr+0x15/0x70 [dm_crypt] Call Trace: ? crypt_subkey_size+0x20/0x20 [dm_crypt] crypt_ctr+0x567/0xfc0 [dm_crypt] dm_table_add_target+0x15f/0x340 [dm_mod]
Fix this by properly using crypt_aead_blocksize() in this case.
--- drivers/md/dm-crypt.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
drivers/md/dm-crypt.c +8 -2
@@ -331,8 +331,14 @@ static int crypt_iv_essiv_gen(struct crystatic int crypt_iv_benbi_ctr (struct crypt_config *cc,struct dm_target *ti,const char *opts) { -unsigned bs =crypto_skcipher_blocksize (any_tfm (cc)); -int log =ilog2 (bs); +unsigned bs; +int log; + +if (test_bit (CRYPT_MODE_INTEGRITY_AEAD , &cc->cipher_flags)) + bs =crypto_aead_blocksize (any_tfm_aead (cc)); +else + bs =crypto_skcipher_blocksize (any_tfm (cc)); + log =ilog2 (bs);/* we need to calculate how far we must shift the sector count * to get the cipher block count, we use this shift in _gen */
Greg Kroah-Hartman
maintainerPATCH 132/309 dm thin metadata: use pool locking at end of dm_pool_metadata_close
In reply to Greg Kroah-HartmanFrom: Mike Snitzer <[email protected]>
commit 44d8ebf436399a40fcd10dd31b29d37823d62fcc upstream.
Ensure that the pool is locked during calls to __commit_transaction and __destroy_persistent_data_objects. Just being consistent with locking, but reality is dm_pool_metadata_close is called once pool is being destroyed so access to pool shouldn't be contended.
Also, use pmd_write_lock_in_core rather than __pmd_write_lock in dm_pool_commit_metadata and rename __pmd_write_lock to pmd_write_lock_in_core -- there was no need for the alias.
In addition, verify that the pool is locked in __commit_transaction().
--- drivers/md/dm-thin-metadata.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/md/dm-thin-metadata.c +6 -4
@@ -387,16 +387,15 @@ static int subtree_equal(void *context,* Variant that is used for in-core only changes or code that * shouldn't put the pool in service on its own (e.g. commit). */ -static inline void __pmd_write_lock (struct dm_pool_metadata *pmd) +static inline void pmd_write_lock_in_core (struct dm_pool_metadata *pmd) __acquires(pmd->root_lock) {down_write (&pmd->root_lock); } -#define pmd_write_lock_in_core (pmd) __pmd_write_lock((pmd))static inline void pmd_write_lock (struct dm_pool_metadata *pmd) { -__pmd_write_lock (pmd); +pmd_write_lock_in_core (pmd);if (unlikely (!pmd->in_service)) pmd->in_service = true; }
@@ -831,6 +830,7 @@ static int __commit_transaction(struct d* We need to know if the thin_disk_superblock exceeds a 512-byte sector. */ BUILD_BUG_ON (sizeof (struct thin_disk_superblock ) >512 ); +BUG_ON (!rwsem_is_locked (&pmd->root_lock));if (unlikely (!pmd->in_service))return 0 ;
@@ -953,6 +953,7 @@ int dm_pool_metadata_close(struct dm_pooreturn -EBUSY ; } +pmd_write_lock_in_core (pmd);if (!dm_bm_is_read_only (pmd->bm) && !pmd->fail_io) { r =__commit_transaction (pmd);if (r <0 )
@@ -961,6 +962,7 @@ int dm_pool_metadata_close(struct dm_poo }if (!pmd->fail_io)__destroy_persistent_data_objects (pmd); +pmd_write_unlock (pmd);kfree (pmd);return 0 ;
@@ -1841,7 +1843,7 @@ int dm_pool_commit_metadata(struct dm_po* Care is taken to not have commit be what * triggers putting the thin-pool in-service. */ -__pmd_write_lock (pmd); +pmd_write_lock_in_core (pmd);if (pmd->fail_io) goto out;
Greg Kroah-Hartman
maintainerPATCH 133/309 dm: fix potential for q->make_request_fn NULL pointer
In reply to Greg Kroah-HartmanFrom: Mike Snitzer <[email protected]>
commit 47ace7e012b9f7ad71d43ac9063d335ea3d6820b upstream.
Move blk_queue_make_request() to dm.c:alloc_dev() so that q->make_request_fn is never NULL during the lifetime of a DM device (even one that is created without a DM table).
Otherwise generic_make_request() will crash simply by doing:
dmsetup create -n test
mount /dev/dm-N /mnt
While at it, move ->congested_data initialization out of dm.c:alloc_dev() and into the bio-based specific init method.
Depends-on: c12c9a3c3860c ("dm: various cleanups to md->queue initialization code")
--- drivers/md/dm.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/md/dm.c +7 -2
@@ -1880,6 +1880,7 @@ static void dm_init_normal_md_queue(stru/* * Initialize aspects of queue that aren't relevant for blk-mq */ + md->queue->backing_dev_info->congested_data = md; md->queue->backing_dev_info->congested_fn = dm_any_congested; }
@@ -1970,7 +1971,12 @@ static struct mapped_device *alloc_dev(iif (!md->queue) goto bad; md->queue->queuedata = md; - md->queue->backing_dev_info->congested_data = md; +/* +* default to bio-based required ->make_request_fn until DM +* table is loaded and md->type established. If request-based +* table is loaded: blk-mq will override accordingly. +*/ +blk_queue_make_request (md->queue, dm_make_request); md->disk =alloc_disk_node (1 , md->numa_node_id);if (!md->disk)
@@ -2285,7 +2291,6 @@ int dm_setup_md_queue(struct mapped_devicase DM_TYPE_DAX_BIO_BASED :case DM_TYPE_NVME_BIO_BASED :dm_init_normal_md_queue (md); -blk_queue_make_request (md->queue, dm_make_request);break ;case DM_TYPE_NONE :WARN_ON_ONCE (true);
Greg Kroah-Hartman
maintainerPATCH 134/309 scsi: qla2xxx: Fix stuck login session using prli_pend_timer
In reply to Greg Kroah-HartmanFrom: Quinn Tran <[email protected]>
[ Upstream commit 8aaac2d7da873aebeba92c666f82c00bbd74aaf9 ]
Session is stuck if driver sees FW has received a PRLI. Driver allows FW to finish with processing of PRLI by checking back with FW at a later time to see if the PRLI has finished. Instead, driver failed to push forward after re-checking PRLI completion.
--- drivers/scsi/qla2xxx/qla_def.h | 5 +++++ drivers/scsi/qla2xxx/qla_init.c | 34 +++++++++++++++++++++++-------- drivers/scsi/qla2xxx/qla_target.c | 1 + 3 files changed, 32 insertions(+), 8 deletions(-)
drivers/scsi/qla2xxx/qla_def.h +5 -0
@@ -2402,6 +2402,7 @@ typedef struct fc_port { unsigned int scan_needed:1; unsigned int n2n_flag:1; unsigned int explicit_logout:1; + unsigned int prli_pend_timer:1;struct completion nvme_del_done;uint32_t nvme_prli_service_param;
@@ -2428,6 +2429,7 @@ typedef struct fc_port {struct work_struct free_work;struct work_struct reg_work;uint64_t jiffies_at_registration; +unsigned long prli_expired;struct qlt_plogi_ack_t *plogi_link[QLT_PLOGI_LINK_MAX ];uint16_t tgt_id;
@@ -4821,6 +4823,9 @@ struct sff_8247_a0 { ha->current_topology == ISP_CFG_N || \ !ha->current_topology) +#define PRLI_PHASE (_cls) \ + ((_cls == DSC_LS_PRLI_PEND) || (_cls == DSC_LS_PRLI_COMP)) +#include "qla_target.h" #include "qla_gbl.h" #include "qla_dbg.h"
drivers/scsi/qla2xxx/qla_init.c +26 -8
@@ -686,7 +686,7 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,port_id_t id;u64 wwn;u16 data[2 ]; -u8 current_login_state; +u8 current_login_state, nvme_cls; fcport = ea->fcport; ql_dbg(ql_dbg_disc, vha, 0xffff,
@@ -745,10 +745,17 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha, loop_id =le16_to_cpu (e->nport_handle); loop_id = (loop_id &0x7fff ); -if (fcport->fc4f_nvme) - current_login_state = e->current_login_state >>4 ; -else - current_login_state = e->current_login_state &0xf ; + nvme_cls = e->current_login_state >>4 ; + current_login_state = e->current_login_state &0xf ; + +if (PRLI_PHASE (nvme_cls)) { + current_login_state = nvme_cls; + fcport->fc4_type &= ~FS_FC4TYPE_FCP ; + fcport->fc4_type |=FS_FC4TYPE_NVME ; + }else if (PRLI_PHASE (current_login_state)) { + fcport->fc4_type |=FS_FC4TYPE_FCP ; + fcport->fc4_type &= ~FS_FC4TYPE_NVME ; + } ql_dbg(ql_dbg_disc, vha, 0x20e2,
@@ -1219,12 +1226,19 @@ qla24xx_async_prli(struct scsi_qla_host *vha, fc_port_t *fcport)struct srb_iocb *lio;int rval =QLA_FUNCTION_FAILED ; -if (!vha->flags.online) +if (!vha->flags.online) { +ql_dbg (ql_dbg_disc, vha,0xffff ,"%s %d %8phC exit\n" , + __func__, __LINE__, fcport->port_name);return rval; + } -if (fcport->fw_login_state ==DSC_LS_PLOGI_PEND || - fcport->fw_login_state ==DSC_LS_PRLI_PEND ) +if ((fcport->fw_login_state ==DSC_LS_PLOGI_PEND || + fcport->fw_login_state ==DSC_LS_PRLI_PEND ) && +qla_dual_mode_enabled (vha)) { +ql_dbg (ql_dbg_disc, vha,0xffff ,"%s %d %8phC exit\n" , + __func__, __LINE__, fcport->port_name);return rval; + } sp =qla2x00_get_sp (vha, fcport,GFP_KERNEL );if (!sp)
@@ -1602,6 +1616,10 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)break ;default :if (fcport->login_pause) { +ql_dbg (ql_dbg_disc, vha,0x20d8 , +"%s %d %8phC exit\n" , + __func__, __LINE__, + fcport->port_name); fcport->last_rscn_gen = fcport->rscn_gen; fcport->last_login_gen = fcport->login_gen;set_bit (RELOGIN_NEEDED , &vha->dpc_flags);
drivers/scsi/qla2xxx/qla_target.c +1 -0
@@ -1257,6 +1257,7 @@ void qlt_schedule_sess_for_deletion(struct fc_port *sess) sess->deleted =QLA_SESS_DELETION_IN_PROGRESS ;spin_unlock_irqrestore (&sess->vha->work_lock, flags); + sess->prli_pend_timer =0 ; sess->disc_state =DSC_DELETE_PEND ;qla24xx_chk_fcp_state (sess);
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 135/309 ASoC: SOF: Introduce state machine for FW boot
In reply to Greg Kroah-HartmanFrom: Ranjani Sridharan <[email protected]>
[ Upstream commit 6ca5cecbd1c1758666ab79446f19e0e61ed11444 ]
Add a state machine for FW boot to track the different stages of FW boot and replace the boot_complete field with fw_state field in struct snd_sof_dev. This will be used to determine the actions to be performed during system suspend.
One of the main motivations for adding this change is the fact that errors during the top-level SOF device probe cannot be propagated and therefore suspending the SOF device normally during system suspend could potentially run into errors. For example, with the current flow, if the FW boot failed for some reason and the system suspends, the SOF device suspend could fail because the CTX_SAVE IPC would be attempted even though the FW never really booted successfully causing it to time out. Another scenario that the state machine fixes is when the runtime suspend for the SOF device fails and the DSP is powered down nevertheless, the CTX_SAVE IPC during system suspend would timeout because the DSP is already powered down.
--- sound/soc/sof/core.c | 50 +++++++++++++++++++++++++++++++- sound/soc/sof/intel/hda-loader.c | 1 - sound/soc/sof/intel/hda.c | 4 +-- sound/soc/sof/ipc.c | 17 ++++------- sound/soc/sof/loader.c | 19 ++++++++---- sound/soc/sof/pm.c | 21 +++++++++++++- sound/soc/sof/sof-priv.h | 11 ++++++- 7 files changed, 99 insertions(+), 24 deletions(-)
sound/soc/sof/core.c +49 -1
@@ -288,6 +288,46 @@ static int sof_machine_check(struct snd_sof_dev *sdev)#endif } +/* +* FW Boot State Transition Diagram +* +* +-----------------------------------------------------------------------+ +* | | +* ------------------ ------------------ | +* | | | | | +* | BOOT_FAILED | | READY_FAILED |-------------------------+ | +* | | | | | | +* ------------------ ------------------ | | +* ^ ^ | | +* | | | | +* (FW Boot Timeout) (FW_READY FAIL) | | +* | | | | +* | | | | +* ------------------ | ------------------ | | +* | | | | | | | +* | IN_PROGRESS |---------------+------------->| COMPLETE | | | +* | | (FW Boot OK) (FW_READY OK) | | | | +* ------------------ ------------------ | | +* ^ | | | +* | | | | +* (FW Loading OK) (System Suspend/Runtime Suspend) +* | | | | +* | | | | +* ------------------ ------------------ | | | +* | | | |<-----+ | | +* | PREPARE | | NOT_STARTED |<---------------------+ | +* | | | |<---------------------------+ +* ------------------ ------------------ +* | ^ | ^ +* | | | | +* | +-----------------------+ | +* | (DSP Probe OK) | +* | | +* | | +* +------------------------------------+ +* (System Suspend/Runtime Suspend) +*/ +static int sof_probe_continue (struct snd_sof_dev *sdev) {struct snd_sof_pdata *plat_data = sdev->pdata;
@@ -303,6 +343,8 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)return ret; } + sdev->fw_state =SOF_FW_BOOT_PREPARE ; +/* check machine info */ ret =sof_machine_check (sdev);if (ret <0 ) {
@@ -342,7 +384,12 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) goto fw_load_err; } -/* boot the firmware */ + sdev->fw_state =SOF_FW_BOOT_IN_PROGRESS ; + +/* +* Boot the firmware. The FW boot status will be modified +* in snd_sof_run_firmware() depending on the outcome. +*/ ret =snd_sof_run_firmware (sdev);if (ret <0 ) { dev_err(sdev->dev, "error: failed to boot DSP firmware %d\n",
@@ -450,6 +497,7 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) sdev->pdata = plat_data; sdev->first_boot = true; + sdev->fw_state =SOF_FW_BOOT_NOT_STARTED ;dev_set_drvdata (dev, sdev);/* check all mandatory ops */
sound/soc/sof/intel/hda-loader.c +0 -1
@@ -278,7 +278,6 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)/* init for booting wait */ init_waitqueue_head (&sdev->boot_wait); - sdev->boot_complete = false;/* prepare DMA for code loader stream */ tag = cl_stream_prepare(sdev, 0x40, stripped_firmware.size,
sound/soc/sof/intel/hda.c +2 -2
@@ -166,7 +166,7 @@ void hda_dsp_dump_skl(struct snd_sof_dev *sdev, u32 flags) panic =snd_sof_dsp_read (sdev,HDA_DSP_BAR ,HDA_ADSP_ERROR_CODE_SKL +0x4 ); -if (sdev->boot_complete) { +if (sdev->fw_state ==SOF_FW_BOOT_COMPLETE ) {hda_dsp_get_registers (sdev, &xoops, &panic_info, stack,HDA_DSP_STACK_DUMP_SIZE ); snd_sof_get_status(sdev, status, panic, &xoops, &panic_info,
@@ -193,7 +193,7 @@ void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags) HDA_DSP_SRAM_REG_FW_STATUS); panic =snd_sof_dsp_read (sdev,HDA_DSP_BAR ,HDA_DSP_SRAM_REG_FW_TRACEP ); -if (sdev->boot_complete) { +if (sdev->fw_state ==SOF_FW_BOOT_COMPLETE ) {hda_dsp_get_registers (sdev, &xoops, &panic_info, stack,HDA_DSP_STACK_DUMP_SIZE ); snd_sof_get_status(sdev, status, panic, &xoops, &panic_info,
sound/soc/sof/ipc.c +5 -12
@@ -348,19 +348,12 @@ void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev)break ;case SOF_IPC_FW_READY :/* check for FW boot completion */ -if (!sdev->boot_complete) { +if (sdev->fw_state ==SOF_FW_BOOT_IN_PROGRESS ) { err =sof_ops (sdev)->fw_ready (sdev, cmd); -if (err <0 ) { -/* -* this indicates a mismatch in ABI -* between the driver and fw -*/ -dev_err (sdev->dev,"error: ABI mismatch %d\n" , - err); - }else { -/* firmware boot completed OK */ - sdev->boot_complete = true; - } +if (err <0 ) + sdev->fw_state =SOF_FW_BOOT_READY_FAILED ; +else + sdev->fw_state =SOF_FW_BOOT_COMPLETE ;/* wake up firmware loader */ wake_up (&sdev->boot_wait);
sound/soc/sof/loader.c +13 -6
@@ -511,7 +511,6 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev)int init_core_mask;init_waitqueue_head (&sdev->boot_wait); - sdev->boot_complete = false;/* create read-only fw_version debugfs to store boot version info */ if (sdev->first_boot) {
@@ -543,19 +542,27 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev) init_core_mask = ret; -/* now wait for the DSP to boot */ - ret =wait_event_timeout (sdev->boot_wait, sdev->boot_complete, +/* +* now wait for the DSP to boot. There are 3 possible outcomes: +* 1. Boot wait times out indicating FW boot failure. +* 2. FW boots successfully and fw_ready op succeeds. +* 3. FW boots but fw_ready op fails. +*/ + ret =wait_event_timeout (sdev->boot_wait, + sdev->fw_state >SOF_FW_BOOT_IN_PROGRESS ,msecs_to_jiffies (sdev->boot_timeout));if (ret ==0 ) {dev_err (sdev->dev,"error: firmware boot failure\n" );snd_sof_dsp_dbg_dump (sdev,SOF_DBG_REGS |SOF_DBG_MBOX |SOF_DBG_TEXT |SOF_DBG_PCI ); -/* after this point FW_READY msg should be ignored */ - sdev->boot_complete = true; + sdev->fw_state =SOF_FW_BOOT_FAILED ;return -EIO ; } -dev_info (sdev->dev,"firmware boot complete\n" ); +if (sdev->fw_state ==SOF_FW_BOOT_COMPLETE ) +dev_info (sdev->dev,"firmware boot complete\n" ); +else +return -EIO ;/* FW boots but fw_ready op failed */ /* perform post fw run operations */ ret =snd_sof_dsp_post_fw_run (sdev);
sound/soc/sof/pm.c +20 -1
@@ -283,6 +283,8 @@ static int sof_resume(struct device *dev, bool runtime_resume)return ret; } + sdev->fw_state =SOF_FW_BOOT_PREPARE ; +/* load the firmware */ ret =snd_sof_load_firmware (sdev);if (ret <0 ) {
@@ -292,7 +294,12 @@ static int sof_resume(struct device *dev, bool runtime_resume)return ret; } -/* boot the firmware */ + sdev->fw_state =SOF_FW_BOOT_IN_PROGRESS ; + +/* +* Boot the firmware. The FW boot status will be modified +* in snd_sof_run_firmware() depending on the outcome. +*/ ret =snd_sof_run_firmware (sdev);if (ret <0 ) { dev_err(sdev->dev,
@@ -338,6 +345,9 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)if (!sof_ops (sdev)->suspend)return 0 ; +if (sdev->fw_state !=SOF_FW_BOOT_COMPLETE ) + goto power_down; +/* release trace */ snd_sof_release_trace (sdev);
@@ -375,6 +385,12 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) ret); } +power_down: + +/* return if the DSP was not probed successfully */ +if (sdev->fw_state ==SOF_FW_BOOT_NOT_STARTED ) +return 0 ; +/* power down all DSP cores */ if (runtime_suspend) ret =snd_sof_dsp_runtime_suspend (sdev);
@@ -385,6 +401,9 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)"error: failed to power down DSP during suspend %d\n" , ret); +/* reset FW state */ + sdev->fw_state =SOF_FW_BOOT_NOT_STARTED ; +return ret; }
sound/soc/sof/sof-priv.h +10 -1
@@ -356,6 +356,15 @@ struct snd_sof_dai {struct list_head list;/* list in sdev dai list */ }; +enum snd_sof_fw_state { +SOF_FW_BOOT_NOT_STARTED =0 , +SOF_FW_BOOT_PREPARE , +SOF_FW_BOOT_IN_PROGRESS , +SOF_FW_BOOT_FAILED , +SOF_FW_BOOT_READY_FAILED ,/* firmware booted but fw_ready op failed */ +SOF_FW_BOOT_COMPLETE , +}; +/* * SOF Device Level. */
@@ -372,7 +381,7 @@ struct snd_sof_dev {/* DSP firmware boot */ wait_queue_head_t boot_wait; -u32 boot_complete; +enum snd_sof_fw_state fw_state;u32 first_boot;/* work queue in case the probe is implemented in two steps */
Signature · 1 line
2.20.1