5.15.7-rc1 review
Subsystems (2)
Greg Kroah-Hartman
maintainercover 5.15.7-rc1 review
This is the start of the stable review cycle for the 5.15.7 release. There are 207 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, 08 Dec 2021 14:55:37 +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.15.7-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.15.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 5.15.7-rc1
Wei Yongjun <[email protected]>
ipmi: msghandler: Make symbol 'remove_work_wq' static
Johan Hovold <[email protected]>
serial: liteuart: fix minor-number leak on probe errors
Johan Hovold <[email protected]>
serial: liteuart: fix use-after-free and memleak on unbind
Ilia Sergachev <[email protected]>
serial: liteuart: Fix NULL pointer dereference in ->remove()
Lukas Wunner <[email protected]>
serial: 8250: Fix RTS modem control while in rs485 mode
Jay Dolan <[email protected]>
serial: 8250_pci: rewrite pericom_do_set_divisor()
Jay Dolan <[email protected]>
serial: 8250_pci: Fix ACCES entries in pci_serial_quirks array
Johan Hovold <[email protected]>
serial: core: fix transmit-buffer reset and memleak
Patrik John <[email protected]>
serial: tegra: Change lower tolerance baud rate limit for tegra20 and tegra30
Pierre Gondois <[email protected]>
serial: pl011: Add ACPI SBSA UART match id
Sven Eckelmann <[email protected]>
tty: serial: msm_serial: Deactivate RX DMA for polling support
Joerg Roedel <[email protected]>
x86/64/mm: Map all kernel memory into trampoline_pgd
Feng Tang <[email protected]>
x86/tsc: Disable clocksource watchdog for TSC on qualified platorms
Feng Tang <[email protected]>
x86/tsc: Add a timer to make sure TSC_adjust is always checked
Zhou Qingyang <[email protected]>
usb: cdnsp: Fix a NULL pointer dereference in cdnsp_endpoint_init()
Frank Li <[email protected]>
usb: cdns3: gadget: fix new urb never complete if ep cancel previous requests
Badhri Jagan Sridharan <[email protected]>
usb: typec: tcpm: Wait in SNK_DEBOUNCED until disconnect
Ole Ernst <[email protected]>
USB: NO_LPM quirk Lenovo Powered USB-C Travel Hub
Mathias Nyman <[email protected]>
xhci: Fix commad ring abort, write all 64 bits to CRCR register.
Maciej W. Rozycki <[email protected]>
vgacon: Propagate console boot parameters before calling `vc_resize'
Helge Deller <[email protected]>
parisc: Mark cr16 CPU clocksource unstable on all SMP machines
Helge Deller <[email protected]>
parisc: Fix "make install" on newer debian releases
Helge Deller <[email protected]>
parisc: Fix KBUILD_IMAGE for self-extracting kernel
Al Cooper <[email protected]>
serial: 8250_bcm7271: UART errors after resuming from S2
Tariq Toukan <[email protected]>
net/mlx5e: Sync TIR params updates against concurrent create/modify
Khalid Manaa <[email protected]>
net/mlx5e: Rename TIR lro functions to TIR packet merge functions
Ben Ben-Ishay <[email protected]>
net/mlx5e: Rename lro_timeout to packet_merge_timeout
Sean Christopherson <[email protected]>
KVM: x86/mmu: Remove spurious TLB flushes in TDP MMU zap collapsible path
David Matlack <[email protected]>
KVM: x86/mmu: Rename slot_handle_leaf to slot_handle_level_4k
Sean Christopherson <[email protected]>
KVM: SEV: Return appropriate error codes if SEV-ES scratch setup fails
Qais Yousef <[email protected]>
sched/uclamp: Fix rq->uclamp_max not set on first enqueue
Andrew Halaney <[email protected]>
preempt/dynamic: Fix setup_preempt_mode() return value
Lai Jiangshan <[email protected]>
x86/xen: Add xenpv_restore_regs_and_return_to_usermode()
Lai Jiangshan <[email protected]>
x86/entry: Use the correct fence macro after swapgs in kernel CR3
Lai Jiangshan <[email protected]>
x86/entry: Add a fence for kernel entry SWAPGS in paranoid_entry()
Michael Sterritt <[email protected]>
x86/sev: Fix SEV-ES INS/OUTS instructions for word, dword, and qword
Jens Axboe <[email protected]>
io-wq: don't retry task_work creation failure on fatal conditions
José Roberto de Souza <[email protected]>
Revert "drm/i915: Implement Wa_1508744258"
Matt Johnston <[email protected]>
mctp: Don't let RTM_DELROUTE delete local routes
Dan Carpenter <[email protected]>
KVM: VMX: Set failure code in prepare_vmcs02()
Like Xu <[email protected]>
KVM: x86/pmu: Fix reserved bits for AMD PerfEvtSeln register
Dmytro Linkin <[email protected]>
net/mlx5: E-Switch, Check group pointer before reading bw_share value
Mark Bloch <[email protected]>
net/mlx5: E-Switch, fix single FDB creation on BlueField
Dmytro Linkin <[email protected]>
net/mlx5: E-switch, Respect BW share of the new group
Moshe Shemesh <[email protected]>
net/mlx5: Move MODIFY_RQT command to ignore list in internal error state
Raed Salem <[email protected]>
net/mlx5e: Fix missing IPsec statistics on uplink representor
Paolo Bonzini <[email protected]>
KVM: SEV: initialize regions_list of a mirror VM
Lai Jiangshan <[email protected]>
KVM: X86: Fix when shadow_root_level=5 && guest root_level<4
Christophe JAILLET <[email protected]>
iwlwifi: Fix memory leaks in error handling path
Nicolas Frattaroli <[email protected]>
ASoC: rk817: Add module alias for rk817-codec
Rob Clark <[email protected]>
drm/msm: Restore error return on invalid fence
Rob Clark <[email protected]>
drm/msm: Fix wait_fence submitqueue leak
Douglas Anderson <[email protected]>
drm/msm: Fix mmap to include VM_IO and VM_DONTDUMP
Rob Clark <[email protected]>
drm/msm/devfreq: Fix OPP refcnt leak
Hou Wenlong <[email protected]>
KVM: x86/mmu: Pass parameter flush as false in kvm_tdp_mmu_zap_collapsible_sptes()
Hou Wenlong <[email protected]>
KVM: x86/mmu: Skip tlb flush if it has been done in zap_gfn_range()
Sameer Saurabh <[email protected]>
atlantic: Remove warn trace message.
Dmitry Bogdanov <[email protected]>
atlantic: Fix statistics logic for production hardware
Sameer Saurabh <[email protected]>
Remove Half duplex mode speed capabilities.
Nikita Danilov <[email protected]>
atlantic: Add missing DIDs and fix 115c.
Sameer Saurabh <[email protected]>
atlantic: Fix to display FW bundle version instead of FW mac version.
Nikita Danilov <[email protected]>
atlatnic: enable Nbase-t speeds with base-t
Dmitry Bogdanov <[email protected]>
atlantic: Increase delay for fw transactions
Maxime Ripard <[email protected]>
drm/vc4: kms: Fix previous HVS commit wait
Maxime Ripard <[email protected]>
drm/vc4: kms: Don't duplicate pending commit
Maxime Ripard <[email protected]>
drm/vc4: kms: Clear the HVS FIFO commit pointer once done
Maxime Ripard <[email protected]>
drm/vc4: kms: Add missing drm_crtc_commit_put
Maxime Ripard <[email protected]>
drm/vc4: kms: Fix return code check
Maxime Ripard <[email protected]>
drm/vc4: kms: Wait for the commit before increasing our clock rate
Rob Clark <[email protected]>
drm/msm: Do hw_init() before capturing GPU state
Douglas Anderson <[email protected]>
drm/msm/a6xx: Allocate enough space for GMU registers
Tony Lu <[email protected]>
net/smc: Keep smc_close_final rc during active close
William Kucharski <[email protected]>
net/rds: correct socket tunable error in rds_tcp_tune()
Dust Li <[email protected]>
net/smc: fix wrong list_del in smc_lgr_cleanup_early
Eric Dumazet <[email protected]>
ipv4: convert fib_num_tclassid_users to atomic_t
Eric Dumazet <[email protected]>
net: annotate data-races on txq->xmit_lock_owner
Zhou Qingyang <[email protected]>
octeontx2-af: Fix a memleak bug in rvu_mbox_init()
Dongliang Mu <[email protected]>
dpaa2-eth: destroy workqueue at the end of remove function
Christophe JAILLET <[email protected]>
net: marvell: mvpp2: Fix the computation of shared CPUs
Sven Schuchmann <[email protected]>
net: usb: lan78xx: lan78xx_phy_init(): use PHY_POLL instead of "0" if no IRQ is available
Vincent Whitchurch <[email protected]>
net: stmmac: Avoid DMA_CHAN_CONTROL write if no Split Header support
Pierre-Louis Bossart <[email protected]>
ALSA: intel-dsp-config: add quirk for CML devices based on ES8336 codec
Eiichi Tsukata <[email protected]>
rxrpc: Fix rxrpc_local leak in rxrpc_lookup_peer()
Eiichi Tsukata <[email protected]>
rxrpc: Fix rxrpc_peer leak in rxrpc_look_up_bundle()
Sameer Pujar <[email protected]>
ASoC: tegra: Fix kcontrol put callback in AHUB
Sameer Pujar <[email protected]>
ASoC: tegra: Fix kcontrol put callback in DSPK
Sameer Pujar <[email protected]>
ASoC: tegra: Fix kcontrol put callback in DMIC
Sameer Pujar <[email protected]>
ASoC: tegra: Fix kcontrol put callback in I2S
Sameer Pujar <[email protected]>
ASoC: tegra: Fix kcontrol put callback in ADMAIF
Sameer Pujar <[email protected]>
ASoC: tegra: Fix wrong value type in DSPK
Sameer Pujar <[email protected]>
ASoC: tegra: Fix wrong value type in DMIC
Sameer Pujar <[email protected]>
ASoC: tegra: Fix wrong value type in I2S
Sameer Pujar <[email protected]>
ASoC: tegra: Fix wrong value type in ADMAIF
Lorenzo Bianconi <[email protected]>
mt76: mt7915: fix NULL pointer dereference in mt7915_get_phy_mode
Florian Fainelli <[email protected]>
net: dsa: b53: Add SPI ID table
Li Zhijian <[email protected]>
selftests: net: Correct case name
Zhou Qingyang <[email protected]>
net/mlx4_en: Fix an use-after-free bug in mlx4_en_try_alloc_resources()
Raed Salem <[email protected]>
net/mlx5e: IPsec: Fix Software parser inner l3 type setting in case of encapsulation
Łukasz Bartosik <[email protected]>
iwlwifi: fix warnings produced by kernel debug options
Mark Rutland <[email protected]>
arm64: ftrace: add missing BTIs
Arnd Bergmann <[email protected]>
siphash: use _unaligned version by default
Benjamin Poirier <[email protected]>
net: mpls: Fix notifications when deleting a device
Zhou Qingyang <[email protected]>
net: qlogic: qlcnic: Fix a NULL pointer dereference in qlcnic_83xx_add_rings()
Paolo Abeni <[email protected]>
tcp: fix page frag corruption on page fault
Randy Dunlap <[email protected]>
natsemi: xtensa: fix section mismatch warnings
Aaro Koskinen <[email protected]>
i2c: cbus-gpio: set atomic transfer callback
Alain Volmat <[email protected]>
i2c: stm32f7: stop dma transfer in case of NACK
Alain Volmat <[email protected]>
i2c: stm32f7: recover the bus on access timeout
Alain Volmat <[email protected]>
i2c: stm32f7: flush TX FIFO upon transfer errors
Gustavo A. R. Silva <[email protected]>
wireguard: ratelimiter: use kvcalloc() instead of kvzalloc()
Jason A. Donenfeld <[email protected]>
wireguard: receive: drop handshakes if queue lock is contended
Jason A. Donenfeld <[email protected]>
wireguard: receive: use ring buffer for incoming handshakes
Jason A. Donenfeld <[email protected]>
wireguard: device: reset peer src endpoint when netns exits
Li Zhijian <[email protected]>
wireguard: selftests: rename DEBUG_PI_LIST to DEBUG_PLIST
Jason A. Donenfeld <[email protected]>
wireguard: selftests: actually test for routing loops
Jason A. Donenfeld <[email protected]>
wireguard: allowedips: add missing __rcu annotation to satisfy sparse
Jason A. Donenfeld <[email protected]>
wireguard: selftests: increase default dmesg log size
Marek Behún <[email protected]>
net: dsa: mv88e6xxx: Link in pcs_get_state() if AN is bypassed
Marek Behún <[email protected]>
net: dsa: mv88e6xxx: Fix inband AN for 2500base-x on 88E6393X family
Marek Behún <[email protected]>
net: dsa: mv88e6xxx: Add fix for erratum 5.2 of 88E6393X family
Marek Behún <[email protected]>
net: dsa: mv88e6xxx: Save power by disabling SerDes trasmitter and receiver
Marek Behún <[email protected]>
net: dsa: mv88e6xxx: Drop unnecessary check in mv88e6393x_serdes_erratum_4_6()
Marek Behún <[email protected]>
net: dsa: mv88e6xxx: Fix application of erratum 4.8 for 88E6393X
Steven Rostedt (VMware) <[email protected]>
tracing/histograms: String compares should not care about signed values
Paolo Bonzini <[email protected]>
KVM: x86: check PIR even for vCPUs with disabled APICv
Lai Jiangshan <[email protected]>
KVM: X86: Use vcpu->arch.walk_mmu for kvm_mmu_invlpg()
Catalin Marinas <[email protected]>
KVM: arm64: Avoid setting the upper 32 bits of TCR_EL2 and CPTR_EL2 to 1
Paolo Bonzini <[email protected]>
KVM: MMU: shadow nested paging does not have PKU
Paolo Bonzini <[email protected]>
KVM: x86: Use a stable condition around all VT-d PI paths
Paolo Bonzini <[email protected]>
KVM: VMX: prepare sync_pir_to_irr for running with APICv disabled
Sean Christopherson <[email protected]>
KVM: nVMX: Abide to KVM_REQ_TLB_FLUSH_GUEST request on nested vmentry/vmexit
Sean Christopherson <[email protected]>
KVM: nVMX: Flush current VPID (L1 vs. L2) for KVM_REQ_TLB_FLUSH_GUEST
Sean Christopherson <[email protected]>
KVM: nVMX: Emulate guest TLB flush on nested VM-Enter with new vpid12
Paolo Bonzini <[email protected]>
KVM: x86: ignore APICv if LAPIC is not enabled
Sean Christopherson <[email protected]>
KVM: Ensure local memslot copies operate on up-to-date arch-specific data
Ben Gardon <[email protected]>
KVM: x86/mmu: Fix TLB flush range when handling disconnected pt
Sean Christopherson <[email protected]>
KVM: Disallow user memslot with size that exceeds "unsigned long"
Paolo Bonzini <[email protected]>
KVM: fix avic_set_running for preemptable kernels
Lyude Paul <[email protected]>
drm/i915/dp: Perform 30ms delay after source OUI write
Nicholas Kazlauskas <[email protected]>
drm/amd/display: Allow DSC on supported MST branch devices
msizanoen1 <[email protected]>
ipv6: fix memory leak in fib6_rule_suppress
Adrian Hunter <[email protected]>
scsi: ufs: ufs-pci: Add support for Intel ADL
James Smart <[email protected]>
scsi: lpfc: Fix non-recovery of remote ports following an unsolicited LOGO
Baokun Li <[email protected]>
sata_fsl: fix warning in remove_proc_entry when rmmod sata_fsl
Baokun Li <[email protected]>
sata_fsl: fix UAF in sata_fsl_port_stop when rmmod sata_fsl
Linus Torvalds <[email protected]>
fget: check that the fd still exists after getting a ref to it
Niklas Schnelle <[email protected]>
s390/pci: move pseudo-MMIO to prevent MIO overlap
Guangming <[email protected]>
dma-buf: system_heap: Use 'for_each_sgtable_sg' in pages free flow
Mordechay Goodstein <[email protected]>
iwlwifi: mvm: retry init flow if failed
Xiongfeng Wang <[email protected]>
cpufreq: Fix get_cpu_device() failure in add_cpu_dev_symlink()
Ioanna Alifieraki <[email protected]>
ipmi: Move remove_work to dedicated workqueue
Stanislaw Gruszka <[email protected]>
rt2x00: do not mark device gone on EPROTO errors during start
Stefan Binding <[email protected]>
ALSA: hda/cs8409: Set PMSG_ON earlier inside cs8409 driver
Masami Hiramatsu <[email protected]>
kprobes: Limit max data_size of the kretprobe instances
Stephen Suryaputra <[email protected]>
vrf: Reset IPCB/IP6CB when processing outbound pkts in vrf dev xmit
Tianjia Zhang <[email protected]>
net/tls: Fix authentication failure in CCM mode
Mario Limonciello <[email protected]>
ACPI: Add stubs for wakeup handler functions
Wen Gu <[email protected]>
net/smc: Avoid warning of possible recursive locking
Nikita Yushchenko <[email protected]>
tracing: Don't use out-of-sync va_list in event printing
Ian Rogers <[email protected]>
perf report: Fix memory leaks around perf_tip()
Ian Rogers <[email protected]>
perf hist: Fix memory leak of a perf_hpp_fmt
German Gomez <[email protected]>
perf inject: Fix ARM SPE handling
Namhyung Kim <[email protected]>
perf sort: Fix the 'p_stage_cyc' sort key behavior
Namhyung Kim <[email protected]>
perf sort: Fix the 'ins_lat' sort key behavior
Namhyung Kim <[email protected]>
perf sort: Fix the 'weight' sort key behavior
Teng Qi <[email protected]>
net: ethernet: dec: tulip: de4x5: fix possible array overflows in type3_infoblock()
zhangyue <[email protected]>
net: tulip: de4x5: fix the problem that the array 'lp->phy[8]' may be out of bound
Jordy Zomer <[email protected]>
ipv6: check return value of ipv6_skip_exthdr
Teng Qi <[email protected]>
ethernet: hisilicon: hns: hns_dsaf_misc: fix a possible array overflow in hns_dsaf_ge_srst_by_port()
Mario Limonciello <[email protected]>
ata: libahci: Adjust behavior when StorageD3Enable _DSD is set
Mario Limonciello <[email protected]>
ata: ahci: Add Green Sardine vendor ID as board_ahci_mobile
Bernard Zhao <[email protected]>
drm/amd/amdgpu: fix potential memleak
shaoyunl <[email protected]>
drm/amd/amdkfd: Fix kernel panic when reset failed and been triggered again
Lijo Lazar <[email protected]>
drm/amd/pm: Remove artificial freq level on Navi1x
Aaron Ma <[email protected]>
net: usb: r8152: Add MAC passthrough support for more Lenovo Docks
Mike Christie <[email protected]>
scsi: iscsi: Unblock session then wake up error handler
Manaf Meethalavalappu Pallikunhi <[email protected]>
thermal: core: Reset previous low and high trip during thermal zone init
Wang Yugui <[email protected]>
btrfs: check-integrity: fix a warning on write caching disabled disk
Filipe Manana <[email protected]>
btrfs: silence lockdep when reading chunk tree during mount
Vasily Gorbik <[email protected]>
s390/setup: avoid using memblock_enforce_memory_limit
Slark Xiao <[email protected]>
platform/x86: thinkpad_acpi: Fix WWAN device disabled issue after S3 deep
Jimmy Wang <[email protected]>
platform/x86: thinkpad_acpi: Add support for dual fan control
Thomas Weißschuh <[email protected]>
platform/x86: dell-wmi-descriptor: disable by default
Julian Braha <[email protected]>
pinctrl: qcom: fix unmet dependencies on GPIOLIB for GPIOLIB_IRQCHIP
liuguoqiang <[email protected]>
net: return correct error code
Zekun Shen <[email protected]>
atlantic: Fix OOB read and write in hw_atl_utils_fw_rpc_wait
Wen Gu <[email protected]>
net/smc: Transfer remaining wait queue entries during fallback
Sean Christopherson <[email protected]>
x86/hyperv: Move required MSRs check to initial platform probing
Felix Fietkau <[email protected]>
mac80211: fix throughput LED trigger
Xing Song <[email protected]>
mac80211: do not access the IV when it was stripped
Julian Braha <[email protected]>
drm/sun4i: fix unmet dependency on RESET_CONTROLLER for PHY_SUN6I_MIPI_DPHY
Alexey Kardashevskiy <[email protected]>
powerpc/pseries/ddw: Do not try direct mapping with persistent memory and one window
Alexey Kardashevskiy <[email protected]>
powerpc/pseries/ddw: Revert "Extend upper limit for huge DMA window for persistent memory"
Andreas Gruenbacher <[email protected]>
gfs2: Fix length of holes reported at end-of-file
Bob Peterson <[email protected]>
gfs2: release iopen glock early in evict
Takashi Iwai <[email protected]>
ALSA: usb-audio: Don't start stream for capture at prepare
Takashi Iwai <[email protected]>
ALSA: usb-audio: Switch back to non-latency mode at a later point
Takashi Iwai <[email protected]>
ALSA: usb-audio: Less restriction for low-latency playback mode
Takashi Iwai <[email protected]>
ALSA: usb-audio: Fix packet size calculation regression
Takashi Iwai <[email protected]>
ALSA: usb-audio: Avoid killing in-flight URBs during draining
Takashi Iwai <[email protected]>
ALSA: usb-audio: Improved lowlatency playback support
Takashi Iwai <[email protected]>
ALSA: usb-audio: Add spinlock to stop_urbs()
Takashi Iwai <[email protected]>
ALSA: usb-audio: Check available frames for the next packet size
Takashi Iwai <[email protected]>
ALSA: usb-audio: Disable low-latency mode for implicit feedback sync
Takashi Iwai <[email protected]>
ALSA: usb-audio: Disable low-latency playback for free-wheel mode
Takashi Iwai <[email protected]>
ALSA: usb-audio: Rename early_playback_start flag with lowlatency_playback
Takashi Iwai <[email protected]>
ALSA: usb-audio: Restrict rates for the shared clocks
-------------
Diffstat:
Makefile | 4 +- arch/arm64/include/asm/kvm_arm.h | 4 +- arch/arm64/kernel/entry-ftrace.S | 6 + arch/parisc/Makefile | 5 + arch/parisc/install.sh | 1 + arch/parisc/kernel/time.c | 30 +-- arch/powerpc/platforms/pseries/iommu.c | 15 +- arch/s390/include/asm/pci_io.h | 7 +- arch/s390/kernel/setup.c | 3 - arch/x86/entry/entry_64.S | 35 ++- arch/x86/hyperv/hv_init.c | 9 +- arch/x86/kernel/cpu/mshyperv.c | 20 +- arch/x86/kernel/sev.c | 57 ++-- arch/x86/kernel/tsc.c | 28 +- arch/x86/kernel/tsc_sync.c | 41 +++ arch/x86/kvm/lapic.c | 2 +- arch/x86/kvm/mmu/mmu.c | 37 +-- arch/x86/kvm/mmu/tdp_mmu.c | 36 +-- arch/x86/kvm/mmu/tdp_mmu.h | 5 +- arch/x86/kvm/svm/avic.c | 16 +- arch/x86/kvm/svm/pmu.c | 2 +- arch/x86/kvm/svm/sev.c | 31 ++- arch/x86/kvm/svm/svm.c | 1 - arch/x86/kvm/vmx/nested.c | 49 ++-- arch/x86/kvm/vmx/posted_intr.c | 20 +- arch/x86/kvm/vmx/vmx.c | 62 +++-- arch/x86/kvm/x86.c | 46 +++- arch/x86/kvm/x86.h | 7 +- arch/x86/realmode/init.c | 12 +- arch/x86/xen/xen-asm.S | 20 ++ drivers/ata/ahci.c | 1 + drivers/ata/libahci.c | 15 ++ drivers/ata/sata_fsl.c | 20 +- drivers/char/ipmi/ipmi_msghandler.c | 13 +- drivers/cpufreq/cpufreq.c | 9 +- drivers/dma-buf/heaps/system_heap.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 1 + .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 5 + .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 20 +- drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 13 +- drivers/gpu/drm/i915/display/intel_display_types.h | 3 + drivers/gpu/drm/i915/display/intel_dp.c | 11 + drivers/gpu/drm/i915/display/intel_dp.h | 2 + .../gpu/drm/i915/display/intel_dp_aux_backlight.c | 5 + drivers/gpu/drm/i915/gt/intel_workarounds.c | 7 - drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 4 +- drivers/gpu/drm/msm/msm_debugfs.c | 1 + drivers/gpu/drm/msm/msm_drv.c | 49 ++-- drivers/gpu/drm/msm/msm_gem.c | 3 +- drivers/gpu/drm/msm/msm_gem_submit.c | 1 + drivers/gpu/drm/msm/msm_gpu.h | 3 + drivers/gpu/drm/msm/msm_gpu_devfreq.c | 5 + drivers/gpu/drm/sun4i/Kconfig | 1 + drivers/gpu/drm/vc4/vc4_kms.c | 40 ++- drivers/i2c/busses/i2c-cbus-gpio.c | 5 +- drivers/i2c/busses/i2c-stm32f7.c | 31 ++- drivers/net/dsa/b53/b53_spi.c | 14 + drivers/net/dsa/mv88e6xxx/serdes.c | 252 +++++++++++++++--- drivers/net/dsa/mv88e6xxx/serdes.h | 4 + drivers/net/ethernet/aquantia/atlantic/aq_common.h | 27 +- drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 2 + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 10 +- .../net/ethernet/aquantia/atlantic/aq_pci_func.c | 7 +- drivers/net/ethernet/aquantia/atlantic/aq_vec.c | 3 - .../aquantia/atlantic/hw_atl/hw_atl_utils.c | 25 +- .../aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 3 - .../ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c | 22 +- .../ethernet/aquantia/atlantic/hw_atl2/hw_atl2.h | 2 + .../aquantia/atlantic/hw_atl2/hw_atl2_utils.h | 38 ++- .../aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c | 110 ++++++-- drivers/net/ethernet/dec/tulip/de4x5.c | 34 ++- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 2 + drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c | 4 + drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 2 +- drivers/net/ethernet/marvell/octeontx2/af/rvu.c | 2 +- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 9 +- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en.h | 14 +- .../net/ethernet/mellanox/mlx5/core/en/params.c | 21 +- .../net/ethernet/mellanox/mlx5/core/en/params.h | 6 - drivers/net/ethernet/mellanox/mlx5/core/en/rss.c | 23 +- drivers/net/ethernet/mellanox/mlx5/core/en/rss.h | 7 +- .../net/ethernet/mellanox/mlx5/core/en/rx_res.c | 66 ++++- .../net/ethernet/mellanox/mlx5/core/en/rx_res.h | 11 +- drivers/net/ethernet/mellanox/mlx5/core/en/tir.c | 16 +- drivers/net/ethernet/mellanox/mlx5/core/en/tir.h | 6 +- .../mellanox/mlx5/core/en_accel/ipsec_rxtx.c | 2 +- .../ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c | 24 +- .../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 4 +- .../ethernet/mellanox/mlx5/core/en_fs_ethtool.c | 6 +- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 46 ++-- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 9 +- drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c | 4 +- .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 1 + .../net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c | 7 +- drivers/net/ethernet/natsemi/xtsonic.c | 2 +- .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 10 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 11 +- drivers/net/usb/lan78xx.c | 2 +- drivers/net/usb/r8152.c | 9 +- drivers/net/vrf.c | 2 + drivers/net/wireguard/allowedips.c | 2 +- drivers/net/wireguard/device.c | 39 +-- drivers/net/wireguard/device.h | 9 +- drivers/net/wireguard/queueing.c | 6 +- drivers/net/wireguard/queueing.h | 2 +- drivers/net/wireguard/ratelimiter.c | 4 +- drivers/net/wireguard/receive.c | 39 +-- drivers/net/wireguard/socket.c | 2 +- drivers/net/wireless/intel/iwlwifi/fw/uefi.c | 6 + drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 22 +- drivers/net/wireless/intel/iwlwifi/iwl-drv.h | 3 + drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 24 +- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 3 + drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 5 + drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 4 +- drivers/net/wireless/ralink/rt2x00/rt2x00usb.c | 3 + drivers/pinctrl/qcom/Kconfig | 2 + drivers/platform/x86/dell/Kconfig | 2 +- drivers/platform/x86/thinkpad_acpi.c | 13 +- drivers/scsi/lpfc/lpfc_els.c | 9 +- drivers/scsi/scsi_transport_iscsi.c | 6 +- drivers/scsi/ufs/ufshcd-pci.c | 18 ++ drivers/thermal/thermal_core.c | 2 + drivers/tty/serial/8250/8250_bcm7271.c | 13 + drivers/tty/serial/8250/8250_pci.c | 39 ++- drivers/tty/serial/8250/8250_port.c | 7 - drivers/tty/serial/amba-pl011.c | 1 + drivers/tty/serial/liteuart.c | 20 +- drivers/tty/serial/msm_serial.c | 3 + drivers/tty/serial/serial-tegra.c | 4 +- drivers/tty/serial/serial_core.c | 18 +- drivers/usb/cdns3/cdns3-gadget.c | 20 +- drivers/usb/cdns3/cdnsp-mem.c | 3 + drivers/usb/core/quirks.c | 3 + drivers/usb/host/xhci-ring.c | 21 +- drivers/usb/typec/tcpm/tcpm.c | 4 - drivers/video/console/vgacon.c | 14 +- fs/btrfs/disk-io.c | 14 +- fs/btrfs/volumes.c | 18 +- fs/file.c | 4 + fs/gfs2/bmap.c | 2 +- fs/gfs2/super.c | 14 +- fs/io-wq.c | 7 + include/linux/acpi.h | 9 + include/linux/kprobes.h | 2 + include/linux/mlx5/mlx5_ifc.h | 8 +- include/linux/netdevice.h | 19 +- include/linux/siphash.h | 14 +- include/net/dst_cache.h | 11 + include/net/fib_rules.h | 4 +- include/net/ip_fib.h | 2 +- include/net/netns/ipv4.h | 2 +- include/net/sock.h | 13 +- kernel/kprobes.c | 3 + kernel/sched/core.c | 6 +- kernel/trace/trace.c | 12 + kernel/trace/trace_events_hist.c | 2 +- lib/siphash.c | 12 +- net/core/dev.c | 5 +- net/core/dst_cache.c | 19 ++ net/core/fib_rules.c | 2 +- net/ipv4/devinet.c | 2 +- net/ipv4/fib_frontend.c | 2 +- net/ipv4/fib_rules.c | 5 +- net/ipv4/fib_semantics.c | 4 +- net/ipv6/esp6.c | 6 + net/ipv6/fib6_rules.c | 4 +- net/mac80211/led.h | 8 +- net/mac80211/rx.c | 10 +- net/mac80211/tx.c | 34 ++- net/mctp/route.c | 9 +- net/mpls/af_mpls.c | 68 +++-- net/rds/tcp.c | 2 +- net/rxrpc/conn_client.c | 14 +- net/rxrpc/peer_object.c | 14 +- net/smc/af_smc.c | 14 + net/smc/smc_close.c | 8 +- net/smc/smc_core.c | 7 +- net/tls/tls_sw.c | 4 +- sound/hda/intel-dsp-config.c | 10 + sound/pci/hda/hda_local.h | 9 + sound/pci/hda/patch_cs8409.c | 5 + sound/soc/codecs/rk817_codec.c | 1 + sound/soc/tegra/tegra186_dspk.c | 181 ++++++++++--- sound/soc/tegra/tegra210_admaif.c | 140 +++++++--- sound/soc/tegra/tegra210_ahub.c | 11 +- sound/soc/tegra/tegra210_dmic.c | 184 ++++++++++--- sound/soc/tegra/tegra210_i2s.c | 296 ++++++++++++++++----- sound/usb/card.h | 10 +- sound/usb/endpoint.c | 223 +++++++++++----- sound/usb/endpoint.h | 13 +- sound/usb/pcm.c | 165 +++++++++--- tools/perf/builtin-report.c | 15 +- tools/perf/ui/hist.c | 28 +- tools/perf/util/arm-spe.c | 15 ++ tools/perf/util/hist.c | 23 +- tools/perf/util/hist.h | 1 - tools/perf/util/sort.c | 52 ++-- tools/perf/util/sort.h | 6 +- tools/perf/util/util.c | 14 +- tools/perf/util/util.h | 2 +- tools/testing/selftests/net/fcnal-test.sh | 4 +- tools/testing/selftests/wireguard/netns.sh | 30 ++- .../testing/selftests/wireguard/qemu/debug.config | 2 +- .../testing/selftests/wireguard/qemu/kernel.config | 1 + virt/kvm/kvm_main.c | 50 ++-- 207 files changed, 2854 insertions(+), 1215 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/207 ALSA: usb-audio: Restrict rates for the shared clocks
From: Takashi Iwai <[email protected]>
commit 4e7cf1fbb34ecb472c073980458cbe413afd4d64 upstream.
When a single clock source is shared among several endpoints, we have to keep the same rate on all active endpoints as long as the clock is being used. For dealing with such a case, this patch adds one more check in the hw params constraint for the rate to take the shared clocks into account. The current rate is evaluated from the endpoint list that applies the same clock source.
--- sound/usb/card.h | 1 + sound/usb/endpoint.c | 21 +++++++++++++++++++++ sound/usb/endpoint.h | 1 + sound/usb/pcm.c | 9 +++++++++ 4 files changed, 32 insertions(+)
sound/usb/card.h +1 -0
@@ -137,6 +137,7 @@ struct snd_usb_endpoint {unsigned int cur_period_frames;unsigned int cur_period_bytes;unsigned int cur_buffer_periods; +unsigned char cur_clock;spinlock_t lock;struct list_head list;
sound/usb/endpoint.c +21 -0
@@ -726,6 +726,7 @@ snd_usb_endpoint_open(struct snd_usb_aud ep->cur_period_frames =params_period_size (params); ep->cur_period_bytes = ep->cur_period_frames * ep->cur_frame_bytes; ep->cur_buffer_periods =params_periods (params); + ep->cur_clock = fp->clock;if (ep->type ==SND_USB_ENDPOINT_TYPE_SYNC )endpoint_set_syncinterval (chip, ep);
@@ -837,6 +838,7 @@ void snd_usb_endpoint_close(struct snd_u ep->altsetting =0 ; ep->cur_audiofmt =NULL ; ep->cur_rate =0 ; + ep->cur_clock =0 ; ep->iface_ref =NULL ;usb_audio_dbg (chip,"EP 0x%x closed\n" , ep->ep_num); }
@@ -1344,6 +1346,25 @@ unlock:return err; } +/* get the current rate set to the given clock by any endpoint */ +int snd_usb_endpoint_get_clock_rate (struct snd_usb_audio *chip,int clock) +{ +struct snd_usb_endpoint *ep; +int rate =0 ; + +if (!clock) +return 0 ; +mutex_lock (&chip->mutex); +list_for_each_entry (ep, &chip->ep_list, list) { +if (ep->cur_clock == clock && ep->cur_rate) { + rate = ep->cur_rate; +break ; + } + } +mutex_unlock (&chip->mutex); +return rate; +} +/** * snd_usb_endpoint_start: start an snd_usb_endpoint *
sound/usb/endpoint.h +1 -0
@@ -19,6 +19,7 @@ void snd_usb_endpoint_close(struct snd_u struct snd_usb_endpoint *ep);int snd_usb_endpoint_configure (struct snd_usb_audio *chip,struct snd_usb_endpoint *ep); +int snd_usb_endpoint_get_clock_rate (struct snd_usb_audio *chip,int clock); bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip, struct snd_usb_endpoint *ep,
sound/usb/pcm.c +9 -0
@@ -734,6 +734,7 @@ static int hw_rule_rate(struct snd_pcm_h struct snd_pcm_hw_rule *rule) {struct snd_usb_substream *subs = rule->private; +struct snd_usb_audio *chip = subs->stream->chip;const struct audioformat *fp;struct snd_interval *it =hw_param_interval (params,SNDRV_PCM_HW_PARAM_RATE );unsigned int rmin, rmax, r;
@@ -745,6 +746,14 @@ static int hw_rule_rate(struct snd_pcm_hlist_for_each_entry (fp, &subs->fmt_list, list) {if (!hw_check_valid_format (subs, params, fp))continue ; + r =snd_usb_endpoint_get_clock_rate (chip, fp->clock); +if (r >0 ) { +if (!snd_interval_test (it, r)) +continue ; + rmin =min (rmin, r); + rmax =max (rmax, r); +continue ; + }if (fp->rate_table && fp->nr_rates) {for (i =0 ; i < fp->nr_rates; i++) { r = fp->rate_table[i];
Greg Kroah-Hartman
maintainerPATCH 2/207 ALSA: usb-audio: Rename early_playback_start flag with lowlatency_playback
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit 9c9a3b9da891cc70405a544da6855700eddcbb71 upstream.
This is a preparation patch for the upcoming low-latency improvement changes.
Rename early_playback_start flag with lowlatency_playback as it's more intuitive. The new flag is basically a reverse meaning.
Along with the rename, factor out the code to set the flag to a function. This makes the complex condition checks simpler.
Also, the same flag is introduced to snd_usb_endpoint, too, that is carried from the snd_usb_substream flag. Currently the endpoint flag isn't still referred, but will be used in later patches.
--- sound/usb/card.h | 3 ++- sound/usb/endpoint.c | 4 ++++ sound/usb/pcm.c | 29 ++++++++++++++++++++--------- 3 files changed, 26 insertions(+), 10 deletions(-)
sound/usb/card.h +2 -1
@@ -126,6 +126,7 @@ struct snd_usb_endpoint {int skip_packets;/* quirks for devices to ignore the first n packets in a stream */ bool implicit_fb_sync;/* syncs with implicit feedback */ +bool lowlatency_playback;/* low-latency playback mode */ bool need_setup;/* (re-)need for configure? */ /* for hw constraints */
@@ -190,7 +191,7 @@ struct snd_usb_substream { } dsd_dop;bool trigger_tstamp_pending_update;/* trigger timestamp being updated from initial estimate */ -bool early_playback_start;/* early start needed for playback? */ +bool lowlatency_playback;/* low-latency playback mode */ struct media_ctl *media_ctl; };
sound/usb/endpoint.c +4 -0
@@ -794,6 +794,10 @@ void snd_usb_endpoint_set_callback(struc { ep->prepare_data_urb = prepare; ep->retire_data_urb = retire; +if (data_subs) + ep->lowlatency_playback = data_subs->lowlatency_playback; +else + ep->lowlatency_playback = false;WRITE_ONCE (ep->data_subs, data_subs); }
sound/usb/pcm.c +20 -9
@@ -581,6 +581,22 @@ static int snd_usb_hw_free(struct snd_pcreturn 0 ; } +/* check whether early start is needed for playback stream */ +static int lowlatency_playback_available (struct snd_usb_substream *subs) +{ +struct snd_usb_audio *chip = subs->stream->chip; + +if (subs->direction ==SNDRV_PCM_STREAM_CAPTURE ) +return false; +/* disabled via module option? */ +if (!chip->lowlatency) +return false; +/* too short periods? */ +if (subs->data_endpoint->nominal_queue_size >= subs->buffer_bytes) +return false; +return true; +} +/* * prepare callback *
@@ -614,13 +630,8 @@ static int snd_usb_pcm_prepare(struct sn subs->period_elapsed_pending =0 ; runtime->delay =0 ; -/* check whether early start is needed for playback stream */ - subs->early_playback_start = - subs->direction ==SNDRV_PCM_STREAM_PLAYBACK && - (!chip->lowlatency || - (subs->data_endpoint->nominal_queue_size >= subs->buffer_bytes)); - -if (subs->early_playback_start) + subs->lowlatency_playback =lowlatency_playback_available (subs); +if (!subs->lowlatency_playback) ret =start_endpoints (subs); unlock:
@@ -1412,7 +1423,7 @@ static void prepare_playback_urb(struct subs->trigger_tstamp_pending_update = false; } -if (period_elapsed && !subs->running && !subs->early_playback_start) { +if (period_elapsed && !subs->running && subs->lowlatency_playback) { subs->period_elapsed_pending =1 ; period_elapsed =0 ; }
@@ -1466,7 +1477,7 @@ static int snd_usb_substream_playback_tr prepare_playback_urb, retire_playback_urb, subs); -if (!subs->early_playback_start && +if (subs->lowlatency_playback && cmd ==SNDRV_PCM_TRIGGER_START ) { err =start_endpoints (subs);if (err <0 ) {
Greg Kroah-Hartman
maintainerPATCH 3/207 ALSA: usb-audio: Disable low-latency playback for free-wheel mode
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit e581f1cec4f899f788f6c9477f805b1d5fef25e2 upstream.
The free-wheel stream operation like dmix may not update the appl_ptr appropriately, and it doesn't fit with the low-latency playback mode. Disable the low-latency playback operation when the stream is set up in such a mode.
--- sound/usb/pcm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
sound/usb/pcm.c +6 -2
@@ -582,7 +582,8 @@ static int snd_usb_hw_free(struct snd_pc }/* check whether early start is needed for playback stream */ -static int lowlatency_playback_available (struct snd_usb_substream *subs) +static int lowlatency_playback_available (struct snd_pcm_runtime *runtime, +struct snd_usb_substream *subs) {struct snd_usb_audio *chip = subs->stream->chip;
@@ -591,6 +592,9 @@ static int lowlatency_playback_available/* disabled via module option? */ if (!chip->lowlatency)return false; +/* free-wheeling mode? (e.g. dmix) */ +if (runtime->stop_threshold > runtime->buffer_size) +return false;/* too short periods? */ if (subs->data_endpoint->nominal_queue_size >= subs->buffer_bytes)return false;
@@ -630,7 +634,7 @@ static int snd_usb_pcm_prepare(struct sn subs->period_elapsed_pending =0 ; runtime->delay =0 ; - subs->lowlatency_playback =lowlatency_playback_available (subs); + subs->lowlatency_playback =lowlatency_playback_available (runtime, subs);if (!subs->lowlatency_playback) ret =start_endpoints (subs);
Greg Kroah-Hartman
maintainerPATCH 4/207 ALSA: usb-audio: Disable low-latency mode for implicit feedback sync
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit bceee75387554f682638e719d1ea60125ea78cea upstream.
When a playback stream runs in the implicit feedback mode, its operation is passive and won't start unless the capture packet is received. This behavior contradicts with the low-latency playback mode, and we should turn off lowlatency_playback flag accordingly.
In theory, we may take the low-latency mode when the playback-first quirk is set, but it still conflicts with the later operation with the fixed packet numbers, so it's disabled all together for now.
--- sound/usb/pcm.c | 3 +++ 1 file changed, 3 insertions(+)
sound/usb/pcm.c +3 -0
@@ -595,6 +595,9 @@ static int lowlatency_playback_available/* free-wheeling mode? (e.g. dmix) */ if (runtime->stop_threshold > runtime->buffer_size)return false; +/* implicit feedback mode has own operation mode */ +if (snd_usb_endpoint_implicit_feedback_sink (subs->data_endpoint)) +return false;/* too short periods? */ if (subs->data_endpoint->nominal_queue_size >= subs->buffer_bytes)return false;
Greg Kroah-Hartman
maintainerPATCH 5/207 ALSA: usb-audio: Check available frames for the next packet size
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit d215f63d49da9a8803af3e81acd6cad743686573 upstream.
This is yet more preparation for the upcoming changes.
Extend snd_usb_endpoint_next_packet_size() to check the available frames and return -EAGAIN if the next packet size is equal or exceeds the given size. This will be needed for avoiding XRUN during the low latency operation.
As of this patch, avail=0 is passed, i.e. the check is skipped and no behavior change.
--- sound/usb/endpoint.c | 51 ++++++++++++++++++++++++++++++++++++--------------- sound/usb/endpoint.h | 3 ++- sound/usb/pcm.c | 2 +- 3 files changed, 39 insertions(+), 17 deletions(-)
sound/usb/endpoint.c +36 -15
@@ -148,18 +148,23 @@ int snd_usb_endpoint_implicit_feedback_s* This won't be used for implicit feedback which takes the packet size * returned from the sync source */ -static int slave_next_packet_size (struct snd_usb_endpoint *ep) +static int slave_next_packet_size (struct snd_usb_endpoint *ep, +unsigned int avail) {unsigned long flags; +unsigned int phase;int ret;if (ep->fill_max)return ep->maxframesize;spin_lock_irqsave (&ep->lock, flags); - ep->phase = (ep->phase &0xffff ) - + (ep->freqm << ep->datainterval); - ret =min (ep->phase >>16 , ep->maxframesize); + phase = (ep->phase &0xffff ) + (ep->freqm << ep->datainterval); + ret =min (phase >>16 , ep->maxframesize); +if (avail && ret >= avail) + ret = -EAGAIN ; +else + ep->phase = phase;spin_unlock_irqrestore (&ep->lock, flags);return ret;
@@ -169,20 +174,25 @@ static int slave_next_packet_size(struct* Return the number of samples to be sent in the next packet * for adaptive and synchronous endpoints */ -static int next_packet_size (struct snd_usb_endpoint *ep) +static int next_packet_size (struct snd_usb_endpoint *ep,unsigned int avail) { +unsigned int sample_accum;int ret;if (ep->fill_max)return ep->maxframesize; - ep->sample_accum += ep->sample_rem; -if (ep->sample_accum >= ep->pps) { - ep->sample_accum -= ep->pps; + sample_accum += ep->sample_rem; +if (sample_accum >= ep->pps) { + sample_accum -= ep->pps; ret = ep->packsize[1 ]; }else { ret = ep->packsize[0 ]; } +if (avail && ret >= avail) + ret = -EAGAIN ; +else + ep->sample_accum = sample_accum;return ret; }
@@ -190,16 +200,27 @@ static int next_packet_size(struct snd_u/* * snd_usb_endpoint_next_packet_size: Return the number of samples to be sent * in the next packet +* +* If the size is equal or exceeds @avail, don't proceed but return -EAGAIN +* Exception: @avail = 0 for skipping the check. */ int snd_usb_endpoint_next_packet_size (struct snd_usb_endpoint *ep, -struct snd_urb_ctx *ctx,int idx) +struct snd_urb_ctx *ctx,int idx, +unsigned int avail) { -if (ctx->packet_size[idx]) -return ctx->packet_size[idx]; -else if (ep->sync_source) -return slave_next_packet_size (ep); +unsigned int packet; + + packet = ctx->packet_size[idx]; +if (packet) { +if (avail && packet >= avail) +return -EAGAIN ; +return packet; + } + +if (ep->sync_source) +return slave_next_packet_size (ep, avail);else -return next_packet_size (ep); +return next_packet_size (ep, avail); } static void call_retire_callback(struct snd_usb_endpoint *ep,
@@ -263,7 +284,7 @@ static void prepare_silent_urb(struct snunsigned int length;int counts; - counts =snd_usb_endpoint_next_packet_size (ep, ctx, i); + counts =snd_usb_endpoint_next_packet_size (ep, ctx, i,0 ); length = counts * ep->stride;/* number of silent bytes */ offset = offs * ep->stride + extra * i; urb->iso_frame_desc[i].offset = offset;
sound/usb/endpoint.h +2 -1
@@ -46,6 +46,7 @@ void snd_usb_endpoint_free_all(struct snint snd_usb_endpoint_implicit_feedback_sink (struct snd_usb_endpoint *ep);int snd_usb_endpoint_next_packet_size (struct snd_usb_endpoint *ep, -struct snd_urb_ctx *ctx,int idx); +struct snd_urb_ctx *ctx,int idx, +unsigned int avail);#endif /* __USBAUDIO_ENDPOINT_H */
sound/usb/pcm.c +1 -1
@@ -1365,7 +1365,7 @@ static void prepare_playback_urb(structspin_lock_irqsave (&subs->lock, flags); subs->frame_limit += ep->max_urb_frames;for (i =0 ; i < ctx->packets; i++) { - counts =snd_usb_endpoint_next_packet_size (ep, ctx, i); + counts =snd_usb_endpoint_next_packet_size (ep, ctx, i,0 );/* set up descriptor */ urb->iso_frame_desc[i].offset = frames * stride; urb->iso_frame_desc[i].length = counts * stride;
Greg Kroah-Hartman
maintainerPATCH 6/207 ALSA: usb-audio: Add spinlock to stop_urbs()
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit 0ef74366bc150dda4f53c546dfa6e8f7c707e087 upstream.
In theory, stop_urbs() may be called concurrently. Although we have the state check beforehand, it's safer to apply ep->lock during the critical list head manipulations.
--- sound/usb/endpoint.c | 3 +++ 1 file changed, 3 insertions(+)
sound/usb/endpoint.c +3 -0
@@ -927,6 +927,7 @@ void snd_usb_endpoint_sync_pending_stop(static int stop_urbs (struct snd_usb_endpoint *ep,bool force) {unsigned int i; +unsigned long flags;if (!force &&atomic_read (&ep->running))return -EBUSY ;
@@ -934,9 +935,11 @@ static int stop_urbs(struct snd_usb_endpif (!ep_state_update (ep,EP_STATE_RUNNING ,EP_STATE_STOPPING ))return 0 ; +spin_lock_irqsave (&ep->lock, flags);INIT_LIST_HEAD (&ep->ready_playback_urbs); ep->next_packet_head =0 ; ep->next_packet_queued =0 ; +spin_unlock_irqrestore (&ep->lock, flags);for (i =0 ; i < ep->nurbs; i++) {if (test_bit (i, &ep->active_mask)) {
Greg Kroah-Hartman
maintainerPATCH 7/207 ALSA: usb-audio: Improved lowlatency playback support
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit d5f871f89e21bb71827ea57bd484eedea85839a0 upstream.
This is another attempt to improve further the handling of playback stream in the low latency mode. The latest workaround in commit 4267c5a8f313 ("ALSA: usb-audio: Work around for XRUN with low latency playback") revealed that submitting URBs forcibly in advance may trigger XRUN easily. In the classical mode, this problem was avoided by practically delaying the submission of the actual data with the pre-submissions of silent data before triggering the stream start. But that is exactly what we want to avoid.
Now, in this patch, instead of the previous workaround, we take a similar approach as used in the implicit feedback mode. The URBs are queued at the PCM trigger start like before, but we check whether the buffer has been already filled enough before each submission, and stop queuing if the data overcomes the threshold. The remaining URBs are kept in the ready list, and they will be retrieved in the URB complete callback of other (already queued) URBs. In the complete callback, we try to fill the data and submit as much as possible again. When there is no more available in-flight URBs that may handle the pending data, we'll check in PCM ack callback and submit and process URBs there in addition. In this way, the amount of in-flight URBs may vary dynamically and flexibly depending on the available data without hitting XRUN.
The following things are changed to achieve the behavior above:
* The endpoint prepare callback is changed to return an error code; when there is no enough data available, it may return -EAGAIN. Currently only prepare_playback_urb() returns the error.
The evaluation of the available data is a bit messy here; we can't check with snd_pcm_avail() at the point of prepare callback (as runtime->status->hwptr hasn't been updated yet), hence we manually estimate the appl_ptr and compare with the internal hwptr_done to calculate the available frames.
* snd_usb_endpoint_start() doesn't submit full URBs if the prepare callback returns -EAGAIN, and puts the remaining URBs to the ready list for the later submission.
* snd_complete_urb() treats the URBs in the low-latency mode similarly like the implicit feedback mode, and submissions are done in (now exported) snd_usb_queue_pending_output_urbs().
* snd_usb_queue_pending_output_urbs() again checks the error value from the prepare callback. If it's -EAGAIN for the normal stream (i.e. not implicit feedback mode), we push it back to the ready list again.
* PCM ack callback is introduced for the playback stream, and it calls snd_usb_queue_pending_output_urbs() if there is no in-flight URB while the stream is running. This corresponds to the case where the system needs the appl_ptr update for re-submitting a new URB.
* snd_usb_queue_pending_output_urbs() and the prepare EP callback receive in_stream_lock argument, which is a bool flag indicating the call path from PCM ack. It's needed for avoiding the deadlock of snd_pcm_period_elapsed() calls.
* Set the new SNDRV_PCM_INFO_EXPLICIT_SYNC flag when the new low-latency mode is deployed. This assures catching each applptr update even in the mmap mode.
--- sound/usb/card.h | 6 +- sound/usb/endpoint.c | 130 ++++++++++++++++++++++++++++++++++----------------- sound/usb/endpoint.h | 7 +- sound/usb/pcm.c | 102 +++++++++++++++++++++++++++++++--------- 4 files changed, 177 insertions(+), 68 deletions(-)
sound/usb/card.h +3 -3
@@ -74,8 +74,9 @@ struct snd_usb_endpoint {atomic_t state;/* running state */ -void (*prepare_data_urb) (struct snd_usb_substream *subs, -struct urb *urb); +int (*prepare_data_urb) (struct snd_usb_substream *subs, +struct urb *urb, +bool in_stream_lock);void (*retire_data_urb) (struct snd_usb_substream *subs,struct urb *urb);
@@ -94,7 +95,6 @@ struct snd_usb_endpoint {struct list_head ready_playback_urbs;/* playback URB FIFO for implicit fb */ unsigned int nurbs;/* # urbs */ -unsigned int nominal_queue_size;/* total buffer sizes in URBs */ unsigned long active_mask;/* bitmask of active urbs */ unsigned long unlink_mask;/* bitmask of unlinked urbs */ atomic_t submitted_urbs;/* currently submitted urbs */
sound/usb/endpoint.c +88 -42
253 lines not on this page · raw message
sound/usb/endpoint.h +5 -2
@@ -30,8 +30,9 @@ void snd_usb_endpoint_set_sync(struct snstruct snd_usb_endpoint *data_ep, struct snd_usb_endpoint *sync_ep);void snd_usb_endpoint_set_callback (struct snd_usb_endpoint *ep, -void (*prepare)(struct snd_usb_substream *subs, -struct urb *urb), +int (*prepare)(struct snd_usb_substream *subs, +struct urb *urb, +bool in_stream_lock),void (*retire)(struct snd_usb_substream *subs,struct urb *urb),struct snd_usb_substream *data_subs);
@@ -48,5 +49,7 @@ int snd_usb_endpoint_implicit_feedback_sint snd_usb_endpoint_next_packet_size (struct snd_usb_endpoint *ep,struct snd_urb_ctx *ctx,int idx,unsigned int avail); +void snd_usb_queue_pending_output_urbs (struct snd_usb_endpoint *ep, +bool in_stream_lock);#endif /* __USBAUDIO_ENDPOINT_H */
sound/usb/pcm.c +81 -21
175 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 8/207 ALSA: usb-audio: Avoid killing in-flight URBs during draining
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit 813a17cab9b708bbb1e0db8902e19857b57196ec upstream.
While draining a stream, ALSA PCM core stops the stream by issuing snd_pcm_stop() after all data has been sent out. And, at PCM trigger stop, currently USB-audio driver kills the in-flight URBs explicitly, then at sync-stop ops, sync with the finish of all remaining URBs. This might result in a drop of the drained samples as most of USB-audio devices / hosts allow relatively long in-flight samples (as a sort of FIFO).
For avoiding the trimming, this patch changes the stream-stop behavior during PCM draining state. Under that condition, the pending URBs won't be killed. The leftover in-flight URBs are caught by the sync-stop operation that shall be performed after the trigger-stop operation.
--- sound/usb/endpoint.c | 14 +++++++++----- sound/usb/endpoint.h | 2 +- sound/usb/pcm.c | 16 ++++++++-------- 3 files changed, 18 insertions(+), 14 deletions(-)
sound/usb/endpoint.c +9 -5
@@ -955,7 +955,7 @@ void snd_usb_endpoint_sync_pending_stop(* * This function moves the EP to STOPPING state if it's being RUNNING. */ -static int stop_urbs (struct snd_usb_endpoint *ep,bool force) +static int stop_urbs (struct snd_usb_endpoint *ep,bool force,bool keep_pending) {unsigned int i;unsigned long flags;
@@ -972,6 +972,9 @@ static int stop_urbs(struct snd_usb_endp ep->next_packet_queued =0 ;spin_unlock_irqrestore (&ep->lock, flags); +if (keep_pending) +return 0 ; +for (i =0 ; i < ep->nurbs; i++) {if (test_bit (i, &ep->active_mask)) {if (!test_and_set_bit (i, &ep->unlink_mask)) {
@@ -995,7 +998,7 @@ static int release_urbs(struct snd_usb_esnd_usb_endpoint_set_callback (ep,NULL ,NULL ,NULL );/* stop and unlink urbs */ - err =stop_urbs (ep, force); + err =stop_urbs (ep, force, false);if (err)return err;
@@ -1527,7 +1530,7 @@ int snd_usb_endpoint_start(struct snd_usreturn 0 ; __error: -snd_usb_endpoint_stop (ep); +snd_usb_endpoint_stop (ep, false);return -EPIPE ; }
@@ -1535,6 +1538,7 @@ __error:* snd_usb_endpoint_stop: stop an snd_usb_endpoint * * @ep: the endpoint to stop (may be NULL) +* @keep_pending: keep in-flight URBs * * A call to this function will decrement the running count of the endpoint. * In case the last user has requested the endpoint stop, the URBs will
@@ -1545,7 +1549,7 @@ __error:* The caller needs to synchronize the pending stop operation via * snd_usb_endpoint_sync_pending_stop(). */ -void snd_usb_endpoint_stop (struct snd_usb_endpoint *ep) +void snd_usb_endpoint_stop (struct snd_usb_endpoint *ep,bool keep_pending) {if (!ep)return ;
@@ -1560,7 +1564,7 @@ void snd_usb_endpoint_stop(struct snd_usif (!atomic_dec_return (&ep->running)) {if (ep->sync_source)WRITE_ONCE (ep->sync_source->sync_sink,NULL ); -stop_urbs (ep, false); +stop_urbs (ep, false, keep_pending); } }
sound/usb/endpoint.h +1 -1
@@ -38,7 +38,7 @@ void snd_usb_endpoint_set_callback(struc struct snd_usb_substream *data_subs);int snd_usb_endpoint_start (struct snd_usb_endpoint *ep); -void snd_usb_endpoint_stop (struct snd_usb_endpoint *ep); +void snd_usb_endpoint_stop (struct snd_usb_endpoint *ep,bool keep_pending);void snd_usb_endpoint_sync_pending_stop (struct snd_usb_endpoint *ep);void snd_usb_endpoint_suspend (struct snd_usb_endpoint *ep);int snd_usb_endpoint_activate (struct snd_usb_endpoint *ep);
sound/usb/pcm.c +8 -8
@@ -219,16 +219,16 @@ int snd_usb_init_pitch(struct snd_usb_aureturn 0 ; } -static bool stop_endpoints (struct snd_usb_substream *subs) +static bool stop_endpoints (struct snd_usb_substream *subs,bool keep_pending) {bool stopped =0 ;if (test_and_clear_bit (SUBSTREAM_FLAG_SYNC_EP_STARTED , &subs->flags)) { -snd_usb_endpoint_stop (subs->sync_endpoint); +snd_usb_endpoint_stop (subs->sync_endpoint, keep_pending); stopped = true; }if (test_and_clear_bit (SUBSTREAM_FLAG_DATA_EP_STARTED , &subs->flags)) { -snd_usb_endpoint_stop (subs->data_endpoint); +snd_usb_endpoint_stop (subs->data_endpoint, keep_pending); stopped = true; }return stopped;
@@ -261,7 +261,7 @@ static int start_endpoints(struct snd_usreturn 0 ; error: -stop_endpoints (subs); +stop_endpoints (subs, false);return err; }
@@ -437,7 +437,7 @@ static int configure_endpoints(struct snif (subs->data_endpoint->need_setup) {/* stop any running stream beforehand */ -if (stop_endpoints (subs)) +if (stop_endpoints (subs, false))sync_pending_stops (subs); err =snd_usb_endpoint_configure (chip, subs->data_endpoint);if (err <0 )
@@ -572,7 +572,7 @@ static int snd_usb_hw_free(struct snd_pc subs->cur_audiofmt =NULL ;mutex_unlock (&chip->mutex);if (!snd_usb_lock_shutdown (chip)) { -if (stop_endpoints (subs)) +if (stop_endpoints (subs, false))sync_pending_stops (subs);close_endpoints (chip, subs);snd_usb_unlock_shutdown (chip);
@@ -1559,7 +1559,7 @@ static int snd_usb_substream_playback_trreturn 0 ;case SNDRV_PCM_TRIGGER_SUSPEND :case SNDRV_PCM_TRIGGER_STOP : -stop_endpoints (subs); +stop_endpoints (subs, substream->runtime->status->state ==SNDRV_PCM_STATE_DRAINING );snd_usb_endpoint_set_callback (subs->data_endpoint,NULL ,NULL ,NULL ); subs->running =0 ;
@@ -1607,7 +1607,7 @@ static int snd_usb_substream_capture_trireturn 0 ;case SNDRV_PCM_TRIGGER_SUSPEND :case SNDRV_PCM_TRIGGER_STOP : -stop_endpoints (subs); +stop_endpoints (subs, false); fallthrough;case SNDRV_PCM_TRIGGER_PAUSE_PUSH : snd_usb_endpoint_set_callback(subs->data_endpoint,
Greg Kroah-Hartman
maintainerPATCH 9/207 ALSA: usb-audio: Fix packet size calculation regression
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit 23939115be181bc5dbc33aa8471adcdbffa28910 upstream.
The commit d215f63d49da ("ALSA: usb-audio: Check available frames for the next packet size") introduced the available frame size check, but the conversion forgot to initialize the temporary variable properly, and it resulted in a bogus calculation. This patch fixes it.
--- sound/usb/endpoint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/usb/endpoint.c +1 -1
@@ -182,7 +182,7 @@ static int next_packet_size(struct snd_uif (ep->fill_max)return ep->maxframesize; - sample_accum += ep->sample_rem; + sample_accum = ep->sample_accum + ep->sample_rem;if (sample_accum >= ep->pps) { sample_accum -= ep->pps; ret = ep->packsize[1 ];
Greg Kroah-Hartman
maintainerPATCH 10/207 ALSA: usb-audio: Less restriction for low-latency playback mode
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit 53451b6da8271905941eb1eb369db152c4bd92f2 upstream.
The recent support for the improved low-latency playback mode applied the SNDRV_PCM_INFO_EXPLICIT_SYNC flag for the target streams, but this was a slight overkill. The use of the flag above disables effectively both PCM status and control mmaps, while basically what we want to track is only about the appl_ptr update.
For less restriction, use a more proper flag, SNDRV_PCM_INFO_SYNC_APPLPTR instead, which disables only the control mmap.
--- sound/usb/pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/usb/pcm.c +1 -1
@@ -1095,7 +1095,7 @@ static int snd_usb_pcm_open(struct snd_p/* need an explicit sync to catch applptr update in low-latency mode */ if (direction ==SNDRV_PCM_STREAM_PLAYBACK && as->chip->lowlatency) - runtime->hw.info |=SNDRV_PCM_INFO_EXPLICIT_SYNC ; + runtime->hw.info |=SNDRV_PCM_INFO_SYNC_APPLPTR ; runtime->private_data = subs; subs->pcm_substream = substream;/* runtime PM is also done there */
Greg Kroah-Hartman
maintainerPATCH 11/207 ALSA: usb-audio: Switch back to non-latency mode at a later point
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit eee5d6f1356a016105a974fb176b491288439efa upstream.
The recent regression report revealed that the judgment of the low-latency playback mode based on the runtime->stop_threshold cannot work reliably at the prepare stage, as sw_params call may happen at any time, and PCM dmix actually sets it up after the prepare call. This ended up with the stall of the stream as PCM ack won't be issued at all.
For addressing this, check the free-wheeling mode again at the PCM trigger right before starting the stream again, and allow switching to the non-LL mode at a late stage.
--- sound/usb/pcm.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
sound/usb/pcm.c +9 -2
@@ -581,6 +581,12 @@ static int snd_usb_hw_free(struct snd_pcreturn 0 ; } +/* free-wheeling mode? (e.g. dmix) */ +static int in_free_wheeling_mode (struct snd_pcm_runtime *runtime) +{ +return runtime->stop_threshold > runtime->buffer_size; +} +/* check whether early start is needed for playback stream */ static int lowlatency_playback_available (struct snd_pcm_runtime *runtime,struct snd_usb_substream *subs)
@@ -592,8 +598,7 @@ static int lowlatency_playback_available/* disabled via module option? */ if (!chip->lowlatency)return false; -/* free-wheeling mode? (e.g. dmix) */ -if (runtime->stop_threshold > runtime->buffer_size) +if (in_free_wheeling_mode (runtime))return false;/* implicit feedback mode has own operation mode */ if (snd_usb_endpoint_implicit_feedback_sink (subs->data_endpoint))
@@ -1545,6 +1550,8 @@ static int snd_usb_substream_playback_tr subs);if (subs->lowlatency_playback && cmd ==SNDRV_PCM_TRIGGER_START ) { +if (in_free_wheeling_mode (substream->runtime)) + subs->lowlatency_playback = false; err =start_endpoints (subs);if (err <0 ) { snd_usb_endpoint_set_callback(subs->data_endpoint,
Greg Kroah-Hartman
maintainerPATCH 12/207 ALSA: usb-audio: Dont start stream for capture at prepare
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit 83de8f83816e8e15227dac985163e3d433a2bf9d upstream.
The recent change made mistakenly the stream for capture started at prepare stage. Add the stream direction check to avoid it.
--- sound/usb/pcm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
sound/usb/pcm.c +2 -1
@@ -640,7 +640,8 @@ static int snd_usb_pcm_prepare(struct sn runtime->delay =0 ; subs->lowlatency_playback =lowlatency_playback_available (runtime, subs); -if (!subs->lowlatency_playback) +if (substream->stream ==SNDRV_PCM_STREAM_PLAYBACK && + !subs->lowlatency_playback) ret =start_endpoints (subs); unlock:
Greg Kroah-Hartman
maintainerPATCH 13/207 gfs2: release iopen glock early in evict
In reply to Greg Kroah-HartmanFrom: Bob Peterson <[email protected]>
[ Upstream commit 49462e2be119d38c5eb5759d0d1b712df3a41239 ]
Before this patch, evict would clear the iopen glock's gl_object after releasing the inode glock. In the meantime, another process could reuse the same block and thus glocks for a new inode. It would lock the inode glock (exclusively), and then the iopen glock (shared). The shared locking mode doesn't provide any ordering against the evict, so by the time the iopen glock is reused, evict may not have gotten to setting gl_object to NULL.
Fix that by releasing the iopen glock before the inode glock in gfs2_evict_inode.
--- fs/gfs2/super.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
fs/gfs2/super.c +7 -7
@@ -1402,13 +1402,6 @@ static void gfs2_evict_inode(struct inode *inode)gfs2_ordered_del_inode (ip);clear_inode (inode);gfs2_dir_hash_inval (ip); -if (ip->i_gl) { -glock_clear_object (ip->i_gl, ip); -wait_on_bit_io (&ip->i_flags,GIF_GLOP_PENDING ,TASK_UNINTERRUPTIBLE ); -gfs2_glock_add_to_lru (ip->i_gl); -gfs2_glock_put_eventually (ip->i_gl); - ip->i_gl =NULL ; - }if (gfs2_holder_initialized (&ip->i_iopen_gh)) {struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl;
@@ -1421,6 +1414,13 @@ static void gfs2_evict_inode(struct inode *inode)gfs2_holder_uninit (&ip->i_iopen_gh);gfs2_glock_put_eventually (gl); } +if (ip->i_gl) { +glock_clear_object (ip->i_gl, ip); +wait_on_bit_io (&ip->i_flags,GIF_GLOP_PENDING ,TASK_UNINTERRUPTIBLE ); +gfs2_glock_add_to_lru (ip->i_gl); +gfs2_glock_put_eventually (ip->i_gl); + ip->i_gl =NULL ; + } }static struct inode *gfs2_alloc_inode (struct super_block *sb)
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 14/207 gfs2: Fix length of holes reported at end-of-file
In reply to Greg Kroah-HartmanFrom: Andreas Gruenbacher <[email protected]>
[ Upstream commit f3506eee81d1f700d9ee2d2f4a88fddb669ec032 ]
Fix the length of holes reported at the end of a file: the length is relative to the beginning of the extent, not the seek position which is rounded down to the filesystem block size.
This bug went unnoticed for some time, but is now caught by the following assertion in iomap_iter_done():
WARN_ON_ONCE(iter->iomap.offset + iter->iomap.length <= iter->pos)
--- fs/gfs2/bmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/gfs2/bmap.c +1 -1
@@ -940,7 +940,7 @@ static int __gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length,else if (height == ip->i_height) ret =gfs2_hole_size (inode, lblock, len, mp, iomap);else - iomap->length = size - pos; + iomap->length = size - iomap->offset; }else if (flags &IOMAP_WRITE ) {u64 alloc_size;
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 15/207 powerpc/pseries/ddw: Revert "Extend upper limit for huge DMA window for persistent memory"
In reply to Greg Kroah-HartmanFrom: Alexey Kardashevskiy <[email protected]>
[ Upstream commit 2d33f5504490a9d90924476dbccd4a5349ee1ad0 ]
This reverts commit 54fc3c681ded9437e4548e2501dc1136b23cfa9a which does not allow 1:1 mapping even for the system RAM which is usually possible.
--- arch/powerpc/platforms/pseries/iommu.c | 9 --------- 1 file changed, 9 deletions(-)
arch/powerpc/platforms/pseries/iommu.c +0 -9
@@ -1092,15 +1092,6 @@ static phys_addr_t ddw_memory_hotplug_max(void)phys_addr_t max_addr =memory_hotplug_max ();struct device_node *memory; -/* -* The "ibm,pmemory" can appear anywhere in the address space. -* Assuming it is still backed by page structs, set the upper limit -* for the huge DMA window as MAX_PHYSMEM_BITS. -*/ -if (of_find_node_by_type (NULL ,"ibm,pmemory" )) -return (sizeof (phys_addr_t) *8 <=MAX_PHYSMEM_BITS ) ? - (phys_addr_t) -1 : (1ULL <<MAX_PHYSMEM_BITS ); -for_each_node_by_type (memory,"memory" ) {unsigned long start, size;int n_mem_addr_cells, n_mem_size_cells, len;
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 16/207 powerpc/pseries/ddw: Do not try direct mapping with persistent memory and one window
In reply to Greg Kroah-HartmanFrom: Alexey Kardashevskiy <[email protected]>
[ Upstream commit ad3976025b311cdeb822ad3e7a7554018cb0f83f ]
There is a possibility of having just one DMA window available with a limited capacity which the existing code does not handle that well. If the window is big enough for the system RAM but less than MAX_PHYSMEM_BITS (which we want when persistent memory is present), we create 1:1 window and leave persistent memory without DMA.
This disables 1:1 mapping entirely if there is persistent memory and either:
- the huge DMA window does not cover the entire address space;
- the default DMA window is removed.
This relies on reverted 54fc3c681ded
("powerpc/pseries/ddw: Extend upper limit for huge DMA window for persistent memory") to return the actual amount RAM in ddw_memory_hotplug_max() (posted separately).
--- arch/powerpc/platforms/pseries/iommu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
arch/powerpc/platforms/pseries/iommu.c +4 -2
@@ -1356,8 +1356,10 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) len =order_base_2 (query.largest_available_block << page_shift); win_name =DMA64_PROPNAME ; }else { - direct_mapping = true; - win_name =DIRECT64_PROPNAME ; + direct_mapping = !default_win_removed || + (len ==MAX_PHYSMEM_BITS ) || + (!pmem_present && (len == max_ram_len)); + win_name = direct_mapping ?DIRECT64_PROPNAME :DMA64_PROPNAME ; } ret =create_ddw (dev, ddw_avail, &create, page_shift, len);
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 17/207 drm/sun4i: fix unmet dependency on RESET_CONTROLLER for PHY_SUN6I_MIPI_DPHY
In reply to Greg Kroah-HartmanFrom: Julian Braha <[email protected]>
[ Upstream commit bb162bb2b4394108c8f055d1b115735331205e28 ]
When PHY_SUN6I_MIPI_DPHY is selected, and RESET_CONTROLLER is not selected, Kbuild gives the following warning:
WARNING: unmet direct dependencies detected for PHY_SUN6I_MIPI_DPHY
Depends on [n]: (ARCH_SUNXI [=n] || COMPILE_TEST [=y]) && HAS_IOMEM [=y] && COMMON_CLK [=y] && RESET_CONTROLLER [=n] Selected by [y]:
- DRM_SUN6I_DSI [=y] && HAS_IOMEM [=y] && DRM_SUN4I [=y]
This is because DRM_SUN6I_DSI selects PHY_SUN6I_MIPI_DPHY without selecting or depending on RESET_CONTROLLER, despite PHY_SUN6I_MIPI_DPHY depending on RESET_CONTROLLER.
These unmet dependency bugs were detected by Kismet, a static analysis tool for Kconfig. Please advise if this is not the appropriate solution.
v2:
Fixed indentation to match the rest of the file.
--- drivers/gpu/drm/sun4i/Kconfig | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/sun4i/Kconfig +1 -0
@@ -46,6 +46,7 @@ config DRM_SUN6I_DSI default MACH_SUN8I select CRC_CCITT select DRM_MIPI_DSI + select RESET_CONTROLLER select PHY_SUN6I_MIPI_DPHY help Choose this option if you want have an Allwinner SoC with
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 18/207 mac80211: do not access the IV when it was stripped
In reply to Greg Kroah-HartmanFrom: Xing Song <[email protected]>
[ Upstream commit 77dfc2bc0bb4b8376ecd7a430f27a4a8fff6a5a0 ]
ieee80211_get_keyid() will return false value if IV has been stripped, such as return 0 for IP/ARP frames due to LLC header, and return -EINVAL for disassociation frames due to its length... etc. Don't try to access it if it's not present.
--- net/mac80211/rx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/mac80211/rx.c +2 -1
@@ -1952,7 +1952,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)int keyid = rx->sta->ptk_idx; sta_ptk =rcu_dereference (rx->sta->ptk[keyid]); -if (ieee80211_has_protected (fc)) { +if (ieee80211_has_protected (fc) && + !(status->flag &RX_FLAG_IV_STRIPPED )) { cs = rx->sta->cipher_scheme; keyid =ieee80211_get_keyid (rx->skb, cs);
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 19/207 mac80211: fix throughput LED trigger
In reply to Greg Kroah-HartmanFrom: Felix Fietkau <[email protected]>
[ Upstream commit 30f6cf96912b638d0ddfc325204b598f94efddc2 ]
The codepaths for rx with decap offload and tx with itxq were not updating the counters for the throughput led trigger.
--- net/mac80211/led.h | 8 ++++---- net/mac80211/rx.c | 7 ++++--- net/mac80211/tx.c | 34 +++++++++++++++------------------- 3 files changed, 23 insertions(+), 26 deletions(-)
net/mac80211/led.h +4 -4
@@ -72,19 +72,19 @@ static inline void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local,#endif static inline void -ieee80211_tpt_led_trig_tx (struct ieee80211_local *local,__le16 fc,int bytes) +ieee80211_tpt_led_trig_tx (struct ieee80211_local *local,int bytes) {#ifdef CONFIG_MAC80211_LEDS -if (ieee80211_is_data (fc) &&atomic_read (&local->tpt_led_active)) +if (atomic_read (&local->tpt_led_active)) local->tpt_led_trigger->tx_bytes += bytes;#endif }static inline void -ieee80211_tpt_led_trig_rx (struct ieee80211_local *local,__le16 fc,int bytes) +ieee80211_tpt_led_trig_rx (struct ieee80211_local *local,int bytes) {#ifdef CONFIG_MAC80211_LEDS -if (ieee80211_is_data (fc) &&atomic_read (&local->tpt_led_active)) +if (atomic_read (&local->tpt_led_active)) local->tpt_led_trigger->rx_bytes += bytes;#endif }
net/mac80211/rx.c +4 -3
@@ -4874,6 +4874,7 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,struct ieee80211_rate *rate =NULL ;struct ieee80211_supported_band *sband;struct ieee80211_rx_status *status =IEEE80211_SKB_RXCB (skb); +struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;WARN_ON_ONCE (softirq_count () ==0 );
@@ -4970,9 +4971,9 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,if (!(status->flag &RX_FLAG_8023 )) skb =ieee80211_rx_monitor (local, skb, rate);if (skb) { -ieee80211_tpt_led_trig_rx (local, - ((struct ieee80211_hdr *)skb->data)->frame_control, - skb->len); +if ((status->flag &RX_FLAG_8023 ) || +ieee80211_is_data_present (hdr->frame_control)) +ieee80211_tpt_led_trig_rx (local, skb->len);if (status->flag &RX_FLAG_8023 )__ieee80211_rx_handle_8023 (hw, pubsta, skb, list);
net/mac80211/tx.c +15 -19
@@ -1720,21 +1720,19 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,* Returns false if the frame couldn't be transmitted but was queued instead. */ static bool __ieee80211_tx (struct ieee80211_local *local, -struct sk_buff_head *skbs,int led_len, -struct sta_info *sta,bool txpending) +struct sk_buff_head *skbs,struct sta_info *sta, +bool txpending) {struct ieee80211_tx_info *info;struct ieee80211_sub_if_data *sdata;struct ieee80211_vif *vif;struct sk_buff *skb;bool result; -__le16 fc;if (WARN_ON (skb_queue_empty (skbs)))return true; skb =skb_peek (skbs); - fc = ((struct ieee80211_hdr *)skb->data)->frame_control; info =IEEE80211_SKB_CB (skb); sdata =vif_to_sdata (info->control.vif);if (sta && !sta->uploaded)
@@ -1768,8 +1766,6 @@ static bool __ieee80211_tx(struct ieee80211_local *local, result =ieee80211_tx_frags (local, vif, sta, skbs, txpending); -ieee80211_tpt_led_trig_tx (local, fc, led_len); -WARN_ON_ONCE (!skb_queue_empty (skbs));return result;
@@ -1919,7 +1915,6 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,ieee80211_tx_result res_prepare;struct ieee80211_tx_info *info =IEEE80211_SKB_CB (skb);bool result = true; -int led_len;if (unlikely (skb->len <10 )) {dev_kfree_skb (skb);
@@ -1927,7 +1922,6 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, }/* initialises tx */ - led_len = skb->len; res_prepare =ieee80211_tx_prepare (sdata, &tx, sta, skb);if (unlikely (res_prepare ==TX_DROP )) {
@@ -1950,8 +1944,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,return true;if (!invoke_tx_handlers_late (&tx)) - result =__ieee80211_tx (local, &tx.skbs, led_len, - tx.sta, txpending); + result =__ieee80211_tx (local, &tx.skbs, tx.sta, txpending);return result; }
@@ -4174,6 +4167,7 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,struct ieee80211_local *local = sdata->local;struct sta_info *sta;struct sk_buff *next; +int len = skb->len;if (unlikely (skb->len <ETH_HLEN )) {kfree_skb (skb);
@@ -4220,10 +4214,8 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, } }else {/* we cannot process non-linear frames on this path */ -if (skb_linearize (skb)) { -kfree_skb (skb); - goto out; - } +if (skb_linearize (skb)) + goto out_free;/* the frame could be fragmented, software-encrypted, and other * things so we cannot really handle checksum offload with it -
@@ -4257,7 +4249,10 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, goto out; out_free:kfree_skb (skb); + len =0 ; out: +if (len) +ieee80211_tpt_led_trig_tx (local, len);rcu_read_unlock (); }
@@ -4395,8 +4390,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, }static bool ieee80211_tx_8023 (struct ieee80211_sub_if_data *sdata, -struct sk_buff *skb,int led_len, -struct sta_info *sta, +struct sk_buff *skb,struct sta_info *sta,bool txpending) {struct ieee80211_local *local = sdata->local;
@@ -4409,6 +4403,8 @@ static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata,if (sta)sk_pacing_shift_update (skb->sk, local->hw.tx_sk_pacing_shift); +ieee80211_tpt_led_trig_tx (local, skb->len); +if (ieee80211_queue_skb (local, sdata, sta, skb))return true;
@@ -4497,7 +4493,7 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,if (key) info->control.hw_key = &key->conf; -ieee80211_tx_8023 (sdata, skb, skb->len, sta, false); +ieee80211_tx_8023 (sdata, skb, sta, false);return ;
@@ -4636,7 +4632,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,if (IS_ERR (sta) || (sta && !sta->uploaded)) sta =NULL ; - result =ieee80211_tx_8023 (sdata, skb, skb->len, sta, true); + result =ieee80211_tx_8023 (sdata, skb, sta, true); }else {struct sk_buff_head skbs;
@@ -4646,7 +4642,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, hdr = (struct ieee80211_hdr *)skb->data; sta =sta_info_get (sdata, hdr->addr1); - result =__ieee80211_tx (local, &skbs, skb->len, sta, true); + result =__ieee80211_tx (local, &skbs, sta, true); }return result;
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 20/207 x86/hyperv: Move required MSRs check to initial platform probing
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
[ Upstream commit f3e613e72f66226b3bea1046c1b864f67a3000a4 ]
Explicitly check for MSR_HYPERCALL and MSR_VP_INDEX support when probing for running as a Hyper-V guest instead of waiting until hyperv_init() to detect the bogus configuration. Add messages to give the admin a heads up that they are likely running on a broken virtual machine setup.
At best, silently disabling Hyper-V is confusing and difficult to debug, e.g. the kernel _says_ it's using all these fancy Hyper-V features, but always falls back to the native versions. At worst, the half baked setup will crash/hang the kernel.
--- arch/x86/hyperv/hv_init.c | 9 +-------- arch/x86/kernel/cpu/mshyperv.c | 20 +++++++++++++++----- 2 files changed, 16 insertions(+), 13 deletions(-)
arch/x86/hyperv/hv_init.c +1 -8
@@ -348,20 +348,13 @@ static void __init hv_get_partition_id(void)*/ void __init hyperv_init (void ) { -u64 guest_id, required_msrs; +u64 guest_id;union hv_x64_msr_hypercall_contents hypercall_msr;int cpuhp;if (x86_hyper_type !=X86_HYPER_MS_HYPERV )return ; -/* Absolutely required MSRs */ - required_msrs =HV_MSR_HYPERCALL_AVAILABLE | -HV_MSR_VP_INDEX_AVAILABLE ; - -if ((ms_hyperv.features & required_msrs) != required_msrs) -return ; -if (hv_common_init ())return ;
arch/x86/kernel/cpu/mshyperv.c +15 -5
@@ -163,12 +163,22 @@ static uint32_t __init ms_hyperv_platform(void)cpuid (HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS , &eax, &hyp_signature[0 ], &hyp_signature[1 ], &hyp_signature[2 ]); -if (eax >=HYPERV_CPUID_MIN && - eax <=HYPERV_CPUID_MAX && - !memcmp ("Microsoft Hv" , hyp_signature,12 )) -return HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS ; +if (eax <HYPERV_CPUID_MIN || eax >HYPERV_CPUID_MAX || +memcmp ("Microsoft Hv" , hyp_signature,12 )) +return 0 ; -return 0 ; +/* HYPERCALL and VP_INDEX MSRs are mandatory for all features. */ + eax =cpuid_eax (HYPERV_CPUID_FEATURES ); +if (!(eax &HV_MSR_HYPERCALL_AVAILABLE )) { +pr_warn ("x86/hyperv: HYPERCALL MSR not available.\n" ); +return 0 ; + } +if (!(eax &HV_MSR_VP_INDEX_AVAILABLE )) { +pr_warn ("x86/hyperv: VP_INDEX MSR not available.\n" ); +return 0 ; + } + +return HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS ; }static unsigned char hv_get_nmi_reason (void )
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 21/207 net/smc: Transfer remaining wait queue entries during fallback
In reply to Greg Kroah-HartmanFrom: Wen Gu <[email protected]>
[ Upstream commit 2153bd1e3d3dbf6a3403572084ef6ed31c53c5f0 ]
The SMC fallback is incomplete currently. There may be some wait queue entries remaining in smc socket->wq, which should be removed to clcsocket->wq during the fallback.
For example, in nginx/wrk benchmark, this issue causes an all-zeros test result:
server: nginx -g 'daemon off;'
client: smc_run wrk -c 1 -t 1 -d 5 http://11.200.15.93/index.html
Running 5s test @ http://11.200.15.93/index.html
1 threads and 1 connections
Thread Stats Avg Stdev Max ± Stdev
Latency 0.00us 0.00us 0.00us -nan%
Req/Sec 0.00 0.00 0.00 -nan%
0 requests in 5.00s, 0.00B read
Requests/sec: 0.00
Transfer/sec: 0.00BThe reason for this all-zeros result is that when wrk used SMC to replace TCP, it added an eppoll_entry into smc socket->wq and expected to be notified if epoll events like EPOLL_IN/ EPOLL_OUT occurred on the smc socket.
However, once a fallback occurred, wrk switches to use clcsocket. Now it is clcsocket->wq instead of smc socket->wq which will be woken up. The eppoll_entry remaining in smc socket->wq does not work anymore and wrk stops the test.
This patch fixes this issue by removing remaining wait queue entries from smc socket->wq to clcsocket->wq during the fallback.
--- net/smc/af_smc.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
net/smc/af_smc.c +14 -0
@@ -548,6 +548,10 @@ static void smc_stat_fallback(struct smc_sock *smc)static void smc_switch_to_fallback (struct smc_sock *smc,int reason_code) { +wait_queue_head_t *smc_wait =sk_sleep (&smc->sk); +wait_queue_head_t *clc_wait =sk_sleep (smc->clcsock->sk); +unsigned long flags; + smc->use_fallback = true; smc->fallback_rsn = reason_code;smc_stat_fallback (smc);
@@ -556,6 +560,16 @@ static void smc_switch_to_fallback(struct smc_sock *smc, int reason_code) smc->clcsock->file->private_data = smc->clcsock; smc->clcsock->wq.fasync_list = smc->sk.sk_socket->wq.fasync_list; + +/* There may be some entries remaining in +* smc socket->wq, which should be removed +* to clcsocket->wq during the fallback. +*/ +spin_lock_irqsave (&smc_wait->lock, flags); +spin_lock (&clc_wait->lock); +list_splice_init (&smc_wait->head, &clc_wait->head); +spin_unlock (&clc_wait->lock); +spin_unlock_irqrestore (&smc_wait->lock, flags); } }
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 22/207 atlantic: Fix OOB read and write in hw_atl_utils_fw_rpc_wait
In reply to Greg Kroah-HartmanFrom: Zekun Shen <[email protected]>
[ Upstream commit b922f622592af76b57cbc566eaeccda0b31a3496 ]
This bug report shows up when running our research tools. The reports is SOOB read, but it seems SOOB write is also possible a few lines below.
In details, fw.len and sw.len are inputs coming from io. A len over the size of self->rpc triggers SOOB. The patch fixes the bugs by adding sanity checks.
The bugs are triggerable with compromised/malfunctioning devices. They are potentially exploitable given they first leak up to 0xffff bytes and able to overwrite the region later.
The patch is tested with QEMU emulater.
This is NOT tested with a real device.
Attached is the log we found by fuzzing.
BUG: KASAN: slab-out-of-bounds in hw_atl_utils_fw_upload_dwords+0x393/0x3c0 [atlantic] Read of size 4 at addr ffff888016260b08 by task modprobe/213 CPU: 0 PID: 213 Comm: modprobe Not tainted 5.6.0 #1 Call Trace: dump_stack+0x76/0xa0 print_address_description.constprop.0+0x16/0x200 ? hw_atl_utils_fw_upload_dwords+0x393/0x3c0 [atlantic] ? hw_atl_utils_fw_upload_dwords+0x393/0x3c0 [atlantic] __kasan_report.cold+0x37/0x7c ? aq_hw_read_reg_bit+0x60/0x70 [atlantic] ? hw_atl_utils_fw_upload_dwords+0x393/0x3c0 [atlantic] kasan_report+0xe/0x20 hw_atl_utils_fw_upload_dwords+0x393/0x3c0 [atlantic] hw_atl_utils_fw_rpc_call+0x95/0x130 [atlantic] hw_atl_utils_fw_rpc_wait+0x176/0x210 [atlantic] hw_atl_utils_mpi_create+0x229/0x2e0 [atlantic] ? hw_atl_utils_fw_rpc_wait+0x210/0x210 [atlantic] ? hw_atl_utils_initfw+0x9f/0x1c8 [atlantic] hw_atl_utils_initfw+0x12a/0x1c8 [atlantic] aq_nic_ndev_register+0x88/0x650 [atlantic] ? aq_nic_ndev_init+0x235/0x3c0 [atlantic] aq_pci_probe+0x731/0x9b0 [atlantic] ? aq_pci_func_init+0xc0/0xc0 [atlantic] local_pci_probe+0xd3/0x160 pci_device_probe+0x23f/0x3e0
--- .../ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +10 -0
@@ -559,6 +559,11 @@ int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self, goto err_exit;if (fw.len ==0xFFFFU ) { +if (sw.len >sizeof (self->rpc)) { +printk (KERN_INFO "Invalid sw len: %x\n" , sw.len); + err = -EINVAL ; + goto err_exit; + } err =hw_atl_utils_fw_rpc_call (self, sw.len);if (err <0 ) goto err_exit;
@@ -567,6 +572,11 @@ int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,if (rpc) {if (fw.len) { +if (fw.len >sizeof (self->rpc)) { +printk (KERN_INFO "Invalid fw len: %x\n" , fw.len); + err = -EINVAL ; + goto err_exit; + } err = hw_atl_utils_fw_downld_dwords(self, self->rpc_addr,
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 23/207 net: return correct error code
In reply to Greg Kroah-HartmanFrom: liuguoqiang <[email protected]>
[ Upstream commit 6def480181f15f6d9ec812bca8cbc62451ba314c ]
When kmemdup called failed and register_net_sysctl return NULL, should return ENOMEM instead of ENOBUFS
--- net/ipv4/devinet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/devinet.c +1 -1
@@ -2587,7 +2587,7 @@ static int __devinet_sysctl_register(struct net *net, char *dev_name, free:kfree (t); out: -return -ENOBUFS ; +return -ENOMEM ; } static void __devinet_sysctl_unregister(struct net *net,
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 24/207 pinctrl: qcom: fix unmet dependencies on GPIOLIB for GPIOLIB_IRQCHIP
In reply to Greg Kroah-HartmanFrom: Julian Braha <[email protected]>
[ Upstream commit 60430d4c4eddcdf8eac2bdbec9704f84a436eedf ]
When PINCTRL_QCOM_SPMI_PMIC or PINCTRL_QCOM_SSBI_PMIC is selected, and GPIOLIB is not selected, Kbuild gives the following warnings:
WARNING: unmet direct dependencies detected for GPIOLIB_IRQCHIP
Depends on [n]: GPIOLIB [=n]
Selected by [y]:
- PINCTRL_QCOM_SPMI_PMIC [=y] && PINCTRL [=y] && (ARCH_QCOM [=n] || COMPILE_TEST [=y]) && OF [=y] && SPMI [=y]
WARNING: unmet direct dependencies detected for GPIOLIB_IRQCHIP
Depends on [n]: GPIOLIB [=n]
Selected by [y]:
- PINCTRL_QCOM_SSBI_PMIC [=y] && PINCTRL [=y] && (ARCH_QCOM [=n] || COMPILE_TEST [=y]) && OF [=y]
This is because these config options enable GPIOLIB_IRQCHIP without selecting or depending on GPIOLIB, despite GPIOLIB_IRQCHIP depending on GPIOLIB.
These unmet dependency bugs were detected by Kismet, a static analysis tool for Kconfig. Please advise if this is not the appropriate solution.
--- drivers/pinctrl/qcom/Kconfig | 2 ++ 1 file changed, 2 insertions(+)
drivers/pinctrl/qcom/Kconfig +2 -0
@@ -189,6 +189,7 @@ config PINCTRL_QCOM_SPMI_PMIC select PINMUX select PINCONF select GENERIC_PINCONF + select GPIOLIB select GPIOLIB_IRQCHIP select IRQ_DOMAIN_HIERARCHY help
@@ -203,6 +204,7 @@ config PINCTRL_QCOM_SSBI_PMIC select PINMUX select PINCONF select GENERIC_PINCONF + select GPIOLIB select GPIOLIB_IRQCHIP select IRQ_DOMAIN_HIERARCHY help
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 25/207 platform/x86: dell-wmi-descriptor: disable by default
In reply to Greg Kroah-HartmanFrom: Thomas Weißschuh <[email protected]>
[ Upstream commit 0f07c023dcd08ca49b6d3dd018abc7cd56301478 ]
dell-wmi-descriptor only provides symbols to other drivers. These drivers already select dell-wmi-descriptor when needed.
This fixes an issue where dell-wmi-descriptor is compiled as a module with localyesconfig on a non-Dell machine.
--- drivers/platform/x86/dell/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/platform/x86/dell/Kconfig +1 -1
@@ -187,7 +187,7 @@ config DELL_WMI_AIO config DELL_WMI_DESCRIPTOR tristate - default m + default n depends on ACPI_WMI config DELL_WMI_LED
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 26/207 platform/x86: thinkpad_acpi: Add support for dual fan control
In reply to Greg Kroah-HartmanFrom: Jimmy Wang <[email protected]>
[ Upstream commit 1f338954a5fbe21eb22b4223141e31f2a26366d5 ]
This adds dual fan control for P1 / X1 Extreme Gen4
--- drivers/platform/x86/thinkpad_acpi.c | 1 + 1 file changed, 1 insertion(+)
drivers/platform/x86/thinkpad_acpi.c +1 -0
@@ -8853,6 +8853,7 @@ static const struct tpacpi_quirk fan_quirk_table[] __initconst = {TPACPI_Q_LNV3 ('N' ,'2' ,'E' ,TPACPI_FAN_2CTL ),/* P1 / X1 Extreme (1st gen) */ TPACPI_Q_LNV3 ('N' ,'2' ,'O' ,TPACPI_FAN_2CTL ),/* P1 / X1 Extreme (2nd gen) */ TPACPI_Q_LNV3 ('N' ,'2' ,'V' ,TPACPI_FAN_2CTL ),/* P1 / X1 Extreme (3nd gen) */ +TPACPI_Q_LNV3 ('N' ,'4' ,'0' ,TPACPI_FAN_2CTL ),/* P1 / X1 Extreme (4nd gen) */ TPACPI_Q_LNV3 ('N' ,'3' ,'0' ,TPACPI_FAN_2CTL ),/* P15 (1st gen) / P15v (1st gen) */ TPACPI_Q_LNV3('N', '3', '2', TPACPI_FAN_2CTL), /* X1 Carbon (9th gen) */ };
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 27/207 platform/x86: thinkpad_acpi: Fix WWAN device disabled issue after S3 deep
In reply to Greg Kroah-HartmanFrom: Slark Xiao <[email protected]>
[ Upstream commit 39f53292181081d35174a581a98441de5da22bc9 ]
When WWAN device wake from S3 deep, under thinkpad platform, WWAN would be disabled. This disable status could be checked by command 'nmcli r wwan' or 'rfkill list'.
Issue analysis as below:
When host resume from S3 deep, thinkpad_acpi driver would
call hotkey_resume() function. Finnaly, it will use wan_get_status to check the current status of WWAN device. During this resume progress, wan_get_status would always return off even WWAN boot up completely.
In patch V2, Hans said 'sw_state should be unchanged
after a suspend/resume. It's better to drop the tpacpi_rfk_update_swstate call all together from the resume path'.
And it's confimed by Lenovo that GWAN is no longer
available from WHL generation because the design does not match with current pin control.
--- drivers/platform/x86/thinkpad_acpi.c | 12 ------------ 1 file changed, 12 deletions(-)
drivers/platform/x86/thinkpad_acpi.c +0 -12
@@ -1178,15 +1178,6 @@ static int tpacpi_rfk_update_swstate(const struct tpacpi_rfk *tp_rfk)return status; } -/* Query FW and update rfkill sw state for all rfkill switches */ -static void tpacpi_rfk_update_swstate_all (void ) -{ -unsigned int i; - -for (i =0 ; i <TPACPI_RFK_SW_MAX ; i++) -tpacpi_rfk_update_swstate (tpacpi_rfkill_switches[i]); -} -/* * Sync the HW-blocking state of all rfkill switches, * do notice it causes the rfkill core to schedule uevents
@@ -3129,9 +3120,6 @@ static void tpacpi_send_radiosw_update(void)if (wlsw ==TPACPI_RFK_RADIO_OFF )tpacpi_rfk_update_hwblock_state (true); -/* Sync sw blocking state */ -tpacpi_rfk_update_swstate_all (); -/* Sync hw blocking state last if it is hw-unblocked */ if (wlsw ==TPACPI_RFK_RADIO_ON )tpacpi_rfk_update_hwblock_state (false);
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 28/207 s390/setup: avoid using memblock_enforce_memory_limit
In reply to Greg Kroah-HartmanFrom: Vasily Gorbik <[email protected]>
[ Upstream commit 5dbc4cb4667457b0c53bcd7bff11500b3c362975 ]
There is a difference in how architectures treat "mem=" option. For some that is an amount of online memory, for s390 and x86 this is the limiting max address. Some memblock api like memblock_enforce_memory_limit() take limit argument and explicitly treat it as the size of online memory, and use __find_max_addr to convert it to an actual max address. Current s390 usage:
memblock_enforce_memory_limit(memblock_end_of_DRAM());
yields different results depending on presence of memory holes (offline memory blocks in between online memory). If there are no memory holes limit == max_addr in memblock_enforce_memory_limit() and it does trim online memory and reserved memory regions. With memory holes present it actually does nothing.
Since we already use memblock_remove() explicitly to trim online memory regions to potential limit (think mem=, kdump, addressing limits, etc.) drop the usage of memblock_enforce_memory_limit() altogether. Trimming reserved regions should not be required, since we now use memblock_set_current_limit() to limit allocations and any explicit memory reservations above the limit is an actual problem we should not hide.
--- arch/s390/kernel/setup.c | 3 --- 1 file changed, 3 deletions(-)
arch/s390/kernel/setup.c +0 -3
@@ -816,9 +816,6 @@ static void __init setup_memory(void)storage_key_init_range (start, end);psw_set_key (PAGE_DEFAULT_KEY ); - -/* Only cosmetics */ -memblock_enforce_memory_limit (memblock_end_of_DRAM ()); }static void __init relocate_amode31_section (void )
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 29/207 btrfs: silence lockdep when reading chunk tree during mount
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
[ Upstream commit 4d9380e0da7be2351437cdac71673a9cd94e50fd ]
Often some test cases like btrfs/161 trigger lockdep splats that complain about possible unsafe lock scenario due to the fact that during mount, when reading the chunk tree we end up calling blkdev_get_by_path() while holding a read lock on a leaf of the chunk tree. That produces a lockdep splat like the following:
[ 3653.683975] ======================================================
[ 3653.685148] WARNING: possible circular locking dependency detected
[ 3653.686301] 5.15.0-rc7-btrfs-next-103 #1 Not tainted
[ 3653.687239] ------------------------------------------------------
[ 3653.688400] mount/447465 is trying to acquire lock:
[ 3653.689320] ffff8c6b0c76e528 (&disk->open_mutex){+.+.}-{3:3}, at: blkdev_get_by_dev.part.0+0xe7/0x320
[ 3653.691054]
but task is already holding lock:
[ 3653.692155] ffff8c6b0a9f39e0 (btrfs-chunk-00){++++}-{3:3}, at: __btrfs_tree_read_lock+0x24/0x110 [btrfs]
[ 3653.693978]
which lock already depends on the new lock.[ 3653.695510]
the existing dependency chain (in reverse order) is:
[ 3653.696915]
-> #3 (btrfs-chunk-00){++++}-{3:3}:
[ 3653.698053] down_read_nested+0x4b/0x140
[ 3653.698893] __btrfs_tree_read_lock+0x24/0x110 [btrfs]
[ 3653.699988] btrfs_read_lock_root_node+0x31/0x40 [btrfs]
[ 3653.701205] btrfs_search_slot+0x537/0xc00 [btrfs]
[ 3653.702234] btrfs_insert_empty_items+0x32/0x70 [btrfs]
[ 3653.703332] btrfs_init_new_device+0x563/0x15b0 [btrfs]
[ 3653.704439] btrfs_ioctl+0x2110/0x3530 [btrfs]
[ 3653.705405] __x64_sys_ioctl+0x83/0xb0
[ 3653.706215] do_syscall_64+0x3b/0xc0
[ 3653.706990] entry_SYSCALL_64_after_hwframe+0x44/0xae
[ 3653.708040]
-> #2 (sb_internal#2){.+.+}-{0:0}:
[ 3653.708994] lock_release+0x13d/0x4a0
[ 3653.709533] up_write+0x18/0x160
[ 3653.710017] btrfs_sync_file+0x3f3/0x5b0 [btrfs]
[ 3653.710699] __loop_update_dio+0xbd/0x170 [loop]
[ 3653.711360] lo_ioctl+0x3b1/0x8a0 [loop]
[ 3653.711929] block_ioctl+0x48/0x50
[ 3653.712442] __x64_sys_ioctl+0x83/0xb0
[ 3653.712991] do_syscall_64+0x3b/0xc0
[ 3653.713519] entry_SYSCALL_64_after_hwframe+0x44/0xae
[ 3653.714233]
-> #1 (&lo->lo_mutex){+.+.}-{3:3}:
[ 3653.715026] __mutex_lock+0x92/0x900
[ 3653.715648] lo_open+0x28/0x60 [loop]
[ 3653.716275] blkdev_get_whole+0x28/0x90
[ 3653.716867] blkdev_get_by_dev.part.0+0x142/0x320
[ 3653.717537] blkdev_open+0x5e/0xa0
[ 3653.718043] do_dentry_open+0x163/0x390
[ 3653.718604] path_openat+0x3f0/0xa80
[ 3653.719128] do_filp_open+0xa9/0x150
[ 3653.719652] do_sys_openat2+0x97/0x160
[ 3653.720197] __x64_sys_openat+0x54/0x90
[ 3653.720766] do_syscall_64+0x3b/0xc0
[ 3653.721285] entry_SYSCALL_64_after_hwframe+0x44/0xae
[ 3653.721986]
-> #0 (&disk->open_mutex){+.+.}-{3:3}:
[ 3653.722775] __lock_acquire+0x130e/0x2210
[ 3653.723348] lock_acquire+0xd7/0x310
[ 3653.723867] __mutex_lock+0x92/0x900
[ 3653.724394] blkdev_get_by_dev.part.0+0xe7/0x320
[ 3653.725041] blkdev_get_by_path+0xb8/0xd0
[ 3653.725614] btrfs_get_bdev_and_sb+0x1b/0xb0 [btrfs]
[ 3653.726332] open_fs_devices+0xd7/0x2c0 [btrfs]
[ 3653.726999] btrfs_read_chunk_tree+0x3ad/0x870 [btrfs]
[ 3653.727739] open_ctree+0xb8e/0x17bf [btrfs]
[ 3653.728384] btrfs_mount_root.cold+0x12/0xde [btrfs]
[ 3653.729130] legacy_get_tree+0x30/0x50
[ 3653.729676] vfs_get_tree+0x28/0xc0
[ 3653.730192] vfs_kern_mount.part.0+0x71/0xb0
[ 3653.730800] btrfs_mount+0x11d/0x3a0 [btrfs]
[ 3653.731427] legacy_get_tree+0x30/0x50
[ 3653.731970] vfs_get_tree+0x28/0xc0
[ 3653.732486] path_mount+0x2d4/0xbe0
[ 3653.732997] __x64_sys_mount+0x103/0x140
[ 3653.733560] do_syscall_64+0x3b/0xc0
[ 3653.734080] entry_SYSCALL_64_after_hwframe+0x44/0xae
[ 3653.734782]
other info that might help us debug this:[ 3653.735784] Chain exists of:
&disk->open_mutex --> sb_internal#2 --> btrfs-chunk-00[ 3653.737123] Possible unsafe locking scenario:
[ 3653.737865] CPU0 CPU1
[ 3653.738435] ---- ----
[ 3653.739007] lock(btrfs-chunk-00);
[ 3653.739449] lock(sb_internal#2);
[ 3653.740193] lock(btrfs-chunk-00);
[ 3653.740955] lock(&disk->open_mutex);
[ 3653.741431]
*** DEADLOCK ***[ 3653.742176] 3 locks held by mount/447465:
[ 3653.742739] #0: ffff8c6acf85c0e8 (&type->s_umount_key#44/1){+.+.}-{3:3}, at: alloc_super+0xd5/0x3b0
[ 3653.744114] #1: ffffffffc0b28f70 (uuid_mutex){+.+.}-{3:3}, at: btrfs_read_chunk_tree+0x59/0x870 [btrfs]
[ 3653.745563] #2: ffff8c6b0a9f39e0 (btrfs-chunk-00){++++}-{3:3}, at: __btrfs_tree_read_lock+0x24/0x110 [btrfs]
[ 3653.747066]
stack backtrace:
[ 3653.747723] CPU: 4 PID: 447465 Comm: mount Not tainted 5.15.0-rc7-btrfs-next-103 #1
[ 3653.748873] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014
[ 3653.750592] Call Trace:
[ 3653.750967] dump_stack_lvl+0x57/0x72
[ 3653.751526] check_noncircular+0xf3/0x110
[ 3653.752136] ? stack_trace_save+0x4b/0x70
[ 3653.752748] __lock_acquire+0x130e/0x2210
[ 3653.753356] lock_acquire+0xd7/0x310
[ 3653.753898] ? blkdev_get_by_dev.part.0+0xe7/0x320
[ 3653.754596] ? lock_is_held_type+0xe8/0x140
[ 3653.755125] ? blkdev_get_by_dev.part.0+0xe7/0x320
[ 3653.755729] ? blkdev_get_by_dev.part.0+0xe7/0x320
[ 3653.756338] __mutex_lock+0x92/0x900
[ 3653.756794] ? blkdev_get_by_dev.part.0+0xe7/0x320
[ 3653.757400] ? do_raw_spin_unlock+0x4b/0xa0
[ 3653.757930] ? _raw_spin_unlock+0x29/0x40
[ 3653.758437] ? bd_prepare_to_claim+0x129/0x150
[ 3653.758999] ? trace_module_get+0x2b/0xd0
[ 3653.759508] ? try_module_get.part.0+0x50/0x80
[ 3653.760072] blkdev_get_by_dev.part.0+0xe7/0x320
[ 3653.760661] ? devcgroup_check_permission+0xc1/0x1f0
[ 3653.761288] blkdev_get_by_path+0xb8/0xd0
[ 3653.761797] btrfs_get_bdev_and_sb+0x1b/0xb0 [btrfs]
[ 3653.762454] open_fs_devices+0xd7/0x2c0 [btrfs]
[ 3653.763055] ? clone_fs_devices+0x8f/0x170 [btrfs]
[ 3653.763689] btrfs_read_chunk_tree+0x3ad/0x870 [btrfs]
[ 3653.764370] ? kvm_sched_clock_read+0x14/0x40
[ 3653.764922] open_ctree+0xb8e/0x17bf [btrfs]
[ 3653.765493] ? super_setup_bdi_name+0x79/0xd0
[ 3653.766043] btrfs_mount_root.cold+0x12/0xde [btrfs]
[ 3653.766780] ? rcu_read_lock_sched_held+0x3f/0x80
[ 3653.767488] ? kfree+0x1f2/0x3c0
[ 3653.767979] legacy_get_tree+0x30/0x50
[ 3653.768548] vfs_get_tree+0x28/0xc0
[ 3653.769076] vfs_kern_mount.part.0+0x71/0xb0
[ 3653.769718] btrfs_mount+0x11d/0x3a0 [btrfs]
[ 3653.770381] ? rcu_read_lock_sched_held+0x3f/0x80
[ 3653.771086] ? kfree+0x1f2/0x3c0
[ 3653.771574] legacy_get_tree+0x30/0x50
[ 3653.772136] vfs_get_tree+0x28/0xc0
[ 3653.772673] path_mount+0x2d4/0xbe0
[ 3653.773201] __x64_sys_mount+0x103/0x140
[ 3653.773793] do_syscall_64+0x3b/0xc0
[ 3653.774333] entry_SYSCALL_64_after_hwframe+0x44/0xae
[ 3653.775094] RIP: 0033:0x7f648bc45aaaThis happens because through btrfs_read_chunk_tree(), which is called only during mount, ends up acquiring the mutex open_mutex of a block device while holding a read lock on a leaf of the chunk tree while other paths need to acquire other locks before locking extent buffers of the chunk tree.
Since at mount time when we call btrfs_read_chunk_tree() we know that we don't have other tasks running in parallel and modifying the chunk tree, we can simply skip locking of chunk tree extent buffers. So do that and move the assertion that checks the fs is not yet mounted to the top block of btrfs_read_chunk_tree(), with a comment before doing it.
--- fs/btrfs/volumes.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-)
fs/btrfs/volumes.c +13 -5
@@ -7488,6 +7488,19 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)*/ fs_info->fs_devices->total_rw_bytes =0 ; +/* +* Lockdep complains about possible circular locking dependency between +* a disk's open_mutex (struct gendisk.open_mutex), the rw semaphores +* used for freeze procection of a fs (struct super_block.s_writers), +* which we take when starting a transaction, and extent buffers of the +* chunk tree if we call read_one_dev() while holding a lock on an +* extent buffer of the chunk tree. Since we are mounting the filesystem +* and at this point there can't be any concurrent task modifying the +* chunk tree, to keep it simple, just skip locking on the chunk tree. +*/ +ASSERT (!test_bit (BTRFS_FS_OPEN , &fs_info->flags)); + path->skip_locking =1 ; +/* * Read all device items, and then all the chunk items. All * device items are found before any chunk item (their object id
@@ -7513,10 +7526,6 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info) goto error;break ; } -/* -* The nodes on level 1 are not locked but we don't need to do -* that during mount time as nothing else can access the tree -*/ node = path->nodes[1 ];if (node) {if (last_ra_node != node->start) {
@@ -7544,7 +7553,6 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)* requirement for chunk allocation, see the comment on * top of btrfs_chunk_alloc() for details. */ -ASSERT (!test_bit (BTRFS_FS_OPEN , &fs_info->flags)); chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk); ret =read_one_chunk (&found_key, leaf, chunk);if (ret)
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 30/207 btrfs: check-integrity: fix a warning on write caching disabled disk
In reply to Greg Kroah-HartmanFrom: Wang Yugui <[email protected]>
[ Upstream commit a91cf0ffbc244792e0b3ecf7d0fddb2f344b461f ]
When a disk has write caching disabled, we skip submission of a bio with flush and sync requests before writing the superblock, since it's not needed. However when the integrity checker is enabled, this results in reports that there are metadata blocks referred by a superblock that were not properly flushed. So don't skip the bio submission only when the integrity checker is enabled for the sake of simplicity, since this is a debug tool and not meant for use in non-debug builds.
fstests/btrfs/220 trigger a check-integrity warning like the following when CONFIG_BTRFS_FS_CHECK_INTEGRITY=y and the disk with WCE=0.
btrfs: attempt to write superblock which references block M @5242880 (sdb2/5242880/0) which is not flushed out of disk's write cache (block flush_gen=1, dev->flush_gen=0)!
------------[ cut here ]------------ WARNING: CPU: 28 PID: 843680 at fs/btrfs/check-integrity.c:2196 btrfsic_process_written_superblock+0x22a/0x2a0 [btrfs] CPU: 28 PID: 843680 Comm: umount Not tainted 5.15.0-0.rc5.39.el8.x86_64 #1 Hardware name: Dell Inc. Precision T7610/0NK70N, BIOS A18 09/11/2019 RIP: 0010:btrfsic_process_written_superblock+0x22a/0x2a0 [btrfs] RSP: 0018:ffffb642afb47940 EFLAGS: 00010246 RAX: 0000000000000000 RBX: 0000000000000002 RCX: 0000000000000000 RDX: 00000000ffffffff RSI: ffff8b722fc97d00 RDI: ffff8b722fc97d00 RBP: ffff8b5601c00000 R08: 0000000000000000 R09: c0000000ffff7fff R10: 0000000000000001 R11: ffffb642afb476f8 R12: ffffffffffffffff R13: ffffb642afb47974 R14: ffff8b5499254c00 R15: 0000000000000003 FS: 00007f00a06d4080(0000) GS:ffff8b722fc80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fff5cff5ff0 CR3: 00000001c0c2a006 CR4: 00000000001706e0 Call Trace: btrfsic_process_written_block+0x2f7/0x850 [btrfs] __btrfsic_submit_bio.part.19+0x310/0x330 [btrfs] ? bio_associate_blkg_from_css+0xa4/0x2c0 btrfsic_submit_bio+0x18/0x30 [btrfs] write_dev_supers+0x81/0x2a0 [btrfs] ? find_get_pages_range_tag+0x219/0x280 ? pagevec_lookup_range_tag+0x24/0x30 ? __filemap_fdatawait_range+0x6d/0xf0 ? __raw_callee_save___native_queued_spin_unlock+0x11/0x1e ? find_first_extent_bit+0x9b/0x160 [btrfs] ? __raw_callee_save___native_queued_spin_unlock+0x11/0x1e write_all_supers+0x1b3/0xa70 [btrfs] ? __raw_callee_save___native_queued_spin_unlock+0x11/0x1e btrfs_commit_transaction+0x59d/0xac0 [btrfs] close_ctree+0x11d/0x339 [btrfs] generic_shutdown_super+0x71/0x110 kill_anon_super+0x14/0x30 btrfs_kill_super+0x12/0x20 [btrfs] deactivate_locked_super+0x31/0x70 cleanup_mnt+0xb8/0x140 task_work_run+0x6d/0xb0 exit_to_user_mode_prepare+0x1f0/0x200 syscall_exit_to_user_mode+0x12/0x30 do_syscall_64+0x46/0x80 entry_SYSCALL_64_after_hwframe+0x44/0xae RIP: 0033:0x7f009f711dfb RSP: 002b:00007fff5cff7928 EFLAGS: 00000246 ORIG_RAX: 00000000000000a6 RAX: 0000000000000000 RBX: 000055b68c6c9970 RCX: 00007f009f711dfb RDX: 0000000000000001 RSI: 0000000000000000 RDI: 000055b68c6c9b50 RBP: 0000000000000000 R08: 000055b68c6ca900 R09: 00007f009f795580 R10: 0000000000000000 R11: 0000000000000246 R12: 000055b68c6c9b50 R13: 00007f00a04bf184 R14: 0000000000000000 R15: 00000000ffffffff ---[ end trace 2c4b82abcef9eec4 ]--- S-65536(sdb2/65536/1) --> M-1064960(sdb2/1064960/1)
--- fs/btrfs/disk-io.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
fs/btrfs/disk-io.c +13 -1
@@ -3970,11 +3970,23 @@ static void btrfs_end_empty_barrier(struct bio *bio)*/ static void write_dev_flush (struct btrfs_device *device) { -struct request_queue *q =bdev_get_queue (device->bdev);struct bio *bio = device->flush_bio; +#ifndef CONFIG_BTRFS_FS_CHECK_INTEGRITY +/* +* When a disk has write caching disabled, we skip submission of a bio +* with flush and sync requests before writing the superblock, since +* it's not needed. However when the integrity checker is enabled, this +* results in reports that there are metadata blocks referred by a +* superblock that were not properly flushed. So don't skip the bio +* submission only when the integrity checker is enabled for the sake +* of simplicity, since this is a debug tool and not meant for use in +* non-debug builds. +*/ +struct request_queue *q =bdev_get_queue (device->bdev);if (!test_bit (QUEUE_FLAG_WC , &q->queue_flags))return ; +#endif bio_reset (bio); bio->bi_end_io = btrfs_end_empty_barrier;
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 31/207 thermal: core: Reset previous low and high trip during thermal zone init
In reply to Greg Kroah-HartmanFrom: Manaf Meethalavalappu Pallikunhi <[email protected]>
[ Upstream commit 99b63316c39988039965693f5f43d8b4ccb1c86c ]
During the suspend is in process, thermal_zone_device_update bails out thermal zone re-evaluation for any sensor trip violation without setting next valid trip to that sensor. It assumes during resume it will re-evaluate same thermal zone and update trip. But when it is in suspend temperature goes down and on resume path while updating thermal zone if temperature is less than previously violated trip, thermal zone set trip function evaluates the same previous high and previous low trip as new high and low trip. Since there is no change in high/low trip, it bails out from thermal zone set trip API without setting any trip. It leads to a case where sensor high trip or low trip is disabled forever even though thermal zone has a valid high or low trip.
During thermal zone device init, reset thermal zone previous high and low trip. It resolves above mentioned scenario.
--- drivers/thermal/thermal_core.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/thermal/thermal_core.c +2 -0
@@ -419,6 +419,8 @@ static void thermal_zone_device_init(struct thermal_zone_device *tz) {struct thermal_instance *pos; tz->temperature =THERMAL_TEMP_INVALID ; + tz->prev_low_trip = -INT_MAX ; + tz->prev_high_trip =INT_MAX ;list_for_each_entry (pos, &tz->thermal_instances, tz_node) pos->initialized = false; }
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 32/207 scsi: iscsi: Unblock session then wake up error handler
In reply to Greg Kroah-HartmanFrom: Mike Christie <[email protected]>
[ Upstream commit a0c2f8b6709a9a4af175497ca65f93804f57b248 ]
We can race where iscsi_session_recovery_timedout() has woken up the error handler thread and it's now setting the devices to offline, and session_recovery_timedout()'s call to scsi_target_unblock() is also trying to set the device's state to transport-offline. We can then get a mix of states.
For the case where we can't relogin we want the devices to be in transport-offline so when we have repaired the connection __iscsi_unblock_session() can set the state back to running.
Set the device state then call into libiscsi to wake up the error handler.
--- drivers/scsi/scsi_transport_iscsi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/scsi/scsi_transport_iscsi.c +3 -3
@@ -1899,12 +1899,12 @@ static void session_recovery_timedout(struct work_struct *work) }spin_unlock_irqrestore (&session->lock, flags); -if (session->transport->session_recovery_timedout) - session->transport->session_recovery_timedout (session); -ISCSI_DBG_TRANS_SESSION (session,"Unblocking SCSI target\n" );scsi_target_unblock (&session->dev,SDEV_TRANSPORT_OFFLINE );ISCSI_DBG_TRANS_SESSION (session,"Completed unblocking SCSI target\n" ); + +if (session->transport->session_recovery_timedout) + session->transport->session_recovery_timedout (session); }static void __iscsi_unblock_session (struct work_struct *work)
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 33/207 net: usb: r8152: Add MAC passthrough support for more Lenovo Docks
In reply to Greg Kroah-HartmanFrom: Aaron Ma <[email protected]>
[ Upstream commit f77b83b5bbab53d2be339184838b19ed2c62c0a5 ]
Like ThinkaPad Thunderbolt 4 Dock, more Lenovo docks start to use the original Realtek USB ethernet chip ID 0bda:8153.
Lenovo Docks always use their own IDs for usb hub, even for older Docks. If parent hub is from Lenovo, then r8152 should try MAC passthrough. Verified on Lenovo TBT3 dock too.
--- drivers/net/usb/r8152.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
drivers/net/usb/r8152.c +3 -6
@@ -9603,12 +9603,9 @@ static int rtl8152_probe(struct usb_interface *intf, netdev->hw_features &= ~NETIF_F_RXCSUM ; } -if (le16_to_cpu (udev->descriptor.idVendor) ==VENDOR_ID_LENOVO ) { -switch (le16_to_cpu (udev->descriptor.idProduct)) { -case DEVICE_ID_THINKPAD_THUNDERBOLT3_DOCK_GEN2 : -case DEVICE_ID_THINKPAD_USB_C_DOCK_GEN2 : - tp->lenovo_macpassthru =1 ; - } +if (udev->parent && +le16_to_cpu (udev->parent->descriptor.idVendor) ==VENDOR_ID_LENOVO ) { + tp->lenovo_macpassthru =1 ; } if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x3011 && udev->serial &&
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 34/207 drm/amd/pm: Remove artificial freq level on Navi1x
In reply to Greg Kroah-HartmanFrom: Lijo Lazar <[email protected]>
[ Upstream commit be83a5676767c99c2417083c29d42aa1e109a69d ]
Print Navi1x fine grained clocks in a consistent manner with other SOCs. Don't show aritificial DPM level when the current clock equals min or max.
--- drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +8 -5
@@ -1265,7 +1265,7 @@ static int navi10_print_clk_levels(struct smu_context *smu, enum smu_clk_type clk_type, char *buf) { uint16_t *curve_settings; -int i, size =0 , ret =0 ; +int i, levels, size =0 , ret =0 ;uint32_t cur_value =0 , value =0 , count =0 ;uint32_t freq_values[3 ] = {0 };uint32_t mark_index =0 ;
@@ -1319,14 +1319,17 @@ static int navi10_print_clk_levels(struct smu_context *smu, freq_values[1 ] = cur_value; mark_index = cur_value == freq_values[0 ] ?0 : cur_value == freq_values[2 ] ?2 :1 ; -if (mark_index !=1 ) - freq_values[1 ] = (freq_values[0 ] + freq_values[2 ]) /2 ; -for (i =0 ; i <3 ; i++) { + levels =3 ; +if (mark_index !=1 ) { + levels =2 ; + freq_values[1 ] = freq_values[2 ]; + } + +for (i =0 ; i < levels; i++) { size +=sysfs_emit_at (buf, size,"%d: %uMhz %s\n" , i, freq_values[i], i == mark_index ?"*" :"" ); } - }break ;case SMU_PCIE :
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 35/207 drm/amd/amdkfd: Fix kernel panic when reset failed and been triggered again
In reply to Greg Kroah-HartmanFrom: shaoyunl <[email protected]>
[ Upstream commit 2cf49e00d40d5132e3d067b5aa6d84791929ab15 ]
In SRIOV configuration, the reset may failed to bring asic back to normal but stop cpsch already been called, the start_cpsch will not be called since there is no resume in this case. When reset been triggered again, driver should avoid to do uninitialization again.
--- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +5 -0
@@ -1225,6 +1225,11 @@ static int stop_cpsch(struct device_queue_manager *dqm)bool hanging;dqm_lock (dqm); +if (!dqm->sched_running) { +dqm_unlock (dqm); +return 0 ; + } +if (!dqm->is_hws_hang)unmap_queues_cpsch (dqm,KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES ,0 ); hanging = dqm->is_hws_hang || dqm->is_resetting;
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 36/207 drm/amd/amdgpu: fix potential memleak
In reply to Greg Kroah-HartmanFrom: Bernard Zhao <[email protected]>
[ Upstream commit 27dfaedc0d321b4ea4e10c53e4679d6911ab17aa ]
In function amdgpu_get_xgmi_hive, when kobject_init_and_add failed There is a potential memleak if not call kobject_put.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +1 -0
@@ -386,6 +386,7 @@ struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev) "%s", "xgmi_hive_info");if (ret) {dev_err (adev->dev,"XGMI: failed initializing kobject for xgmi hive\n" ); +kobject_put (&hive->kobj);kfree (hive); hive =NULL ; goto pro_end;
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 37/207 ata: ahci: Add Green Sardine vendor ID as board_ahci_mobile
In reply to Greg Kroah-HartmanFrom: Mario Limonciello <[email protected]>
[ Upstream commit 1527f69204fe35f341cb599f1cb01bd02daf4374 ]
AMD requires that the SATA controller be configured for devsleep in order for S0i3 entry to work properly.
commit b1a9585cc396 ("ata: ahci: Enable DEVSLP by default on x86 with SLP_S0") sets up a kernel policy to enable devsleep on Intel mobile platforms that are using s0ix. Add the PCI ID for the SATA controller in Green Sardine platforms to extend this policy by default for AMD based systems using s0i3 as well.
--- drivers/ata/ahci.c | 1 + 1 file changed, 1 insertion(+)
drivers/ata/ahci.c +1 -0
@@ -442,6 +442,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {/* AMD */ { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */ { PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */ + { PCI_VDEVICE(AMD, 0x7901), board_ahci_mobile }, /* AMD Green Sardine *//* AMD is using RAID class only for ahci controllers */ { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 38/207 ata: libahci: Adjust behavior when StorageD3Enable _DSD is set
In reply to Greg Kroah-HartmanFrom: Mario Limonciello <[email protected]>
[ Upstream commit 7c5f641a5914ce0303b06bcfcd7674ee64aeebe9 ]
The StorageD3Enable _DSD is used for the vendor to indicate that the disk should be opted into or out of a different behavior based upon the platform design.
For AMD's Renoir and Green Sardine platforms it's important that any attached SATA storage has transitioned into DevSlp when s2idle is used.
If the disk is left in active/partial/slumber, then the system is not able to resume properly.
When the StorageD3Enable _DSD is detected, check the system is using s2idle and DevSlp is enabled and if so explicitly wait long enough for the disk to enter DevSlp.
--- drivers/ata/libahci.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
drivers/ata/libahci.c +15 -0
@@ -2305,6 +2305,18 @@ int ahci_port_resume(struct ata_port *ap)EXPORT_SYMBOL_GPL (ahci_port_resume);#ifdef CONFIG_PM +static void ahci_handle_s2idle (struct ata_port *ap) +{ +void __iomem *port_mmio =ahci_port_base (ap); +u32 devslp; + +if (pm_suspend_via_firmware ()) +return ; + devslp =readl (port_mmio +PORT_DEVSLP ); +if ((devslp &PORT_DEVSLP_ADSE )) +ata_msleep (ap, devslp_idle_timeout); +} +static int ahci_port_suspend (struct ata_port *ap,pm_message_t mesg) {const char *emsg =NULL ;
@@ -2318,6 +2330,9 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)ata_port_freeze (ap); } +if (acpi_storage_d3 (ap->host->dev)) +ahci_handle_s2idle (ap); +ahci_rpm_put_port (ap);return rc; }
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 39/207 ethernet: hisilicon: hns: hns_dsaf_misc: fix a possible array overflow in hns_dsaf_ge_srst_by_port()
In reply to Greg Kroah-HartmanFrom: Teng Qi <[email protected]>
[ Upstream commit a66998e0fbf213d47d02813b9679426129d0d114 ]
The if statement:
if (port >= DSAF_GE_NUM)
return;
limits the value of port less than DSAF_GE_NUM (i.e., 8). However, if the value of port is 6 or 7, an array overflow could occur:
port_rst_off = dsaf_dev->mac_cb[port]->port_rst_off;
because the length of dsaf_dev->mac_cb is DSAF_MAX_PORT_NUM (i.e., 6).
To fix this possible array overflow, we first check port and if it is greater than or equal to DSAF_MAX_PORT_NUM, the function returns.
--- drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c +4 -0
@@ -400,6 +400,10 @@ static void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port,return ;if (!HNS_DSAF_IS_DEBUG (dsaf_dev)) { +/* DSAF_MAX_PORT_NUM is 6, but DSAF_GE_NUM is 8. +We need check to prevent array overflow */ +if (port >=DSAF_MAX_PORT_NUM ) +return ; reg_val_1 =0x1 << port; port_rst_off = dsaf_dev->mac_cb[port]->port_rst_off;/* there is difference between V1 and V2 in register.*/
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 40/207 ipv6: check return value of ipv6_skip_exthdr
In reply to Greg Kroah-HartmanFrom: Jordy Zomer <[email protected]>
[ Upstream commit 5f9c55c8066bcd93ac25234a02585701fe2e31df ]
The offset value is used in pointer math on skb->data. Since ipv6_skip_exthdr may return -1 the pointer to uh and th may not point to the actual udp and tcp headers and potentially overwrite other stuff. This is why I think this should be checked.
EDIT: added {}'s, thanks Kees
--- net/ipv6/esp6.c | 6 ++++++ 1 file changed, 6 insertions(+)
net/ipv6/esp6.c +6 -0
@@ -808,6 +808,12 @@ int esp6_input_done2(struct sk_buff *skb, int err)struct tcphdr *th; offset =ipv6_skip_exthdr (skb, offset, &nexthdr, &frag_off); + +if (offset <0 ) { + err = -EINVAL ; + goto out; + } + uh = (void *)(skb->data + offset); th = (void *)(skb->data + offset); hdr_len += offset;
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 41/207 net: tulip: de4x5: fix the problem that the array lp->phy[8] may be out of bound
In reply to Greg Kroah-HartmanFrom: zhangyue <[email protected]>
[ Upstream commit 61217be886b5f7402843677e4be7e7e83de9cb41 ]
In line 5001, if all id in the array 'lp->phy[8]' is not 0, when the 'for' end, the 'k' is 8.
At this time, the array 'lp->phy[8]' may be out of bound.
--- drivers/net/ethernet/dec/tulip/de4x5.c | 30 +++++++++++++++----------- 1 file changed, 17 insertions(+), 13 deletions(-)
drivers/net/ethernet/dec/tulip/de4x5.c +17 -13
@@ -4999,19 +4999,23 @@ mii_get_phy(struct net_device *dev) }if ((j == limit) && (i <DE4X5_MAX_MII )) {for (k=0 ; k <DE4X5_MAX_PHY && lp->phy[k].id; k++); - lp->phy[k].addr = i; - lp->phy[k].id = id; - lp->phy[k].spd.reg =GENERIC_REG ;/* ANLPA register */ - lp->phy[k].spd.mask =GENERIC_MASK ;/* 100Mb/s technologies */ - lp->phy[k].spd.value =GENERIC_VALUE ;/* TX & T4, H/F Duplex */ - lp->mii_cnt++; - lp->active++; -printk ("%s: Using generic MII device control. If the board doesn't operate,\nplease mail the following dump to the author:\n" , dev->name); - j = de4x5_debug; - de4x5_debug |=DEBUG_MII ; -de4x5_dbg_mii (dev, k); - de4x5_debug = j; -printk ("\n" ); +if (k <DE4X5_MAX_PHY ) { + lp->phy[k].addr = i; + lp->phy[k].id = id; + lp->phy[k].spd.reg =GENERIC_REG ;/* ANLPA register */ + lp->phy[k].spd.mask =GENERIC_MASK ;/* 100Mb/s technologies */ + lp->phy[k].spd.value =GENERIC_VALUE ;/* TX & T4, H/F Duplex */ + lp->mii_cnt++; + lp->active++; +printk ("%s: Using generic MII device control. If the board doesn't operate,\nplease mail the following dump to the author:\n" , dev->name); + j = de4x5_debug; + de4x5_debug |=DEBUG_MII ; +de4x5_dbg_mii (dev, k); + de4x5_debug = j; +printk ("\n" ); + }else { + goto purgatory; + } } } purgatory:
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 42/207 net: ethernet: dec: tulip: de4x5: fix possible array overflows in type3_infoblock()
In reply to Greg Kroah-HartmanFrom: Teng Qi <[email protected]>
[ Upstream commit 0fa68da72c3be09e06dd833258ee89c33374195f ]
The definition of macro MOTO_SROM_BUG is:
#define MOTO_SROM_BUG (lp->active == 8 && (get_unaligned_le32(
dev->dev_addr) & 0x00ffffff) == 0x3e0008)
and the if statement
if (MOTO_SROM_BUG) lp->active = 0;
using this macro indicates lp->active could be 8. If lp->active is 8 and the second comparison of this macro is false. lp->active will remain 8 in:
lp->phy[lp->active].gep = (*p ? p : NULL); p += (2 * (*p) + 1); lp->phy[lp->active].rst = (*p ? p : NULL); p += (2 * (*p) + 1); lp->phy[lp->active].mc = get_unaligned_le16(p); p += 2; lp->phy[lp->active].ana = get_unaligned_le16(p); p += 2; lp->phy[lp->active].fdx = get_unaligned_le16(p); p += 2; lp->phy[lp->active].ttm = get_unaligned_le16(p); p += 2; lp->phy[lp->active].mci = *p;
However, the length of array lp->phy is 8, so array overflows can occur. To fix these possible array overflows, we first check lp->active and then return -EINVAL if it is greater or equal to ARRAY_SIZE(lp->phy) (i.e. 8).
--- drivers/net/ethernet/dec/tulip/de4x5.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/ethernet/dec/tulip/de4x5.c +4 -0
@@ -4708,6 +4708,10 @@ type3_infoblock(struct net_device *dev, u_char count, u_char *p) lp->ibn =3 ; lp->active = *p++;if (MOTO_SROM_BUG ) lp->active =0 ; +/* if (MOTO_SROM_BUG) statement indicates lp->active could +* be 8 (i.e. the size of array lp->phy) */ +if (WARN_ON (lp->active >=ARRAY_SIZE (lp->phy))) +return -EINVAL ; lp->phy[lp->active].gep = (*p ? p :NULL ); p += (2 * (*p) +1 ); lp->phy[lp->active].rst = (*p ? p :NULL ); p += (2 * (*p) +1 ); lp->phy[lp->active].mc =get_unaligned_le16 (p); p +=2 ;
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 43/207 perf sort: Fix the weight sort key behavior
In reply to Greg Kroah-HartmanFrom: Namhyung Kim <[email protected]>
[ Upstream commit 784e8adda4cdb3e2510742023729851b6c08803c ]
Currently, the 'weight' field in the perf sample has latency information for some instructions like in memory accesses. And perf tool has 'weight' and 'local_weight' sort keys to display the info.
But it's somewhat confusing what it shows exactly. In my understanding, 'local_weight' shows a weight in a single sample, and (global) 'weight' shows a sum of the weights in the hist_entry.
For example:
$ perf mem record -t load dd if=/dev/zero of=/dev/null bs=4k count=1M
$ perf report --stdio -n -s +local_weight
...
#
# Overhead Samples Command Shared Object Symbol Local Weight
# ........ ....... ....... ................ ......................... ............
#
21.23% 313 dd [kernel.vmlinux] [k] lockref_get_not_zero 32
12.43% 183 dd [kernel.vmlinux] [k] lockref_get_not_zero 35
11.97% 159 dd [kernel.vmlinux] [k] lockref_get_not_zero 36
10.40% 141 dd [kernel.vmlinux] [k] lockref_put_return 32
7.63% 113 dd [kernel.vmlinux] [k] lockref_get_not_zero 33
6.37% 92 dd [kernel.vmlinux] [k] lockref_get_not_zero 34
6.15% 90 dd [kernel.vmlinux] [k] lockref_put_return 33
...So let's look at the 'lockref_get_not_zero' symbols. The top entry shows that 313 samples were captured with 'local_weight' 32, so the total weight should be 313 x 32 = 10016. But it's not the case:
$ perf report --stdio -n -s +local_weight,weight -S lockref_get_not_zero
...
#
# Overhead Samples Command Shared Object Local Weight Weight
# ........ ....... ....... ................ ............ ......
#
1.36% 4 dd [kernel.vmlinux] 36 144
0.47% 4 dd [kernel.vmlinux] 37 148
0.42% 4 dd [kernel.vmlinux] 32 128
0.40% 4 dd [kernel.vmlinux] 34 136
0.35% 4 dd [kernel.vmlinux] 36 144
0.34% 4 dd [kernel.vmlinux] 35 140
0.30% 4 dd [kernel.vmlinux] 36 144
0.30% 4 dd [kernel.vmlinux] 34 136
0.30% 4 dd [kernel.vmlinux] 32 128
0.30% 4 dd [kernel.vmlinux] 32 128
...With the 'weight' sort key, it's divided to 4 samples even with the same info ('comm', 'dso', 'sym' and 'local_weight'). I don't think this is what we want.
I found this because of the way it aggregates the 'weight' value. Since it's not a period, we should not add them in the he->stat. Otherwise, two 32 'weight' entries will create a 64 'weight' entry.
After that, new 32 'weight' samples don't have a matching entry so it'd create a new entry and make it a 64 'weight' entry again and again. Later, they will be merged into 128 'weight' entries during the hists__collapse_resort() with 4 samples, multiple times like above.
Let's keep the weight and display it differently. For 'local_weight', it can show the weight as is, and for (global) 'weight' it can display the number multiplied by the number of samples.
With this change, I can see the expected numbers.
$ perf report --stdio -n -s +local_weight,weight -S lockref_get_not_zero
...
#
# Overhead Samples Command Shared Object Local Weight Weight
# ........ ....... ....... ................ ............ .....
#
21.23% 313 dd [kernel.vmlinux] 32 10016
12.43% 183 dd [kernel.vmlinux] 35 6405
11.97% 159 dd [kernel.vmlinux] 36 5724
7.63% 113 dd [kernel.vmlinux] 33 3729
6.37% 92 dd [kernel.vmlinux] 34 3128
4.17% 59 dd [kernel.vmlinux] 37 2183
0.08% 1 dd [kernel.vmlinux] 269 269
0.08% 1 dd [kernel.vmlinux] 38 38--- tools/perf/util/hist.c | 14 +++++--------- tools/perf/util/sort.c | 24 +++++++----------------- tools/perf/util/sort.h | 2 +- 3 files changed, 13 insertions(+), 27 deletions(-)
tools/perf/util/hist.c +5 -9
@@ -290,11 +290,9 @@ static long hist_time(unsigned long htime) }static void he_stat__add_period (struct he_stat *he_stat,u64 period, -u64 weight,u64 ins_lat,u64 p_stage_cyc) +u64 ins_lat,u64 p_stage_cyc) { - he_stat->period += period; - he_stat->weight += weight; he_stat->nr_events +=1 ; he_stat->ins_lat += ins_lat; he_stat->p_stage_cyc += p_stage_cyc;
@@ -308,9 +306,8 @@ static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src) dest->period_guest_sys += src->period_guest_sys; dest->period_guest_us += src->period_guest_us; dest->nr_events += src->nr_events; - dest->weight += src->weight; dest->ins_lat += src->ins_lat; - dest->p_stage_cyc += src->p_stage_cyc; + dest->p_stage_cyc += src->p_stage_cyc; }static void he_stat__decay (struct he_stat *he_stat)
@@ -598,7 +595,6 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,struct hist_entry *he;int64_t cmp;u64 period = entry->stat.period; -u64 weight = entry->stat.weight;u64 ins_lat = entry->stat.ins_lat;u64 p_stage_cyc = entry->stat.p_stage_cyc;bool leftmost = true;
@@ -619,11 +615,11 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,if (!cmp) {if (sample_self) { -he_stat__add_period (&he->stat, period, weight, ins_lat, p_stage_cyc); +he_stat__add_period (&he->stat, period, ins_lat, p_stage_cyc);hist_entry__add_callchain_period (he, period); }if (symbol_conf.cumulate_callchain) -he_stat__add_period (he->stat_acc, period, weight, ins_lat, p_stage_cyc); +he_stat__add_period (he->stat_acc, period, ins_lat, p_stage_cyc);/* * This mem info was allocated from sample__resolve_mem
@@ -733,7 +729,6 @@ __hists__add_entry(struct hists *hists, .stat = { .nr_events = 1, .period = sample->period, - .weight = sample->weight, .ins_lat = sample->ins_lat, .p_stage_cyc = sample->p_stage_cyc, },
@@ -748,6 +743,7 @@ __hists__add_entry(struct hists *hists, .raw_size = sample->raw_size, .ops = ops, .time = hist_time(sample->time), + .weight = sample->weight, }, *he = hists__findnew_entry(hists, &entry, al, sample_self);if (!hists->has_callchains && he && he->callchain_size !=0 )
tools/perf/util/sort.c +7 -17
@@ -1325,45 +1325,35 @@ struct sort_entry sort_mispredict = { .se_width_idx = HISTC_MISPREDICT, }; -static u64 he_weight (struct hist_entry *he) -{ -return he->stat.nr_events ? he->stat.weight / he->stat.nr_events :0 ; -} -static int64_t -sort__local_weight_cmp (struct hist_entry *left,struct hist_entry *right) +sort__weight_cmp (struct hist_entry *left,struct hist_entry *right) { -return he_weight (left) -he_weight (right); +return left->weight - right->weight; }static int hist_entry__local_weight_snprintf (struct hist_entry *he,char *bf,size_t size,unsigned int width) { -return repsep_snprintf (bf, size,"%-*llu" , width,he_weight (he)); +return repsep_snprintf (bf, size,"%-*llu" , width, he->weight); }struct sort_entry sort_local_weight = { .se_header ="Local Weight" , - .se_cmp = sort__local_weight_cmp, + .se_cmp = sort__weight_cmp, .se_snprintf = hist_entry__local_weight_snprintf, .se_width_idx =HISTC_LOCAL_WEIGHT , }; -static int64_t -sort__global_weight_cmp (struct hist_entry *left,struct hist_entry *right) -{ -return left->stat.weight - right->stat.weight; -} -static int hist_entry__global_weight_snprintf (struct hist_entry *he,char *bf,size_t size,unsigned int width) { -return repsep_snprintf (bf, size,"%-*llu" , width, he->stat.weight); +return repsep_snprintf (bf, size,"%-*llu" , width, + he->weight * he->stat.nr_events); }struct sort_entry sort_global_weight = { .se_header ="Weight" , - .se_cmp = sort__global_weight_cmp, + .se_cmp = sort__weight_cmp, .se_snprintf = hist_entry__global_weight_snprintf, .se_width_idx =HISTC_GLOBAL_WEIGHT , };
tools/perf/util/sort.h +1 -1
@@ -49,7 +49,6 @@ struct he_stat {u64 period_us;u64 period_guest_sys;u64 period_guest_us; -u64 weight;u64 ins_lat;u64 p_stage_cyc;u32 nr_events;
@@ -109,6 +108,7 @@ struct hist_entry {s32 socket;s32 cpu;u64 code_page_size; +u64 weight;u8 cpumode;u8 depth;
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 44/207 perf sort: Fix the ins_lat sort key behavior
In reply to Greg Kroah-HartmanFrom: Namhyung Kim <[email protected]>
[ Upstream commit 4d03c75363eeca861c843319a0e6f4426234ed6c ]
Handle 'ins_lat' (for instruction latency) and 'local_ins_lat' sort keys with the same rationale as for the 'weight' and 'local_weight', see the previous fix in this series for a full explanation.
But I couldn't test it actually, so only build tested.
--- tools/perf/util/hist.c | 11 ++++------- tools/perf/util/sort.c | 24 +++++++----------------- tools/perf/util/sort.h | 2 +- 3 files changed, 12 insertions(+), 25 deletions(-)
tools/perf/util/hist.c +4 -7
@@ -290,11 +290,10 @@ static long hist_time(unsigned long htime) }static void he_stat__add_period (struct he_stat *he_stat,u64 period, -u64 ins_lat,u64 p_stage_cyc) +u64 p_stage_cyc) { he_stat->period += period; he_stat->nr_events +=1 ; - he_stat->ins_lat += ins_lat; he_stat->p_stage_cyc += p_stage_cyc; }
@@ -306,7 +305,6 @@ static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src) dest->period_guest_sys += src->period_guest_sys; dest->period_guest_us += src->period_guest_us; dest->nr_events += src->nr_events; - dest->ins_lat += src->ins_lat; dest->p_stage_cyc += src->p_stage_cyc; }
@@ -595,7 +593,6 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,struct hist_entry *he;int64_t cmp;u64 period = entry->stat.period; -u64 ins_lat = entry->stat.ins_lat;u64 p_stage_cyc = entry->stat.p_stage_cyc;bool leftmost = true;
@@ -615,11 +612,11 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,if (!cmp) {if (sample_self) { -he_stat__add_period (&he->stat, period, ins_lat, p_stage_cyc); +he_stat__add_period (&he->stat, period, p_stage_cyc);hist_entry__add_callchain_period (he, period); }if (symbol_conf.cumulate_callchain) -he_stat__add_period (he->stat_acc, period, ins_lat, p_stage_cyc); +he_stat__add_period (he->stat_acc, period, p_stage_cyc);/* * This mem info was allocated from sample__resolve_mem
@@ -729,7 +726,6 @@ __hists__add_entry(struct hists *hists, .stat = { .nr_events = 1, .period = sample->period, - .ins_lat = sample->ins_lat, .p_stage_cyc = sample->p_stage_cyc, }, .parent = sym_parent,
@@ -744,6 +740,7 @@ __hists__add_entry(struct hists *hists, .ops = ops, .time = hist_time(sample->time), .weight = sample->weight, + .ins_lat = sample->ins_lat, }, *he = hists__findnew_entry(hists, &entry, al, sample_self);if (!hists->has_callchains && he && he->callchain_size !=0 )
tools/perf/util/sort.c +7 -17
@@ -1358,45 +1358,35 @@ struct sort_entry sort_global_weight = { .se_width_idx = HISTC_GLOBAL_WEIGHT, }; -static u64 he_ins_lat (struct hist_entry *he) -{ -return he->stat.nr_events ? he->stat.ins_lat / he->stat.nr_events :0 ; -} -static int64_t -sort__local_ins_lat_cmp (struct hist_entry *left,struct hist_entry *right) +sort__ins_lat_cmp (struct hist_entry *left,struct hist_entry *right) { -return he_ins_lat (left) -he_ins_lat (right); +return left->ins_lat - right->ins_lat; }static int hist_entry__local_ins_lat_snprintf (struct hist_entry *he,char *bf,size_t size,unsigned int width) { -return repsep_snprintf (bf, size,"%-*u" , width,he_ins_lat (he)); +return repsep_snprintf (bf, size,"%-*u" , width, he->ins_lat); }struct sort_entry sort_local_ins_lat = { .se_header ="Local INSTR Latency" , - .se_cmp = sort__local_ins_lat_cmp, + .se_cmp = sort__ins_lat_cmp, .se_snprintf = hist_entry__local_ins_lat_snprintf, .se_width_idx =HISTC_LOCAL_INS_LAT , }; -static int64_t -sort__global_ins_lat_cmp (struct hist_entry *left,struct hist_entry *right) -{ -return left->stat.ins_lat - right->stat.ins_lat; -} -static int hist_entry__global_ins_lat_snprintf (struct hist_entry *he,char *bf,size_t size,unsigned int width) { -return repsep_snprintf (bf, size,"%-*u" , width, he->stat.ins_lat); +return repsep_snprintf (bf, size,"%-*u" , width, + he->ins_lat * he->stat.nr_events); }struct sort_entry sort_global_ins_lat = { .se_header ="INSTR Latency" , - .se_cmp = sort__global_ins_lat_cmp, + .se_cmp = sort__ins_lat_cmp, .se_snprintf = hist_entry__global_ins_lat_snprintf, .se_width_idx =HISTC_GLOBAL_INS_LAT , };
tools/perf/util/sort.h +1 -1
@@ -49,7 +49,6 @@ struct he_stat {u64 period_us;u64 period_guest_sys;u64 period_guest_us; -u64 ins_lat;u64 p_stage_cyc;u32 nr_events; };
@@ -109,6 +108,7 @@ struct hist_entry {s32 cpu;u64 code_page_size;u64 weight; +u64 ins_lat;u8 cpumode;u8 depth;
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 45/207 perf sort: Fix the p_stage_cyc sort key behavior
In reply to Greg Kroah-HartmanFrom: Namhyung Kim <[email protected]>
[ Upstream commit db4b284029099224f387d75198e5995df1cb8aef ]
andle 'p_stage_cyc' (for pipeline stage cycles) sort key with the same rationale as for the 'weight' and 'local_weight', see the fix in this series for a full explanation.
Not sure it also needs the local and global variants.
But I couldn't test it actually because I don't have the machine.
--- tools/perf/util/hist.c | 12 ++++-------- tools/perf/util/sort.c | 4 ++-- tools/perf/util/sort.h | 2 +- 3 files changed, 7 insertions(+), 11 deletions(-)
tools/perf/util/hist.c +4 -8
@@ -289,12 +289,10 @@ static long hist_time(unsigned long htime)return htime; } -static void he_stat__add_period (struct he_stat *he_stat,u64 period, -u64 p_stage_cyc) +static void he_stat__add_period (struct he_stat *he_stat,u64 period) { he_stat->period += period; he_stat->nr_events +=1 ; - he_stat->p_stage_cyc += p_stage_cyc; }static void he_stat__add_stat (struct he_stat *dest,struct he_stat *src)
@@ -305,7 +303,6 @@ static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src) dest->period_guest_sys += src->period_guest_sys; dest->period_guest_us += src->period_guest_us; dest->nr_events += src->nr_events; - dest->p_stage_cyc += src->p_stage_cyc; }static void he_stat__decay (struct he_stat *he_stat)
@@ -593,7 +590,6 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,struct hist_entry *he;int64_t cmp;u64 period = entry->stat.period; -u64 p_stage_cyc = entry->stat.p_stage_cyc;bool leftmost = true; p = &hists->entries_in->rb_root.rb_node;
@@ -612,11 +608,11 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,if (!cmp) {if (sample_self) { -he_stat__add_period (&he->stat, period, p_stage_cyc); +he_stat__add_period (&he->stat, period);hist_entry__add_callchain_period (he, period); }if (symbol_conf.cumulate_callchain) -he_stat__add_period (he->stat_acc, period, p_stage_cyc); +he_stat__add_period (he->stat_acc, period);/* * This mem info was allocated from sample__resolve_mem
@@ -726,7 +722,6 @@ __hists__add_entry(struct hists *hists, .stat = { .nr_events = 1, .period = sample->period, - .p_stage_cyc = sample->p_stage_cyc, }, .parent = sym_parent, .filtered = symbol__parent_filter(sym_parent) | al->filtered,
@@ -741,6 +736,7 @@ __hists__add_entry(struct hists *hists, .time = hist_time(sample->time), .weight = sample->weight, .ins_lat = sample->ins_lat, + .p_stage_cyc = sample->p_stage_cyc, }, *he = hists__findnew_entry(hists, &entry, al, sample_self);if (!hists->has_callchains && he && he->callchain_size !=0 )
tools/perf/util/sort.c +2 -2
@@ -1394,13 +1394,13 @@ struct sort_entry sort_global_ins_lat = {static int64_t sort__global_p_stage_cyc_cmp (struct hist_entry *left,struct hist_entry *right) { -return left->stat.p_stage_cyc - right->stat.p_stage_cyc; +return left->p_stage_cyc - right->p_stage_cyc; }static int hist_entry__p_stage_cyc_snprintf (struct hist_entry *he,char *bf,size_t size,unsigned int width) { -return repsep_snprintf (bf, size,"%-*u" , width, he->stat.p_stage_cyc); +return repsep_snprintf (bf, size,"%-*u" , width, he->p_stage_cyc); }struct sort_entry sort_p_stage_cyc = {
tools/perf/util/sort.h +1 -1
@@ -49,7 +49,6 @@ struct he_stat {u64 period_us;u64 period_guest_sys;u64 period_guest_us; -u64 p_stage_cyc;u32 nr_events; };
@@ -109,6 +108,7 @@ struct hist_entry {u64 code_page_size;u64 weight;u64 ins_lat; +u64 p_stage_cyc;u8 cpumode;u8 depth;
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 46/207 perf inject: Fix ARM SPE handling
In reply to Greg Kroah-HartmanFrom: German Gomez <[email protected]>
[ Upstream commit 9e1a8d9f683260d50e0a14176d3f7c46a93b2700 ]
'perf inject' is currently not working for Arm SPE. When you try to run 'perf inject' and 'perf report' with a perf.data file that contains SPE traces, the tool reports a "Bad address" error:
# ./perf record -e arm_spe_0/ts_enable=1,store_filter=1,branch_filter=1,load_filter=1/ -a -- sleep 1 # ./perf inject -i perf.data -o perf.inject.data --itrace # ./perf report -i perf.inject.data --stdio
0x42c00 [0x8]: failed to process type: 9 [Bad address] Error:
failed to process sample
As far as I know, the issue was first spotted in [1], but 'perf inject' was not yet injecting the samples. This patch does something similar to what cs_etm does for injecting the samples [2], but for SPE.
[1] https://patchwork.kernel.org/project/linux-arm-kernel/cover/[email protected]/#24117339
[2] https://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git/tree/tools/perf/util/cs-etm.c?h=perf/core&id=133fe2e617e48ca0948983329f43877064ffda3e#n1196
--- tools/perf/util/arm-spe.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
tools/perf/util/arm-spe.c +15 -0
@@ -51,6 +51,7 @@ struct arm_spe {u8 timeless_decoding;u8 data_queued; +u64 sample_type;u8 sample_flc;u8 sample_llc;u8 sample_tlb;
@@ -248,6 +249,12 @@ static void arm_spe_prep_sample(struct arm_spe *spe, event->sample.header.size =sizeof (struct perf_event_header ); } +static int arm_spe__inject_event (union perf_event *event,struct perf_sample *sample,u64 type) +{ + event->header.size =perf_event__sample_event_size (sample, type,0 ); +return perf_event__synthesize_sample (event, type,0 , sample); +} + static inline int arm_spe_deliver_synth_event(struct arm_spe *spe, struct arm_spe_queue *speq __maybe_unused,
@@ -256,6 +263,12 @@ arm_spe_deliver_synth_event(struct arm_spe *spe, {int ret; +if (spe->synth_opts.inject) { + ret =arm_spe__inject_event (event, sample, spe->sample_type); +if (ret) +return ret; + } + ret =perf_session__deliver_synth_event (spe->session, event, sample);if (ret)pr_err ("ARM SPE: failed to deliver event, error %d\n" , ret);
@@ -920,6 +933,8 @@ arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session)else attr.sample_type |=PERF_SAMPLE_TIME ; + spe->sample_type = attr.sample_type; + attr.exclude_user = evsel->core.attr.exclude_user; attr.exclude_kernel = evsel->core.attr.exclude_kernel; attr.exclude_hv = evsel->core.attr.exclude_hv;
Signature · 9 lines
2.33.0 _______________________________________________ linux-arm-kernel mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Greg Kroah-Hartman
maintainerPATCH 47/207 perf hist: Fix memory leak of a perf_hpp_fmt
In reply to Greg Kroah-HartmanFrom: Ian Rogers <[email protected]>
[ Upstream commit 0ca1f534a776cc7d42f2c33da4732b74ec2790cd ]
perf_hpp__column_unregister() removes an entry from a list but doesn't free the memory causing a memory leak spotted by leak sanitizer.
Add the free while at the same time reducing the scope of the function to static.
--- tools/perf/ui/hist.c | 28 ++++++++++++++-------------- tools/perf/util/hist.h | 1 - 2 files changed, 14 insertions(+), 15 deletions(-)
tools/perf/ui/hist.c +14 -14
@@ -535,6 +535,18 @@ struct perf_hpp_list perf_hpp_list = {#undef __HPP_SORT_ACC_FN#undef __HPP_SORT_RAW_FN +static void fmt_free (struct perf_hpp_fmt *fmt) +{ +/* +* At this point fmt should be completely +* unhooked, if not it's a bug. +*/ +BUG_ON (!list_empty (&fmt->list)); +BUG_ON (!list_empty (&fmt->sort_list)); + +if (fmt->free) + fmt->free (fmt); +}void perf_hpp__init (void ) {
@@ -598,9 +610,10 @@ void perf_hpp_list__prepend_sort_field(struct perf_hpp_list *list,list_add (&format->sort_list, &list->sorts); } -void perf_hpp__column_unregister (struct perf_hpp_fmt *format) +static void perf_hpp__column_unregister (struct perf_hpp_fmt *format) {list_del_init (&format->list); +fmt_free (format); }void perf_hpp__cancel_cumulate (void )
@@ -672,19 +685,6 @@ void perf_hpp__append_sort_keys(struct perf_hpp_list *list) } -static void fmt_free (struct perf_hpp_fmt *fmt) -{ -/* -* At this point fmt should be completely -* unhooked, if not it's a bug. -*/ -BUG_ON (!list_empty (&fmt->list)); -BUG_ON (!list_empty (&fmt->sort_list)); - -if (fmt->free) - fmt->free (fmt); -} -void perf_hpp__reset_output_field (struct perf_hpp_list *list) {struct perf_hpp_fmt *fmt, *tmp;
tools/perf/util/hist.h +0 -1
@@ -369,7 +369,6 @@ enum { };void perf_hpp__init (void ); -void perf_hpp__column_unregister (struct perf_hpp_fmt *format);void perf_hpp__cancel_cumulate (void );void perf_hpp__setup_output_field (struct perf_hpp_list *list);void perf_hpp__reset_output_field (struct perf_hpp_list *list);
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 48/207 perf report: Fix memory leaks around perf_tip()
In reply to Greg Kroah-HartmanFrom: Ian Rogers <[email protected]>
[ Upstream commit d9fc706108c15f8bc2d4ccccf8e50f74830fabd9 ]
perf_tip() may allocate memory or use a literal, this means memory wasn't freed if allocated. Change the API so that literals aren't used.
At the same time add missing frees for system_path. These issues were spotted using leak sanitizer.
--- tools/perf/builtin-report.c | 15 +++++++++------ tools/perf/util/util.c | 14 +++++++------- tools/perf/util/util.h | 2 +- 3 files changed, 17 insertions(+), 14 deletions(-)
tools/perf/builtin-report.c +9 -6
@@ -619,14 +619,17 @@ static int report__browse_hists(struct report *rep)int ret;struct perf_session *session = rep->session;struct evlist *evlist = session->evlist; -const char *help =perf_tip (system_path (TIPDIR )); +char *help =NULL , *path =NULL ; -if (help ==NULL ) { + path =system_path (TIPDIR ); +if (perf_tip (&help, path) || help ==NULL ) {/* fallback for people who don't install perf ;-) */ - help =perf_tip (DOCDIR ); -if (help ==NULL ) - help ="Cannot load tips.txt file, please install perf!" ; +free (path); + path =system_path (DOCDIR ); +if (perf_tip (&help, path) || help ==NULL ) + help =strdup ("Cannot load tips.txt file, please install perf!" ); } +free (path);switch (use_browser) {case 1 :
@@ -651,7 +654,7 @@ static int report__browse_hists(struct report *rep) ret =evlist__tty_browse_hists (evlist, rep, help);break ; } - +free (help);return ret; }
tools/perf/util/util.c +7 -7
@@ -379,32 +379,32 @@ fetch_kernel_version(unsigned int *puint, char *str,return 0 ; } -const char *perf_tip (const char *dirpath) +int perf_tip (char **strp,const char *dirpath) {struct strlist *tips;struct str_node *node; -char *tip =NULL ;struct strlist_config conf = { .dirname = dirpath, .file_only = true, }; +int ret =0 ; + *strp =NULL ; tips =strlist__new ("tips.txt" , &conf);if (tips ==NULL ) -return errno ==ENOENT ?NULL : -"Tip: check path of tips.txt or get more memory! ;-p" ; +return -errno;if (strlist__nr_entries (tips) ==0 ) goto out; node =strlist__entry (tips,random () %strlist__nr_entries (tips)); -if (asprintf (&tip,"Tip: %s" , node->s) <0 ) - tip = (char *)"Tip: get more memory! ;-)" ; +if (asprintf (strp,"Tip: %s" , node->s) <0 ) + ret = -ENOMEM ; out:strlist__delete (tips); -return tip; +return ret; }char *perf_exe (char *buf,int len)
tools/perf/util/util.h +1 -1
@@ -39,7 +39,7 @@ int fetch_kernel_version(unsigned int *puint,#define KVER_FMT "%d.%d.%d"#define KVER_PARAM (x) KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x) -const char *perf_tip (const char *dirpath); +int perf_tip (char **strp,const char *dirpath);#ifndef HAVE_SCHED_GETCPU_SUPPORT int sched_getcpu (void );
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 49/207 tracing: Dont use out-of-sync va_list in event printing
In reply to Greg Kroah-HartmanFrom: Nikita Yushchenko <[email protected]>
[ Upstream commit 2ef75e9bd2c998f1c6f6f23a3744136105ddefd5 ]
If trace_seq becomes full, trace_seq_vprintf() no longer consumes arguments from va_list, making va_list out of sync with format processing by trace_check_vprintf().
This causes va_arg() in trace_check_vprintf() to return wrong positional argument, which results into a WARN_ON_ONCE() hit.
ftrace_stress_test from LTP triggers this situation.
Fix it by explicitly avoiding further use if va_list at the point when it's consistency can no longer be guaranteed.
--- kernel/trace/trace.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
kernel/trace/trace.c +12 -0
@@ -3836,6 +3836,18 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt, iter->fmt[i] ='\0' ;trace_seq_vprintf (&iter->seq, iter->fmt, ap); +/* +* If iter->seq is full, the above call no longer guarantees +* that ap is in sync with fmt processing, and further calls +* to va_arg() can return wrong positional arguments. +* +* Ensure that ap is no longer used in this case. +*/ +if (iter->seq.full) { + p ="" ; +break ; + } +if (star) len =va_arg (ap, int);
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 50/207 net/smc: Avoid warning of possible recursive locking
In reply to Greg Kroah-HartmanFrom: Wen Gu <[email protected]>
[ Upstream commit 7a61432dc81375be06b02f0061247d3efbdfce3a ]
Possible recursive locking is detected by lockdep when SMC falls back to TCP. The corresponding warnings are as follows:
============================================
WARNING: possible recursive locking detected
5.16.0-rc1+ #18 Tainted: G E
--------------------------------------------
wrk/1391 is trying to acquire lock:
ffff975246c8e7d8 (&ei->socket.wq.wait){..-.}-{3:3}, at: smc_switch_to_fallback+0x109/0x250 [smc]
but task is already holding lock:
ffff975246c8f918 (&ei->socket.wq.wait){..-.}-{3:3}, at: smc_switch_to_fallback+0xfe/0x250 [smc]
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0
---- lock(&ei->socket.wq.wait);
lock(&ei->socket.wq.wait);
*** DEADLOCK ***
May be due to missing lock nesting notation
2 locks held by wrk/1391:
#0: ffff975246040130 (sk_lock-AF_SMC){+.+.}-{0:0}, at: smc_connect+0x43/0x150 [smc] #1: ffff975246c8f918 (&ei->socket.wq.wait){..-.}-{3:3}, at: smc_switch_to_fallback+0xfe/0x250 [smc]
stack backtrace: Call Trace: <TASK> dump_stack_lvl+0x56/0x7b __lock_acquire+0x951/0x11f0 lock_acquire+0x27a/0x320 ? smc_switch_to_fallback+0x109/0x250 [smc] ? smc_switch_to_fallback+0xfe/0x250 [smc] _raw_spin_lock_irq+0x3b/0x80 ? smc_switch_to_fallback+0x109/0x250 [smc] smc_switch_to_fallback+0x109/0x250 [smc] smc_connect_fallback+0xe/0x30 [smc] __smc_connect+0xcf/0x1090 [smc] ? mark_held_locks+0x61/0x80 ? __local_bh_enable_ip+0x77/0xe0 ? lockdep_hardirqs_on+0xbf/0x130 ? smc_connect+0x12a/0x150 [smc] smc_connect+0x12a/0x150 [smc] __sys_connect+0x8a/0xc0 ? syscall_enter_from_user_mode+0x20/0x70 __x64_sys_connect+0x16/0x20 do_syscall_64+0x34/0x90 entry_SYSCALL_64_after_hwframe+0x44/0xae
The nested locking in smc_switch_to_fallback() is considered to possibly cause a deadlock because smc_wait->lock and clc_wait->lock are the same type of lock. But actually it is safe so far since there is no other place trying to obtain smc_wait->lock when clc_wait->lock is held. So the patch replaces spin_lock() with spin_lock_nested() to avoid false report by lockdep.
--- net/smc/af_smc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/smc/af_smc.c +1 -1
@@ -566,7 +566,7 @@ static void smc_switch_to_fallback(struct smc_sock *smc, int reason_code)* to clcsocket->wq during the fallback. */ spin_lock_irqsave (&smc_wait->lock, flags); -spin_lock (&clc_wait->lock); +spin_lock_nested (&clc_wait->lock,SINGLE_DEPTH_NESTING );list_splice_init (&smc_wait->head, &clc_wait->head);spin_unlock (&clc_wait->lock);spin_unlock_irqrestore (&smc_wait->lock, flags);
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 51/207 ACPI: Add stubs for wakeup handler functions
In reply to Greg Kroah-HartmanFrom: Mario Limonciello <[email protected]>
[ Upstream commit e9380df851878cee71df5a1c7611584421527f7e ]
The commit ddfd9dcf270c ("ACPI: PM: Add acpi_[un]register_wakeup_handler()") added new functions for drivers to use during the s2idle wakeup path, but didn't add stubs for when CONFIG_ACPI wasn't set.
Add those stubs in for other drivers to be able to use.
--- include/linux/acpi.h | 9 +++++++++ 1 file changed, 9 insertions(+)
include/linux/acpi.h +9 -0
@@ -976,6 +976,15 @@ static inline int acpi_get_local_address(acpi_handle handle, u32 *addr) return -ENODEV; } +static inline int acpi_register_wakeup_handler (int wake_irq, +bool (*wakeup)(void *context),void *context) +{ +return -ENXIO ; +} + +static inline void acpi_unregister_wakeup_handler ( +bool (*wakeup)(void *context),void *context) { } +#endif /* !CONFIG_ACPI */ #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
Signature · 1 line
2.33.0
Greg Kroah-Hartman
maintainerPATCH 52/207 net/tls: Fix authentication failure in CCM mode
In reply to Greg Kroah-HartmanFrom: Tianjia Zhang <[email protected]>
commit 5961060692f8b17cd2080620a3d27b95d2ae05ca upstream.
When the TLS cipher suite uses CCM mode, including AES CCM and SM4 CCM, the first byte of the B0 block is flags, and the real IV starts from the second byte. The XOR operation of the IV and rec_seq should be skip this byte, that is, add the iv_offset.
--- net/tls/tls_sw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/tls/tls_sw.c +2 -2
@@ -515,7 +515,7 @@ static int tls_do_encryption(struct sockmemcpy (&rec->iv_data[iv_offset], tls_ctx->tx.iv, prot->iv_size + prot->salt_size); -xor_iv_with_seq (prot, rec->iv_data, tls_ctx->tx.rec_seq); +xor_iv_with_seq (prot, rec->iv_data + iv_offset, tls_ctx->tx.rec_seq); sge->offset += prot->prepend_size; sge->length -= prot->prepend_size;
@@ -1487,7 +1487,7 @@ static int decrypt_internal(struct sockelse memcpy (iv + iv_offset, tls_ctx->rx.iv, prot->salt_size); -xor_iv_with_seq (prot, iv, tls_ctx->rx.rec_seq); +xor_iv_with_seq (prot, iv + iv_offset, tls_ctx->rx.rec_seq);/* Prepare AAD */ tls_make_aad(aad, rxm->full_len - prot->overhead_size +
Greg Kroah-Hartman
maintainerPATCH 53/207 vrf: Reset IPCB/IP6CB when processing outbound pkts in vrf dev xmit
In reply to Greg Kroah-HartmanFrom: Stephen Suryaputra <[email protected]>
commit ee201011c1e1563c114a55c86eb164b236f18e84 upstream.
IPCB/IP6CB need to be initialized when processing outbound v4 or v6 pkts in the codepath of vrf device xmit function so that leftover garbage doesn't cause futher code that uses the CB to incorrectly process the pkt.
One occasion of the issue might occur when MPLS route uses the vrf device as the outgoing device such as when the route is added using "ip -f mpls route add <label> dev <vrf>" command.
The problems seems to exist since day one. Hence I put the day one commits on the Fixes tags.
--- drivers/net/vrf.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/vrf.c +2 -0
@@ -497,6 +497,7 @@ static netdev_tx_t vrf_process_v6_outbou/* strip the ethernet header added for pass through VRF device */ __skb_pull (skb,skb_network_offset (skb)); +memset (IP6CB (skb),0 ,sizeof (*IP6CB (skb))); ret =vrf_ip6_local_out (net, skb->sk, skb);if (unlikely (net_xmit_eval (ret))) dev->stats.tx_errors++;
@@ -579,6 +580,7 @@ static netdev_tx_t vrf_process_v4_outbou RT_SCOPE_LINK); } +memset (IPCB (skb),0 ,sizeof (*IPCB (skb))); ret =vrf_ip_local_out (dev_net (skb_dst (skb)->dev), skb->sk, skb);if (unlikely (net_xmit_eval (ret))) vrf_dev->stats.tx_errors++;
Greg Kroah-Hartman
maintainerPATCH 54/207 kprobes: Limit max data_size of the kretprobe instances
In reply to Greg Kroah-HartmanFrom: Masami Hiramatsu <[email protected]>
commit 6bbfa44116689469267f1a6e3d233b52114139d2 upstream.
The 'kprobe::data_size' is unsigned, thus it can not be negative. But if user sets it enough big number (e.g. (size_t)-8), the result of 'data_size
+ sizeof(struct kretprobe_instance)' becomes smaller than sizeof(struct kretprobe_instance) or zero. In result, the kretprobe_instance are allocated without enough memory, and kretprobe accesses outside of allocated memory.
To avoid this issue, introduce a max limitation of the kretprobe::data_size. 4KB per instance should be OK.
--- include/linux/kprobes.h | 2 ++ kernel/kprobes.c | 3 +++ 2 files changed, 5 insertions(+)
include/linux/kprobes.h +2 -0
@@ -154,6 +154,8 @@ struct kretprobe {struct kretprobe_holder *rph; }; +#define KRETPROBE_MAX_DATA_SIZE 4096 +struct kretprobe_instance {union {struct freelist_node freelist;
kernel/kprobes.c +3 -0
@@ -2006,6 +2006,9 @@ int register_kretprobe(struct kretprobe } } +if (rp->data_size >KRETPROBE_MAX_DATA_SIZE ) +return -E2BIG ; + rp->kp.pre_handler = pre_handler_kretprobe; rp->kp.post_handler =NULL ;
Greg Kroah-Hartman
maintainerPATCH 55/207 ALSA: hda/cs8409: Set PMSG_ON earlier inside cs8409 driver
In reply to Greg Kroah-HartmanFrom: Stefan Binding <[email protected]>
commit 65cc4ad62a9ed47c0b4fcd7af667d97d7c29f19d upstream.
For cs8409, it is required to run Jack Detect on resume. Jack Detect on cs8409+cs42l42 requires an interrupt from cs42l42 to be sent to cs8409 which is propogated to the driver via an unsolicited event.
However, the hda_codec drops unsolicited events if the power_state is not set to PMSG_ON. Which is set at the end of the resume call. This means there is a race condition between setting power_state to PMSG_ON and receiving the interrupt.
To solve this, we can add an API to set the power_state earlier and call that before we start Jack Detect.
This does not cause issues, since we know inside our driver that we are already initialized, and ready to handle the unsolicited events.
--- sound/pci/hda/hda_local.h | 9 +++++++++ sound/pci/hda/patch_cs8409.c | 5 +++++ 2 files changed, 14 insertions(+)
sound/pci/hda/hda_local.h +9 -0
@@ -438,6 +438,15 @@ int snd_hda_codec_set_pin_target(struct#define for_each_hda_codec_node (nid, codec) \ for ((nid) = (codec)->core.start_nid; (nid) < (codec)->core.end_nid; (nid)++) +/* Set the codec power_state flag to indicate to allow unsol event handling; +* see hda_codec_unsol_event() in hda_bind.c. Calling this might confuse the +* state tracking, so use with care. +*/ +static inline void snd_hda_codec_allow_unsol_events (struct hda_codec *codec) +{ + codec->core.dev.power.power_state =PMSG_ON ; +} +/* * get widget capabilities */
sound/pci/hda/patch_cs8409.c +5 -0
@@ -750,6 +750,11 @@ static void cs42l42_resume(struct sub_coif (cs42l42->full_scale_vol)cs8409_i2c_write (cs42l42,0x2001 ,0x01 ); +/* we have to explicitly allow unsol event handling even during the +* resume phase so that the jack event is processed properly +*/ +snd_hda_codec_allow_unsol_events (cs42l42->codec); +cs42l42_enable_jack_detect (cs42l42); }
Greg Kroah-Hartman
maintainerPATCH 56/207 rt2x00: do not mark device gone on EPROTO errors during start
In reply to Greg Kroah-HartmanFrom: Stanislaw Gruszka <[email protected]>
commit ed53ae75693096f1c10b4561edd31a07b631bd72 upstream.
As reported by Exuvo is possible that we have lot's of EPROTO errors during device start i.e. firmware load. But after that device works correctly. Hence marking device gone by few EPROTO errors done by commit e383c70474db ("rt2x00: check number of EPROTO errors") caused regression - Exuvo device stop working after kernel update. To fix disable the check during device start.
--- drivers/net/wireless/ralink/rt2x00/rt2x00usb.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/wireless/ralink/rt2x00/rt2x00usb.c +3 -0
@@ -25,6 +25,9 @@ static bool rt2x00usb_check_usb_error(stif (status == -ENODEV || status == -ENOENT )return true; +if (!test_bit (DEVICE_STATE_STARTED , &rt2x00dev->flags)) +return false; +if (status == -EPROTO || status == -ETIMEDOUT ) rt2x00dev->num_proto_errs++;else
Greg Kroah-Hartman
maintainerPATCH 57/207 ipmi: Move remove_work to dedicated workqueue
In reply to Greg Kroah-HartmanFrom: Ioanna Alifieraki <[email protected]>
commit 1d49eb91e86e8c1c1614c72e3e958b6b7e2472a9 upstream.
Currently when removing an ipmi_user the removal is deferred as a work on the system's workqueue. Although this guarantees the free operation will occur in non atomic context, it can race with the ipmi_msghandler module removal (see [1]) . In case a remove_user work is scheduled for removal and shortly after ipmi_msghandler module is removed we can end up in a situation where the module is removed fist and when the work is executed the system crashes with :
BUG: unable to handle page fault for address: ffffffffc05c3450
PF: supervisor instruction fetch in kernel mode
PF: error_code(0x0010) - not-present page
because the pages of the module are gone. In cleanup_ipmi() there is no easy way to detect if there are any pending works to flush them before removing the module. This patch creates a separate workqueue and schedules the remove_work works on it. When removing the module the workqueue is drained when destroyed to avoid the race.
[1] https://bugs.launchpad.net/bugs/1950666
Message-Id: <[email protected]>
--- drivers/char/ipmi/ipmi_msghandler.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
drivers/char/ipmi/ipmi_msghandler.c +12 -1
@@ -191,6 +191,8 @@ struct ipmi_user {struct work_struct remove_work; }; +struct workqueue_struct *remove_work_wq; +static struct ipmi_user *acquire_ipmi_user (struct ipmi_user *user,int *index) __acquires(user->release_barrier) {
@@ -1261,7 +1263,7 @@ static void free_user(struct kref *ref) struct ipmi_user *user = container_of(ref, struct ipmi_user, refcount);/* SRCU cleanup must happen in task context. */ -schedule_work (&user->remove_work); +queue_work (remove_work_wq, &user->remove_work); }static void _ipmi_destroy_user (struct ipmi_user *user)
@@ -5153,6 +5155,13 @@ static int ipmi_init_msghandler(void)atomic_notifier_chain_register (&panic_notifier_list, &panic_block); + remove_work_wq =create_singlethread_workqueue ("ipmi-msghandler-remove-wq" ); +if (!remove_work_wq) { +pr_err ("unable to create ipmi-msghandler-remove-wq workqueue" ); + rv = -ENOMEM ; + goto out; + } + initialized = true; out:
@@ -5178,6 +5187,8 @@ static void __exit cleanup_ipmi(void)int count;if (initialized) { +destroy_workqueue (remove_work_wq); +atomic_notifier_chain_unregister (&panic_notifier_list, &panic_block);
Greg Kroah-Hartman
maintainerPATCH 58/207 cpufreq: Fix get_cpu_device() failure in add_cpu_dev_symlink()
In reply to Greg Kroah-HartmanFrom: Xiongfeng Wang <[email protected]>
commit 2c1b5a84669d2477d8fffe9136e86a2cff591729 upstream.
When I hot added a CPU, I found 'cpufreq' directory was not created below /sys/devices/system/cpu/cpuX/.
It is because get_cpu_device() failed in add_cpu_dev_symlink().
cpufreq_add_dev() is the .add_dev callback of a CPU subsys interface. It will be called when the CPU device registered into the system. The call chain is as follows:
register_cpu()
->device_register()
->device_add()
->bus_probe_device()
->cpufreq_add_dev()But only after the CPU device has been registered, we can get the CPU device by get_cpu_device(), otherwise it will return NULL.
Since we already have the CPU device in cpufreq_add_dev(), pass it to add_cpu_dev_symlink().
I noticed that the 'kobj' of the CPU device has been added into the system before cpufreq_add_dev().
--- drivers/cpufreq/cpufreq.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/cpufreq/cpufreq.c +4 -5
@@ -1004,10 +1004,9 @@ static struct kobj_type ktype_cpufreq = .release = cpufreq_sysfs_release, }; -static void add_cpu_dev_symlink (struct cpufreq_policy *policy,unsigned int cpu) +static void add_cpu_dev_symlink (struct cpufreq_policy *policy,unsigned int cpu, +struct device *dev) { -struct device *dev =get_cpu_device (cpu); -if (unlikely (!dev))return ;
@@ -1391,7 +1390,7 @@ static int cpufreq_online(unsigned int cif (new_policy) {for_each_cpu (j, policy->related_cpus) {per_cpu (cpufreq_cpu_data, j) = policy; -add_cpu_dev_symlink (policy, j); +add_cpu_dev_symlink (policy, j,get_cpu_device (j)); } policy->min_freq_req = kzalloc(2 * sizeof(*policy->min_freq_req),
@@ -1565,7 +1564,7 @@ static int cpufreq_add_dev(struct device/* Create sysfs link on CPU registration */ policy =per_cpu (cpufreq_cpu_data, cpu);if (policy) -add_cpu_dev_symlink (policy, cpu); +add_cpu_dev_symlink (policy, cpu, dev);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 59/207 iwlwifi: mvm: retry init flow if failed
In reply to Greg Kroah-HartmanFrom: Mordechay Goodstein <[email protected]>
commit 5283dd677e52af9db6fe6ad11b2f12220d519d0c upstream.
In some very rare cases the init flow may fail. In many cases, this is recoverable, so we can retry. Implement a loop to retry two more times after the first attempt failed.
This can happen in two different situations, namely during probe and during mac80211 start. For the first case, a simple loop is enough. For the second case, we need to add a flag to prevent mac80211 from trying to restart it as well, leaving full control with the driver.
--- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 22 +++++++++++++------- drivers/net/wireless/intel/iwlwifi/iwl-drv.h | 3 ++ drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 24 +++++++++++++++++++++- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 3 ++ drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 3 ++ 5 files changed, 47 insertions(+), 8 deletions(-)
drivers/net/wireless/intel/iwlwifi/iwl-drv.c +15 -7
@@ -1271,23 +1271,31 @@ _iwl_op_mode_start(struct iwl_drv *drv,const struct iwl_op_mode_ops *ops = op->ops;struct dentry *dbgfs_dir =NULL ;struct iwl_op_mode *op_mode =NULL ; +int retry, max_retry = !!iwlwifi_mod_params.fw_restart *IWL_MAX_INIT_RETRY ; + +for (retry =0 ; retry <= max_retry; retry++) {#ifdef CONFIG_IWLWIFI_DEBUGFS - drv->dbgfs_op_mode =debugfs_create_dir (op->name, - drv->dbgfs_drv); - dbgfs_dir = drv->dbgfs_op_mode; + drv->dbgfs_op_mode =debugfs_create_dir (op->name, + drv->dbgfs_drv); + dbgfs_dir = drv->dbgfs_op_mode;#endif - op_mode = ops->start (drv->trans, drv->trans->cfg, &drv->fw, dbgfs_dir); + op_mode = ops->start (drv->trans, drv->trans->cfg, + &drv->fw, dbgfs_dir); + +if (op_mode) +return op_mode; + +IWL_ERR (drv,"retry init count %d\n" , retry);#ifdef CONFIG_IWLWIFI_DEBUGFS -if (!op_mode) {debugfs_remove_recursive (drv->dbgfs_op_mode); drv->dbgfs_op_mode =NULL ; - }#endif + } -return op_mode; +return NULL ; }static void _iwl_op_mode_stop (struct iwl_drv *drv)
drivers/net/wireless/intel/iwlwifi/iwl-drv.h +3 -0
@@ -90,4 +90,7 @@ void iwl_drv_stop(struct iwl_drv *drv);#define IWL_EXPORT_SYMBOL (sym)#endif +/* max retry for init flow */ +#define IWL_MAX_INIT_RETRY 2 +#endif /* __iwl_drv_h__ */
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +23 -1
@@ -16,6 +16,7 @@#include <net/ieee80211_radiotap.h> #include <net/tcp.h> +#include "iwl-drv.h" #include "iwl-op-mode.h" #include "iwl-io.h" #include "mvm.h"
@@ -1116,9 +1117,30 @@ static int iwl_mvm_mac_start(struct ieee {struct iwl_mvm *mvm =IWL_MAC80211_GET_MVM (hw);int ret; +int retry, max_retry =0 ;mutex_lock (&mvm->mutex); - ret =__iwl_mvm_mac_start (mvm); + +/* we are starting the mac not in error flow, and restart is enabled */ +if (!test_bit (IWL_MVM_STATUS_HW_RESTART_REQUESTED , &mvm->status) && + iwlwifi_mod_params.fw_restart) { + max_retry =IWL_MAX_INIT_RETRY ; +/* +* This will prevent mac80211 recovery flows to trigger during +* init failures +*/ +set_bit (IWL_MVM_STATUS_STARTING , &mvm->status); + } + +for (retry =0 ; retry <= max_retry; retry++) { + ret =__iwl_mvm_mac_start (mvm); +if (!ret) +break ; + +IWL_ERR (mvm,"mac start retry %d\n" , retry); + } +clear_bit (IWL_MVM_STATUS_STARTING , &mvm->status); +mutex_unlock (&mvm->mutex);return ret;
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +3 -0
@@ -1121,6 +1121,8 @@ struct iwl_mvm {* @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running * @IWL_MVM_STATUS_NEED_FLUSH_P2P: need to flush P2P bcast STA * @IWL_MVM_STATUS_IN_D3: in D3 (or at least about to go into it) +* @IWL_MVM_STATUS_STARTING: starting mac, +* used to disable restart flow while in STARTING state */ enum iwl_mvm_status {IWL_MVM_STATUS_HW_RFKILL ,
@@ -1132,6 +1134,7 @@ enum iwl_mvm_status {IWL_MVM_STATUS_FIRMWARE_RUNNING ,IWL_MVM_STATUS_NEED_FLUSH_P2P ,IWL_MVM_STATUS_IN_D3 , + IWL_MVM_STATUS_STARTING, };/* Keep track of completed init configuration */
drivers/net/wireless/intel/iwlwifi/mvm/ops.c +3 -0
@@ -1424,6 +1424,9 @@ void iwl_mvm_nic_restart(struct iwl_mvm*/ if (!mvm->fw_restart && fw_error) {iwl_fw_error_collect (&mvm->fwrt, false); + }else if (test_bit (IWL_MVM_STATUS_STARTING , + &mvm->status)) { +IWL_ERR (mvm,"Starting mac, retry will be triggered anyway\n" ); }else if (test_bit (IWL_MVM_STATUS_IN_HW_RESTART , &mvm->status)) {struct iwl_mvm_reprobe *reprobe;
Greg Kroah-Hartman
maintainerPATCH 60/207 dma-buf: system_heap: Use for_each_sgtable_sg in pages free flow
In reply to Greg Kroah-HartmanFrom: Guangming <[email protected]>
commit 679d94cd7d900871e5bc9cf780bd5b73af35ab42 upstream.
For previous version, it uses 'sg_table.nent's to traverse sg_table in pages free flow.
However, 'sg_table.nents' is reassigned in 'dma_map_sg', it means the number of created entries in the DMA adderess space.
So, use 'sg_table.nents' in pages free flow will case some pages can't be freed.
Here we should use sg_table.orig_nents to free pages memory, but use the sgtable helper 'for each_sgtable_sg'(, instead of the previous rather common helper 'for_each_sg' which maybe cause memory leak) is much better.
--- drivers/dma-buf/heaps/system_heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/dma-buf/heaps/system_heap.c +1 -1
@@ -289,7 +289,7 @@ static void system_heap_dma_buf_release(int i; table = &buffer->sg_table; -for_each_sg (table->sgl, sg, table->nents, i) { +for_each_sgtable_sg (table, sg, i) {struct page *page =sg_page (sg);__free_pages (page,compound_order (page));
Greg Kroah-Hartman
maintainerPATCH 61/207 s390/pci: move pseudo-MMIO to prevent MIO overlap
In reply to Greg Kroah-HartmanFrom: Niklas Schnelle <[email protected]>
commit 52d04d408185b7aa47628d2339c28ec70074e0ae upstream.
When running without MIO support, with pci=nomio or for devices which are not MIO-capable the zPCI subsystem generates pseudo-MMIO addresses to allow access to PCI BARs via MMIO based Linux APIs even though the platform uses function handles and BAR numbers.
This is done by stashing an index into our global IOMAP array which contains the function handle in the 16 most significant bits of the addresses returned by ioremap() always setting the most significant bit.
On the other hand the MIO addresses assigned by the platform for use, while requiring special instructions, allow PCI access with virtually mapped physical addresses. Now the problem is that these MIO addresses and our own pseudo-MMIO addresses may overlap, while functionally this would not be a problem by itself this overlap is detected by common code as both address types are added as resources in the iomem_resource tree. This leads to the overlapping resource claim of either the MIO capable or non-MIO capable devices with being rejected.
Since PCI is tightly coupled to the use of the iomem_resource tree, see for example the code for request_mem_region(), we can't reasonably get rid of the overlap being detected by keeping our pseudo-MMIO addresses out of the iomem_resource tree.
Instead let's move the range used by our own pseudo-MMIO addresses by starting at (1UL << 62) and only using addresses below (1UL << 63) thus avoiding the range currently used for MIO addresses.
--- arch/s390/include/asm/pci_io.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
arch/s390/include/asm/pci_io.h +4 -3
@@ -14,12 +14,13 @@/* I/O Map */ #define ZPCI_IOMAP_SHIFT 48 -#define ZPCI_IOMAP_ADDR_BASE 0x8000000000000000UL +#define ZPCI_IOMAP_ADDR_SHIFT 62 +#define ZPCI_IOMAP_ADDR_BASE (1UL << ZPCI_IOMAP_ADDR_SHIFT)#define ZPCI_IOMAP_ADDR_OFF_MASK ((1UL << ZPCI_IOMAP_SHIFT) - 1)#define ZPCI_IOMAP_MAX_ENTRIES \ - ((ULONG_MAX - ZPCI_IOMAP_ADDR_BASE + 1) / (1UL << ZPCI_IOMAP_SHIFT)) + (1UL << (ZPCI_IOMAP_ADDR_SHIFT - ZPCI_IOMAP_SHIFT))#define ZPCI_IOMAP_ADDR_IDX_MASK \ - (~ZPCI_IOMAP_ADDR_OFF_MASK - ZPCI_IOMAP_ADDR_BASE) + ((ZPCI_IOMAP_ADDR_BASE - 1) & ~ZPCI_IOMAP_ADDR_OFF_MASK)struct zpci_iomap_entry {u32 fh;
Greg Kroah-Hartman
maintainerPATCH 62/207 fget: check that the fd still exists after getting a ref to it
In reply to Greg Kroah-HartmanFrom: Linus Torvalds <[email protected]>
commit 054aa8d439b9185d4f5eb9a90282d1ce74772969 upstream.
Jann Horn points out that there is another possible race wrt Unix domain socket garbage collection, somewhat reminiscent of the one fixed in commit cbcf01128d0a ("af_unix: fix garbage collect vs MSG_PEEK").
See the extended comment about the garbage collection requirements added to unix_peek_fds() by that commit for details.
The race comes from how we can locklessly look up a file descriptor just as it is in the process of being closed, and with the right artificial timing (Jann added a few strategic 'mdelay(500)' calls to do that), the Unix domain socket garbage collector could see the reference count decrement of the close() happen before fget() took its reference to the file and the file was attached onto a new file descriptor.
This is all (intentionally) correct on the 'struct file *' side, with RCU lookups and lockless reference counting very much part of the design. Getting that reference count out of order isn't a problem per se.
But the garbage collector can get confused by seeing this situation of having seen a file not having any remaining external references and then seeing it being attached to an fd.
In commit cbcf01128d0a ("af_unix: fix garbage collect vs MSG_PEEK") the fix was to serialize the file descriptor install with the garbage collector by taking and releasing the unix_gc_lock.
That's not really an option here, but since this all happens when we are in the process of looking up a file descriptor, we can instead simply just re-check that the file hasn't been closed in the meantime, and just re-do the lookup if we raced with a concurrent close() of the same file descriptor.
--- fs/file.c | 4 ++++ 1 file changed, 4 insertions(+)
fs/file.c +4 -0
@@ -858,6 +858,10 @@ loop: file =NULL ; else if (!get_file_rcu_many(file, refs)) goto loop; + else if (files_lookup_fd_raw(files, fd) != file) { +fput_many (file, refs); + goto loop; + } }rcu_read_unlock ();
Greg Kroah-Hartman
maintainerPATCH 63/207 sata_fsl: fix UAF in sata_fsl_port_stop when rmmod sata_fsl
In reply to Greg Kroah-HartmanFrom: Baokun Li <[email protected]>
commit 6c8ad7e8cf29eb55836e7a0215f967746ab2b504 upstream.
When the rmmod sata_fsl.ko command is executed in the PPC64 GNU/Linux, a bug is reported:
==================================================================
BUG: Unable to handle kernel data access on read at 0x80000800805b502c Oops: Kernel access of bad area, sig: 11 [#1] NIP [c0000000000388a4] .ioread32+0x4/0x20 LR [80000000000c6034] .sata_fsl_port_stop+0x44/0xe0 [sata_fsl] Call Trace: .free_irq+0x1c/0x4e0 (unreliable) .ata_host_stop+0x74/0xd0 [libata] .release_nodes+0x330/0x3f0 .device_release_driver_internal+0x178/0x2c0 .driver_detach+0x64/0xd0 .bus_remove_driver+0x70/0xf0 .driver_unregister+0x38/0x80 .platform_driver_unregister+0x14/0x30 .fsl_sata_driver_exit+0x18/0xa20 [sata_fsl] .__se_sys_delete_module+0x1ec/0x2d0 .system_call_exception+0xfc/0x1f0 system_call_common+0xf8/0x200 ==================================================================
The triggering of the BUG is shown in the following stack:
driver_detach
device_release_driver_internal
__device_release_driver
drv->remove(dev) --> platform_drv_remove/platform_remove
drv->remove(dev) --> sata_fsl_remove
iounmap(host_priv->hcr_base); <---- unmap
kfree(host_priv); <---- free
devres_release_all
release_nodes
dr->node.release(dev, dr->data) --> ata_host_stop
ap->ops->port_stop(ap) --> sata_fsl_port_stop
ioread32(hcr_base + HCONTROL) <---- UAF
host->ops->host_stop(host)The iounmap(host_priv->hcr_base) and kfree(host_priv) functions should not be executed in drv->remove. These functions should be executed in host_stop after port_stop. Therefore, we move these functions to the new function sata_fsl_host_stop and bind the new function to host_stop.
--- drivers/ata/sata_fsl.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
drivers/ata/sata_fsl.c +10 -2
@@ -1394,6 +1394,14 @@ static int sata_fsl_init_controller(strureturn 0 ; } +static void sata_fsl_host_stop (struct ata_host *host) +{ +struct sata_fsl_host_priv *host_priv = host->private_data; + +iounmap (host_priv->hcr_base); +kfree (host_priv); +} +/* * scsi mid-layer and libata interface structures */
@@ -1426,6 +1434,8 @@ static struct ata_port_operations sata_f .port_start = sata_fsl_port_start, .port_stop = sata_fsl_port_stop, + .host_stop = sata_fsl_host_stop, + .pmp_attach = sata_fsl_pmp_attach, .pmp_detach = sata_fsl_pmp_detach, };
@@ -1558,8 +1568,6 @@ static int sata_fsl_remove(struct platfoata_host_detach (host);irq_dispose_mapping (host_priv->irq); -iounmap (host_priv->hcr_base); -kfree (host_priv);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 64/207 sata_fsl: fix warning in remove_proc_entry when rmmod sata_fsl
In reply to Greg Kroah-HartmanFrom: Baokun Li <[email protected]>
commit 6f48394cf1f3e8486591ad98c11cdadb8f1ef2ad upstream.
Trying to remove the fsl-sata module in the PPC64 GNU/Linux leads to the following warning:
------------[ cut here ]------------ remove_proc_entry: removing non-empty directory 'irq/69', leaking at least 'fsl-sata[ff0221000.sata]' WARNING: CPU: 3 PID: 1048 at fs/proc/generic.c:722 .remove_proc_entry+0x20c/0x220 IRQMASK: 0 NIP [c00000000033826c] .remove_proc_entry+0x20c/0x220 LR [c000000000338268] .remove_proc_entry+0x208/0x220 Call Trace: .remove_proc_entry+0x208/0x220 (unreliable) .unregister_irq_proc+0x104/0x140 .free_desc+0x44/0xb0 .irq_free_descs+0x9c/0xf0 .irq_dispose_mapping+0x64/0xa0 .sata_fsl_remove+0x58/0xa0 [sata_fsl] .platform_drv_remove+0x40/0x90 .device_release_driver_internal+0x160/0x2c0 .driver_detach+0x64/0xd0 .bus_remove_driver+0x70/0xf0 .driver_unregister+0x38/0x80 .platform_driver_unregister+0x14/0x30 .fsl_sata_driver_exit+0x18/0xa20 [sata_fsl] ---[ end trace 0ea876d4076908f5 ]---
The driver creates the mapping by calling irq_of_parse_and_map(), so it also has to dispose the mapping. But the easy way out is to simply use platform_get_irq() instead of irq_of_parse_map(). Also we should adapt return value checking and propagate error values.
In this case the mapping is not managed by the device but by the of core, so the device has not to dispose the mapping.
--- drivers/ata/sata_fsl.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
drivers/ata/sata_fsl.c +3 -5
@@ -1490,9 +1490,9 @@ static int sata_fsl_probe(struct platfor host_priv->ssr_base = ssr_base; host_priv->csr_base = csr_base; - irq =irq_of_parse_and_map (ofdev->dev.of_node,0 ); -if (!irq) { -dev_err (&ofdev->dev,"invalid irq from platform\n" ); + irq =platform_get_irq (ofdev,0 ); +if (irq <0 ) { + retval = irq; goto error_exit_with_cleanup; } host_priv->irq = irq;
@@ -1567,8 +1567,6 @@ static int sata_fsl_remove(struct platfoata_host_detach (host); -irq_dispose_mapping (host_priv->irq); -return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 65/207 scsi: lpfc: Fix non-recovery of remote ports following an unsolicited LOGO
In reply to Greg Kroah-HartmanFrom: James Smart <[email protected]>
commit 0956ba63bd94355bf38cd40f7eb9104577739ab8 upstream.
A commit introduced formal regstration of all Fabric nodes to the SCSI transport as well as REG/UNREG RPI mailbox requests. The commit introduced the NLP_RELEASE_RPI flag for rports set in the lpfc_cmpl_els_logo_acc() routine to help clean up the RPIs. This new code caused the driver to release the RPI value used for the remote port and marked the RPI invalid. When the driver later attempted to re-login, it would use the invalid RPI and the adapter rejected the PLOGI request. As no login occurred, the devloss timer on the rport expired and connectivity was lost.
This patch corrects the code by removing the snippet that requests the rpi to be unregistered. This change only occurs on a node that is already marked to be rediscovered. This puts the code back to its original behavior, preserving the already-assigned rpi value (registered or not) which can be used on the re-login attempts.
--- drivers/scsi/lpfc/lpfc_els.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-)
drivers/scsi/lpfc/lpfc_els.c +2 -7
@@ -5075,14 +5075,9 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba */* NPort Recovery mode or node is just allocated */ if (!lpfc_nlp_not_used (ndlp)) {/* A LOGO is completing and the node is in NPR state. -* If this a fabric node that cleared its transport -* registration, release the rpi. +* Just unregister the RPI because the node is still +* required. */ -spin_lock_irq (&ndlp->lock); - ndlp->nlp_flag &= ~NLP_NPR_2B_DISC ; -if (phba->sli_rev ==LPFC_SLI_REV4 ) - ndlp->nlp_flag |=NLP_RELEASE_RPI ; -spin_unlock_irq (&ndlp->lock);lpfc_unreg_rpi (vport, ndlp); }else {/* Indicate the node has already released, should
Greg Kroah-Hartman
maintainerPATCH 66/207 scsi: ufs: ufs-pci: Add support for Intel ADL
In reply to Greg Kroah-HartmanFrom: Adrian Hunter <[email protected]>
commit 7dc9fb47bc9a95f1cc6c5655341860c5e50f91d4 upstream.
Add PCI ID and callbacks to support Intel Alder Lake.
--- drivers/scsi/ufs/ufshcd-pci.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
drivers/scsi/ufs/ufshcd-pci.c +18 -0
@@ -421,6 +421,13 @@ static int ufs_intel_lkf_init(struct ufsreturn err; } +static int ufs_intel_adl_init (struct ufs_hba *hba) +{ + hba->nop_out_timeout =200 ; + hba->quirks |=UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8 ; +return ufs_intel_common_init (hba); +} +static struct ufs_hba_variant_ops ufs_intel_cnl_hba_vops = { .name ="intel-pci" , .init = ufs_intel_common_init,
@@ -449,6 +456,15 @@ static struct ufs_hba_variant_ops ufs_in .device_reset = ufs_intel_device_reset, }; +static struct ufs_hba_variant_ops ufs_intel_adl_hba_vops = { + .name ="intel-pci" , + .init = ufs_intel_adl_init, + .exit = ufs_intel_common_exit, + .link_startup_notify = ufs_intel_link_startup_notify, + .resume = ufs_intel_resume, + .device_reset = ufs_intel_device_reset, +}; +#ifdef CONFIG_PM_SLEEP static int ufshcd_pci_restore (struct device *dev) {
@@ -563,6 +579,8 @@ static const struct pci_device_id ufshcd { PCI_VDEVICE(INTEL, 0x4B41), (kernel_ulong_t)&ufs_intel_ehl_hba_vops }, { PCI_VDEVICE(INTEL, 0x4B43), (kernel_ulong_t)&ufs_intel_ehl_hba_vops }, { PCI_VDEVICE(INTEL, 0x98FA), (kernel_ulong_t)&ufs_intel_lkf_hba_vops }, + { PCI_VDEVICE(INTEL, 0x51FF), (kernel_ulong_t)&ufs_intel_adl_hba_vops }, + { PCI_VDEVICE(INTEL, 0x54FF), (kernel_ulong_t)&ufs_intel_adl_hba_vops }, { } /* terminate list */ };
Greg Kroah-Hartman
maintainerPATCH 67/207 ipv6: fix memory leak in fib6_rule_suppress
In reply to Greg Kroah-HartmanFrom: msizanoen1 <[email protected]>
commit cdef485217d30382f3bf6448c54b4401648fe3f1 upstream.
The kernel leaks memory when a fib rule is present in IPv6 nftables firewall rules and a suppress_prefix rule is present in the IPv6 routing rules (used by certain tools such as wg-quick). In such scenarios, every incoming packet will leak an allocation in ip6_dst_cache slab cache.
After some hours of bpftrace-ing and source code reading, I tracked down the issue to ca7a03c41753 ("ipv6: do not free rt if FIB_LOOKUP_NOREF is set on suppress rule").
The problem with that change is that the generic args->flags always have FIB_LOOKUP_NOREF set[1][2] but the IPv6-specific flag RT6_LOOKUP_F_DST_NOREF might not be, leading to fib6_rule_suppress not decreasing the refcount when needed.
How to reproduce:
- Add the following nftables rule to a prerouting chain:
meta nfproto ipv6 fib saddr . mark . iif oif missing drop
This can be done with:
sudo nft create table inet test
sudo nft create chain inet test test_chain '{ type filter hook prerouting priority filter + 10; policy accept; }' sudo nft add rule inet test test_chain meta nfproto ipv6 fib saddr . mark . iif oif missing drop
- Run:
sudo ip -6 rule add table main suppress_prefixlength 0
- Watch sudo slabtop -o | grep ip6_dst_cache to see memory usage increase
with every incoming ipv6 packet.
This patch exposes the protocol-specific flags to the protocol specific suppress function, and check the protocol-specific flags argument for RT6_LOOKUP_F_DST_NOREF instead of the generic FIB_LOOKUP_NOREF when decreasing the refcount, like this.
[1]: https://github.com/torvalds/linux/blob/ca7a03c4175366a92cee0ccc4fec0038c3266e26/net/ipv6/fib6_rules.c#L71
[2]: https://github.com/torvalds/linux/blob/ca7a03c4175366a92cee0ccc4fec0038c3266e26/net/ipv6/fib6_rules.c#L99
--- include/net/fib_rules.h | 4 +++- net/core/fib_rules.c | 2 +- net/ipv4/fib_rules.c | 1 + net/ipv6/fib6_rules.c | 4 ++-- 4 files changed, 7 insertions(+), 4 deletions(-)
include/net/fib_rules.h +3 -1
@@ -69,7 +69,7 @@ struct fib_rules_ops {int (*action)(struct fib_rule *,struct flowi *,int ,struct fib_lookup_arg *); -bool (*suppress)(struct fib_rule *, +bool (*suppress)(struct fib_rule *,int ,struct fib_lookup_arg *);int (*match)(struct fib_rule *,struct flowi *,int );
@@ -218,7 +218,9 @@ INDIRECT_CALLABLE_DECLARE(int fib4_rule_ struct fib_lookup_arg *arg)); INDIRECT_CALLABLE_DECLARE(bool fib6_rule_suppress(struct fib_rule *rule, +int flags,struct fib_lookup_arg *arg)); INDIRECT_CALLABLE_DECLARE(bool fib4_rule_suppress(struct fib_rule *rule, +int flags,struct fib_lookup_arg *arg));#endif
net/core/fib_rules.c +1 -1
@@ -323,7 +323,7 @@ jumped:if (!err && ops->suppress &&INDIRECT_CALL_MT (ops->suppress, fib6_rule_suppress, fib4_rule_suppress, - rule, arg)) + rule, flags, arg))continue ;if (err != -EAGAIN ) {
net/ipv4/fib_rules.c +1 -0
@@ -141,6 +141,7 @@ INDIRECT_CALLABLE_SCOPE int fib4_rule_ac } INDIRECT_CALLABLE_SCOPE bool fib4_rule_suppress(struct fib_rule *rule, +int flags,struct fib_lookup_arg *arg) {struct fib_result *result = (struct fib_result *) arg->result;
net/ipv6/fib6_rules.c +2 -2
@@ -267,6 +267,7 @@ INDIRECT_CALLABLE_SCOPE int fib6_rule_ac } INDIRECT_CALLABLE_SCOPE bool fib6_rule_suppress(struct fib_rule *rule, +int flags,struct fib_lookup_arg *arg) {struct fib6_result *res = arg->result;
@@ -294,8 +295,7 @@ INDIRECT_CALLABLE_SCOPE bool fib6_rule_sreturn false; suppress_route: -if (!(arg->flags &FIB_LOOKUP_NOREF )) -ip6_rt_put (rt); +ip6_rt_put_flags (rt, flags);return true; }
Greg Kroah-Hartman
maintainerPATCH 68/207 drm/amd/display: Allow DSC on supported MST branch devices
In reply to Greg Kroah-HartmanFrom: Nicholas Kazlauskas <[email protected]>
commit 94ebc035456a4ccacfbbef60c444079a256623ad upstream.
[Why]
When trying to lightup two 4k60 non-DSC displays behind a branch device that supports DSC we can't lightup both at once due to bandwidth limitations - each requires 48 VCPI slots but we only have 63.
[How]
The workaround already exists in the code but is guarded by a CONFIG that cannot be set by the user and shouldn't need to be.
Check for specific branch device IDs to device whether to enable the workaround for multiple display scenarios.
--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 20 +++++++++--- 1 file changed, 16 insertions(+), 4 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +16 -4
@@ -36,6 +36,8 @@#include "dm_helpers.h" #include "dc_link_ddc.h" +#include "ddc_service_types.h" +#include "dpcd_defs.h" #include "i2caux_interface.h" #include "dmub_cmd.h"
@@ -155,6 +157,16 @@ static const struct drm_connector_funcs };#if defined(CONFIG_DRM_AMD_DC_DCN ) +static bool needs_dsc_aux_workaround (struct dc_link *link) +{ +if (link->dpcd_caps.branch_dev_id ==DP_BRANCH_DEVICE_ID_90CC24 && + (link->dpcd_caps.dpcd_rev.raw ==DPCD_REV_14 || link->dpcd_caps.dpcd_rev.raw ==DPCD_REV_12 ) && + link->dpcd_caps.sink_count.bits.SINK_COUNT >=2 ) +return true; + +return false; +} +static bool validate_dsc_caps_on_connector (struct amdgpu_dm_connector *aconnector) {struct dc_sink *dc_sink = aconnector->dc_sink;
@@ -164,7 +176,7 @@ static bool validate_dsc_caps_on_connectu8 *dsc_branch_dec_caps =NULL ; aconnector->dsc_aux =drm_dp_mst_dsc_aux_for_port (port); -#if defined(CONFIG_HP_HOOK_WORKAROUND ) +/* * drm_dp_mst_dsc_aux_for_port() will return NULL for certain configs * because it only check the dsc/fec caps of the "port variable" and not the dock
@@ -174,10 +186,10 @@ static bool validate_dsc_caps_on_connect* Workaround: explicitly check the use case above and use the mst dock's aux as dsc_aux * */ - -if (!aconnector->dsc_aux && !port->parent->port_parent) +if (!aconnector->dsc_aux && !port->parent->port_parent && +needs_dsc_aux_workaround (aconnector->dc_link)) aconnector->dsc_aux = &aconnector->mst_port->dm_dp_aux.aux; -#endif +if (!aconnector->dsc_aux)return false;
Greg Kroah-Hartman
maintainerPATCH 69/207 drm/i915/dp: Perform 30ms delay after source OUI write
In reply to Greg Kroah-HartmanFrom: Lyude Paul <[email protected]>
commit a44f42ba7f1ad7d3c17bc7d91013fe814a53c5dc upstream.
While working on supporting the Intel HDR backlight interface, I noticed that there's a couple of laptops that will very rarely manage to boot up without detecting Intel HDR backlight support - even though it's supported on the system. One example of such a laptop is the Lenovo P17 1st generation.
Following some investigation Ville Syrjälä did through the docs they have available to them, they discovered that there's actually supposed to be a 30ms wait after writing the source OUI before we begin setting up the rest of the backlight interface.
This seems to be correct, as adding this 30ms delay seems to have completely fixed the probing issues I was previously seeing. So - let's start performing a 30ms wait after writing the OUI, which we do in a manner similar to how we keep track of PPS delays (e.g. record the timestamp of the OUI write, and then wait for however many ms are left since that timestamp right before we interact with the backlight) in order to avoid waiting any longer then we need to. As well, this also avoids us performing this delay on systems where we don't end up using the HDR backlight interface.
V3:
* Move last_oui_write into intel_dp
V2:
* Move panel delays into intel_pps
--- drivers/gpu/drm/i915/display/intel_display_types.h | 3 +++ drivers/gpu/drm/i915/display/intel_dp.c | 11 +++++++++++ drivers/gpu/drm/i915/display/intel_dp.h | 2 ++ drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 5 +++++ 4 files changed, 21 insertions(+)
drivers/gpu/drm/i915/display/intel_display_types.h +3 -0
@@ -1639,6 +1639,9 @@ struct intel_dp {struct intel_dp_pcon_frl frl;struct intel_psr psr; + +/* When we last wrote the OUI for eDP */ +unsigned long last_oui_write; };enum lspcon_vendor {
drivers/gpu/drm/i915/display/intel_dp.c +11 -0
@@ -29,6 +29,7 @@#include <linux/i2c.h> #include <linux/notifier.h> #include <linux/slab.h> +#include <linux/timekeeping.h> #include <linux/types.h> #include <asm/byteorder.h>
@@ -1864,6 +1865,16 @@ intel_edp_init_source_oui(struct intel_dif (drm_dp_dpcd_write (&intel_dp->aux,DP_SOURCE_OUI , oui,sizeof (oui)) <0 )drm_err (&i915->drm,"Failed to write source OUI\n" ); + + intel_dp->last_oui_write = jiffies; +} + +void intel_dp_wait_source_oui (struct intel_dp *intel_dp) +{ +struct drm_i915_private *i915 =dp_to_i915 (intel_dp); + +drm_dbg_kms (&i915->drm,"Performing OUI wait\n" ); +wait_remaining_ms_from_jiffies (intel_dp->last_oui_write,30 ); }/* If the device supports it, try to set the power state appropriately */
drivers/gpu/drm/i915/display/intel_dp.h +2 -0
@@ -129,4 +129,6 @@ void intel_dp_pcon_dsc_configure(struct const struct intel_crtc_state *crtc_state);void intel_dp_phy_test (struct intel_encoder *encoder); +void intel_dp_wait_source_oui (struct intel_dp *intel_dp); +#endif /* __INTEL_DP_H__ */
drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +5 -0
@@ -35,6 +35,7 @@*/ #include "intel_display_types.h" +#include "intel_dp.h" #include "intel_dp_aux_backlight.h" #include "intel_panel.h"
@@ -106,6 +107,8 @@ intel_dp_aux_supports_hdr_backlight(struint ret;u8 tcon_cap[4 ]; +intel_dp_wait_source_oui (intel_dp); + ret =drm_dp_dpcd_read (aux,INTEL_EDP_HDR_TCON_CAP0 , tcon_cap,sizeof (tcon_cap));if (ret !=sizeof (tcon_cap))return false;
@@ -204,6 +207,8 @@ intel_dp_aux_hdr_enable_backlight(constint ret;u8 old_ctrl, ctrl; +intel_dp_wait_source_oui (intel_dp); + ret =drm_dp_dpcd_readb (&intel_dp->aux,INTEL_EDP_HDR_GETSET_CTRL_PARAMS , &old_ctrl);if (ret !=1 ) {drm_err (&i915->drm,"Failed to read current backlight control mode: %d\n" , ret);
Greg Kroah-Hartman
maintainerPATCH 70/207 KVM: fix avic_set_running for preemptable kernels
In reply to Greg Kroah-HartmanFrom: Paolo Bonzini <[email protected]>
commit 7cfc5c653b07782e7059527df8dc1e3143a7591e upstream.
avic_set_running() passes the current CPU to avic_vcpu_load(), albeit via vcpu->cpu rather than smp_processor_id(). If the thread is migrated while avic_set_running runs, the call to avic_vcpu_load() can use a stale value for the processor id. Avoid this by blocking preemption over the entire execution of avic_set_running().
--- arch/x86/kvm/svm/avic.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
arch/x86/kvm/svm/avic.c +9 -7
@@ -988,16 +988,18 @@ void avic_vcpu_put(struct kvm_vcpu *vcpustatic void avic_set_running (struct kvm_vcpu *vcpu,bool is_run) {struct vcpu_svm *svm =to_svm (vcpu); +int cpu =get_cpu (); +WARN_ON (cpu != vcpu->cpu); svm->avic_is_running = is_run; -if (!kvm_vcpu_apicv_active (vcpu)) -return ; - -if (is_run) -avic_vcpu_load (vcpu, vcpu->cpu); -else -avic_vcpu_put (vcpu); +if (kvm_vcpu_apicv_active (vcpu)) { +if (is_run) +avic_vcpu_load (vcpu, cpu); +else +avic_vcpu_put (vcpu); + } +put_cpu (); }void svm_vcpu_blocking (struct kvm_vcpu *vcpu)
Greg Kroah-Hartman
maintainerPATCH 71/207 KVM: Disallow user memslot with size that exceeds "unsigned long"
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit 6b285a5587506bae084cf9a3ed5aa491d623b91b upstream.
Reject userspace memslots whose size exceeds the storage capacity of an "unsigned long". KVM's uAPI takes the size as u64 to support large slots on 64-bit hosts, but does not account for the size being truncated on 32-bit hosts in various flows. The access_ok() check on the userspace virtual address in particular casts the size to "unsigned long" and will check the wrong number of bytes.
KVM doesn't actually support slots whose size doesn't fit in an "unsigned long", e.g. KVM's internal kvm_memory_slot.npages is an "unsigned long", not a "u64", and misc arch specific code follows that behavior.
Message-Id: <[email protected]>
--- virt/kvm/kvm_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
virt/kvm/kvm_main.c +2 -1
@@ -1664,7 +1664,8 @@ int __kvm_set_memory_region(struct kvm * id = (u16 )mem->slot;/* General sanity checks */ -if (mem->memory_size & (PAGE_SIZE -1 )) +if ((mem->memory_size & (PAGE_SIZE -1 )) || + (mem->memory_size != (unsigned long )mem->memory_size))return -EINVAL ;if (mem->guest_phys_addr & (PAGE_SIZE -1 ))return -EINVAL ;
Greg Kroah-Hartman
maintainerPATCH 72/207 KVM: x86/mmu: Fix TLB flush range when handling disconnected pt
In reply to Greg Kroah-HartmanFrom: Ben Gardon <[email protected]>
commit 574c3c55e969096cea770eda3375ff35ccf91702 upstream.
When recursively clearing out disconnected pts, the range based TLB flush in handle_removed_tdp_mmu_page uses the wrong starting GFN, resulting in the flush mostly missing the affected range. Fix this by using base_gfn for the flush.
In response to feedback from David Matlack on the RFC version of this patch, also move a few definitions into the for loop in the function to prevent unintended references to them in the future.
Message-Id: <[email protected]>
--- arch/x86/kvm/mmu/tdp_mmu.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
arch/x86/kvm/mmu/tdp_mmu.c +4 -6
@@ -316,9 +316,6 @@ static void handle_removed_tdp_mmu_page(struct kvm_mmu_page *sp =sptep_to_sp (rcu_dereference (pt));int level = sp->role.level;gfn_t base_gfn = sp->gfn; -u64 old_child_spte; -u64 *sptep; -gfn_t gfn;int i;trace_kvm_mmu_prepare_zap_page (sp);
@@ -326,8 +323,9 @@ static void handle_removed_tdp_mmu_page(tdp_mmu_unlink_page (kvm, sp, shared);for (i =0 ; i <PT64_ENT_PER_PAGE ; i++) { - sptep =rcu_dereference (pt) + i; - gfn = base_gfn + i *KVM_PAGES_PER_HPAGE (level); +u64 *sptep =rcu_dereference (pt) + i; +gfn_t gfn = base_gfn + i *KVM_PAGES_PER_HPAGE (level); +u64 old_child_spte;if (shared) {/*
@@ -373,7 +371,7 @@ static void handle_removed_tdp_mmu_page( shared); } -kvm_flush_remote_tlbs_with_address (kvm, gfn, +kvm_flush_remote_tlbs_with_address (kvm, base_gfn,KVM_PAGES_PER_HPAGE (level +1 ));call_rcu (&sp->rcu_head, tdp_mmu_free_sp_rcu_callback);
Greg Kroah-Hartman
maintainerPATCH 73/207 KVM: Ensure local memslot copies operate on up-to-date arch-specific data
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit bda44d844758c70c8dc1478e6fc9c25efa90c5a7 upstream.
When modifying memslots, snapshot the "old" memslot and copy it to the "new" memslot's arch data after (re)acquiring slots_arch_lock. x86 can change a memslot's arch data while memslot updates are in-progress so long as it holds slots_arch_lock, thus snapshotting a memslot without holding the lock can result in the consumption of stale data.
Message-Id: <[email protected]>
--- virt/kvm/kvm_main.c | 47 +++++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 16 deletions(-)
virt/kvm/kvm_main.c +31 -16
@@ -1523,11 +1523,10 @@ static struct kvm_memslots *kvm_dup_memsstatic int kvm_set_memslot (struct kvm *kvm,const struct kvm_userspace_memory_region *mem, -struct kvm_memory_slot *old,struct kvm_memory_slot *new,int as_id,enum kvm_mr_change change) { -struct kvm_memory_slot *slot; +struct kvm_memory_slot *slot, old;struct kvm_memslots *slots;int r;
@@ -1558,7 +1557,7 @@ static int kvm_set_memslot(struct kvm *k* Note, the INVALID flag needs to be in the appropriate entry * in the freshly allocated memslots, not in @old or @new. */ - slot =id_to_memslot (slots, old->id); + slot =id_to_memslot (slots, new->id); slot->flags |=KVM_MEMSLOT_INVALID ;/*
@@ -1589,6 +1588,26 @@ static int kvm_set_memslot(struct kvm *kkvm_copy_memslots (slots,__kvm_memslots (kvm, as_id)); } +/* +* Make a full copy of the old memslot, the pointer will become stale +* when the memslots are re-sorted by update_memslots(), and the old +* memslot needs to be referenced after calling update_memslots(), e.g. +* to free its resources and for arch specific behavior. This needs to +* happen *after* (re)acquiring slots_arch_lock. +*/ + slot =id_to_memslot (slots, new->id); +if (slot) { + old = *slot; + }else { +WARN_ON_ONCE (change !=KVM_MR_CREATE ); +memset (&old,0 ,sizeof (old)); + old.id = new->id; + old.as_id = as_id; + } + +/* Copy the arch-specific data, again after (re)acquiring slots_arch_lock. */ +memcpy (&new->arch, &old.arch,sizeof (old.arch)); + r =kvm_arch_prepare_memory_region (kvm, new, mem, change);if (r) goto out_slots;
@@ -1596,14 +1615,18 @@ static int kvm_set_memslot(struct kvm *kupdate_memslots (slots, new, change); slots =install_new_memslots (kvm, as_id, slots); -kvm_arch_commit_memory_region (kvm, mem, old, new, change); +kvm_arch_commit_memory_region (kvm, mem, &old, new, change); + +/* Free the old memslot's metadata. Note, this is the full copy!!! */ +if (change ==KVM_MR_DELETE ) +kvm_free_memslot (kvm, &old);kvfree (slots);return 0 ; out_slots:if (change ==KVM_MR_DELETE || change ==KVM_MR_MOVE ) { - slot =id_to_memslot (slots, old->id); + slot =id_to_memslot (slots, new->id); slot->flags &= ~KVM_MEMSLOT_INVALID ; slots =install_new_memslots (kvm, as_id, slots); }else {
@@ -1618,7 +1641,6 @@ static int kvm_delete_memslot(struct kvm struct kvm_memory_slot *old, int as_id) {struct kvm_memory_slot new; -int r;if (!old->npages)return -EINVAL ;
@@ -1631,12 +1653,7 @@ static int kvm_delete_memslot(struct kvm*/ new.as_id = as_id; - r =kvm_set_memslot (kvm, mem, old, &new, as_id,KVM_MR_DELETE ); -if (r) -return r; - -kvm_free_memslot (kvm, old); -return 0 ; +return kvm_set_memslot (kvm, mem, &new, as_id,KVM_MR_DELETE ); }/*
@@ -1711,7 +1728,6 @@ int __kvm_set_memory_region(struct kvm *if (!old.npages) { change =KVM_MR_CREATE ; new.dirty_bitmap =NULL ; -memset (&new.arch,0 ,sizeof (new.arch)); }else {/* Modify an existing slot. */ if ((new.userspace_addr != old.userspace_addr) || (new.npages != old.npages) ||
@@ -1725,9 +1741,8 @@ int __kvm_set_memory_region(struct kvm *else /* Nothing to change. */ return 0 ; -/* Copy dirty_bitmap and arch from the current memslot. */ +/* Copy dirty_bitmap from the current memslot. */ new.dirty_bitmap = old.dirty_bitmap; -memcpy (&new.arch, &old.arch,sizeof (new.arch)); }if ((change ==KVM_MR_CREATE ) || (change ==KVM_MR_MOVE )) {
@@ -1753,7 +1768,7 @@ int __kvm_set_memory_region(struct kvm *bitmap_set (new.dirty_bitmap,0 , new.npages); } - r =kvm_set_memslot (kvm, mem, &old, &new, as_id, change); + r =kvm_set_memslot (kvm, mem, &new, as_id, change);if (r) goto out_bitmap;
Greg Kroah-Hartman
maintainerPATCH 74/207 KVM: x86: ignore APICv if LAPIC is not enabled
In reply to Greg Kroah-HartmanFrom: Paolo Bonzini <[email protected]>
commit 78311a514099932cd8434d5d2194aa94e56ab67c upstream.
Synchronize the two calls to kvm_x86_sync_pir_to_irr. The one in the reenter-guest fast path invoked the callback unconditionally even if LAPIC is present but disabled. In this case, there are no interrupts to deliver, and therefore posted interrupts can be ignored.
--- arch/x86/kvm/x86.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kvm/x86.c +1 -1
@@ -9723,7 +9723,7 @@ static int vcpu_enter_guest(struct kvm_vif (likely (exit_fastpath !=EXIT_FASTPATH_REENTER_GUEST ))break ; -if (vcpu->arch.apicv_active) +if (kvm_lapic_enabled (vcpu) && vcpu->arch.apicv_active)static_call (kvm_x86_sync_pir_to_irr)(vcpu);if (unlikely (kvm_vcpu_exit_request (vcpu))) {
Greg Kroah-Hartman
maintainerPATCH 75/207 KVM: nVMX: Emulate guest TLB flush on nested VM-Enter with new vpid12
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit 712494de96f35f3e146b36b752c2afe0fdc0f0cc upstream.
Fully emulate a guest TLB flush on nested VM-Enter which changes vpid12, i.e. L2's VPID, instead of simply doing INVVPID to flush real hardware's TLB entries for vpid02. From L1's perspective, changing L2's VPID is effectively a TLB flush unless "hardware" has previously cached entries for the new vpid12. Because KVM tracks only a single vpid12, KVM doesn't know if the new vpid12 has been used in the past and so must treat it as a brand new, never been used VPID, i.e. must assume that the new vpid12 represents a TLB flush from L1's perspective.
For example, if L1 and L2 share a CR3, the first VM-Enter to L2 (with a VPID) is effectively a TLB flush as hardware/KVM has never seen vpid12 and thus can't have cached entries in the TLB for vpid12.
Message-Id: <[email protected]>
--- arch/x86/kvm/vmx/nested.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-)
arch/x86/kvm/vmx/nested.c +17 -20
@@ -1180,29 +1180,26 @@ static void nested_vmx_transition_tlb_flWARN_ON (!enable_vpid);/* -* If VPID is enabled and used by vmc12, but L2 does not have a unique -* TLB tag (ASID), i.e. EPT is disabled and KVM was unable to allocate -* a VPID for L2, flush the current context as the effective ASID is -* common to both L1 and L2. -* -* Defer the flush so that it runs after vmcs02.EPTP has been set by -* KVM_REQ_LOAD_MMU_PGD (if nested EPT is enabled) and to avoid -* redundant flushes further down the nested pipeline. -* -* If a TLB flush isn't required due to any of the above, and vpid12 is -* changing then the new "virtual" VPID (vpid12) will reuse the same -* "real" VPID (vpid02), and so needs to be flushed. There's no direct -* mapping between vpid02 and vpid12, vpid02 is per-vCPU and reused for -* all nested vCPUs. Remember, a flush on VM-Enter does not invalidate -* guest-physical mappings, so there is no need to sync the nEPT MMU. +* VPID is enabled and in use by vmcs12. If vpid12 is changing, then +* emulate a guest TLB flush as KVM does not track vpid12 history nor +* is the VPID incorporated into the MMU context. I.e. KVM must assume +* that the new vpid12 has never been used and thus represents a new +* guest ASID that cannot have entries in the TLB. */ -if (!nested_has_guest_tlb_tag (vcpu)) { -kvm_make_request (KVM_REQ_TLB_FLUSH_CURRENT , vcpu); - }else if (is_vmenter && - vmcs12->virtual_processor_id != vmx->nested.last_vpid) { +if (is_vmenter && vmcs12->virtual_processor_id != vmx->nested.last_vpid) { vmx->nested.last_vpid = vmcs12->virtual_processor_id; -vpid_sync_context (nested_get_vpid02 (vcpu)); +kvm_make_request (KVM_REQ_TLB_FLUSH_GUEST , vcpu); +return ; } + +/* +* If VPID is enabled, used by vmc12, and vpid12 is not changing but +* does not have a unique TLB tag (ASID), i.e. EPT is disabled and +* KVM was unable to allocate a VPID for L2, flush the current context +* as the effective ASID is common to both L1 and L2. +*/ +if (!nested_has_guest_tlb_tag (vcpu)) +kvm_make_request (KVM_REQ_TLB_FLUSH_CURRENT , vcpu); }static bool is_bitwise_subset (u64 superset,u64 subset,u64 mask)
Greg Kroah-Hartman
maintainerPATCH 76/207 KVM: nVMX: Flush current VPID (L1 vs. L2) for KVM_REQ_TLB_FLUSH_GUEST
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit 2b4a5a5d56881ece3c66b9a9a8943a6f41bd7349 upstream.
Flush the current VPID when handling KVM_REQ_TLB_FLUSH_GUEST instead of always flushing vpid01. Any TLB flush that is triggered when L2 is active is scoped to L2's VPID (if it has one), e.g. if L2 toggles CR4.PGE and L1 doesn't intercept PGE writes, then KVM's emulation of the TLB flush needs to be applied to L2's VPID.
Message-Id: <[email protected]>
--- arch/x86/kvm/vmx/vmx.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-)
arch/x86/kvm/vmx/vmx.c +14 -9
@@ -2916,6 +2916,13 @@ static void vmx_flush_tlb_all(struct kvm } } +static inline int vmx_get_current_vpid (struct kvm_vcpu *vcpu) +{ +if (is_guest_mode (vcpu)) +return nested_get_vpid02 (vcpu); +return to_vmx (vcpu)->vpid; +} +static void vmx_flush_tlb_current (struct kvm_vcpu *vcpu) {struct kvm_mmu *mmu = vcpu->arch.mmu;
@@ -2928,31 +2935,29 @@ static void vmx_flush_tlb_current(structif (enable_ept)ept_sync_context (construct_eptp (vcpu, root_hpa, mmu->shadow_root_level)); -else if (!is_guest_mode (vcpu)) -vpid_sync_context (to_vmx (vcpu)->vpid);else -vpid_sync_context (nested_get_vpid02 (vcpu)); +vpid_sync_context (vmx_get_current_vpid (vcpu)); }static void vmx_flush_tlb_gva (struct kvm_vcpu *vcpu,gva_t addr) {/* -* vpid_sync_vcpu_addr() is a nop if vmx->vpid==0, see the comment in +* vpid_sync_vcpu_addr() is a nop if vpid==0, see the comment in * vmx_flush_tlb_guest() for an explanation of why this is ok. */ -vpid_sync_vcpu_addr (to_vmx (vcpu)->vpid, addr); +vpid_sync_vcpu_addr (vmx_get_current_vpid (vcpu), addr); }static void vmx_flush_tlb_guest (struct kvm_vcpu *vcpu) {/* -* vpid_sync_context() is a nop if vmx->vpid==0, e.g. if enable_vpid==0 -* or a vpid couldn't be allocated for this vCPU. VM-Enter and VM-Exit -* are required to flush GVA->{G,H}PA mappings from the TLB if vpid is +* vpid_sync_context() is a nop if vpid==0, e.g. if enable_vpid==0 or a +* vpid couldn't be allocated for this vCPU. VM-Enter and VM-Exit are +* required to flush GVA->{G,H}PA mappings from the TLB if vpid is * disabled (VM-Enter with vpid enabled and vpid==0 is disallowed), * i.e. no explicit INVVPID is necessary. */ -vpid_sync_context (to_vmx (vcpu)->vpid); +vpid_sync_context (vmx_get_current_vpid (vcpu)); }void vmx_ept_load_pdptrs (struct kvm_vcpu *vcpu)
Greg Kroah-Hartman
maintainerPATCH 77/207 KVM: nVMX: Abide to KVM_REQ_TLB_FLUSH_GUEST request on nested vmentry/vmexit
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit 40e5f9080472b614eeedcc5ba678289cd98d70df upstream.
Like KVM_REQ_TLB_FLUSH_CURRENT, the GUEST variant needs to be serviced at nested transitions, as KVM doesn't track requests for L1 vs L2. E.g. if there's a pending flush when a nested VM-Exit occurs, then the flush was requested in the context of L2 and needs to be handled before switching to L1, otherwise the flush for L2 would effectiely be lost.
Opportunistically add a helper to handle CURRENT and GUEST as a pair, the logic for when they need to be serviced is identical as both requests are tied to L1 vs. L2, the only difference is the scope of the flush.
Message-Id: <[email protected]>
--- arch/x86/kvm/vmx/nested.c | 8 +++----- arch/x86/kvm/x86.c | 28 ++++++++++++++++++++++++---- arch/x86/kvm/x86.h | 7 +------ 3 files changed, 28 insertions(+), 15 deletions(-)
arch/x86/kvm/vmx/nested.c +3 -5
@@ -3355,8 +3355,7 @@ enum nvmx_vmentry_status nested_vmx_ente };u32 failed_index; -if (kvm_check_request (KVM_REQ_TLB_FLUSH_CURRENT , vcpu)) -kvm_vcpu_flush_tlb_current (vcpu); +kvm_service_local_tlb_flush_requests (vcpu); evaluate_pending_interrupts =exec_controls_get (vmx) & (CPU_BASED_INTR_WINDOW_EXITING |CPU_BASED_NMI_WINDOW_EXITING );
@@ -4513,9 +4512,8 @@ void nested_vmx_vmexit(struct kvm_vcpu * (void )nested_get_evmcs_page (vcpu); } -/* Service the TLB flush request for L2 before switching to L1. */ -if (kvm_check_request (KVM_REQ_TLB_FLUSH_CURRENT , vcpu)) -kvm_vcpu_flush_tlb_current (vcpu); +/* Service pending TLB flush requests for L2 before switching to L1. */ +kvm_service_local_tlb_flush_requests (vcpu);/* * VCPU_EXREG_PDPTR will be clobbered in arch/x86/kvm/vmx/vmx.h between
arch/x86/kvm/x86.c +24 -4
@@ -3193,6 +3193,29 @@ static void kvm_vcpu_flush_tlb_guest(strstatic_call (kvm_x86_tlb_flush_guest)(vcpu); } + +static inline void kvm_vcpu_flush_tlb_current (struct kvm_vcpu *vcpu) +{ + ++vcpu->stat.tlb_flush; +static_call (kvm_x86_tlb_flush_current)(vcpu); +} + +/* +* Service "local" TLB flush requests, which are specific to the current MMU +* context. In addition to the generic event handling in vcpu_enter_guest(), +* TLB flushes that are targeted at an MMU context also need to be serviced +* prior before nested VM-Enter/VM-Exit. +*/ +void kvm_service_local_tlb_flush_requests (struct kvm_vcpu *vcpu) +{ +if (kvm_check_request (KVM_REQ_TLB_FLUSH_CURRENT , vcpu)) +kvm_vcpu_flush_tlb_current (vcpu); + +if (kvm_check_request (KVM_REQ_TLB_FLUSH_GUEST , vcpu)) +kvm_vcpu_flush_tlb_guest (vcpu); +} +EXPORT_SYMBOL_GPL (kvm_service_local_tlb_flush_requests); +static void record_steal_time (struct kvm_vcpu *vcpu) {struct gfn_to_hva_cache *ghc = &vcpu->arch.st.cache;
@@ -9530,10 +9553,7 @@ static int vcpu_enter_guest(struct kvm_v/* Flushing all ASIDs flushes the current ASID... */ kvm_clear_request (KVM_REQ_TLB_FLUSH_CURRENT , vcpu); } -if (kvm_check_request (KVM_REQ_TLB_FLUSH_CURRENT , vcpu)) -kvm_vcpu_flush_tlb_current (vcpu); -if (kvm_check_request (KVM_REQ_TLB_FLUSH_GUEST , vcpu)) -kvm_vcpu_flush_tlb_guest (vcpu); +kvm_service_local_tlb_flush_requests (vcpu);if (kvm_check_request (KVM_REQ_REPORT_TPR_ACCESS , vcpu)) { vcpu->run->exit_reason =KVM_EXIT_TPR_ACCESS ;
arch/x86/kvm/x86.h +1 -6
@@ -103,6 +103,7 @@ static inline unsigned int __shrink_ple_#define MSR_IA32_CR_PAT_DEFAULT 0x0007040600070406ULL +void kvm_service_local_tlb_flush_requests (struct kvm_vcpu *vcpu);int kvm_check_nested_events (struct kvm_vcpu *vcpu);static inline void kvm_clear_exception_queue (struct kvm_vcpu *vcpu)
@@ -185,12 +186,6 @@ static inline bool mmu_is_nested(structreturn vcpu->arch.walk_mmu == &vcpu->arch.nested_mmu; } -static inline void kvm_vcpu_flush_tlb_current (struct kvm_vcpu *vcpu) -{ - ++vcpu->stat.tlb_flush; -static_call (kvm_x86_tlb_flush_current)(vcpu); -} -static inline int is_pae (struct kvm_vcpu *vcpu) {return kvm_read_cr4_bits (vcpu,X86_CR4_PAE );
Greg Kroah-Hartman
maintainerPATCH 78/207 KVM: VMX: prepare sync_pir_to_irr for running with APICv disabled
In reply to Greg Kroah-HartmanFrom: Paolo Bonzini <[email protected]>
commit 7e1901f6c86c896acff6609e0176f93f756d8b2a upstream.
If APICv is disabled for this vCPU, assigned devices may still attempt to post interrupts. In that case, we need to cancel the vmentry and deliver the interrupt with KVM_REQ_EVENT. Extend the existing code that handles injection of L1 interrupts into L2 to cover this case as well.
vmx_hwapic_irr_update is only called when APICv is active so it would be confusing to add a check for vcpu->arch.apicv_active in there. Instead, just use vmx_set_rvi directly in vmx_sync_pir_to_irr.
Message-Id: <[email protected]>
--- arch/x86/kvm/vmx/vmx.c | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-)
arch/x86/kvm/vmx/vmx.c +25 -14
@@ -6242,9 +6242,9 @@ static int vmx_sync_pir_to_irr(struct kv {struct vcpu_vmx *vmx =to_vmx (vcpu);int max_irr; -bool max_irr_updated; +bool got_posted_interrupt; -if (KVM_BUG_ON (!vcpu->arch.apicv_active, vcpu->kvm)) +if (KVM_BUG_ON (!enable_apicv, vcpu->kvm))return -EIO ;if (pi_test_on (&vmx->pi_desc)) {
@@ -6254,22 +6254,33 @@ static int vmx_sync_pir_to_irr(struct kv* But on x86 this is just a compiler barrier anyway. */ smp_mb__after_atomic (); - max_irr_updated = + got_posted_interrupt =kvm_apic_update_irr (vcpu, vmx->pi_desc.pir, &max_irr); - -/* -* If we are running L2 and L1 has a new pending interrupt -* which can be injected, this may cause a vmexit or it may -* be injected into L2. Either way, this interrupt will be -* processed via KVM_REQ_EVENT, not RVI, because we do not use -* virtual interrupt delivery to inject L1 interrupts into L2. -*/ -if (is_guest_mode (vcpu) && max_irr_updated) -kvm_make_request (KVM_REQ_EVENT , vcpu); }else { max_irr =kvm_lapic_find_highest_irr (vcpu); + got_posted_interrupt = false; } -vmx_hwapic_irr_update (vcpu, max_irr); + +/* +* Newly recognized interrupts are injected via either virtual interrupt +* delivery (RVI) or KVM_REQ_EVENT. Virtual interrupt delivery is +* disabled in two cases: +* +* 1) If L2 is running and the vCPU has a new pending interrupt. If L1 +* wants to exit on interrupts, KVM_REQ_EVENT is needed to synthesize a +* VM-Exit to L1. If L1 doesn't want to exit, the interrupt is injected +* into L2, but KVM doesn't use virtual interrupt delivery to inject +* interrupts into L2, and so KVM_REQ_EVENT is again needed. +* +* 2) If APICv is disabled for this vCPU, assigned devices may still +* attempt to post interrupts. The posted interrupt vector will cause +* a VM-Exit and the subsequent entry will call sync_pir_to_irr. +*/ +if (!is_guest_mode (vcpu) &&kvm_vcpu_apicv_active (vcpu)) +vmx_set_rvi (max_irr); +else if (got_posted_interrupt) +kvm_make_request (KVM_REQ_EVENT , vcpu); +return max_irr; }
Greg Kroah-Hartman
maintainerPATCH 79/207 KVM: x86: Use a stable condition around all VT-d PI paths
In reply to Greg Kroah-HartmanFrom: Paolo Bonzini <[email protected]>
commit 53b7ca1a359389276c76fbc9e1009d8626a17e40 upstream.
Currently, checks for whether VT-d PI can be used refer to the current status of the feature in the current vCPU; or they more or less pick vCPU 0 in case a specific vCPU is not available.
However, these checks do not attempt to synchronize with changes to the IRTE. In particular, there is no path that updates the IRTE when APICv is re-activated on vCPU 0; and there is no path to wakeup a CPU that has APICv disabled, if the wakeup occurs because of an IRTE that points to a posted interrupt.
To fix this, always go through the VT-d PI path as long as there are assigned devices and APICv is available on both the host and the VM side. Since the relevant condition was copied over three times, take the hint and factor it into a separate function.
Message-Id: <[email protected]>
--- arch/x86/kvm/vmx/posted_intr.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-)
arch/x86/kvm/vmx/posted_intr.c +11 -9
@@ -5,6 +5,7 @@#include <asm/cpu.h> #include "lapic.h" +#include "irq.h" #include "posted_intr.h" #include "trace.h" #include "vmx.h"
@@ -77,13 +78,18 @@ after_clear_sn:pi_set_on (pi_desc); } +static bool vmx_can_use_vtd_pi (struct kvm *kvm) +{ +return irqchip_in_kernel (kvm) && enable_apicv && +kvm_arch_has_assigned_device (kvm) && +irq_remapping_cap (IRQ_POSTING_CAP ); +} +void vmx_vcpu_pi_put (struct kvm_vcpu *vcpu) {struct pi_desc *pi_desc =vcpu_to_pi_desc (vcpu); -if (!kvm_arch_has_assigned_device (vcpu->kvm) || - !irq_remapping_cap (IRQ_POSTING_CAP ) || - !kvm_vcpu_apicv_active (vcpu)) +if (!vmx_can_use_vtd_pi (vcpu->kvm))return ;/* Set SN when the vCPU is preempted */
@@ -141,9 +147,7 @@ int pi_pre_block(struct kvm_vcpu *vcpu)struct pi_desc old, new;struct pi_desc *pi_desc =vcpu_to_pi_desc (vcpu); -if (!kvm_arch_has_assigned_device (vcpu->kvm) || - !irq_remapping_cap (IRQ_POSTING_CAP ) || - !kvm_vcpu_apicv_active (vcpu)) +if (!vmx_can_use_vtd_pi (vcpu->kvm))return 0 ;WARN_ON (irqs_disabled ());
@@ -270,9 +274,7 @@ int pi_update_irte(struct kvm *kvm, unsistruct vcpu_data vcpu_info;int idx, ret =0 ; -if (!kvm_arch_has_assigned_device (kvm) || - !irq_remapping_cap (IRQ_POSTING_CAP ) || - !kvm_vcpu_apicv_active (kvm->vcpus[0 ])) +if (!vmx_can_use_vtd_pi (kvm))return 0 ; idx =srcu_read_lock (&kvm->irq_srcu);
Greg Kroah-Hartman
maintainerPATCH 80/207 KVM: MMU: shadow nested paging does not have PKU
In reply to Greg Kroah-HartmanFrom: Paolo Bonzini <[email protected]>
commit 28f091bc2f8c23b7eac2402956b692621be7f9f4 upstream.
Initialize the mask for PKU permissions as if CR4.PKE=0, avoiding incorrect interpretations of the nested hypervisor's page tables.
--- arch/x86/kvm/mmu/mmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/kvm/mmu/mmu.c +2 -2
@@ -4852,7 +4852,7 @@ void kvm_init_shadow_npt_mmu(struct kvm_struct kvm_mmu *context = &vcpu->arch.guest_mmu;struct kvm_mmu_role_regs regs = { .cr0 = cr0, - .cr4 = cr4, + .cr4 = cr4 & ~X86_CR4_PKE , .efer = efer, };union kvm_mmu_role new_role;
@@ -4916,7 +4916,7 @@ void kvm_init_shadow_ept_mmu(struct kvm_ context->direct_map = false;update_permission_bitmask (context, true); -update_pkru_bitmask (context); + context->pkru_mask =0 ;reset_rsvds_bits_mask_ept (vcpu, context, execonly);reset_ept_shadow_zero_bits_mask (vcpu, context, execonly); }
Greg Kroah-Hartman
maintainerPATCH 81/207 KVM: arm64: Avoid setting the upper 32 bits of TCR_EL2 and CPTR_EL2 to 1
In reply to Greg Kroah-HartmanFrom: Catalin Marinas <[email protected]>
commit 1f80d15020d7f130194821feb1432b67648c632d upstream.
Having a signed (1 << 31) constant for TCR_EL2_RES1 and CPTR_EL2_TCPAC causes the upper 32-bit to be set to 1 when assigning them to a 64-bit variable. Bit 32 in TCR_EL2 is no longer RES0 in ARMv8.7: with FEAT_LPA2 it changes the meaning of bits 49:48 and 9:8 in the stage 1 EL2 page table entries. As a result of the sign-extension, a non-VHE kernel can no longer boot on a model with ARMv8.7 enabled.
CPTR_EL2 still has the top 32 bits RES0 but we should preempt any future problems
Make these top bit constants unsigned as per commit df655b75c43f ("arm64: KVM: Avoid setting the upper 32 bits of VTCR_EL2 to 1").
--- arch/arm64/include/asm/kvm_arm.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/include/asm/kvm_arm.h +2 -2
@@ -91,7 +91,7 @@#define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)/* TCR_EL2 Registers bits */ -#define TCR_EL2_RES1 ((1 << 31) | (1 << 23)) +#define TCR_EL2_RES1 ((1U << 31) | (1 << 23))#define TCR_EL2_TBI (1 << 20)#define TCR_EL2_PS_SHIFT 16#define TCR_EL2_PS_MASK (7 << TCR_EL2_PS_SHIFT)
@@ -276,7 +276,7 @@#define CPTR_EL2_TFP_SHIFT 10/* Hyp Coprocessor Trap Register */ -#define CPTR_EL2_TCPAC (1 << 31) +#define CPTR_EL2_TCPAC (1U << 31)#define CPTR_EL2_TAM (1 << 30)#define CPTR_EL2_TTA (1 << 20)#define CPTR_EL2_TFP (1 << CPTR_EL2_TFP_SHIFT)
Greg Kroah-Hartman
maintainerPATCH 82/207 KVM: X86: Use vcpu->arch.walk_mmu for kvm_mmu_invlpg()
In reply to Greg Kroah-HartmanFrom: Lai Jiangshan <[email protected]>
commit 05b29633c7a956d5675f5fbba70db0d26aa5e73e upstream.
INVLPG operates on guest virtual address, which are represented by vcpu->arch.walk_mmu. In nested virtualization scenarios, kvm_mmu_invlpg() was using the wrong MMU structure; if L2's invlpg were emulated by L0 (in practice, it hardly happen) when nested two-dimensional paging is enabled, the call to ->tlb_flush_gva() would be skipped and the hardware TLB entry would not be invalidated.
Message-Id: <[email protected]>
--- arch/x86/kvm/mmu/mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kvm/mmu/mmu.c +1 -1
@@ -5369,7 +5369,7 @@ void kvm_mmu_invalidate_gva(struct kvm_vvoid kvm_mmu_invlpg (struct kvm_vcpu *vcpu,gva_t gva) { -kvm_mmu_invalidate_gva (vcpu, vcpu->arch.mmu, gva,INVALID_PAGE ); +kvm_mmu_invalidate_gva (vcpu, vcpu->arch.walk_mmu, gva,INVALID_PAGE ); ++vcpu->stat.invlpg; }EXPORT_SYMBOL_GPL (kvm_mmu_invlpg);
Greg Kroah-Hartman
maintainerPATCH 83/207 KVM: x86: check PIR even for vCPUs with disabled APICv
In reply to Greg Kroah-HartmanFrom: Paolo Bonzini <[email protected]>
commit 37c4dbf337c5c2cdb24365ffae6ed70ac1e74d7a upstream.
The IRTE for an assigned device can trigger a POSTED_INTR_VECTOR even if APICv is disabled on the vCPU that receives it. In that case, the interrupt will just cause a vmexit and leave the ON bit set together with the PIR bit corresponding to the interrupt.
Right now, the interrupt would not be delivered until APICv is re-enabled. However, fixing this is just a matter of always doing the PIR->IRR synchronization, even if the vCPU has temporarily disabled APICv.
This is not a problem for performance, or if anything it is an improvement. First, in the common case where vcpu->arch.apicv_active is true, one fewer check has to be performed. Second, static_call_cond will elide the function call if APICv is not present or disabled. Finally, in the case for AMD hardware we can remove the sync_pir_to_irr callback:
it is only needed for apic_has_interrupt_for_ppr, and that function already has a fallback for !APICv.
Message-Id: <[email protected]>
--- arch/x86/kvm/lapic.c | 2 +- arch/x86/kvm/svm/svm.c | 1 - arch/x86/kvm/x86.c | 18 +++++++++--------- 3 files changed, 10 insertions(+), 11 deletions(-)
arch/x86/kvm/lapic.c +1 -1
@@ -707,7 +707,7 @@ static void pv_eoi_clr_pending(struct kvstatic int apic_has_interrupt_for_ppr (struct kvm_lapic *apic,u32 ppr) {int highest_irr; -if (apic->vcpu->arch.apicv_active) +if (kvm_x86_ops.sync_pir_to_irr) highest_irr =static_call (kvm_x86_sync_pir_to_irr)(apic->vcpu);else highest_irr =apic_find_highest_irr (apic);
arch/x86/kvm/svm/svm.c +0 -1
@@ -4592,7 +4592,6 @@ static struct kvm_x86_ops svm_x86_ops __ .load_eoi_exitmap = svm_load_eoi_exitmap, .hwapic_irr_update = svm_hwapic_irr_update, .hwapic_isr_update = svm_hwapic_isr_update, - .sync_pir_to_irr = kvm_lapic_find_highest_irr, .apicv_post_state_restore = avic_post_state_restore, .set_tss_addr = svm_set_tss_addr,
arch/x86/kvm/x86.c +9 -9
@@ -4405,8 +4405,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *static int kvm_vcpu_ioctl_get_lapic (struct kvm_vcpu *vcpu,struct kvm_lapic_state *s) { -if (vcpu->arch.apicv_active) -static_call (kvm_x86_sync_pir_to_irr)(vcpu); +static_call_cond (kvm_x86_sync_pir_to_irr)(vcpu);return kvm_apic_get_state (vcpu, s); }
@@ -9433,8 +9432,7 @@ static void vcpu_scan_ioapic(struct kvm_if (irqchip_split (vcpu->kvm))kvm_scan_ioapic_routes (vcpu, vcpu->arch.ioapic_handled_vectors);else { -if (vcpu->arch.apicv_active) -static_call (kvm_x86_sync_pir_to_irr)(vcpu); +static_call_cond (kvm_x86_sync_pir_to_irr)(vcpu);if (ioapic_in_kernel (vcpu->kvm))kvm_ioapic_scan_entry (vcpu, vcpu->arch.ioapic_handled_vectors); }
@@ -9704,10 +9702,12 @@ static int vcpu_enter_guest(struct kvm_v/* * This handles the case where a posted interrupt was -* notified with kvm_vcpu_kick. +* notified with kvm_vcpu_kick. Assigned devices can +* use the POSTED_INTR_VECTOR even if APICv is disabled, +* so do it even if APICv is disabled on this vCPU. */ -if (kvm_lapic_enabled (vcpu) && vcpu->arch.apicv_active) -static_call (kvm_x86_sync_pir_to_irr)(vcpu); +if (kvm_lapic_enabled (vcpu)) +static_call_cond (kvm_x86_sync_pir_to_irr)(vcpu);if (kvm_vcpu_exit_request (vcpu)) { vcpu->mode =OUTSIDE_GUEST_MODE ;
@@ -9743,8 +9743,8 @@ static int vcpu_enter_guest(struct kvm_vif (likely (exit_fastpath !=EXIT_FASTPATH_REENTER_GUEST ))break ; -if (kvm_lapic_enabled (vcpu) && vcpu->arch.apicv_active) -static_call (kvm_x86_sync_pir_to_irr)(vcpu); +if (kvm_lapic_enabled (vcpu)) +static_call_cond (kvm_x86_sync_pir_to_irr)(vcpu);if (unlikely (kvm_vcpu_exit_request (vcpu))) { exit_fastpath =EXIT_FASTPATH_EXIT_HANDLED ;
Greg Kroah-Hartman
maintainerPATCH 84/207 tracing/histograms: String compares should not care about signed values
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (VMware) <[email protected]>
commit 450fec13d9170127678f991698ac1a5b05c02e2f upstream.
When comparing two strings for the "onmatch" histogram trigger, fields that are strings use string comparisons, which do not care about being signed or not.
Do not fail to match two string fields if one is unsigned char array and the other is a signed char array.
--- kernel/trace/trace_events_hist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/trace/trace_events_hist.c +1 -1
@@ -3419,7 +3419,7 @@ static int check_synth_field(struct syntif (strcmp (field->type, hist_field->type) !=0 ) {if (field->size != hist_field->size || - field->is_signed != hist_field->is_signed) + (!field->is_string && field->is_signed != hist_field->is_signed))return -EINVAL ; }
Greg Kroah-Hartman
maintainerPATCH 85/207 net: dsa: mv88e6xxx: Fix application of erratum 4.8 for 88E6393X
In reply to Greg Kroah-HartmanFrom: Marek Behún <[email protected]>
commit 21635d9203e1cf2b73b67e9a86059a62f62a3563 upstream.
According to SERDES scripts for 88E6393X, erratum 4.8 has to be applied every time before SerDes is powered on.
Split the code for erratum 4.8 into separate function and call it in mv88e6393x_serdes_power().
--- drivers/net/dsa/mv88e6xxx/serdes.c | 53 +++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 20 deletions(-)
drivers/net/dsa/mv88e6xxx/serdes.c +33 -20
@@ -1271,9 +1271,9 @@ void mv88e6390_serdes_get_regs(struct mv } } -static int mv88e6393x_serdes_port_errata (struct mv88e6xxx_chip *chip,int lane) +static int mv88e6393x_serdes_erratum_4_6 (struct mv88e6xxx_chip *chip,int lane) { -u16 reg, pcs; +u16 reg;int err;/* mv88e6393x family errata 4.6:
@@ -1300,11 +1300,32 @@ static int mv88e6393x_serdes_port_errataif (err)return err; - err =mv88e6390_serdes_power_sgmii (chip, lane, false); -if (err) -return err; +return mv88e6390_serdes_power_sgmii (chip, lane, false); } +return 0 ; +} + +int mv88e6393x_serdes_setup_errata (struct mv88e6xxx_chip *chip) +{ +int err; + + err =mv88e6393x_serdes_erratum_4_6 (chip,MV88E6393X_PORT0_LANE ); +if (err) +return err; + + err =mv88e6393x_serdes_erratum_4_6 (chip,MV88E6393X_PORT9_LANE ); +if (err) +return err; + +return mv88e6393x_serdes_erratum_4_6 (chip,MV88E6393X_PORT10_LANE ); +} + +static int mv88e6393x_serdes_erratum_4_8 (struct mv88e6xxx_chip *chip,int lane) +{ +u16 reg, pcs; +int err; +/* mv88e6393x family errata 4.8: * When a SERDES port is operating in 1000BASE-X or SGMII mode link may * not come up after hardware reset or software reset of SERDES core.
@@ -1334,29 +1355,21 @@ static int mv88e6393x_serdes_port_errata MV88E6393X_ERRATA_4_8_REG, reg); } -int mv88e6393x_serdes_setup_errata (struct mv88e6xxx_chip *chip) -{ -int err; - - err =mv88e6393x_serdes_port_errata (chip,MV88E6393X_PORT0_LANE ); -if (err) -return err; - - err =mv88e6393x_serdes_port_errata (chip,MV88E6393X_PORT9_LANE ); -if (err) -return err; - -return mv88e6393x_serdes_port_errata (chip,MV88E6393X_PORT10_LANE ); -} -int mv88e6393x_serdes_power (struct mv88e6xxx_chip *chip,int port,int lane,bool on) {u8 cmode = chip->ports[port].cmode; +int err;if (port !=0 && port !=9 && port !=10 )return -EOPNOTSUPP ; +if (on) { + err =mv88e6393x_serdes_erratum_4_8 (chip, lane); +if (err) +return err; + } +switch (cmode) {case MV88E6XXX_PORT_STS_CMODE_SGMII :case MV88E6XXX_PORT_STS_CMODE_1000BASEX :
Greg Kroah-Hartman
maintainerPATCH 86/207 net: dsa: mv88e6xxx: Drop unnecessary check in mv88e6393x_serdes_erratum_4_6()
In reply to Greg Kroah-HartmanFrom: Marek Behún <[email protected]>
commit 8c3318b4874e2dee867f5ae8f6d38f78e044bf71 upstream.
The check for lane is unnecessary, since the function is called only with allowed lane argument.
--- drivers/net/dsa/mv88e6xxx/serdes.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-)
drivers/net/dsa/mv88e6xxx/serdes.c +11 -17
@@ -1284,26 +1284,20 @@ static int mv88e6393x_serdes_erratum_4_6* It seems that after this workaround the SERDES is automatically * powered up (the bit is cleared), so power it down. */ -if (lane ==MV88E6393X_PORT0_LANE || lane ==MV88E6393X_PORT9_LANE || - lane ==MV88E6393X_PORT10_LANE ) { - err =mv88e6390_serdes_read (chip, lane, -MDIO_MMD_PHYXS , -MV88E6393X_SERDES_POC , ®); -if (err) -return err; + err =mv88e6390_serdes_read (chip, lane,MDIO_MMD_PHYXS , +MV88E6393X_SERDES_POC , ®); +if (err) +return err; - reg &= ~MV88E6393X_SERDES_POC_PDOWN ; - reg |=MV88E6393X_SERDES_POC_RESET ; + reg &= ~MV88E6393X_SERDES_POC_PDOWN ; + reg |=MV88E6393X_SERDES_POC_RESET ; - err =mv88e6390_serdes_write (chip, lane,MDIO_MMD_PHYXS , -MV88E6393X_SERDES_POC , reg); -if (err) -return err; + err =mv88e6390_serdes_write (chip, lane,MDIO_MMD_PHYXS , +MV88E6393X_SERDES_POC , reg); +if (err) +return err; -return mv88e6390_serdes_power_sgmii (chip, lane, false); - } - -return 0 ; +return mv88e6390_serdes_power_sgmii (chip, lane, false); }int mv88e6393x_serdes_setup_errata (struct mv88e6xxx_chip *chip)
Greg Kroah-Hartman
maintainerPATCH 87/207 net: dsa: mv88e6xxx: Save power by disabling SerDes trasmitter and receiver
In reply to Greg Kroah-HartmanFrom: Marek Behún <[email protected]>
commit 7527d66260ac0c603c6baca5146748061fcddbd6 upstream.
Save power on 88E6393X by disabling SerDes receiver and transmitter after SerDes is SerDes is disabled.
--- drivers/net/dsa/mv88e6xxx/serdes.c | 46 +++++++++++++++++++++++++++++++++---- drivers/net/dsa/mv88e6xxx/serdes.h | 3 ++ 2 files changed, 45 insertions(+), 4 deletions(-)
drivers/net/dsa/mv88e6xxx/serdes.c +42 -4
@@ -1271,6 +1271,28 @@ void mv88e6390_serdes_get_regs(struct mv } } +static int mv88e6393x_serdes_power_lane (struct mv88e6xxx_chip *chip,int lane, +bool on) +{ +u16 reg; +int err; + + err =mv88e6390_serdes_read (chip, lane,MDIO_MMD_PHYXS , +MV88E6393X_SERDES_CTRL1 , ®); +if (err) +return err; + +if (on) + reg &= ~(MV88E6393X_SERDES_CTRL1_TX_PDOWN | +MV88E6393X_SERDES_CTRL1_RX_PDOWN ); +else + reg |=MV88E6393X_SERDES_CTRL1_TX_PDOWN | +MV88E6393X_SERDES_CTRL1_RX_PDOWN ; + +return mv88e6390_serdes_write (chip, lane,MDIO_MMD_PHYXS , +MV88E6393X_SERDES_CTRL1 , reg); +} +static int mv88e6393x_serdes_erratum_4_6 (struct mv88e6xxx_chip *chip,int lane) {u16 reg;
@@ -1297,7 +1319,11 @@ static int mv88e6393x_serdes_erratum_4_6if (err)return err; -return mv88e6390_serdes_power_sgmii (chip, lane, false); + err =mv88e6390_serdes_power_sgmii (chip, lane, false); +if (err) +return err; + +return mv88e6393x_serdes_power_lane (chip, lane, false); }int mv88e6393x_serdes_setup_errata (struct mv88e6xxx_chip *chip)
@@ -1362,17 +1388,29 @@ int mv88e6393x_serdes_power(struct mv88e err =mv88e6393x_serdes_erratum_4_8 (chip, lane);if (err)return err; + + err =mv88e6393x_serdes_power_lane (chip, lane, true); +if (err) +return err; }switch (cmode) {case MV88E6XXX_PORT_STS_CMODE_SGMII :case MV88E6XXX_PORT_STS_CMODE_1000BASEX :case MV88E6XXX_PORT_STS_CMODE_2500BASEX : -return mv88e6390_serdes_power_sgmii (chip, lane, on); + err =mv88e6390_serdes_power_sgmii (chip, lane, on); +break ;case MV88E6393X_PORT_STS_CMODE_5GBASER :case MV88E6393X_PORT_STS_CMODE_10GBASER : -return mv88e6390_serdes_power_10g (chip, lane, on); + err =mv88e6390_serdes_power_10g (chip, lane, on); +break ; } -return 0 ; +if (err) +return err; + +if (!on) + err =mv88e6393x_serdes_power_lane (chip, lane, false); + +return err; }
drivers/net/dsa/mv88e6xxx/serdes.h +3 -0
@@ -93,6 +93,9 @@#define MV88E6393X_SERDES_POC_PCS_MASK 0x0007#define MV88E6393X_SERDES_POC_RESET BIT(15)#define MV88E6393X_SERDES_POC_PDOWN BIT(5) +#define MV88E6393X_SERDES_CTRL1 0xf003 +#define MV88E6393X_SERDES_CTRL1_TX_PDOWN BIT(9) +#define MV88E6393X_SERDES_CTRL1_RX_PDOWN BIT(8)#define MV88E6393X_ERRATA_4_8_REG 0xF074#define MV88E6393X_ERRATA_4_8_BIT BIT(14)
Greg Kroah-Hartman
maintainerPATCH 88/207 net: dsa: mv88e6xxx: Add fix for erratum 5.2 of 88E6393X family
In reply to Greg Kroah-HartmanFrom: Marek Behún <[email protected]>
commit 93fd8207bed80ce19aaf59932cbe1c03d418a37d upstream.
Add fix for erratum 5.2 of the 88E6393X (Amethyst) family: for 10gbase-r mode, some undocumented registers need to be written some special values.
--- drivers/net/dsa/mv88e6xxx/serdes.c | 48 +++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+)
drivers/net/dsa/mv88e6xxx/serdes.c +48 -0
@@ -1375,6 +1375,50 @@ static int mv88e6393x_serdes_erratum_4_8 MV88E6393X_ERRATA_4_8_REG, reg); } +static int mv88e6393x_serdes_erratum_5_2 (struct mv88e6xxx_chip *chip,int lane, +u8 cmode) +{ +static const struct { +u16 dev, reg, val, mask; + } fixes[] = { + {MDIO_MMD_VEND1 ,0x8093 ,0xcb5a ,0xffff }, + {MDIO_MMD_VEND1 ,0x8171 ,0x7088 ,0xffff }, + {MDIO_MMD_VEND1 ,0x80c9 ,0x311a ,0xffff }, + {MDIO_MMD_VEND1 ,0x80a2 ,0x8000 ,0xff7f }, + {MDIO_MMD_VEND1 ,0x80a9 ,0x0000 ,0xfff0 }, + {MDIO_MMD_VEND1 ,0x80a3 ,0x0000 ,0xf8ff }, + {MDIO_MMD_PHYXS ,MV88E6393X_SERDES_POC , +MV88E6393X_SERDES_POC_RESET ,MV88E6393X_SERDES_POC_RESET }, + }; +int err, i; +u16 reg; + +/* mv88e6393x family errata 5.2: +* For optimal signal integrity the following sequence should be applied +* to SERDES operating in 10G mode. These registers only apply to 10G +* operation and have no effect on other speeds. +*/ +if (cmode !=MV88E6393X_PORT_STS_CMODE_10GBASER ) +return 0 ; + +for (i =0 ; i <ARRAY_SIZE (fixes); ++i) { + err =mv88e6390_serdes_read (chip, lane, fixes[i].dev, + fixes[i].reg, ®); +if (err) +return err; + + reg &= ~fixes[i].mask; + reg |= fixes[i].val; + + err =mv88e6390_serdes_write (chip, lane, fixes[i].dev, + fixes[i].reg, reg); +if (err) +return err; + } + +return 0 ; +} +int mv88e6393x_serdes_power (struct mv88e6xxx_chip *chip,int port,int lane,bool on) {
@@ -1389,6 +1433,10 @@ int mv88e6393x_serdes_power(struct mv88eif (err)return err; + err =mv88e6393x_serdes_erratum_5_2 (chip, lane, cmode); +if (err) +return err; + err =mv88e6393x_serdes_power_lane (chip, lane, true);if (err)return err;
Greg Kroah-Hartman
maintainerPATCH 89/207 net: dsa: mv88e6xxx: Fix inband AN for 2500base-x on 88E6393X family
In reply to Greg Kroah-HartmanFrom: Marek Behún <[email protected]>
commit 163000dbc772c1eae9bdfe7c8fe30155db1efd74 upstream.
Inband AN is broken on Amethyst in 2500base-x mode when set by standard mechanism (via cmode).
(There probably is some weird setting done by default in the switch for
this mode that make it cycle in some state or something, because when the peer is the mvneta controller, it receives link change interrupts every ~0.3ms, but the link is always down.)
Get around this by configuring the PCS mode to 1000base-x (where inband AN works), and then changing the SerDes frequency while SerDes transmitter and receiver are disabled, before enabling SerDes PHY. After disabling SerDes PHY, change the PCS mode back to 2500base-x, to avoid confusing the device (if we leave it at 1000base-x PCS mode but with different frequency, and then change cmode to sgmii, the device won't change the frequency because it thinks it already has the correct one).
The register which changes the frequency is undocumented. I discovered it by going through all registers in the ranges 4.f000-4.f100 and 1e.8000-1e.8200 for all SerDes cmodes (sgmii, 1000base-x, 2500base-x, 5gbase-r, 10gbase-r, usxgmii) and filtering out registers that didn't make sense (the value was the same for modes which have different frequency). The result of this was:
reg sgmii 1000base-x 2500base-x 5gbase-r 10gbase-r usxgmii
04.f002 005b 0058 0059 005c 005d 005f 04.f076 3000 0000 1000 4000 5000 7000 04.f07c 0950 0950 1850 0550 0150 0150 1e.8000 0059 0059 0058 0055 0051 0051 1e.8140 0e20 0e20 0e28 0e21 0e42 0e42
Register 04.f002 is the documented Port Operational Confiuration register, it's last 3 bits select PCS type, so changing this register also changes the frequency to the appropriate value.
Registers 04.f076 and 04.f07c are not writable.
Undocumented register 1e.8000 was the one: changing bits 3:0 from 9 to 8 changed SerDes frequency to 3.125 GHz, while leaving the value of PCS mode in register 04.f002.2:0 at 1000base-x. Inband autonegotiation started working correctly.
(I didn't try anything with register 1e.8140 since 1e.8000 solved the
problem.)
Since I don't have documentation for this register 1e.8000.3:0, I am using the constants without names, but my hypothesis is that this register selects PHY frequency. If in the future I have access to an oscilloscope able to handle these frequencies, I will try to test this hypothesis.
--- drivers/net/dsa/mv88e6xxx/serdes.c | 61 ++++++++++++++++++++++++++++++++++++- drivers/net/dsa/mv88e6xxx/serdes.h | 1 2 files changed, 61 insertions(+), 1 deletion(-)
drivers/net/dsa/mv88e6xxx/serdes.c +60 -1
@@ -1419,6 +1419,54 @@ static int mv88e6393x_serdes_erratum_5_2return 0 ; } +static int mv88e6393x_serdes_fix_2500basex_an (struct mv88e6xxx_chip *chip, +int lane,u8 cmode,bool on) +{ +u16 reg; +int err; + +if (cmode !=MV88E6XXX_PORT_STS_CMODE_2500BASEX ) +return 0 ; + +/* Inband AN is broken on Amethyst in 2500base-x mode when set by +* standard mechanism (via cmode). +* We can get around this by configuring the PCS mode to 1000base-x +* and then writing value 0x58 to register 1e.8000. (This must be done +* while SerDes receiver and transmitter are disabled, which is, when +* this function is called.) +* It seem that when we do this configuration to 2500base-x mode (by +* changing PCS mode to 1000base-x and frequency to 3.125 GHz from +* 1.25 GHz) and then configure to sgmii or 1000base-x, the device +* thinks that it already has SerDes at 1.25 GHz and does not change +* the 1e.8000 register, leaving SerDes at 3.125 GHz. +* To avoid this, change PCS mode back to 2500base-x when disabling +* SerDes from 2500base-x mode. +*/ + err =mv88e6390_serdes_read (chip, lane,MDIO_MMD_PHYXS , +MV88E6393X_SERDES_POC , ®); +if (err) +return err; + + reg &= ~(MV88E6393X_SERDES_POC_PCS_MASK |MV88E6393X_SERDES_POC_AN ); +if (on) + reg |=MV88E6393X_SERDES_POC_PCS_1000BASEX | +MV88E6393X_SERDES_POC_AN ; +else + reg |=MV88E6393X_SERDES_POC_PCS_2500BASEX ; + reg |=MV88E6393X_SERDES_POC_RESET ; + + err =mv88e6390_serdes_write (chip, lane,MDIO_MMD_PHYXS , +MV88E6393X_SERDES_POC , reg); +if (err) +return err; + + err =mv88e6390_serdes_write (chip, lane,MDIO_MMD_VEND1 ,0x8000 ,0x58 ); +if (err) +return err; + +return 0 ; +} +int mv88e6393x_serdes_power (struct mv88e6xxx_chip *chip,int port,int lane,bool on) {
@@ -1437,6 +1485,11 @@ int mv88e6393x_serdes_power(struct mv88eif (err)return err; + err =mv88e6393x_serdes_fix_2500basex_an (chip, lane, cmode, + true); +if (err) +return err; + err =mv88e6393x_serdes_power_lane (chip, lane, true);if (err)return err;
@@ -1457,8 +1510,14 @@ int mv88e6393x_serdes_power(struct mv88eif (err)return err; -if (!on) +if (!on) { err =mv88e6393x_serdes_power_lane (chip, lane, false); +if (err) +return err; + + err =mv88e6393x_serdes_fix_2500basex_an (chip, lane, cmode, + false); + }return err; }
drivers/net/dsa/mv88e6xxx/serdes.h +1 -0
@@ -93,6 +93,7 @@#define MV88E6393X_SERDES_POC_PCS_MASK 0x0007#define MV88E6393X_SERDES_POC_RESET BIT(15)#define MV88E6393X_SERDES_POC_PDOWN BIT(5) +#define MV88E6393X_SERDES_POC_AN BIT(3)#define MV88E6393X_SERDES_CTRL1 0xf003#define MV88E6393X_SERDES_CTRL1_TX_PDOWN BIT(9)#define MV88E6393X_SERDES_CTRL1_RX_PDOWN BIT(8)
Greg Kroah-Hartman
maintainerPATCH 90/207 net: dsa: mv88e6xxx: Link in pcs_get_state() if AN is bypassed
In reply to Greg Kroah-HartmanFrom: Marek Behún <[email protected]>
commit ede359d8843a2779d232ed30bc36089d4b5962e4 upstream.
Function mv88e6xxx_serdes_pcs_get_state() currently does not report link up if AN is enabled, Link bit is set, but Speed and Duplex Resolved bit is not set, which testing shows is the case for when auto-negotiation was bypassed (we have AN enabled but link partner does not).
An example of such link partner is Marvell 88X3310 PHY, when put into the mode where host interface changes between 10gbase-r, 5gbase-r, 2500base-x and sgmii according to copper speed. The 88X3310 does not enable AN in 2500base-x, and so SerDes on mv88e6xxx currently does not link with it.
Fix this.
--- drivers/net/dsa/mv88e6xxx/serdes.c | 48 ++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 6 deletions(-)
drivers/net/dsa/mv88e6xxx/serdes.c +42 -6
@@ -50,11 +50,22 @@ static int mv88e6390_serdes_write(struct }static int mv88e6xxx_serdes_pcs_get_state (struct mv88e6xxx_chip *chip, -u16 status,u16 lpa, +u16 ctrl,u16 status,u16 lpa,struct phylink_link_state *state) { + state->link = !!(status &MV88E6390_SGMII_PHY_STATUS_LINK ); +if (status &MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID ) { - state->link = !!(status &MV88E6390_SGMII_PHY_STATUS_LINK ); +/* The Spped and Duplex Resolved register is 1 if AN is enabled +* and complete, or if AN is disabled. So with disabled AN we +* still get here on link up. But we want to set an_complete +* only if AN was enabled, thus we look at BMCR_ANENABLE. +* (According to 802.3-2008 section 22.2.4.2.10, we should be +* able to get this same value from BMSR_ANEGCAPABLE, but tests +* show that these Marvell PHYs don't conform to this part of +* the specificaion - BMSR_ANEGCAPABLE is simply always 1.) +*/ + state->an_complete = !!(ctrl &BMCR_ANENABLE ); state->duplex = status &MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ?DUPLEX_FULL :DUPLEX_HALF ;
@@ -81,6 +92,18 @@ static int mv88e6xxx_serdes_pcs_get_statdev_err (chip->dev,"invalid PHY speed\n" );return -EINVAL ; } + }else if (state->link && + state->interface !=PHY_INTERFACE_MODE_SGMII ) { +/* If Speed and Duplex Resolved register is 0 and link is up, it +* means that AN was enabled, but link partner had it disabled +* and the PHY invoked the Auto-Negotiation Bypass feature and +* linked anyway. +*/ + state->duplex =DUPLEX_FULL ; +if (state->interface ==PHY_INTERFACE_MODE_2500BASEX ) + state->speed =SPEED_2500 ; +else + state->speed =SPEED_1000 ; }else { state->link = false; }
@@ -168,9 +191,15 @@ int mv88e6352_serdes_pcs_config(struct mint mv88e6352_serdes_pcs_get_state (struct mv88e6xxx_chip *chip,int port,int lane,struct phylink_link_state *state) { -u16 lpa, status; +u16 lpa, status, ctrl;int err; + err =mv88e6352_serdes_read (chip,MII_BMCR , &ctrl); +if (err) { +dev_err (chip->dev,"can't read Serdes PHY control: %d\n" , err); +return err; + } + err =mv88e6352_serdes_read (chip,0x11 , &status);if (err) {dev_err (chip->dev,"can't read Serdes PHY status: %d\n" , err);
@@ -183,7 +212,7 @@ int mv88e6352_serdes_pcs_get_state(strucreturn err; } -return mv88e6xxx_serdes_pcs_get_state (chip, status, lpa, state); +return mv88e6xxx_serdes_pcs_get_state (chip, ctrl, status, lpa, state); } int mv88e6352_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
@@ -883,10 +912,17 @@ int mv88e6390_serdes_pcs_config(struct mstatic int mv88e6390_serdes_pcs_get_state_sgmii (struct mv88e6xxx_chip *chip,int port,int lane,struct phylink_link_state *state) { -u16 lpa, status; +u16 lpa, status, ctrl;int err; err =mv88e6390_serdes_read (chip, lane,MDIO_MMD_PHYXS , +MV88E6390_SGMII_BMCR , &ctrl); +if (err) { +dev_err (chip->dev,"can't read Serdes PHY control: %d\n" , err); +return err; + } + + err =mv88e6390_serdes_read (chip, lane,MDIO_MMD_PHYXS ,MV88E6390_SGMII_PHY_STATUS , &status);if (err) {dev_err (chip->dev,"can't read Serdes PHY status: %d\n" , err);
@@ -900,7 +936,7 @@ static int mv88e6390_serdes_pcs_get_statreturn err; } -return mv88e6xxx_serdes_pcs_get_state (chip, status, lpa, state); +return mv88e6xxx_serdes_pcs_get_state (chip, ctrl, status, lpa, state); } static int mv88e6390_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip,
Greg Kroah-Hartman
maintainerPATCH 91/207 wireguard: selftests: increase default dmesg log size
In reply to Greg Kroah-HartmanFrom: Jason A. Donenfeld <[email protected]>
commit 03ff1b1def73f817e196bf96ab36ac259490bd7c upstream.
The selftests currently parse the kernel log at the end to track potential memory leaks. With these tests now reading off the end of the buffer, due to recent optimizations, some creation messages were lost, making the tests think that there was a free without an alloc. Fix this by increasing the kernel log size.
--- tools/testing/selftests/wireguard/qemu/kernel.config | 1 + 1 file changed, 1 insertion(+)
tools/testing/selftests/wireguard/qemu/kernel.config +1 -0
@@ -66,6 +66,7 @@ CONFIG_PROC_SYSCTL=y CONFIG_SYSFS=y CONFIG_TMPFS=y CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 +CONFIG_LOG_BUF_SHIFT=18 CONFIG_PRINTK_TIME=y CONFIG_BLK_DEV_INITRD=y CONFIG_LEGACY_VSYSCALL_NONE=y
Signature · 1 line
2.34.1
Greg Kroah-Hartman
maintainerPATCH 92/207 wireguard: allowedips: add missing __rcu annotation to satisfy sparse
In reply to Greg Kroah-HartmanFrom: Jason A. Donenfeld <[email protected]>
commit ae9287811ba75571cd69505d50ab0e612ace8572 upstream.
A __rcu annotation got lost during refactoring, which caused sparse to become enraged.
--- drivers/net/wireguard/allowedips.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireguard/allowedips.c +1 -1
@@ -163,7 +163,7 @@ static bool node_placement(struct allowereturn exact; } -static inline void connect_node (struct allowedips_node **parent,u8 bit,struct allowedips_node *node) +static inline void connect_node (struct allowedips_node __rcu **parent,u8 bit,struct allowedips_node *node) { node->parent_bit_packed = (unsigned long )parent | bit;rcu_assign_pointer (*parent, node);
Greg Kroah-Hartman
maintainerPATCH 93/207 wireguard: selftests: actually test for routing loops
In reply to Greg Kroah-HartmanFrom: Jason A. Donenfeld <[email protected]>
commit 782c72af567fc2ef09bd7615d0307f24de72c7e0 upstream.
We previously removed the restriction on looping to self, and then added a test to make sure the kernel didn't blow up during a routing loop. The kernel didn't blow up, thankfully, but on certain architectures where skb fragmentation is easier, such as ppc64, the skbs weren't actually being discarded after a few rounds through. But the test wasn't catching this. So actually test explicitly for massive increases in tx to see if we have a routing loop. Note that the actual loop problem will need to be addressed in a different commit.
--- tools/testing/selftests/wireguard/netns.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
tools/testing/selftests/wireguard/netns.sh +5 -1
@@ -276,7 +276,11 @@ n0 ping -W 1 -c 1 192.168.241.2 n1 wg set wg0 peer "$pub2" endpoint 192.168.241.2:7 ip2 link del wg0 ip2 link del wg1 -! n0 ping -W 1 -c 10 -f 192.168.241.2 || false # Should not crash kernel +read _ _ tx_bytes_before < <(n0 wg show wg1 transfer) +! n0 ping -W 1 -c 10 -f 192.168.241.2 || false +sleep 1 +read _ _ tx_bytes_after < <(n0 wg show wg1 transfer) +(( tx_bytes_after - tx_bytes_before < 70000 )) ip0 link del wg1 ip1 link del wg0
Greg Kroah-Hartman
maintainerPATCH 94/207 wireguard: selftests: rename DEBUG_PI_LIST to DEBUG_PLIST
In reply to Greg Kroah-HartmanFrom: Li Zhijian <[email protected]>
commit 7e938beb8321d34f040557b8915b228af125f73c upstream.
DEBUG_PI_LIST was renamed to DEBUG_PLIST since 8e18faeac3 ("lib/plist:
rename DEBUG_PI_LIST to DEBUG_PLIST").
--- tools/testing/selftests/wireguard/qemu/debug.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/wireguard/qemu/debug.config +1 -1
@@ -47,7 +47,7 @@ CONFIG_DEBUG_ATOMIC_SLEEP=y CONFIG_TRACE_IRQFLAGS=y CONFIG_DEBUG_BUGVERBOSE=y CONFIG_DEBUG_LIST=y -CONFIG_DEBUG_PI_LIST=y +CONFIG_DEBUG_PLIST=y CONFIG_PROVE_RCU=y CONFIG_SPARSE_RCU_POINTER=y CONFIG_RCU_CPU_STALL_TIMEOUT=21
Greg Kroah-Hartman
maintainerPATCH 95/207 wireguard: device: reset peer src endpoint when netns exits
In reply to Greg Kroah-HartmanFrom: Jason A. Donenfeld <[email protected]>
commit 20ae1d6aa159eb91a9bf09ff92ccaa94dbea92c2 upstream.
Each peer's endpoint contains a dst_cache entry that takes a reference to another netdev. When the containing namespace exits, we take down the socket and prevent future sockets from being created (by setting creating_net to NULL), which removes that potential reference on the netns. However, it doesn't release references to the netns that a netdev cached in dst_cache might be taking, so the netns still might fail to exit. Since the socket is gimped anyway, we can simply clear all the dst_caches (by way of clearing the endpoint src), which will release all references.
However, the current dst_cache_reset function only releases those references lazily. But it turns out that all of our usages of wg_socket_clear_peer_endpoint_src are called from contexts that are not exactly high-speed or bottle-necked. For example, when there's connection difficulty, or when userspace is reconfiguring the interface. And in particular for this patch, when the netns is exiting. So for those cases, it makes more sense to call dst_release immediately. For that, we add a small helper function to dst_cache.
This patch also adds a test to netns.sh from Hangbin Liu to ensure this doesn't regress.
--- drivers/net/wireguard/device.c | 3 +++ drivers/net/wireguard/socket.c | 2 +- include/net/dst_cache.h | 11 +++++++++++ net/core/dst_cache.c | 19 +++++++++++++++++++ tools/testing/selftests/wireguard/netns.sh | 24 +++++++++++++++++++++++- 5 files changed, 57 insertions(+), 2 deletions(-)
drivers/net/wireguard/device.c +3 -0
@@ -398,6 +398,7 @@ static struct rtnl_link_ops link_ops __rstatic void wg_netns_pre_exit (struct net *net) {struct wg_device *wg; +struct wg_peer *peer;rtnl_lock ();list_for_each_entry (wg, &device_list, device_list) {
@@ -407,6 +408,8 @@ static void wg_netns_pre_exit(struct netmutex_lock (&wg->device_update_lock);rcu_assign_pointer (wg->creating_net,NULL );wg_socket_reinit (wg,NULL ,NULL ); +list_for_each_entry (peer, &wg->peer_list, peer_list) +wg_socket_clear_peer_endpoint_src (peer);mutex_unlock (&wg->device_update_lock); } }
drivers/net/wireguard/socket.c +1 -1
@@ -308,7 +308,7 @@ void wg_socket_clear_peer_endpoint_src(s {write_lock_bh (&peer->endpoint_lock);memset (&peer->endpoint.src6,0 ,sizeof (peer->endpoint.src6)); -dst_cache_reset (&peer->endpoint_cache); +dst_cache_reset_now (&peer->endpoint_cache);write_unlock_bh (&peer->endpoint_lock); }
include/net/dst_cache.h +11 -0
@@ -80,6 +80,17 @@ static inline void dst_cache_reset(struc }/** +* dst_cache_reset_now - invalidate the cache contents immediately +* @dst_cache: the cache +* +* The caller must be sure there are no concurrent users, as this frees +* all dst_cache users immediately, rather than waiting for the next +* per-cpu usage like dst_cache_reset does. Most callers should use the +* higher speed lazily-freed dst_cache_reset function instead. +*/ +void dst_cache_reset_now (struct dst_cache *dst_cache); + +/** * dst_cache_init - initialize the cache, allocating the required storage * @dst_cache: the cache * @gfp: allocation flags
net/core/dst_cache.c +19 -0
@@ -162,3 +162,22 @@ void dst_cache_destroy(struct dst_cachefree_percpu (dst_cache->cache); }EXPORT_SYMBOL_GPL (dst_cache_destroy); + +void dst_cache_reset_now (struct dst_cache *dst_cache) +{ +int i; + +if (!dst_cache->cache) +return ; + + dst_cache->reset_ts = jiffies; +for_each_possible_cpu (i) { +struct dst_cache_pcpu *idst =per_cpu_ptr (dst_cache->cache, i); +struct dst_entry *dst = idst->dst; + + idst->cookie =0 ; + idst->dst =NULL ; +dst_release (dst); + } +} +EXPORT_SYMBOL_GPL (dst_cache_reset_now);
tools/testing/selftests/wireguard/netns.sh +23 -1
@@ -613,6 +613,28 @@ ip0 link set wg0 up kill $ncat_pid ip0 link del wg0 +# Ensure that dst_cache references don't outlive netns lifetime +ip1 link add dev wg0 type wireguard +ip2 link add dev wg0 type wireguard +configure_peers +ip1 link add veth1 type veth peer name veth2 +ip1 link set veth2 netns $netns2 +ip1 addr add fd00:aa::1/64 dev veth1 +ip2 addr add fd00:aa::2/64 dev veth2 +ip1 link set veth1 up +ip2 link set veth2 up +waitiface $netns1 veth1 +waitiface $netns2 veth2 +ip1 -6 route add default dev veth1 via fd00:aa::2 +ip2 -6 route add default dev veth2 via fd00:aa::1 +n1 wg set wg0 peer "$pub2" endpoint [fd00:aa::2]:2 +n2 wg set wg0 peer "$pub1" endpoint [fd00:aa::1]:1 +n1 ping6 -c 1 fd00::2 +pp ip netns delete $netns1 +pp ip netns delete $netns2 +pp ip netns add $netns1 +pp ip netns add $netns2 + # Ensure there aren't circular reference loops ip1 link add wg1 type wireguard ip2 link add wg2 type wireguard
@@ -631,7 +653,7 @@ while read -t 0.1 -r line 2>/dev/null || done < /dev/kmsg alldeleted=1 for object in "${!objects[@]}"; do - if [[ ${objects["$object"]} != *createddestroyed ]]; then + if [[ ${objects["$object"]} != *createddestroyed && ${objects["$object"]} != *createdcreateddestroyeddestroyed ]]; then echo "Error: $object: merely ${objects["$object"]}" >&3 alldeleted=0 fi
Greg Kroah-Hartman
maintainerPATCH 96/207 wireguard: receive: use ring buffer for incoming handshakes
In reply to Greg Kroah-HartmanFrom: Jason A. Donenfeld <[email protected]>
commit 886fcee939adb5e2af92741b90643a59f2b54f97 upstream.
Apparently the spinlock on incoming_handshake's skb_queue is highly contended, and a torrent of handshake or cookie packets can bring the data plane to its knees, simply by virtue of enqueueing the handshake packets to be processed asynchronously. So, we try switching this to a ring buffer to hopefully have less lock contention. This alleviates the problem somewhat, though it still isn't perfect, so future patches will have to improve this further. However, it at least doesn't completely diminish the data plane.
--- drivers/net/wireguard/device.c | 36 ++++++++++++++++++------------------ drivers/net/wireguard/device.h | 9 +++------ drivers/net/wireguard/queueing.c | 6 +++--- drivers/net/wireguard/queueing.h | 2 +- drivers/net/wireguard/receive.c | 27 ++++++++++++--------------- 5 files changed, 37 insertions(+), 43 deletions(-)
drivers/net/wireguard/device.c +18 -18
@@ -98,6 +98,7 @@ static int wg_stop(struct net_device *de {struct wg_device *wg =netdev_priv (dev);struct wg_peer *peer; +struct sk_buff *skb;mutex_lock (&wg->device_update_lock);list_for_each_entry (peer, &wg->peer_list, peer_list) {
@@ -108,7 +109,9 @@ static int wg_stop(struct net_device *dewg_noise_reset_last_sent_handshake (&peer->last_sent_handshake); }mutex_unlock (&wg->device_update_lock); -skb_queue_purge (&wg->incoming_handshakes); +while ((skb =ptr_ring_consume (&wg->handshake_queue.ring)) !=NULL ) +kfree_skb (skb); +atomic_set (&wg->handshake_queue_len,0 );wg_socket_reinit (wg,NULL ,NULL );return 0 ; }
@@ -235,14 +238,13 @@ static void wg_destruct(struct net_devicdestroy_workqueue (wg->handshake_receive_wq);destroy_workqueue (wg->handshake_send_wq);destroy_workqueue (wg->packet_crypt_wq); -wg_packet_queue_free (&wg->decrypt_queue); -wg_packet_queue_free (&wg->encrypt_queue); +wg_packet_queue_free (&wg->handshake_queue, true); +wg_packet_queue_free (&wg->decrypt_queue, false); +wg_packet_queue_free (&wg->encrypt_queue, false);rcu_barrier ();/* Wait for all the peers to be actually freed. */ wg_ratelimiter_uninit ();memzero_explicit (&wg->static_identity,sizeof (wg->static_identity)); -skb_queue_purge (&wg->incoming_handshakes);free_percpu (dev->tstats); -free_percpu (wg->incoming_handshakes_worker);kvfree (wg->index_hashtable);kvfree (wg->peer_hashtable);mutex_unlock (&wg->device_update_lock);
@@ -298,7 +300,6 @@ static int wg_newlink(struct net *src_neinit_rwsem (&wg->static_identity.lock);mutex_init (&wg->socket_update_lock);mutex_init (&wg->device_update_lock); -skb_queue_head_init (&wg->incoming_handshakes);wg_allowedips_init (&wg->peer_allowedips);wg_cookie_checker_init (&wg->cookie_checker, wg);INIT_LIST_HEAD (&wg->peer_list);
@@ -316,16 +317,10 @@ static int wg_newlink(struct net *src_neif (!dev->tstats) goto err_free_index_hashtable; - wg->incoming_handshakes_worker = -wg_packet_percpu_multicore_worker_alloc ( - wg_packet_handshake_receive_worker, wg); -if (!wg->incoming_handshakes_worker) - goto err_free_tstats; - wg->handshake_receive_wq =alloc_workqueue ("wg-kex-%s" ,WQ_CPU_INTENSIVE |WQ_FREEZABLE ,0 , dev->name);if (!wg->handshake_receive_wq) - goto err_free_incoming_handshakes; + goto err_free_tstats; wg->handshake_send_wq =alloc_workqueue ("wg-kex-%s" ,WQ_UNBOUND |WQ_FREEZABLE ,0 , dev->name);
@@ -347,10 +342,15 @@ static int wg_newlink(struct net *src_neif (ret <0 ) goto err_free_encrypt_queue; - ret =wg_ratelimiter_init (); + ret =wg_packet_queue_init (&wg->handshake_queue, wg_packet_handshake_receive_worker, +MAX_QUEUED_INCOMING_HANDSHAKES );if (ret <0 ) goto err_free_decrypt_queue; + ret =wg_ratelimiter_init (); +if (ret <0 ) + goto err_free_handshake_queue; + ret =register_netdevice (dev);if (ret <0 ) goto err_uninit_ratelimiter;
@@ -367,18 +367,18 @@ static int wg_newlink(struct net *src_ne err_uninit_ratelimiter:wg_ratelimiter_uninit (); +err_free_handshake_queue: +wg_packet_queue_free (&wg->handshake_queue, false); err_free_decrypt_queue: -wg_packet_queue_free (&wg->decrypt_queue); +wg_packet_queue_free (&wg->decrypt_queue, false); err_free_encrypt_queue: -wg_packet_queue_free (&wg->encrypt_queue); +wg_packet_queue_free (&wg->encrypt_queue, false); err_destroy_packet_crypt:destroy_workqueue (wg->packet_crypt_wq); err_destroy_handshake_send:destroy_workqueue (wg->handshake_send_wq); err_destroy_handshake_receive:destroy_workqueue (wg->handshake_receive_wq); -err_free_incoming_handshakes: -free_percpu (wg->incoming_handshakes_worker); err_free_tstats:free_percpu (dev->tstats); err_free_index_hashtable:
drivers/net/wireguard/device.h +3 -6
@@ -39,21 +39,18 @@ struct prev_queue {struct wg_device {struct net_device *dev; -struct crypt_queue encrypt_queue, decrypt_queue; +struct crypt_queue encrypt_queue, decrypt_queue, handshake_queue;struct sock __rcu *sock4, *sock6;struct net __rcu *creating_net;struct noise_static_identity static_identity; -struct workqueue_struct *handshake_receive_wq, *handshake_send_wq; -struct workqueue_struct *packet_crypt_wq; -struct sk_buff_head incoming_handshakes; -int incoming_handshake_cpu; -struct multicore_worker __percpu *incoming_handshakes_worker; +struct workqueue_struct *packet_crypt_wq,*handshake_receive_wq, *handshake_send_wq;struct cookie_checker cookie_checker;struct pubkey_hashtable *peer_hashtable;struct index_hashtable *index_hashtable;struct allowedips peer_allowedips;struct mutex device_update_lock, socket_update_lock;struct list_head device_list, peer_list; +atomic_t handshake_queue_len;unsigned int num_peers, device_update_gen;u32 fwmark;u16 incoming_port;
drivers/net/wireguard/queueing.c +3 -3
@@ -38,11 +38,11 @@ int wg_packet_queue_init(struct crypt_qureturn 0 ; } -void wg_packet_queue_free (struct crypt_queue *queue) +void wg_packet_queue_free (struct crypt_queue *queue,bool purge) {free_percpu (queue->worker); -WARN_ON (!__ptr_ring_empty (&queue->ring)); -ptr_ring_cleanup (&queue->ring,NULL ); +WARN_ON (!purge && !__ptr_ring_empty (&queue->ring)); +ptr_ring_cleanup (&queue->ring, purge ? (void (*)(void *))kfree_skb :NULL ); }#define NEXT (skb) ((skb)->prev)
drivers/net/wireguard/queueing.h +1 -1
@@ -23,7 +23,7 @@ struct sk_buff;/* queueing.c APIs: */ int wg_packet_queue_init (struct crypt_queue *queue,work_func_t function,unsigned int len); -void wg_packet_queue_free (struct crypt_queue *queue); +void wg_packet_queue_free (struct crypt_queue *queue,bool purge);struct multicore_worker __percpu *wg_packet_percpu_multicore_worker_alloc (work_func_t function,void *ptr);
drivers/net/wireguard/receive.c +12 -15
@@ -116,8 +116,8 @@ static void wg_receive_handshake_packet(return ; } - under_load =skb_queue_len (&wg->incoming_handshakes) >= -MAX_QUEUED_INCOMING_HANDSHAKES /8 ; + under_load =atomic_read (&wg->handshake_queue_len) >= +MAX_QUEUED_INCOMING_HANDSHAKES /8 ;if (under_load) { last_under_load =ktime_get_coarse_boottime_ns (); }else if (last_under_load) {
@@ -212,13 +212,14 @@ static void wg_receive_handshake_packet(void wg_packet_handshake_receive_worker (struct work_struct *work) { - struct wg_device *wg = container_of(work, struct multicore_worker, - work)->ptr; + struct crypt_queue *queue = container_of(work, struct multicore_worker, work)->ptr; + struct wg_device *wg = container_of(queue, struct wg_device, handshake_queue);struct sk_buff *skb; -while ((skb =skb_dequeue (&wg->incoming_handshakes)) !=NULL ) { +while ((skb =ptr_ring_consume_bh (&queue->ring)) !=NULL ) {wg_receive_handshake_packet (wg, skb);dev_kfree_skb (skb); +atomic_dec (&wg->handshake_queue_len);cond_resched (); } }
@@ -554,21 +555,17 @@ void wg_packet_receive(struct wg_devicecase cpu_to_le32 (MESSAGE_HANDSHAKE_RESPONSE ):case cpu_to_le32 (MESSAGE_HANDSHAKE_COOKIE ): {int cpu; - -if (skb_queue_len (&wg->incoming_handshakes) > -MAX_QUEUED_INCOMING_HANDSHAKES || -unlikely (!rng_is_initialized ())) { +if (unlikely (!rng_is_initialized () || +ptr_ring_produce_bh (&wg->handshake_queue.ring, skb))) {net_dbg_skb_ratelimited ("%s: Dropping handshake packet from %pISpfsc\n" , wg->dev->name, skb); goto err; } -skb_queue_tail (&wg->incoming_handshakes, skb); -/* Queues up a call to packet_process_queued_handshake_ -* packets(skb): -*/ - cpu =wg_cpumask_next_online (&wg->incoming_handshake_cpu); +atomic_inc (&wg->handshake_queue_len); + cpu =wg_cpumask_next_online (&wg->handshake_queue.last_cpu); +/* Queues up a call to packet_process_queued_handshake_packets(skb): */ queue_work_on (cpu, wg->handshake_receive_wq, - &per_cpu_ptr (wg->incoming_handshakes_worker, cpu)->work); + &per_cpu_ptr (wg->handshake_queue.worker, cpu)->work);break ; }case cpu_to_le32 (MESSAGE_DATA ):
Greg Kroah-Hartman
maintainerPATCH 97/207 wireguard: receive: drop handshakes if queue lock is contended
In reply to Greg Kroah-HartmanFrom: Jason A. Donenfeld <[email protected]>
commit fb32f4f606c17b869805d7cede8b03d78339b50a upstream.
If we're being delivered packets from multiple CPUs so quickly that the ring lock is contended for CPU tries, then it's safe to assume that the queue is near capacity anyway, so just drop the packet rather than spinning. This helps deal with multicore DoS that can interfere with data path performance. It _still_ does not completely fix the issue, but it again chips away at it.
--- drivers/net/wireguard/receive.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-)
drivers/net/wireguard/receive.c +13 -3
@@ -554,9 +554,19 @@ void wg_packet_receive(struct wg_devicecase cpu_to_le32 (MESSAGE_HANDSHAKE_INITIATION ):case cpu_to_le32 (MESSAGE_HANDSHAKE_RESPONSE ):case cpu_to_le32 (MESSAGE_HANDSHAKE_COOKIE ): { -int cpu; -if (unlikely (!rng_is_initialized () || -ptr_ring_produce_bh (&wg->handshake_queue.ring, skb))) { +int cpu, ret = -EBUSY ; + +if (unlikely (!rng_is_initialized ())) + goto drop; +if (atomic_read (&wg->handshake_queue_len) >MAX_QUEUED_INCOMING_HANDSHAKES /2 ) { +if (spin_trylock_bh (&wg->handshake_queue.ring.producer_lock)) { + ret =__ptr_ring_produce (&wg->handshake_queue.ring, skb); +spin_unlock_bh (&wg->handshake_queue.ring.producer_lock); + } + }else + ret =ptr_ring_produce_bh (&wg->handshake_queue.ring, skb); +if (ret) { + drop:net_dbg_skb_ratelimited ("%s: Dropping handshake packet from %pISpfsc\n" , wg->dev->name, skb); goto err;
Greg Kroah-Hartman
maintainerPATCH 98/207 wireguard: ratelimiter: use kvcalloc() instead of kvzalloc()
In reply to Greg Kroah-HartmanFrom: Gustavo A. R. Silva <[email protected]>
commit 4e3fd721710553832460c179c2ee5ce67ef7f1e0 upstream.
Use 2-factor argument form kvcalloc() instead of kvzalloc().
[Jason: Gustavo's link above is for KSPP, but this isn't actually a
security fix, as table_size is bounded to 8192 anyway, and gcc realizes this, so the codegen comes out to be about the same.]
--- drivers/net/wireguard/ratelimiter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireguard/ratelimiter.c +2 -2
@@ -176,12 +176,12 @@ int wg_ratelimiter_init(void) (1U << 14) / sizeof(struct hlist_head))); max_entries = table_size *8 ; - table_v4 =kvzalloc (table_size *sizeof (*table_v4),GFP_KERNEL ); + table_v4 =kvcalloc (table_size,sizeof (*table_v4),GFP_KERNEL );if (unlikely (!table_v4)) goto err_kmemcache;#if IS_ENABLED (CONFIG_IPV6 ) - table_v6 =kvzalloc (table_size *sizeof (*table_v6),GFP_KERNEL ); + table_v6 =kvcalloc (table_size,sizeof (*table_v6),GFP_KERNEL );if (unlikely (!table_v6)) {kvfree (table_v4); goto err_kmemcache;
Greg Kroah-Hartman
maintainerPATCH 99/207 i2c: stm32f7: flush TX FIFO upon transfer errors
In reply to Greg Kroah-HartmanFrom: Alain Volmat <[email protected]>
commit 0c21d02ca469574d2082379db52d1a27b99eed0c upstream.
While handling an error during transfer (ex: NACK), it could happen that the driver has already written data into TXDR before the transfer get stopped.
This commit add TXDR Flush after end of transfer in case of error to avoid sending a wrong data on any other slave upon next transfer.
--- drivers/i2c/busses/i2c-stm32f7.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
drivers/i2c/busses/i2c-stm32f7.c +19 -1
@@ -1696,6 +1696,16 @@ static int stm32f7_i2c_xfer(struct i2c_a time_left =wait_for_completion_timeout (&i2c_dev->complete, i2c_dev->adap.timeout); ret = f7_msg->result; +if (ret) { +/* +* It is possible that some unsent data have already been +* written into TXDR. To avoid sending old data in a +* further transfer, flush TXDR in case of any error +*/ +writel_relaxed (STM32F7_I2C_ISR_TXE , + i2c_dev->base +STM32F7_I2C_ISR ); + goto pm_free; + }if (!time_left) { dev_dbg(i2c_dev->dev, "Access to slave 0x%x timed out\n",
@@ -1744,8 +1754,16 @@ static int stm32f7_i2c_smbus_xfer(struct timeout =wait_for_completion_timeout (&i2c_dev->complete, i2c_dev->adap.timeout); ret = f7_msg->result; -if (ret) +if (ret) { +/* +* It is possible that some unsent data have already been +* written into TXDR. To avoid sending old data in a +* further transfer, flush TXDR in case of any error +*/ +writel_relaxed (STM32F7_I2C_ISR_TXE , + i2c_dev->base +STM32F7_I2C_ISR ); goto pm_free; + }if (!timeout) {dev_dbg (dev,"Access to slave 0x%x timed out\n" , f7_msg->addr);
Greg Kroah-Hartman
maintainerPATCH 100/207 i2c: stm32f7: recover the bus on access timeout
In reply to Greg Kroah-HartmanFrom: Alain Volmat <[email protected]>
commit b933d1faf8fa30d16171bcff404e39c41b2a7c84 upstream.
When getting an access timeout, ensure that the bus is in a proper state prior to returning the error.
--- drivers/i2c/busses/i2c-stm32f7.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/i2c/busses/i2c-stm32f7.c +2 -0
@@ -1712,6 +1712,7 @@ static int stm32f7_i2c_xfer(struct i2c_a i2c_dev->msg->addr);if (i2c_dev->use_dma)dmaengine_terminate_all (dma->chan_using); +stm32f7_i2c_wait_free_bus (i2c_dev); ret = -ETIMEDOUT ; }
@@ -1769,6 +1770,7 @@ static int stm32f7_i2c_smbus_xfer(structdev_dbg (dev,"Access to slave 0x%x timed out\n" , f7_msg->addr);if (i2c_dev->use_dma)dmaengine_terminate_all (dma->chan_using); +stm32f7_i2c_wait_free_bus (i2c_dev); ret = -ETIMEDOUT ; goto pm_free; }
Greg Kroah-Hartman
maintainerPATCH 101/207 i2c: stm32f7: stop dma transfer in case of NACK
In reply to Greg Kroah-HartmanFrom: Alain Volmat <[email protected]>
commit 31b90a95ccbbb4b628578ac17e3b3cc8eeacfe31 upstream.
In case of receiving a NACK, the dma transfer should be stopped to avoid feeding data into the FIFO.
Also ensure to properly return the proper error code and avoid waiting for the end of the dma completion in case of error happening during the transmission.
--- drivers/i2c/busses/i2c-stm32f7.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/i2c/busses/i2c-stm32f7.c +7 -2
@@ -1493,6 +1493,7 @@ static irqreturn_t stm32f7_i2c_isr_event {struct stm32f7_i2c_dev *i2c_dev = data;struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg; +struct stm32_i2c_dma *dma = i2c_dev->dma;void __iomem *base = i2c_dev->base;u32 status, mask;int ret =IRQ_HANDLED ;
@@ -1518,6 +1519,10 @@ static irqreturn_t stm32f7_i2c_isr_eventdev_dbg (i2c_dev->dev,"<%s>: Receive NACK (addr %x)\n" , __func__, f7_msg->addr);writel_relaxed (STM32F7_I2C_ICR_NACKCF , base +STM32F7_I2C_ICR ); +if (i2c_dev->use_dma) { +stm32f7_i2c_disable_dma_req (i2c_dev); +dmaengine_terminate_all (dma->chan_using); + } f7_msg->result = -ENXIO ; }
@@ -1533,7 +1538,7 @@ static irqreturn_t stm32f7_i2c_isr_event/* Clear STOP flag */ writel_relaxed (STM32F7_I2C_ICR_STOPCF , base +STM32F7_I2C_ICR ); -if (i2c_dev->use_dma) { +if (i2c_dev->use_dma && !f7_msg->result) { ret =IRQ_WAKE_THREAD ; }else { i2c_dev->master_mode = false;
@@ -1546,7 +1551,7 @@ static irqreturn_t stm32f7_i2c_isr_eventif (f7_msg->stop) { mask =STM32F7_I2C_CR2_STOP ;stm32f7_i2c_set_bits (base +STM32F7_I2C_CR2 , mask); - }else if (i2c_dev->use_dma) { + }else if (i2c_dev->use_dma && !f7_msg->result) { ret =IRQ_WAKE_THREAD ; }else if (f7_msg->smbus) {stm32f7_i2c_smbus_rep_start (i2c_dev);
Greg Kroah-Hartman
maintainerPATCH 102/207 i2c: cbus-gpio: set atomic transfer callback
In reply to Greg Kroah-HartmanFrom: Aaro Koskinen <[email protected]>
commit b12764695c3fcade145890b67f82f8b139174cc7 upstream.
CBUS transfers have always been atomic, but after commit 63b96983a5dd ("i2c: core: introduce callbacks for atomic transfers") we started to see warnings during e.g. poweroff as the atomic callback is not explicitly set. Fix that.
Fixes the following WARNING seen during Nokia N810 power down:
[ 786.570617] reboot: Power down [ 786.573913] ------------[ cut here ]------------ [ 786.578826] WARNING: CPU: 0 PID: 672 at drivers/i2c/i2c-core.h:40 i2c_smbus_xfer+0x100/0x110 [ 786.587799] No atomic I2C transfer handler for 'i2c-2'
--- drivers/i2c/busses/i2c-cbus-gpio.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/i2c/busses/i2c-cbus-gpio.c +3 -2
@@ -195,8 +195,9 @@ static u32 cbus_i2c_func(struct i2c_adap }static const struct i2c_algorithm cbus_i2c_algo = { - .smbus_xfer = cbus_i2c_smbus_xfer, - .functionality = cbus_i2c_func, + .smbus_xfer = cbus_i2c_smbus_xfer, + .smbus_xfer_atomic = cbus_i2c_smbus_xfer, + .functionality = cbus_i2c_func, };static int cbus_i2c_remove (struct platform_device *pdev)
Greg Kroah-Hartman
maintainerPATCH 103/207 natsemi: xtensa: fix section mismatch warnings
In reply to Greg Kroah-HartmanFrom: Randy Dunlap <[email protected]>
commit b0f38e15979fa8851e88e8aa371367f264e7b6e9 upstream.
Fix section mismatch warnings in xtsonic. The first one appears to be bogus and after fixing the second one, the first one is gone.
WARNING: modpost: vmlinux.o(.text+0x529adc): Section mismatch in reference from the function sonic_get_stats() to the function .init.text:set_reset_devices() The function sonic_get_stats() references
the function __init set_reset_devices().
This is often because sonic_get_stats lacks a __init
annotation or the annotation of set_reset_devices is wrong.
WARNING: modpost: vmlinux.o(.text+0x529b3b): Section mismatch in reference from the function xtsonic_probe() to the function .init.text:sonic_probe1() The function xtsonic_probe() references
the function __init sonic_probe1().
This is often because xtsonic_probe lacks a __init
annotation or the annotation of sonic_probe1 is wrong.
--- drivers/net/ethernet/natsemi/xtsonic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/natsemi/xtsonic.c +1 -1
@@ -120,7 +120,7 @@ static const struct net_device_ops xtson .ndo_set_mac_address = eth_mac_addr, }; -static int __init sonic_probe1 (struct net_device *dev) +static int sonic_probe1 (struct net_device *dev) {unsigned int silicon_revision;struct sonic_local *lp =netdev_priv (dev);
Greg Kroah-Hartman
maintainerPATCH 104/207 tcp: fix page frag corruption on page fault
In reply to Greg Kroah-HartmanFrom: Paolo Abeni <[email protected]>
commit dacb5d8875cc6cd3a553363b4d6f06760fcbe70c upstream.
Steffen reported a TCP stream corruption for HTTP requests served by the apache web-server using a cifs mount-point and memory mapping the relevant file.
The root cause is quite similar to the one addressed by commit 20eb4f29b602 ("net: fix sk_page_frag() recursion from memory reclaim"). Here the nested access to the task page frag is caused by a page fault on the (mmapped) user-space memory buffer coming from the cifs file.
The page fault handler performs an smb transaction on a different socket, inside the same process context. Since sk->sk_allaction for such socket does not prevent the usage for the task_frag, the nested allocation modify "under the hood" the page frag in use by the outer sendmsg call, corrupting the stream.
The overall relevant stack trace looks like the following:
httpd 78268 [001] 3461630.850950: probe:tcp_sendmsg_locked:
ffffffff91461d91 tcp_sendmsg_locked+0x1
ffffffff91462b57 tcp_sendmsg+0x27
ffffffff9139814e sock_sendmsg+0x3e
ffffffffc06dfe1d smb_send_kvec+0x28
[...]
ffffffffc06cfaf8 cifs_readpages+0x213
ffffffff90e83c4b read_pages+0x6b
ffffffff90e83f31 __do_page_cache_readahead+0x1c1
ffffffff90e79e98 filemap_fault+0x788
ffffffff90eb0458 __do_fault+0x38
ffffffff90eb5280 do_fault+0x1a0
ffffffff90eb7c84 __handle_mm_fault+0x4d4
ffffffff90eb8093 handle_mm_fault+0xc3
ffffffff90c74f6d __do_page_fault+0x1ed
ffffffff90c75277 do_page_fault+0x37
ffffffff9160111e page_fault+0x1e
ffffffff9109e7b5 copyin+0x25
ffffffff9109eb40 _copy_from_iter_full+0xe0
ffffffff91462370 tcp_sendmsg_locked+0x5e0
ffffffff91462370 tcp_sendmsg_locked+0x5e0
ffffffff91462b57 tcp_sendmsg+0x27
ffffffff9139815c sock_sendmsg+0x4c
ffffffff913981f7 sock_write_iter+0x97
ffffffff90f2cc56 do_iter_readv_writev+0x156
ffffffff90f2dff0 do_iter_write+0x80
ffffffff90f2e1c3 vfs_writev+0xa3
ffffffff90f2e27c do_writev+0x5c
ffffffff90c042bb do_syscall_64+0x5b
ffffffff916000ad entry_SYSCALL_64_after_hwframe+0x65The cifs filesystem rightfully sets sk_allocations to GFP_NOFS, we can avoid the nesting using the sk page frag for allocation lacking the __GFP_FS flag. Do not define an additional mm-helper for that, as this is strictly tied to the sk page frag usage.
v1 -> v2:
- use a stricted sk_page_frag() check instead of reordering the code (Eric)
--- include/net/sock.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
include/net/sock.h +8 -5
@@ -2400,19 +2400,22 @@ struct sk_buff *sk_stream_alloc_skb(stru* @sk: socket * * Use the per task page_frag instead of the per socket one for -* optimization when we know that we're in the normal context and owns +* optimization when we know that we're in process context and own * everything that's associated with %current. * -* gfpflags_allow_blocking() isn't enough here as direct reclaim may nest -* inside other socket operations and end up recursing into sk_page_frag() -* while it's already in use. +* Both direct reclaim and page faults can nest inside other +* socket operations and end up recursing into sk_page_frag() +* while it's already in use: explicitly avoid task page_frag +* usage if the caller is potentially doing any of them. +* This assumes that page fault handlers use the GFP_NOFS flags. * * Return: a per task page_frag if context allows that, * otherwise a per socket one. */ static inline struct page_frag *sk_page_frag (struct sock *sk) { -if (gfpflags_normal_context (sk->sk_allocation)) +if ((sk->sk_allocation & (__GFP_DIRECT_RECLAIM | __GFP_MEMALLOC | __GFP_FS)) == + (__GFP_DIRECT_RECLAIM | __GFP_FS))return ¤t->task_frag;return &sk->sk_frag;
Greg Kroah-Hartman
maintainerPATCH 105/207 net: qlogic: qlcnic: Fix a NULL pointer dereference in qlcnic_83xx_add_rings()
In reply to Greg Kroah-HartmanFrom: Zhou Qingyang <[email protected]>
commit e2dabc4f7e7b60299c20a36d6a7b24ed9bf8e572 upstream.
In qlcnic_83xx_add_rings(), the indirect function of ahw->hw_ops->alloc_mbx_args will be called to allocate memory for cmd.req.arg, and there is a dereference of it in qlcnic_83xx_add_rings(), which could lead to a NULL pointer dereference on failure of the indirect function like qlcnic_83xx_alloc_mbx_args().
Fix this bug by adding a check of alloc_mbx_args(), this patch imitates the logic of mbx_cmd()'s failure handling.
This bug was found by a static analyzer. The analysis employs differential checking to identify inconsistent security operations (e.g., checks or kfrees) between two code paths and confirms that the inconsistent operations are not recovered in the current function or the callers, so they constitute bugs.
Note that, as a bug found by static analysis, it can be a false positive or hard to trigger. Multiple researchers have cross-reviewed the bug.
Builds with CONFIG_QLCNIC=m show no new warnings, and our static analyzer no longer warns about this code.
--- drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +8 -2
@@ -1077,8 +1077,14 @@ static int qlcnic_83xx_add_rings(struct sds_mbx_size =sizeof (struct qlcnic_sds_mbx ); context_id = recv_ctx->context_id; num_sds = adapter->drv_sds_rings -QLCNIC_MAX_SDS_RINGS ; - ahw->hw_ops->alloc_mbx_args (&cmd, adapter, -QLCNIC_CMD_ADD_RCV_RINGS ); + err = ahw->hw_ops->alloc_mbx_args (&cmd, adapter, +QLCNIC_CMD_ADD_RCV_RINGS ); +if (err) { +dev_err (&adapter->pdev->dev, +"Failed to alloc mbx args %d\n" , err); +return err; + } + cmd.req.arg[1 ] =0 | (num_sds <<8 ) | (context_id <<16 );/* set up status rings, mbx 2-81 */
Greg Kroah-Hartman
maintainerPATCH 106/207 net: mpls: Fix notifications when deleting a device
In reply to Greg Kroah-HartmanFrom: Benjamin Poirier <[email protected]>
commit 7d4741eacdefa5f0475431645b56baf00784df1f upstream.
There are various problems related to netlink notifications for mpls route changes in response to interfaces being deleted:
* delete interface of only nexthop
DELROUTE notification is missing RTA_OIF attribute
* delete interface of non-last nexthop
NEWROUTE notification is missing entirely
* delete interface of last nexthop
DELROUTE notification is missing nexthop
All of these problems stem from the fact that existing routes are modified in-place before sending a notification. Restructure mpls_ifdown() to avoid changing the route in the DELROUTE cases and to create a copy in the NEWROUTE case.
--- net/mpls/af_mpls.c | 68 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 16 deletions(-)
net/mpls/af_mpls.c +52 -16
@@ -1491,22 +1491,52 @@ static void mpls_dev_destroy_rcu(structkfree (mdev); } -static void mpls_ifdown (struct net_device *dev,int event) +static int mpls_ifdown (struct net_device *dev,int event) {struct mpls_route __rcu **platform_label;struct net *net =dev_net (dev); -u8 alive, deleted;unsigned index; platform_label =rtnl_dereference (net->mpls.platform_label);for (index =0 ; index < net->mpls.platform_labels; index++) {struct mpls_route *rt =rtnl_dereference (platform_label[index]); +bool nh_del = false; +u8 alive =0 ;if (!rt)continue ; - alive =0 ; - deleted =0 ; +if (event ==NETDEV_UNREGISTER ) { +u8 deleted =0 ; + +for_nexthops (rt) { +struct net_device *nh_dev = +rtnl_dereference (nh->nh_dev); + +if (!nh_dev || nh_dev == dev) + deleted++; +if (nh_dev == dev) + nh_del = true; + }endfor_nexthops (rt); + +/* if there are no more nexthops, delete the route */ +if (deleted == rt->rt_nhn) { +mpls_route_update (net, index,NULL ,NULL ); +continue ; + } + +if (nh_del) { +size_t size =sizeof (*rt) + rt->rt_nhn * + rt->rt_nh_size; +struct mpls_route *orig = rt; + + rt =kmalloc (size,GFP_KERNEL ); +if (!rt) +return -ENOMEM ; +memcpy (rt, orig, size); + } + } +change_nexthops (rt) {unsigned int nh_flags = nh->nh_flags;
@@ -1530,16 +1560,15 @@ static void mpls_ifdown(struct net_devic next:if (!(nh_flags & (RTNH_F_DEAD |RTNH_F_LINKDOWN ))) alive++; -if (!rtnl_dereference (nh->nh_dev)) - deleted++; }endfor_nexthops (rt);WRITE_ONCE (rt->rt_nhn_alive, alive); -/* if there are no more nexthops, delete the route */ -if (event ==NETDEV_UNREGISTER && deleted == rt->rt_nhn) -mpls_route_update (net, index,NULL ,NULL ); +if (nh_del) +mpls_route_update (net, index, rt,NULL ); } + +return 0 ; }static void mpls_ifup (struct net_device *dev,unsigned int flags)
@@ -1597,8 +1626,12 @@ static int mpls_dev_notify(struct notifireturn NOTIFY_OK ;switch (event) { +int err; +case NETDEV_DOWN : -mpls_ifdown (dev, event); + err =mpls_ifdown (dev, event); +if (err) +return notifier_from_errno (err);break ;case NETDEV_UP : flags =dev_get_flags (dev);
@@ -1609,13 +1642,18 @@ static int mpls_dev_notify(struct notifibreak ;case NETDEV_CHANGE : flags =dev_get_flags (dev); -if (flags & (IFF_RUNNING |IFF_LOWER_UP )) +if (flags & (IFF_RUNNING |IFF_LOWER_UP )) {mpls_ifup (dev,RTNH_F_DEAD |RTNH_F_LINKDOWN ); -else -mpls_ifdown (dev, event); + }else { + err =mpls_ifdown (dev, event); +if (err) +return notifier_from_errno (err); + }break ;case NETDEV_UNREGISTER : -mpls_ifdown (dev, event); + err =mpls_ifdown (dev, event); +if (err) +return notifier_from_errno (err); mdev =mpls_dev_get (dev);if (mdev) {mpls_dev_sysctl_unregister (dev, mdev);
@@ -1626,8 +1664,6 @@ static int mpls_dev_notify(struct notificase NETDEV_CHANGENAME : mdev =mpls_dev_get (dev);if (mdev) { -int err; -mpls_dev_sysctl_unregister (dev, mdev); err =mpls_dev_sysctl_register (dev, mdev);if (err)
Greg Kroah-Hartman
maintainerPATCH 107/207 siphash: use _unaligned version by default
In reply to Greg Kroah-HartmanFrom: Arnd Bergmann <[email protected]>
commit f7e5b9bfa6c8820407b64eabc1f29c9a87e8993d upstream.
On ARM v6 and later, we define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS because the ordinary load/store instructions (ldr, ldrh, ldrb) can tolerate any misalignment of the memory address. However, load/store double and load/store multiple instructions (ldrd, ldm) may still only be used on memory addresses that are 32-bit aligned, and so we have to use the CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS macro with care, or we may end up with a severe performance hit due to alignment traps that require fixups by the kernel. Testing shows that this currently happens with clang-13 but not gcc-11. In theory, any compiler version can produce this bug or other problems, as we are dealing with undefined behavior in C99 even on architectures that support this in hardware, see also https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100363.
Fortunately, the get_unaligned() accessors do the right thing: when building for ARMv6 or later, the compiler will emit unaligned accesses using the ordinary load/store instructions (but avoid the ones that require 32-bit alignment). When building for older ARM, those accessors will emit the appropriate sequence of ldrb/mov/orr instructions. And on architectures that can truly tolerate any kind of misalignment, the get_unaligned() accessors resolve to the leXX_to_cpup accessors that operate on aligned addresses.
Since the compiler will in fact emit ldrd or ldm instructions when building this code for ARM v6 or later, the solution is to use the unaligned accessors unconditionally on architectures where this is known to be fast. The _aligned version of the hash function is however still needed to get the best performance on architectures that cannot do any unaligned access in hardware.
This new version avoids the undefined behavior and should produce the fastest hash on all architectures we support.
--- include/linux/siphash.h | 14 ++++---------- lib/siphash.c | 12 ++++++------ 2 files changed, 10 insertions(+), 16 deletions(-)
include/linux/siphash.h +4 -10
@@ -27,9 +27,7 @@ static inline bool siphash_key_is_zero(c }u64 __siphash_aligned (const void *data,size_t len,const siphash_key_t *key); -#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS u64 __siphash_unaligned (const void *data,size_t len,const siphash_key_t *key); -#endif u64 siphash_1u64 (const u64 a,const siphash_key_t *key);u64 siphash_2u64 (const u64 a,const u64 b,const siphash_key_t *key);
@@ -82,10 +80,9 @@ static inline u64 ___siphash_aligned(constatic inline u64 siphash (const void *data,size_t len,const siphash_key_t *key) { -#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS -if (!IS_ALIGNED ((unsigned long )data,SIPHASH_ALIGNMENT )) +if (IS_ENABLED (CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS ) || + !IS_ALIGNED ((unsigned long )data,SIPHASH_ALIGNMENT ))return __siphash_unaligned (data, len, key); -#endif return ___siphash_aligned (data, len, key); }
@@ -96,10 +93,8 @@ typedef struct {u32 __hsiphash_aligned (const void *data,size_t len,const hsiphash_key_t *key); -#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS u32 __hsiphash_unaligned (const void *data,size_t len,const hsiphash_key_t *key); -#endif u32 hsiphash_1u32 (const u32 a,const hsiphash_key_t *key);u32 hsiphash_2u32 (const u32 a,const u32 b,const hsiphash_key_t *key);
@@ -135,10 +130,9 @@ static inline u32 ___hsiphash_aligned(costatic inline u32 hsiphash (const void *data,size_t len,const hsiphash_key_t *key) { -#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS -if (!IS_ALIGNED ((unsigned long )data,HSIPHASH_ALIGNMENT )) +if (IS_ENABLED (CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS ) || + !IS_ALIGNED ((unsigned long )data,HSIPHASH_ALIGNMENT ))return __hsiphash_unaligned (data, len, key); -#endif return ___hsiphash_aligned (data, len, key); }
lib/siphash.c +6 -6
@@ -49,6 +49,7 @@SIPROUND ; \return (v0 ^ v1) ^ (v2 ^ v3); +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS u64 __siphash_aligned (const void *data,size_t len,const siphash_key_t *key) {const u8 *end = data + len - (len %sizeof (u64));
@@ -80,8 +81,8 @@ u64 __siphash_aligned(const void *data,POSTAMBLE }EXPORT_SYMBOL (__siphash_aligned ); +#endif -#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS u64 __siphash_unaligned (const void *data,size_t len,const siphash_key_t *key) {const u8 *end = data + len - (len %sizeof (u64));
@@ -113,7 +114,6 @@ u64 __siphash_unaligned(const void *data POSTAMBLE }EXPORT_SYMBOL (__siphash_unaligned); -#endif /** * siphash_1u64 - compute 64-bit siphash PRF value of a u64
@@ -250,6 +250,7 @@ EXPORT_SYMBOL(siphash_3u32);HSIPROUND ; \return (v0 ^ v1) ^ (v2 ^ v3); +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS u32 __hsiphash_aligned (const void *data,size_t len,const hsiphash_key_t *key) {const u8 *end = data + len - (len %sizeof (u64));
@@ -280,8 +281,8 @@ u32 __hsiphash_aligned(const void *data,HPOSTAMBLE }EXPORT_SYMBOL (__hsiphash_aligned ); +#endif -#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS u32 __hsiphash_unaligned (const void *data,size_t len,const hsiphash_key_t *key) {
@@ -313,7 +314,6 @@ u32 __hsiphash_unaligned(const void *dat HPOSTAMBLE }EXPORT_SYMBOL (__hsiphash_unaligned); -#endif /** * hsiphash_1u32 - compute 64-bit hsiphash PRF value of a u32
@@ -418,6 +418,7 @@ EXPORT_SYMBOL(hsiphash_4u32);HSIPROUND ; \return v1 ^ v3; +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS u32 __hsiphash_aligned (const void *data,size_t len,const hsiphash_key_t *key) {const u8 *end = data + len - (len %sizeof (u32));
@@ -438,8 +439,8 @@ u32 __hsiphash_aligned(const void *data,HPOSTAMBLE }EXPORT_SYMBOL (__hsiphash_aligned ); +#endif -#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS u32 __hsiphash_unaligned (const void *data,size_t len,const hsiphash_key_t *key) {
@@ -461,7 +462,6 @@ u32 __hsiphash_unaligned(const void *dat HPOSTAMBLE }EXPORT_SYMBOL (__hsiphash_unaligned); -#endif /** * hsiphash_1u32 - compute 32-bit hsiphash PRF value of a u32
Greg Kroah-Hartman
maintainerPATCH 108/207 arm64: ftrace: add missing BTIs
In reply to Greg Kroah-HartmanFrom: Mark Rutland <[email protected]>
commit 35b6b28e69985eafb20b3b2c7bd6eca452b56b53 upstream.
When branch target identifiers are in use, code reachable via an indirect branch requires a BTI landing pad at the branch target site.
When building FTRACE_WITH_REGS atop patchable-function-entry, we miss BTIs at the start start of the ftrace_caller and ftrace_regs_caller trampolines, and when these are called from a module via a PLT (which will use a BR X16), we will encounter a BTI failure, e.g.
| # insmod lkdtm.ko | lkdtm: No crash points registered, enable through debugfs | # echo function_graph > /sys/kernel/debug/tracing/current_tracer | # cat /sys/kernel/debug/provoke-crash/DIRECT | Unhandled 64-bit el1h sync exception on CPU0, ESR 0x34000001 -- BTI | CPU: 0 PID: 174 Comm: cat Not tainted 5.16.0-rc2-dirty #3 | Hardware name: linux,dummy-virt (DT) | pstate: 60400405 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=jc) | pc : ftrace_caller+0x0/0x3c | lr : lkdtm_debugfs_open+0xc/0x20 [lkdtm] | sp : ffff800012e43b00 | x29: ffff800012e43b00 x28: 0000000000000000 x27: ffff800012e43c88 | x26: 0000000000000000 x25: 0000000000000000 x24: ffff0000c171f200 | x23: ffff0000c27b1e00 x22: ffff0000c2265240 x21: ffff0000c23c8c30 | x20: ffff8000090ba380 x19: 0000000000000000 x18: 0000000000000000 | x17: 0000000000000000 x16: ffff80001002bb4c x15: 0000000000000000 | x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000900ff0 | x11: ffff0000c4166310 x10: ffff800012e43b00 x9 : ffff8000104f2384 | x8 : 0000000000000001 x7 : 0000000000000000 x6 : 000000000000003f | x5 : 0000000000000040 x4 : ffff800012e43af0 x3 : 0000000000000001 | x2 : ffff8000090b0000 x1 : ffff0000c171f200 x0 : ffff0000c23c8c30 | Kernel panic - not syncing: Unhandled exception | CPU: 0 PID: 174 Comm: cat Not tainted 5.16.0-rc2-dirty #3 | Hardware name: linux,dummy-virt (DT) | Call trace: | dump_backtrace+0x0/0x1a4 | show_stack+0x24/0x30 | dump_stack_lvl+0x68/0x84 | dump_stack+0x1c/0x38 | panic+0x168/0x360 | arm64_exit_nmi.isra.0+0x0/0x80 | el1h_64_sync_handler+0x68/0xd4 | el1h_64_sync+0x78/0x7c | ftrace_caller+0x0/0x3c | do_dentry_open+0x134/0x3b0 | vfs_open+0x38/0x44 | path_openat+0x89c/0xe40 | do_filp_open+0x8c/0x13c | do_sys_openat2+0xbc/0x174 | __arm64_sys_openat+0x6c/0xbc | invoke_syscall+0x50/0x120 | el0_svc_common.constprop.0+0xdc/0x100 | do_el0_svc+0x84/0xa0 | el0_svc+0x28/0x80 | el0t_64_sync_handler+0xa8/0x130 | el0t_64_sync+0x1a0/0x1a4 | SMP: stopping secondary CPUs | Kernel Offset: disabled | CPU features: 0x0,00000f42,da660c5f | Memory Limit: none | ---[ end Kernel panic - not syncing: Unhandled exception ]---
Fix this by adding the required BTI C, as we only require these to be reachable via BL for direct calls or BR X16/X17 for PLTs. For now, these are open-coded in the function prologue, matching the style of the __hwasan_tag_mismatch trampoline.
In future we may wish to consider adding a new SYM_CODE_START_*() variant which has an implicit BTI.
When ftrace is built atop mcount, the trampolines are marked with SYM_FUNC_START(), and so get an implicit BTI. We may need to change these over to SYM_CODE_START() in future for RELIABLE_STACKTRACE, in case we need to apply special care aroud the return address being rewritten.
--- arch/arm64/kernel/entry-ftrace.S | 6 ++++++ 1 file changed, 6 insertions(+)
arch/arm64/kernel/entry-ftrace.S +6 -0
@@ -77,11 +77,17 @@ .endm SYM_CODE_START(ftrace_regs_caller) +#ifdef BTI_C + BTI_C +#endif ftrace_regs_entry 1 b ftrace_common SYM_CODE_END(ftrace_regs_caller) SYM_CODE_START(ftrace_caller) +#ifdef BTI_C + BTI_C +#endif ftrace_regs_entry 0 b ftrace_common SYM_CODE_END(ftrace_caller)
Greg Kroah-Hartman
maintainerPATCH 109/207 iwlwifi: fix warnings produced by kernel debug options
In reply to Greg Kroah-HartmanFrom: Łukasz Bartosik <[email protected]>
commit f5cecf1d4c5ff76172928bc32e99ca56a5ca2f56 upstream.
Fix warnings produced by:
- lockdep_assert_wiphy() in function reg_process_self_managed_hint(),
- wiphy_dereference() in function iwl_mvm_init_fw_regd(). Both function are expected to be called in critical section.
The warnings were discovered when running v5.15 kernel with debug options enabled:
1)
Hardware name: Google Delbin/Delbin RIP: 0010:reg_process_self_managed_hint+0x254/0x347 [cfg80211] ... Call Trace: regulatory_set_wiphy_regd_sync+0x3d/0xb0 iwl_mvm_init_mcc+0x49d/0x5a2 iwl_op_mode_mvm_start+0x1b58/0x2507 ? iwl_mvm_reprobe_wk+0x94/0x94 _iwl_op_mode_start+0x146/0x1a3 iwl_opmode_register+0xda/0x13d init_module+0x28/0x1000
2)drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c:263 suspicious rcu_dereference_protected() usage!
...
Hardware name: Google Delbin/Delbin, BIOS Google_Delbin Call Trace: dump_stack_lvl+0xb1/0xe6 iwl_mvm_init_fw_regd+0x2e7/0x379 iwl_mvm_init_mcc+0x2c6/0x5a2 iwl_op_mode_mvm_start+0x1b58/0x2507 ? iwl_mvm_reprobe_wk+0x94/0x94 _iwl_op_mode_start+0x146/0x1a3 iwl_opmode_register+0xda/0x13d init_module+0x28/0x100
--- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/wireless/intel/iwlwifi/mvm/ops.c +2 -0
@@ -687,6 +687,7 @@ static int iwl_mvm_start_get_nvm(structint ret;rtnl_lock (); +wiphy_lock (mvm->hw->wiphy);mutex_lock (&mvm->mutex); ret =iwl_run_init_mvm_ucode (mvm);
@@ -702,6 +703,7 @@ static int iwl_mvm_start_get_nvm(structiwl_mvm_stop_device (mvm);mutex_unlock (&mvm->mutex); +wiphy_unlock (mvm->hw->wiphy);rtnl_unlock ();if (ret <0 )
Greg Kroah-Hartman
maintainerPATCH 110/207 net/mlx5e: IPsec: Fix Software parser inner l3 type setting in case of encapsulation
In reply to Greg Kroah-HartmanFrom: Raed Salem <[email protected]>
commit c65d638ab39034cbaa36773b980d28106cfc81fa upstream.
Current code wrongly uses the skb->protocol field which reflects the outer l3 protocol to set the inner l3 type in Software Parser (SWP) fields settings in the ethernet segment (eseg) in flows where inner l3 exists like in Vxlan over ESP flow, the above method wrongly use the outer protocol type instead of the inner one. thus breaking cases where inner and outer headers have different protocols.
Fix by setting the inner l3 type in SWP according to the inner l3 ip header version.
--- drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c +1 -1
@@ -191,7 +191,7 @@ static void mlx5e_ipsec_set_swp(struct s eseg->swp_inner_l3_offset =skb_inner_network_offset (skb) /2 ; eseg->swp_inner_l4_offset = (skb->csum_start + skb->head - skb->data) /2 ; -if (skb->protocol ==htons (ETH_P_IPV6 )) +if (inner_ip_hdr (skb)->version ==6 ) eseg->swp_flags |=MLX5_ETH_WQE_SWP_INNER_L3_IPV6 ;break ;default :
Greg Kroah-Hartman
maintainerPATCH 111/207 net/mlx4_en: Fix an use-after-free bug in mlx4_en_try_alloc_resources()
In reply to Greg Kroah-HartmanFrom: Zhou Qingyang <[email protected]>
commit addad7643142f500080417dd7272f49b7a185570 upstream.
In mlx4_en_try_alloc_resources(), mlx4_en_copy_priv() is called and tmp->tx_cq will be freed on the error path of mlx4_en_copy_priv(). After that mlx4_en_alloc_resources() is called and there is a dereference of &tmp->tx_cq[t][i] in mlx4_en_alloc_resources(), which could lead to a use after free problem on failure of mlx4_en_copy_priv().
Fix this bug by adding a check of mlx4_en_copy_priv()
This bug was found by a static analyzer. The analysis employs differential checking to identify inconsistent security operations (e.g., checks or kfrees) between two code paths and confirms that the inconsistent operations are not recovered in the current function or the callers, so they constitute bugs.
Note that, as a bug found by static analysis, it can be a false positive or hard to trigger. Multiple researchers have cross-reviewed the bug.
Builds with CONFIG_MLX4_EN=m show no new warnings, and our static analyzer no longer warns about this code.
--- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/net/ethernet/mellanox/mlx4/en_netdev.c +7 -2
@@ -2286,9 +2286,14 @@ int mlx4_en_try_alloc_resources(struct m bool carry_xdp_prog) {struct bpf_prog *xdp_prog; -int i, t; +int i, t, ret; -mlx4_en_copy_priv (tmp, priv, prof); + ret =mlx4_en_copy_priv (tmp, priv, prof); +if (ret) { +en_warn (priv,"%s: mlx4_en_copy_priv() failed, return\n" , + __func__); +return ret; + }if (mlx4_en_alloc_resources (tmp)) { en_warn(priv,
Greg Kroah-Hartman
maintainerPATCH 112/207 selftests: net: Correct case name
In reply to Greg Kroah-HartmanFrom: Li Zhijian <[email protected]>
commit a05431b22be819d75db72ca3d44381d18a37b092 upstream.
ipv6_addr_bind/ipv4_addr_bind are function names. Previously, bind test would not be run by default due to the wrong case names
--- tools/testing/selftests/net/fcnal-test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/testing/selftests/net/fcnal-test.sh +2 -2
@@ -4002,8 +4002,8 @@ EOF ################################################################################ # main -TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_addr_bind ipv4_runtime ipv4_netfilter" -TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp ipv6_addr_bind ipv6_runtime ipv6_netfilter" +TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_bind ipv4_runtime ipv4_netfilter" +TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp ipv6_bind ipv6_runtime ipv6_netfilter" TESTS_OTHER="use_cases" PAUSE_ON_FAIL=no
Greg Kroah-Hartman
maintainerPATCH 113/207 net: dsa: b53: Add SPI ID table
In reply to Greg Kroah-HartmanFrom: Florian Fainelli <[email protected]>
commit 88362ebfd7fb569c78d5cb507aa9d3c8fc203839 upstream.
Currently autoloading for SPI devices does not use the DT ID table, it uses SPI modalises. Supporting OF modalises is going to be difficult if not impractical, an attempt was made but has been reverted, so ensure that module autoloading works for this driver by adding an id_table listing the SPI IDs for everything.
--- drivers/net/dsa/b53/b53_spi.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
drivers/net/dsa/b53/b53_spi.c +14 -0
@@ -349,6 +349,19 @@ static const struct of_device_id b53_spi };MODULE_DEVICE_TABLE (of, b53_spi_of_match); +static const struct spi_device_id b53_spi_ids[] = { + { .name ="bcm5325" }, + { .name ="bcm5365" }, + { .name ="bcm5395" }, + { .name ="bcm5397" }, + { .name ="bcm5398" }, + { .name ="bcm53115" }, + { .name ="bcm53125" }, + { .name ="bcm53128" }, + {/* sentinel */ } +}; +MODULE_DEVICE_TABLE (spi, b53_spi_ids); +static struct spi_driver b53_spi_driver = { .driver = { .name ="b53-switch" ,
@@ -357,6 +370,7 @@ static struct spi_driver b53_spi_driver .probe = b53_spi_probe, .remove = b53_spi_remove, .shutdown = b53_spi_shutdown, + .id_table = b53_spi_ids, };module_spi_driver (b53_spi_driver);
Greg Kroah-Hartman
maintainerPATCH 114/207 mt76: mt7915: fix NULL pointer dereference in mt7915_get_phy_mode
In reply to Greg Kroah-HartmanFrom: Lorenzo Bianconi <[email protected]>
commit 6e53d6d26920d5221d3f4d4f5ffdd629ea69aa5c upstream.
Fix the following NULL pointer dereference in mt7915_get_phy_mode routine adding an ibss interface to the mt7915 driver.
[ 101.137097] wlan0: Trigger new scan to find an IBSS to join [ 102.827039] wlan0: Creating new IBSS network, BSSID 26:a4:50:1a:6e:69 [ 103.064756] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 [ 103.073670] Mem abort info: [ 103.076520] ESR = 0x96000005 [ 103.079614] EC = 0x25: DABT (current EL), IL = 32 bits [ 103.084934] SET = 0, FnV = 0 [ 103.088042] EA = 0, S1PTW = 0 [ 103.091215] Data abort info: [ 103.094104] ISV = 0, ISS = 0x00000005 [ 103.098041] CM = 0, WnR = 0 [ 103.101044] user pgtable: 4k pages, 39-bit VAs, pgdp=00000000460b1000 [ 103.107565] [0000000000000000] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000 [ 103.116590] Internal error: Oops: 96000005 [#1] SMP [ 103.189066] CPU: 1 PID: 333 Comm: kworker/u4:3 Not tainted 5.10.75 #0 [ 103.195498] Hardware name: MediaTek MT7622 RFB1 board (DT) [ 103.201124] Workqueue: phy0 ieee80211_iface_work [mac80211] [ 103.206695] pstate: 20000005 (nzCv daif -PAN -UAO -TCO BTYPE=--) [ 103.212705] pc : mt7915_get_phy_mode+0x68/0x120 [mt7915e] [ 103.218103] lr : mt7915_mcu_add_bss_info+0x11c/0x760 [mt7915e] [ 103.223927] sp : ffffffc011cdb9e0 [ 103.227235] x29: ffffffc011cdb9e0 x28: ffffff8006563098 [ 103.232545] x27: ffffff8005f4da22 x26: ffffff800685ac40 [ 103.237855] x25: 0000000000000001 x24: 000000000000011f [ 103.243165] x23: ffffff8005f4e260 x22: ffffff8006567918 [ 103.248475] x21: ffffff8005f4df80 x20: ffffff800685ac58 [ 103.253785] x19: ffffff8006744400 x18: 0000000000000000 [ 103.259094] x17: 0000000000000000 x16: 0000000000000001 [ 103.264403] x15: 000899c3a2d9d2e4 x14: 000899bdc3c3a1c8 [ 103.269713] x13: 0000000000000000 x12: 0000000000000000 [ 103.275024] x11: ffffffc010e30c20 x10: 0000000000000000 [ 103.280333] x9 : 0000000000000050 x8 : ffffff8006567d88 [ 103.285642] x7 : ffffff8006563b5c x6 : ffffff8006563b44 [ 103.290952] x5 : 0000000000000002 x4 : 0000000000000001 [ 103.296262] x3 : 0000000000000001 x2 : 0000000000000001 [ 103.301572] x1 : 0000000000000000 x0 : 0000000000000011 [ 103.306882] Call trace: [ 103.309328] mt7915_get_phy_mode+0x68/0x120 [mt7915e] [ 103.314378] mt7915_bss_info_changed+0x198/0x200 [mt7915e] [ 103.319941] ieee80211_bss_info_change_notify+0x128/0x290 [mac80211] [ 103.326360] __ieee80211_sta_join_ibss+0x308/0x6c4 [mac80211] [ 103.332171] ieee80211_sta_create_ibss+0x8c/0x10c [mac80211] [ 103.337895] ieee80211_ibss_work+0x3dc/0x614 [mac80211] [ 103.343185] ieee80211_iface_work+0x388/0x3f0 [mac80211] [ 103.348495] process_one_work+0x288/0x690 [ 103.352499] worker_thread+0x70/0x464 [ 103.356157] kthread+0x144/0x150 [ 103.359380] ret_from_fork+0x10/0x18 [ 103.362952] Code: 394008c3 52800220 394000e4 7100007f (39400023)
--- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +2 -2
@@ -176,7 +176,7 @@ mt7915_get_phy_mode(struct ieee80211_vifif (ht_cap->ht_supported) mode |=PHY_MODE_GN ; -if (he_cap->has_he) +if (he_cap && he_cap->has_he) mode |=PHY_MODE_AX_24G ; }else if (band ==NL80211_BAND_5GHZ ) { mode |=PHY_MODE_A ;
@@ -187,7 +187,7 @@ mt7915_get_phy_mode(struct ieee80211_vifif (vht_cap->vht_supported) mode |=PHY_MODE_AC ; -if (he_cap->has_he) +if (he_cap && he_cap->has_he) mode |=PHY_MODE_AX_5G ; }
Greg Kroah-Hartman
maintainerPATCH 115/207 ASoC: tegra: Fix wrong value type in ADMAIF
In reply to Greg Kroah-HartmanFrom: Sameer Pujar <[email protected]>
commit 884c6cb3b7030f75c46e55b9e625d2372708c306 upstream.
The enum controls are expected to use enumerated value type. Update relevant references in control get/put callbacks.
--- sound/soc/tegra/tegra210_admaif.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
sound/soc/tegra/tegra210_admaif.c +2 -2
@@ -430,7 +430,7 @@ static int tegra_admaif_get_control(strustruct snd_soc_component *cmpnt =snd_soc_kcontrol_component (kcontrol);struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;struct tegra_admaif *admaif =snd_soc_component_get_drvdata (cmpnt); -long *uctl_val = &ucontrol->value.integer.value[0 ]; +unsigned int *uctl_val = &ucontrol->value.enumerated.item[0 ];if (strstr (kcontrol->id.name,"Playback Mono To Stereo" )) *uctl_val = admaif->mono_to_stereo[ADMAIF_TX_PATH ][ec->reg];
@@ -450,7 +450,7 @@ static int tegra_admaif_put_control(strustruct snd_soc_component *cmpnt =snd_soc_kcontrol_component (kcontrol);struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;struct tegra_admaif *admaif =snd_soc_component_get_drvdata (cmpnt); -int value = ucontrol->value.integer.value[0 ]; +unsigned int value = ucontrol->value.enumerated.item[0 ];if (strstr (kcontrol->id.name,"Playback Mono To Stereo" )) admaif->mono_to_stereo[ADMAIF_TX_PATH ][ec->reg] = value;
Greg Kroah-Hartman
maintainerPATCH 116/207 ASoC: tegra: Fix wrong value type in I2S
In reply to Greg Kroah-HartmanFrom: Sameer Pujar <[email protected]>
commit 8a2c2fa0c5331445c801e9241f2bb4e0e2a895a8 upstream.
The enum controls are expected to use enumerated value type. Update relevant references in control get/put callbacks.
--- sound/soc/tegra/tegra210_i2s.c | 42 +++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-)
sound/soc/tegra/tegra210_i2s.c +24 -18
@@ -317,24 +317,27 @@ static int tegra210_i2s_get_control(stru {struct snd_soc_component *compnt =snd_soc_kcontrol_component (kcontrol);struct tegra210_i2s *i2s =snd_soc_component_get_drvdata (compnt); -long *uctl_val = &ucontrol->value.integer.value[0 ];if (strstr (kcontrol->id.name,"Loopback" )) - *uctl_val = i2s->loopback; + ucontrol->value.integer.value[0 ] = i2s->loopback;else if (strstr (kcontrol->id.name,"FSYNC Width" )) - *uctl_val = i2s->fsync_width; + ucontrol->value.integer.value[0 ] = i2s->fsync_width;else if (strstr (kcontrol->id.name,"Capture Stereo To Mono" )) - *uctl_val = i2s->stereo_to_mono[I2S_TX_PATH ]; + ucontrol->value.enumerated.item[0 ] = + i2s->stereo_to_mono[I2S_TX_PATH ];else if (strstr (kcontrol->id.name,"Capture Mono To Stereo" )) - *uctl_val = i2s->mono_to_stereo[I2S_TX_PATH ]; + ucontrol->value.enumerated.item[0 ] = + i2s->mono_to_stereo[I2S_TX_PATH ];else if (strstr (kcontrol->id.name,"Playback Stereo To Mono" )) - *uctl_val = i2s->stereo_to_mono[I2S_RX_PATH ]; + ucontrol->value.enumerated.item[0 ] = + i2s->stereo_to_mono[I2S_RX_PATH ];else if (strstr (kcontrol->id.name,"Playback Mono To Stereo" )) - *uctl_val = i2s->mono_to_stereo[I2S_RX_PATH ]; + ucontrol->value.enumerated.item[0 ] = + i2s->mono_to_stereo[I2S_RX_PATH ];else if (strstr (kcontrol->id.name,"Playback FIFO Threshold" )) - *uctl_val = i2s->rx_fifo_th; + ucontrol->value.integer.value[0 ] = i2s->rx_fifo_th;else if (strstr (kcontrol->id.name,"BCLK Ratio" )) - *uctl_val = i2s->bclk_ratio; + ucontrol->value.integer.value[0 ] = i2s->bclk_ratio;return 0 ; }
@@ -344,10 +347,9 @@ static int tegra210_i2s_put_control(stru {struct snd_soc_component *compnt =snd_soc_kcontrol_component (kcontrol);struct tegra210_i2s *i2s =snd_soc_component_get_drvdata (compnt); -int value = ucontrol->value.integer.value[0 ];if (strstr (kcontrol->id.name,"Loopback" )) { - i2s->loopback = value; + i2s->loopback = ucontrol->value.integer.value[0 ]; regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, I2S_CTRL_LPBK_MASK,
@@ -362,24 +364,28 @@ static int tegra210_i2s_put_control(stru* cases mixer control is used to update custom values. A value * of "N" here means, width is "N + 1" bit clock wide. */ - i2s->fsync_width = value; + i2s->fsync_width = ucontrol->value.integer.value[0 ];regmap_update_bits (i2s->regmap,TEGRA210_I2S_CTRL ,I2S_CTRL_FSYNC_WIDTH_MASK , i2s->fsync_width <<I2S_FSYNC_WIDTH_SHIFT ); }else if (strstr (kcontrol->id.name,"Capture Stereo To Mono" )) { - i2s->stereo_to_mono[I2S_TX_PATH ] = value; + i2s->stereo_to_mono[I2S_TX_PATH ] = + ucontrol->value.enumerated.item[0 ]; }else if (strstr (kcontrol->id.name,"Capture Mono To Stereo" )) { - i2s->mono_to_stereo[I2S_TX_PATH ] = value; + i2s->mono_to_stereo[I2S_TX_PATH ] = + ucontrol->value.enumerated.item[0 ]; }else if (strstr (kcontrol->id.name,"Playback Stereo To Mono" )) { - i2s->stereo_to_mono[I2S_RX_PATH ] = value; + i2s->stereo_to_mono[I2S_RX_PATH ] = + ucontrol->value.enumerated.item[0 ]; }else if (strstr (kcontrol->id.name,"Playback Mono To Stereo" )) { - i2s->mono_to_stereo[I2S_RX_PATH ] = value; + i2s->mono_to_stereo[I2S_RX_PATH ] = + ucontrol->value.enumerated.item[0 ]; }else if (strstr (kcontrol->id.name,"Playback FIFO Threshold" )) { - i2s->rx_fifo_th = value; + i2s->rx_fifo_th = ucontrol->value.integer.value[0 ]; }else if (strstr (kcontrol->id.name,"BCLK Ratio" )) { - i2s->bclk_ratio = value; + i2s->bclk_ratio = ucontrol->value.integer.value[0 ]; }return 0 ;
Greg Kroah-Hartman
maintainerPATCH 117/207 ASoC: tegra: Fix wrong value type in DMIC
In reply to Greg Kroah-HartmanFrom: Sameer Pujar <[email protected]>
commit 559d234569a998a4004de1bd1f12da5487fb826e upstream.
The enum controls are expected to use enumerated value type. Update relevant references in control get/put callbacks.
--- sound/soc/tegra/tegra210_dmic.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-)
sound/soc/tegra/tegra210_dmic.c +11 -12
@@ -165,15 +165,15 @@ static int tegra210_dmic_get_control(strif (strstr (kcontrol->id.name,"Boost Gain Volume" )) ucontrol->value.integer.value[0 ] = dmic->boost_gain;else if (strstr (kcontrol->id.name,"Channel Select" )) - ucontrol->value.integer.value[0 ] = dmic->ch_select; + ucontrol->value.enumerated.item[0 ] = dmic->ch_select;else if (strstr (kcontrol->id.name,"Mono To Stereo" )) - ucontrol->value.integer.value[0 ] = dmic->mono_to_stereo; + ucontrol->value.enumerated.item[0 ] = dmic->mono_to_stereo;else if (strstr (kcontrol->id.name,"Stereo To Mono" )) - ucontrol->value.integer.value[0 ] = dmic->stereo_to_mono; + ucontrol->value.enumerated.item[0 ] = dmic->stereo_to_mono;else if (strstr (kcontrol->id.name,"OSR Value" )) - ucontrol->value.integer.value[0 ] = dmic->osr_val; + ucontrol->value.enumerated.item[0 ] = dmic->osr_val;else if (strstr (kcontrol->id.name,"LR Polarity Select" )) - ucontrol->value.integer.value[0 ] = dmic->lrsel; + ucontrol->value.enumerated.item[0 ] = dmic->lrsel;return 0 ; }
@@ -183,20 +183,19 @@ static int tegra210_dmic_put_control(str {struct snd_soc_component *comp =snd_soc_kcontrol_component (kcontrol);struct tegra210_dmic *dmic =snd_soc_component_get_drvdata (comp); -int value = ucontrol->value.integer.value[0 ];if (strstr (kcontrol->id.name,"Boost Gain Volume" )) - dmic->boost_gain = value; + dmic->boost_gain = ucontrol->value.integer.value[0 ];else if (strstr (kcontrol->id.name,"Channel Select" )) - dmic->ch_select = ucontrol->value.integer.value[0 ]; + dmic->ch_select = ucontrol->value.enumerated.item[0 ];else if (strstr (kcontrol->id.name,"Mono To Stereo" )) - dmic->mono_to_stereo = value; + dmic->mono_to_stereo = ucontrol->value.enumerated.item[0 ];else if (strstr (kcontrol->id.name,"Stereo To Mono" )) - dmic->stereo_to_mono = value; + dmic->stereo_to_mono = ucontrol->value.enumerated.item[0 ];else if (strstr (kcontrol->id.name,"OSR Value" )) - dmic->osr_val = value; + dmic->osr_val = ucontrol->value.enumerated.item[0 ];else if (strstr (kcontrol->id.name,"LR Polarity Select" )) - dmic->lrsel = value; + dmic->lrsel = ucontrol->value.enumerated.item[0 ];return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 118/207 ASoC: tegra: Fix wrong value type in DSPK
In reply to Greg Kroah-HartmanFrom: Sameer Pujar <[email protected]>
commit 3aa0d5c8bb3f5ef622ec2764823f551a1f630711 upstream.
The enum controls are expected to use enumerated value type. Update relevant references in control get/put callbacks.
--- sound/soc/tegra/tegra186_dspk.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-)
sound/soc/tegra/tegra186_dspk.c +11 -12
@@ -35,15 +35,15 @@ static int tegra186_dspk_get_control(strif (strstr (kcontrol->id.name,"FIFO Threshold" )) ucontrol->value.integer.value[0 ] = dspk->rx_fifo_th;else if (strstr (kcontrol->id.name,"OSR Value" )) - ucontrol->value.integer.value[0 ] = dspk->osr_val; + ucontrol->value.enumerated.item[0 ] = dspk->osr_val;else if (strstr (kcontrol->id.name,"LR Polarity Select" )) - ucontrol->value.integer.value[0 ] = dspk->lrsel; + ucontrol->value.enumerated.item[0 ] = dspk->lrsel;else if (strstr (kcontrol->id.name,"Channel Select" )) - ucontrol->value.integer.value[0 ] = dspk->ch_sel; + ucontrol->value.enumerated.item[0 ] = dspk->ch_sel;else if (strstr (kcontrol->id.name,"Mono To Stereo" )) - ucontrol->value.integer.value[0 ] = dspk->mono_to_stereo; + ucontrol->value.enumerated.item[0 ] = dspk->mono_to_stereo;else if (strstr (kcontrol->id.name,"Stereo To Mono" )) - ucontrol->value.integer.value[0 ] = dspk->stereo_to_mono; + ucontrol->value.enumerated.item[0 ] = dspk->stereo_to_mono;return 0 ; }
@@ -53,20 +53,19 @@ static int tegra186_dspk_put_control(str {struct snd_soc_component *codec =snd_soc_kcontrol_component (kcontrol);struct tegra186_dspk *dspk =snd_soc_component_get_drvdata (codec); -int val = ucontrol->value.integer.value[0 ];if (strstr (kcontrol->id.name,"FIFO Threshold" )) - dspk->rx_fifo_th = val; + dspk->rx_fifo_th = ucontrol->value.integer.value[0 ];else if (strstr (kcontrol->id.name,"OSR Value" )) - dspk->osr_val = val; + dspk->osr_val = ucontrol->value.enumerated.item[0 ];else if (strstr (kcontrol->id.name,"LR Polarity Select" )) - dspk->lrsel = val; + dspk->lrsel = ucontrol->value.enumerated.item[0 ];else if (strstr (kcontrol->id.name,"Channel Select" )) - dspk->ch_sel = val; + dspk->ch_sel = ucontrol->value.enumerated.item[0 ];else if (strstr (kcontrol->id.name,"Mono To Stereo" )) - dspk->mono_to_stereo = val; + dspk->mono_to_stereo = ucontrol->value.enumerated.item[0 ];else if (strstr (kcontrol->id.name,"Stereo To Mono" )) - dspk->stereo_to_mono = val; + dspk->stereo_to_mono = ucontrol->value.enumerated.item[0 ];return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 119/207 ASoC: tegra: Fix kcontrol put callback in ADMAIF
In reply to Greg Kroah-HartmanFrom: Sameer Pujar <[email protected]>
commit e2b87a18a60c02d0dcd1de801d669587e516cc4d upstream.
The kcontrol put callback is expected to return 1 when there is change in HW or when the update is acknowledged by driver. This would ensure that change notifications are sent to subscribed applications. Update the ADMAIF driver accordingly.
--- sound/soc/tegra/tegra210_admaif.c | 138 ++++++++++++++++++++++++++++++-------- 1 file changed, 109 insertions(+), 29 deletions(-)
sound/soc/tegra/tegra210_admaif.c +109 -29
@@ -424,46 +424,122 @@ static const struct snd_soc_dai_ops tegr .trigger = tegra_admaif_trigger, }; -static int tegra_admaif_get_control (struct snd_kcontrol *kcontrol, -struct snd_ctl_elem_value *ucontrol) +static int tegra210_admaif_pget_mono_to_stereo (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) {struct snd_soc_component *cmpnt =snd_soc_kcontrol_component (kcontrol); +struct tegra_admaif *admaif =snd_soc_component_get_drvdata (cmpnt);struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; + + ucontrol->value.enumerated.item[0 ] = + admaif->mono_to_stereo[ADMAIF_TX_PATH ][ec->reg]; + +return 0 ; +} + +static int tegra210_admaif_pput_mono_to_stereo (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *cmpnt =snd_soc_kcontrol_component (kcontrol);struct tegra_admaif *admaif =snd_soc_component_get_drvdata (cmpnt); -unsigned int *uctl_val = &ucontrol->value.enumerated.item[0 ]; +struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; +unsigned int value = ucontrol->value.enumerated.item[0 ]; -if (strstr (kcontrol->id.name,"Playback Mono To Stereo" )) - *uctl_val = admaif->mono_to_stereo[ADMAIF_TX_PATH ][ec->reg]; -else if (strstr (kcontrol->id.name,"Capture Mono To Stereo" )) - *uctl_val = admaif->mono_to_stereo[ADMAIF_RX_PATH ][ec->reg]; -else if (strstr (kcontrol->id.name,"Playback Stereo To Mono" )) - *uctl_val = admaif->stereo_to_mono[ADMAIF_TX_PATH ][ec->reg]; -else if (strstr (kcontrol->id.name,"Capture Stereo To Mono" )) - *uctl_val = admaif->stereo_to_mono[ADMAIF_RX_PATH ][ec->reg]; +if (value == admaif->mono_to_stereo[ADMAIF_TX_PATH ][ec->reg]) +return 0 ; + + admaif->mono_to_stereo[ADMAIF_TX_PATH ][ec->reg] = value; + +return 1 ; +} + +static int tegra210_admaif_cget_mono_to_stereo (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *cmpnt =snd_soc_kcontrol_component (kcontrol); +struct tegra_admaif *admaif =snd_soc_component_get_drvdata (cmpnt); +struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; + + ucontrol->value.enumerated.item[0 ] = + admaif->mono_to_stereo[ADMAIF_RX_PATH ][ec->reg];return 0 ; } -static int tegra_admaif_put_control (struct snd_kcontrol *kcontrol, -struct snd_ctl_elem_value *ucontrol) +static int tegra210_admaif_cput_mono_to_stereo (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) {struct snd_soc_component *cmpnt =snd_soc_kcontrol_component (kcontrol); +struct tegra_admaif *admaif =snd_soc_component_get_drvdata (cmpnt);struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; +unsigned int value = ucontrol->value.enumerated.item[0 ]; + +if (value == admaif->mono_to_stereo[ADMAIF_RX_PATH ][ec->reg]) +return 0 ; + + admaif->mono_to_stereo[ADMAIF_RX_PATH ][ec->reg] = value; + +return 1 ; +} + +static int tegra210_admaif_pget_stereo_to_mono (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *cmpnt =snd_soc_kcontrol_component (kcontrol);struct tegra_admaif *admaif =snd_soc_component_get_drvdata (cmpnt); +struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; + + ucontrol->value.enumerated.item[0 ] = + admaif->stereo_to_mono[ADMAIF_TX_PATH ][ec->reg]; + +return 0 ; +} + +static int tegra210_admaif_pput_stereo_to_mono (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *cmpnt =snd_soc_kcontrol_component (kcontrol); +struct tegra_admaif *admaif =snd_soc_component_get_drvdata (cmpnt); +struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;unsigned int value = ucontrol->value.enumerated.item[0 ]; -if (strstr (kcontrol->id.name,"Playback Mono To Stereo" )) - admaif->mono_to_stereo[ADMAIF_TX_PATH ][ec->reg] = value; -else if (strstr (kcontrol->id.name,"Capture Mono To Stereo" )) - admaif->mono_to_stereo[ADMAIF_RX_PATH ][ec->reg] = value; -else if (strstr (kcontrol->id.name,"Playback Stereo To Mono" )) - admaif->stereo_to_mono[ADMAIF_TX_PATH ][ec->reg] = value; -else if (strstr (kcontrol->id.name,"Capture Stereo To Mono" )) - admaif->stereo_to_mono[ADMAIF_RX_PATH ][ec->reg] = value; +if (value == admaif->stereo_to_mono[ADMAIF_TX_PATH ][ec->reg]) +return 0 ; + + admaif->stereo_to_mono[ADMAIF_TX_PATH ][ec->reg] = value; + +return 1 ; +} + +static int tegra210_admaif_cget_stereo_to_mono (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *cmpnt =snd_soc_kcontrol_component (kcontrol); +struct tegra_admaif *admaif =snd_soc_component_get_drvdata (cmpnt); +struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; + + ucontrol->value.enumerated.item[0 ] = + admaif->stereo_to_mono[ADMAIF_RX_PATH ][ec->reg];return 0 ; } +static int tegra210_admaif_cput_stereo_to_mono (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *cmpnt =snd_soc_kcontrol_component (kcontrol); +struct tegra_admaif *admaif =snd_soc_component_get_drvdata (cmpnt); +struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; +unsigned int value = ucontrol->value.enumerated.item[0 ]; + +if (value == admaif->stereo_to_mono[ADMAIF_RX_PATH ][ec->reg]) +return 0 ; + + admaif->stereo_to_mono[ADMAIF_RX_PATH ][ec->reg] = value; + +return 1 ; +} +static int tegra_admaif_dai_probe (struct snd_soc_dai *dai) {struct tegra_admaif *admaif =snd_soc_dai_get_drvdata (dai);
@@ -559,17 +635,21 @@ static const char * const tegra_admaif_m }#define TEGRA_ADMAIF_CIF_CTRL (reg) \ - NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1,\ - tegra_admaif_get_control, tegra_admaif_put_control, \ + NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1, \ + tegra210_admaif_pget_mono_to_stereo, \ + tegra210_admaif_pput_mono_to_stereo, \ tegra_admaif_mono_conv_text), \ - NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1,\ - tegra_admaif_get_control, tegra_admaif_put_control, \ + NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1, \ + tegra210_admaif_pget_stereo_to_mono, \ + tegra210_admaif_pput_stereo_to_mono, \ tegra_admaif_stereo_conv_text), \ - NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \ - tegra_admaif_get_control, tegra_admaif_put_control, \ + NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \ + tegra210_admaif_cget_mono_to_stereo, \ + tegra210_admaif_cput_mono_to_stereo, \ tegra_admaif_mono_conv_text), \ - NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \ - tegra_admaif_get_control, tegra_admaif_put_control, \ + NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \ + tegra210_admaif_cget_stereo_to_mono, \ + tegra210_admaif_cput_stereo_to_mono, \ tegra_admaif_stereo_conv_text)static struct snd_kcontrol_new tegra210_admaif_controls[] = {
Greg Kroah-Hartman
maintainerPATCH 120/207 ASoC: tegra: Fix kcontrol put callback in I2S
In reply to Greg Kroah-HartmanFrom: Sameer Pujar <[email protected]>
commit f21a9df3f7cb0005947679d7b9237c90574e229a upstream.
The kcontrol put callback is expected to return 1 when there is change in HW or when the update is acknowledged by driver. This would ensure that change notifications are sent to subscribed applications. Update the I2S driver accordingly.
--- sound/soc/tegra/tegra210_i2s.c | 322 ++++++++++++++++++++++++++++++----------- 1 file changed, 236 insertions(+), 86 deletions(-)
sound/soc/tegra/tegra210_i2s.c +236 -86
@@ -302,91 +302,235 @@ static int tegra210_i2s_set_tdm_slot(strreturn 0 ; } -static int tegra210_i2s_set_dai_bclk_ratio (struct snd_soc_dai *dai, -unsigned int ratio) +static int tegra210_i2s_get_loopback (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) { -struct tegra210_i2s *i2s =snd_soc_dai_get_drvdata (dai); +struct snd_soc_component *compnt =snd_soc_kcontrol_component (kcontrol); +struct tegra210_i2s *i2s =snd_soc_component_get_drvdata (compnt); - i2s->bclk_ratio = ratio; + ucontrol->value.integer.value[0 ] = i2s->loopback;return 0 ; } -static int tegra210_i2s_get_control (struct snd_kcontrol *kcontrol, -struct snd_ctl_elem_value *ucontrol) +static int tegra210_i2s_put_loopback (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) {struct snd_soc_component *compnt =snd_soc_kcontrol_component (kcontrol);struct tegra210_i2s *i2s =snd_soc_component_get_drvdata (compnt); +int value = ucontrol->value.integer.value[0 ]; -if (strstr (kcontrol->id.name,"Loopback" )) - ucontrol->value.integer.value[0 ] = i2s->loopback; -else if (strstr (kcontrol->id.name,"FSYNC Width" )) - ucontrol->value.integer.value[0 ] = i2s->fsync_width; -else if (strstr (kcontrol->id.name,"Capture Stereo To Mono" )) - ucontrol->value.enumerated.item[0 ] = - i2s->stereo_to_mono[I2S_TX_PATH ]; -else if (strstr (kcontrol->id.name,"Capture Mono To Stereo" )) - ucontrol->value.enumerated.item[0 ] = - i2s->mono_to_stereo[I2S_TX_PATH ]; -else if (strstr (kcontrol->id.name,"Playback Stereo To Mono" )) - ucontrol->value.enumerated.item[0 ] = - i2s->stereo_to_mono[I2S_RX_PATH ]; -else if (strstr (kcontrol->id.name,"Playback Mono To Stereo" )) - ucontrol->value.enumerated.item[0 ] = - i2s->mono_to_stereo[I2S_RX_PATH ]; -else if (strstr (kcontrol->id.name,"Playback FIFO Threshold" )) - ucontrol->value.integer.value[0 ] = i2s->rx_fifo_th; -else if (strstr (kcontrol->id.name,"BCLK Ratio" )) - ucontrol->value.integer.value[0 ] = i2s->bclk_ratio; - -return 0 ; -} - -static int tegra210_i2s_put_control (struct snd_kcontrol *kcontrol, -struct snd_ctl_elem_value *ucontrol) -{ -struct snd_soc_component *compnt =snd_soc_kcontrol_component (kcontrol); -struct tegra210_i2s *i2s =snd_soc_component_get_drvdata (compnt); - -if (strstr (kcontrol->id.name,"Loopback" )) { - i2s->loopback = ucontrol->value.integer.value[0 ]; - -regmap_update_bits (i2s->regmap,TEGRA210_I2S_CTRL , -I2S_CTRL_LPBK_MASK , - i2s->loopback <<I2S_CTRL_LPBK_SHIFT ); - - }else if (strstr (kcontrol->id.name,"FSYNC Width" )) { -/* -* Frame sync width is used only for FSYNC modes and not -* applicable for LRCK modes. Reset value for this field is "0", -* which means the width is one bit clock wide. -* The width requirement may depend on the codec and in such -* cases mixer control is used to update custom values. A value -* of "N" here means, width is "N + 1" bit clock wide. -*/ - i2s->fsync_width = ucontrol->value.integer.value[0 ]; - -regmap_update_bits (i2s->regmap,TEGRA210_I2S_CTRL , -I2S_CTRL_FSYNC_WIDTH_MASK , - i2s->fsync_width <<I2S_FSYNC_WIDTH_SHIFT ); - - }else if (strstr (kcontrol->id.name,"Capture Stereo To Mono" )) { - i2s->stereo_to_mono[I2S_TX_PATH ] = - ucontrol->value.enumerated.item[0 ]; - }else if (strstr (kcontrol->id.name,"Capture Mono To Stereo" )) { - i2s->mono_to_stereo[I2S_TX_PATH ] = - ucontrol->value.enumerated.item[0 ]; - }else if (strstr (kcontrol->id.name,"Playback Stereo To Mono" )) { - i2s->stereo_to_mono[I2S_RX_PATH ] = - ucontrol->value.enumerated.item[0 ]; - }else if (strstr (kcontrol->id.name,"Playback Mono To Stereo" )) { - i2s->mono_to_stereo[I2S_RX_PATH ] = - ucontrol->value.enumerated.item[0 ]; - }else if (strstr (kcontrol->id.name,"Playback FIFO Threshold" )) { - i2s->rx_fifo_th = ucontrol->value.integer.value[0 ]; - }else if (strstr (kcontrol->id.name,"BCLK Ratio" )) { - i2s->bclk_ratio = ucontrol->value.integer.value[0 ]; - } +if (value == i2s->loopback) +return 0 ; + + i2s->loopback = value; + +regmap_update_bits (i2s->regmap,TEGRA210_I2S_CTRL ,I2S_CTRL_LPBK_MASK , + i2s->loopback <<I2S_CTRL_LPBK_SHIFT ); + +return 1 ; +} + +static int tegra210_i2s_get_fsync_width (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *compnt =snd_soc_kcontrol_component (kcontrol); +struct tegra210_i2s *i2s =snd_soc_component_get_drvdata (compnt); + + ucontrol->value.integer.value[0 ] = i2s->fsync_width; + +return 0 ; +} + +static int tegra210_i2s_put_fsync_width (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *compnt =snd_soc_kcontrol_component (kcontrol); +struct tegra210_i2s *i2s =snd_soc_component_get_drvdata (compnt); +int value = ucontrol->value.integer.value[0 ]; + +if (value == i2s->fsync_width) +return 0 ; + + i2s->fsync_width = value; + +/* +* Frame sync width is used only for FSYNC modes and not +* applicable for LRCK modes. Reset value for this field is "0", +* which means the width is one bit clock wide. +* The width requirement may depend on the codec and in such +* cases mixer control is used to update custom values. A value +* of "N" here means, width is "N + 1" bit clock wide. +*/ +regmap_update_bits (i2s->regmap,TEGRA210_I2S_CTRL , +I2S_CTRL_FSYNC_WIDTH_MASK , + i2s->fsync_width <<I2S_FSYNC_WIDTH_SHIFT ); + +return 1 ; +} + +static int tegra210_i2s_cget_stereo_to_mono (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *compnt =snd_soc_kcontrol_component (kcontrol); +struct tegra210_i2s *i2s =snd_soc_component_get_drvdata (compnt); + + ucontrol->value.enumerated.item[0 ] = i2s->stereo_to_mono[I2S_TX_PATH ]; + +return 0 ; +} + +static int tegra210_i2s_cput_stereo_to_mono (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *compnt =snd_soc_kcontrol_component (kcontrol); +struct tegra210_i2s *i2s =snd_soc_component_get_drvdata (compnt); +unsigned int value = ucontrol->value.enumerated.item[0 ]; + +if (value == i2s->stereo_to_mono[I2S_TX_PATH ]) +return 0 ; + + i2s->stereo_to_mono[I2S_TX_PATH ] = value; + +return 1 ; +} + +static int tegra210_i2s_cget_mono_to_stereo (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *compnt =snd_soc_kcontrol_component (kcontrol); +struct tegra210_i2s *i2s =snd_soc_component_get_drvdata (compnt); + + ucontrol->value.enumerated.item[0 ] = i2s->mono_to_stereo[I2S_TX_PATH ]; + +return 0 ; +} + +static int tegra210_i2s_cput_mono_to_stereo (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *compnt =snd_soc_kcontrol_component (kcontrol); +struct tegra210_i2s *i2s =snd_soc_component_get_drvdata (compnt); +unsigned int value = ucontrol->value.enumerated.item[0 ]; + +if (value == i2s->mono_to_stereo[I2S_TX_PATH ]) +return 0 ; + + i2s->mono_to_stereo[I2S_TX_PATH ] = value; + +return 1 ; +} + +static int tegra210_i2s_pget_stereo_to_mono (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *compnt =snd_soc_kcontrol_component (kcontrol); +struct tegra210_i2s *i2s =snd_soc_component_get_drvdata (compnt); + + ucontrol->value.enumerated.item[0 ] = i2s->stereo_to_mono[I2S_RX_PATH ]; + +return 0 ; +} + +static int tegra210_i2s_pput_stereo_to_mono (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *compnt =snd_soc_kcontrol_component (kcontrol); +struct tegra210_i2s *i2s =snd_soc_component_get_drvdata (compnt); +unsigned int value = ucontrol->value.enumerated.item[0 ]; + +if (value == i2s->stereo_to_mono[I2S_RX_PATH ]) +return 0 ; + + i2s->stereo_to_mono[I2S_RX_PATH ] = value; + +return 1 ; +} + +static int tegra210_i2s_pget_mono_to_stereo (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *compnt =snd_soc_kcontrol_component (kcontrol); +struct tegra210_i2s *i2s =snd_soc_component_get_drvdata (compnt); + + ucontrol->value.enumerated.item[0 ] = i2s->mono_to_stereo[I2S_RX_PATH ]; + +return 0 ; +} + +static int tegra210_i2s_pput_mono_to_stereo (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *compnt =snd_soc_kcontrol_component (kcontrol); +struct tegra210_i2s *i2s =snd_soc_component_get_drvdata (compnt); +unsigned int value = ucontrol->value.enumerated.item[0 ]; + +if (value == i2s->mono_to_stereo[I2S_RX_PATH ]) +return 0 ; + + i2s->mono_to_stereo[I2S_RX_PATH ] = value; + +return 1 ; +} + +static int tegra210_i2s_pget_fifo_th (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *compnt =snd_soc_kcontrol_component (kcontrol); +struct tegra210_i2s *i2s =snd_soc_component_get_drvdata (compnt); + + ucontrol->value.integer.value[0 ] = i2s->rx_fifo_th; + +return 0 ; +} + +static int tegra210_i2s_pput_fifo_th (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *compnt =snd_soc_kcontrol_component (kcontrol); +struct tegra210_i2s *i2s =snd_soc_component_get_drvdata (compnt); +int value = ucontrol->value.integer.value[0 ]; + +if (value == i2s->rx_fifo_th) +return 0 ; + + i2s->rx_fifo_th = value; + +return 1 ; +} + +static int tegra210_i2s_get_bclk_ratio (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *compnt =snd_soc_kcontrol_component (kcontrol); +struct tegra210_i2s *i2s =snd_soc_component_get_drvdata (compnt); + + ucontrol->value.integer.value[0 ] = i2s->bclk_ratio; + +return 0 ; +} + +static int tegra210_i2s_put_bclk_ratio (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *compnt =snd_soc_kcontrol_component (kcontrol); +struct tegra210_i2s *i2s =snd_soc_component_get_drvdata (compnt); +int value = ucontrol->value.integer.value[0 ]; + +if (value == i2s->bclk_ratio) +return 0 ; + + i2s->bclk_ratio = value; + +return 1 ; +} + +static int tegra210_i2s_set_dai_bclk_ratio (struct snd_soc_dai *dai, +unsigned int ratio) +{ +struct tegra210_i2s *i2s =snd_soc_dai_get_drvdata (dai); + + i2s->bclk_ratio = ratio;return 0 ; }
@@ -604,22 +748,28 @@ static const struct soc_enum tegra210_i2 tegra210_i2s_stereo_conv_text);static const struct snd_kcontrol_new tegra210_i2s_controls[] = { -SOC_SINGLE_EXT ("Loopback" ,0 ,0 ,1 ,0 , tegra210_i2s_get_control, - tegra210_i2s_put_control), -SOC_SINGLE_EXT ("FSYNC Width" ,0 ,0 ,255 ,0 , tegra210_i2s_get_control, - tegra210_i2s_put_control), +SOC_SINGLE_EXT ("Loopback" ,0 ,0 ,1 ,0 , tegra210_i2s_get_loopback, + tegra210_i2s_put_loopback), +SOC_SINGLE_EXT ("FSYNC Width" ,0 ,0 ,255 ,0 , + tegra210_i2s_get_fsync_width, + tegra210_i2s_put_fsync_width),SOC_ENUM_EXT ("Capture Stereo To Mono" , tegra210_i2s_stereo_conv_enum, - tegra210_i2s_get_control, tegra210_i2s_put_control), + tegra210_i2s_cget_stereo_to_mono, + tegra210_i2s_cput_stereo_to_mono),SOC_ENUM_EXT ("Capture Mono To Stereo" , tegra210_i2s_mono_conv_enum, - tegra210_i2s_get_control, tegra210_i2s_put_control), + tegra210_i2s_cget_mono_to_stereo, + tegra210_i2s_cput_mono_to_stereo),SOC_ENUM_EXT ("Playback Stereo To Mono" , tegra210_i2s_stereo_conv_enum, - tegra210_i2s_get_control, tegra210_i2s_put_control), + tegra210_i2s_pget_mono_to_stereo, + tegra210_i2s_pput_mono_to_stereo),SOC_ENUM_EXT ("Playback Mono To Stereo" , tegra210_i2s_mono_conv_enum, - tegra210_i2s_get_control, tegra210_i2s_put_control), + tegra210_i2s_pget_stereo_to_mono, + tegra210_i2s_pput_stereo_to_mono),SOC_SINGLE_EXT ("Playback FIFO Threshold" ,0 ,0 ,I2S_RX_FIFO_DEPTH -1 , -0 , tegra210_i2s_get_control, tegra210_i2s_put_control), -SOC_SINGLE_EXT ("BCLK Ratio" ,0 ,0 ,INT_MAX ,0 , tegra210_i2s_get_control, - tegra210_i2s_put_control), +0 , tegra210_i2s_pget_fifo_th, tegra210_i2s_pput_fifo_th), +SOC_SINGLE_EXT ("BCLK Ratio" ,0 ,0 ,INT_MAX ,0 , + tegra210_i2s_get_bclk_ratio, + tegra210_i2s_put_bclk_ratio), };static const struct snd_soc_dapm_widget tegra210_i2s_widgets[] = {
Greg Kroah-Hartman
maintainerPATCH 121/207 ASoC: tegra: Fix kcontrol put callback in DMIC
In reply to Greg Kroah-HartmanFrom: Sameer Pujar <[email protected]>
commit a347dfa10262fa0a10e2b1970ea0194e3d4a3251 upstream.
The kcontrol put callback is expected to return 1 when there is change in HW or when the update is acknowledged by driver. This would ensure that change notifications are sent to subscribed applications. Update the DMIC driver accordingly.
--- sound/soc/tegra/tegra210_dmic.c | 183 ++++++++++++++++++++++++++++++++-------- 1 file changed, 149 insertions(+), 34 deletions(-)
sound/soc/tegra/tegra210_dmic.c +149 -34
@@ -156,50 +156,162 @@ static int tegra210_dmic_hw_params(strucreturn 0 ; } -static int tegra210_dmic_get_control (struct snd_kcontrol *kcontrol, +static int tegra210_dmic_get_boost_gain (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *comp =snd_soc_kcontrol_component (kcontrol); +struct tegra210_dmic *dmic =snd_soc_component_get_drvdata (comp); + + ucontrol->value.integer.value[0 ] = dmic->boost_gain; + +return 0 ; +} + +static int tegra210_dmic_put_boost_gain (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *comp =snd_soc_kcontrol_component (kcontrol); +struct tegra210_dmic *dmic =snd_soc_component_get_drvdata (comp); +int value = ucontrol->value.integer.value[0 ]; + +if (value == dmic->boost_gain) +return 0 ; + + dmic->boost_gain = value; + +return 1 ; +} + +static int tegra210_dmic_get_ch_select (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *comp =snd_soc_kcontrol_component (kcontrol); +struct tegra210_dmic *dmic =snd_soc_component_get_drvdata (comp); + + ucontrol->value.enumerated.item[0 ] = dmic->ch_select; + +return 0 ; +} + +static int tegra210_dmic_put_ch_select (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *comp =snd_soc_kcontrol_component (kcontrol); +struct tegra210_dmic *dmic =snd_soc_component_get_drvdata (comp); +unsigned int value = ucontrol->value.enumerated.item[0 ]; + +if (value == dmic->ch_select) +return 0 ; + + dmic->ch_select = value; + +return 1 ; +} + +static int tegra210_dmic_get_mono_to_stereo (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *comp =snd_soc_kcontrol_component (kcontrol); +struct tegra210_dmic *dmic =snd_soc_component_get_drvdata (comp); + + ucontrol->value.enumerated.item[0 ] = dmic->mono_to_stereo; + +return 0 ; +} + +static int tegra210_dmic_put_mono_to_stereo (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *comp =snd_soc_kcontrol_component (kcontrol); +struct tegra210_dmic *dmic =snd_soc_component_get_drvdata (comp); +unsigned int value = ucontrol->value.enumerated.item[0 ]; + +if (value == dmic->mono_to_stereo) +return 0 ; + + dmic->mono_to_stereo = value; + +return 1 ; +} + +static int tegra210_dmic_get_stereo_to_mono (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *comp =snd_soc_kcontrol_component (kcontrol); +struct tegra210_dmic *dmic =snd_soc_component_get_drvdata (comp); + + ucontrol->value.enumerated.item[0 ] = dmic->stereo_to_mono; + +return 0 ; +} + +static int tegra210_dmic_put_stereo_to_mono (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *comp =snd_soc_kcontrol_component (kcontrol); +struct tegra210_dmic *dmic =snd_soc_component_get_drvdata (comp); +unsigned int value = ucontrol->value.enumerated.item[0 ]; + +if (value == dmic->stereo_to_mono) +return 0 ; + + dmic->stereo_to_mono = value; + +return 1 ; +} + +static int tegra210_dmic_get_osr_val (struct snd_kcontrol *kcontrol,struct snd_ctl_elem_value *ucontrol) {struct snd_soc_component *comp =snd_soc_kcontrol_component (kcontrol);struct tegra210_dmic *dmic =snd_soc_component_get_drvdata (comp); -if (strstr (kcontrol->id.name,"Boost Gain Volume" )) - ucontrol->value.integer.value[0 ] = dmic->boost_gain; -else if (strstr (kcontrol->id.name,"Channel Select" )) - ucontrol->value.enumerated.item[0 ] = dmic->ch_select; -else if (strstr (kcontrol->id.name,"Mono To Stereo" )) - ucontrol->value.enumerated.item[0 ] = dmic->mono_to_stereo; -else if (strstr (kcontrol->id.name,"Stereo To Mono" )) - ucontrol->value.enumerated.item[0 ] = dmic->stereo_to_mono; -else if (strstr (kcontrol->id.name,"OSR Value" )) - ucontrol->value.enumerated.item[0 ] = dmic->osr_val; -else if (strstr (kcontrol->id.name,"LR Polarity Select" )) - ucontrol->value.enumerated.item[0 ] = dmic->lrsel; + ucontrol->value.enumerated.item[0 ] = dmic->osr_val;return 0 ; } -static int tegra210_dmic_put_control (struct snd_kcontrol *kcontrol, +static int tegra210_dmic_put_osr_val (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *comp =snd_soc_kcontrol_component (kcontrol); +struct tegra210_dmic *dmic =snd_soc_component_get_drvdata (comp); +unsigned int value = ucontrol->value.enumerated.item[0 ]; + +if (value == dmic->osr_val) +return 0 ; + + dmic->osr_val = value; + +return 1 ; +} + +static int tegra210_dmic_get_pol_sel (struct snd_kcontrol *kcontrol,struct snd_ctl_elem_value *ucontrol) {struct snd_soc_component *comp =snd_soc_kcontrol_component (kcontrol);struct tegra210_dmic *dmic =snd_soc_component_get_drvdata (comp); -if (strstr (kcontrol->id.name,"Boost Gain Volume" )) - dmic->boost_gain = ucontrol->value.integer.value[0 ]; -else if (strstr (kcontrol->id.name,"Channel Select" )) - dmic->ch_select = ucontrol->value.enumerated.item[0 ]; -else if (strstr (kcontrol->id.name,"Mono To Stereo" )) - dmic->mono_to_stereo = ucontrol->value.enumerated.item[0 ]; -else if (strstr (kcontrol->id.name,"Stereo To Mono" )) - dmic->stereo_to_mono = ucontrol->value.enumerated.item[0 ]; -else if (strstr (kcontrol->id.name,"OSR Value" )) - dmic->osr_val = ucontrol->value.enumerated.item[0 ]; -else if (strstr (kcontrol->id.name,"LR Polarity Select" )) - dmic->lrsel = ucontrol->value.enumerated.item[0 ]; + ucontrol->value.enumerated.item[0 ] = dmic->lrsel;return 0 ; } +static int tegra210_dmic_put_pol_sel (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *comp =snd_soc_kcontrol_component (kcontrol); +struct tegra210_dmic *dmic =snd_soc_component_get_drvdata (comp); +unsigned int value = ucontrol->value.enumerated.item[0 ]; + +if (value == dmic->lrsel) +return 0 ; + + dmic->lrsel = value; + +return 1 ; +} +static const struct snd_soc_dai_ops tegra210_dmic_dai_ops = { .hw_params = tegra210_dmic_hw_params, };
@@ -286,19 +398,22 @@ static const struct soc_enum tegra210_dmstatic const struct snd_kcontrol_new tegra210_dmic_controls[] = {SOC_SINGLE_EXT ("Boost Gain Volume" ,0 ,0 ,MAX_BOOST_GAIN ,0 , - tegra210_dmic_get_control, tegra210_dmic_put_control), + tegra210_dmic_get_boost_gain, + tegra210_dmic_put_boost_gain),SOC_ENUM_EXT ("Channel Select" , tegra210_dmic_ch_enum, - tegra210_dmic_get_control, tegra210_dmic_put_control), + tegra210_dmic_get_ch_select, tegra210_dmic_put_ch_select),SOC_ENUM_EXT ("Mono To Stereo" , - tegra210_dmic_mono_conv_enum, tegra210_dmic_get_control, - tegra210_dmic_put_control), + tegra210_dmic_mono_conv_enum, + tegra210_dmic_get_mono_to_stereo, + tegra210_dmic_put_mono_to_stereo),SOC_ENUM_EXT ("Stereo To Mono" , - tegra210_dmic_stereo_conv_enum, tegra210_dmic_get_control, - tegra210_dmic_put_control), + tegra210_dmic_stereo_conv_enum, + tegra210_dmic_get_stereo_to_mono, + tegra210_dmic_put_stereo_to_mono),SOC_ENUM_EXT ("OSR Value" , tegra210_dmic_osr_enum, - tegra210_dmic_get_control, tegra210_dmic_put_control), + tegra210_dmic_get_osr_val, tegra210_dmic_put_osr_val),SOC_ENUM_EXT ("LR Polarity Select" , tegra210_dmic_lrsel_enum, - tegra210_dmic_get_control, tegra210_dmic_put_control), + tegra210_dmic_get_pol_sel, tegra210_dmic_put_pol_sel), };static const struct snd_soc_component_driver tegra210_dmic_compnt = {
Greg Kroah-Hartman
maintainerPATCH 122/207 ASoC: tegra: Fix kcontrol put callback in DSPK
In reply to Greg Kroah-HartmanFrom: Sameer Pujar <[email protected]>
commit d6202a57e79d102271d38c34481fedc9d4c79694 upstream.
The kcontrol put callback is expected to return 1 when there is change in HW or when the update is acknowledged by driver. This would ensure that change notifications are sent to subscribed applications. Update the DSPK driver accordingly.
--- sound/soc/tegra/tegra186_dspk.c | 178 ++++++++++++++++++++++++++++++++-------- 1 file changed, 146 insertions(+), 32 deletions(-)
sound/soc/tegra/tegra186_dspk.c +146 -32
@@ -26,50 +26,162 @@ static const struct reg_default tegra186 { TEGRA186_DSPK_CODEC_CTRL, 0x03000000 }, }; -static int tegra186_dspk_get_control (struct snd_kcontrol *kcontrol, +static int tegra186_dspk_get_fifo_th (struct snd_kcontrol *kcontrol,struct snd_ctl_elem_value *ucontrol) {struct snd_soc_component *codec =snd_soc_kcontrol_component (kcontrol);struct tegra186_dspk *dspk =snd_soc_component_get_drvdata (codec); -if (strstr (kcontrol->id.name,"FIFO Threshold" )) - ucontrol->value.integer.value[0 ] = dspk->rx_fifo_th; -else if (strstr (kcontrol->id.name,"OSR Value" )) - ucontrol->value.enumerated.item[0 ] = dspk->osr_val; -else if (strstr (kcontrol->id.name,"LR Polarity Select" )) - ucontrol->value.enumerated.item[0 ] = dspk->lrsel; -else if (strstr (kcontrol->id.name,"Channel Select" )) - ucontrol->value.enumerated.item[0 ] = dspk->ch_sel; -else if (strstr (kcontrol->id.name,"Mono To Stereo" )) - ucontrol->value.enumerated.item[0 ] = dspk->mono_to_stereo; -else if (strstr (kcontrol->id.name,"Stereo To Mono" )) - ucontrol->value.enumerated.item[0 ] = dspk->stereo_to_mono; + ucontrol->value.integer.value[0 ] = dspk->rx_fifo_th;return 0 ; } -static int tegra186_dspk_put_control (struct snd_kcontrol *kcontrol, +static int tegra186_dspk_put_fifo_th (struct snd_kcontrol *kcontrol,struct snd_ctl_elem_value *ucontrol) {struct snd_soc_component *codec =snd_soc_kcontrol_component (kcontrol);struct tegra186_dspk *dspk =snd_soc_component_get_drvdata (codec); +int value = ucontrol->value.integer.value[0 ]; -if (strstr (kcontrol->id.name,"FIFO Threshold" )) - dspk->rx_fifo_th = ucontrol->value.integer.value[0 ]; -else if (strstr (kcontrol->id.name,"OSR Value" )) - dspk->osr_val = ucontrol->value.enumerated.item[0 ]; -else if (strstr (kcontrol->id.name,"LR Polarity Select" )) - dspk->lrsel = ucontrol->value.enumerated.item[0 ]; -else if (strstr (kcontrol->id.name,"Channel Select" )) - dspk->ch_sel = ucontrol->value.enumerated.item[0 ]; -else if (strstr (kcontrol->id.name,"Mono To Stereo" )) - dspk->mono_to_stereo = ucontrol->value.enumerated.item[0 ]; -else if (strstr (kcontrol->id.name,"Stereo To Mono" )) - dspk->stereo_to_mono = ucontrol->value.enumerated.item[0 ]; +if (value == dspk->rx_fifo_th) +return 0 ; + + dspk->rx_fifo_th = value; + +return 1 ; +} + +static int tegra186_dspk_get_osr_val (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *codec =snd_soc_kcontrol_component (kcontrol); +struct tegra186_dspk *dspk =snd_soc_component_get_drvdata (codec); + + ucontrol->value.enumerated.item[0 ] = dspk->osr_val; + +return 0 ; +} + +static int tegra186_dspk_put_osr_val (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *codec =snd_soc_kcontrol_component (kcontrol); +struct tegra186_dspk *dspk =snd_soc_component_get_drvdata (codec); +unsigned int value = ucontrol->value.enumerated.item[0 ]; + +if (value == dspk->osr_val) +return 0 ; + + dspk->osr_val = value; + +return 1 ; +} + +static int tegra186_dspk_get_pol_sel (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *codec =snd_soc_kcontrol_component (kcontrol); +struct tegra186_dspk *dspk =snd_soc_component_get_drvdata (codec); + + ucontrol->value.enumerated.item[0 ] = dspk->lrsel; + +return 0 ; +} + +static int tegra186_dspk_put_pol_sel (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *codec =snd_soc_kcontrol_component (kcontrol); +struct tegra186_dspk *dspk =snd_soc_component_get_drvdata (codec); +unsigned int value = ucontrol->value.enumerated.item[0 ]; + +if (value == dspk->lrsel) +return 0 ; + + dspk->lrsel = value; + +return 1 ; +} + +static int tegra186_dspk_get_ch_sel (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *codec =snd_soc_kcontrol_component (kcontrol); +struct tegra186_dspk *dspk =snd_soc_component_get_drvdata (codec); + + ucontrol->value.enumerated.item[0 ] = dspk->ch_sel; + +return 0 ; +} + +static int tegra186_dspk_put_ch_sel (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *codec =snd_soc_kcontrol_component (kcontrol); +struct tegra186_dspk *dspk =snd_soc_component_get_drvdata (codec); +unsigned int value = ucontrol->value.enumerated.item[0 ]; + +if (value == dspk->ch_sel) +return 0 ; + + dspk->ch_sel = value; + +return 1 ; +} + +static int tegra186_dspk_get_mono_to_stereo (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *codec =snd_soc_kcontrol_component (kcontrol); +struct tegra186_dspk *dspk =snd_soc_component_get_drvdata (codec); + + ucontrol->value.enumerated.item[0 ] = dspk->mono_to_stereo; + +return 0 ; +} + +static int tegra186_dspk_put_mono_to_stereo (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *codec =snd_soc_kcontrol_component (kcontrol); +struct tegra186_dspk *dspk =snd_soc_component_get_drvdata (codec); +unsigned int value = ucontrol->value.enumerated.item[0 ]; + +if (value == dspk->mono_to_stereo) +return 0 ; + + dspk->mono_to_stereo = value; + +return 1 ; +} + +static int tegra186_dspk_get_stereo_to_mono (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *codec =snd_soc_kcontrol_component (kcontrol); +struct tegra186_dspk *dspk =snd_soc_component_get_drvdata (codec); + + ucontrol->value.enumerated.item[0 ] = dspk->stereo_to_mono;return 0 ; } +static int tegra186_dspk_put_stereo_to_mono (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *codec =snd_soc_kcontrol_component (kcontrol); +struct tegra186_dspk *dspk =snd_soc_component_get_drvdata (codec); +unsigned int value = ucontrol->value.enumerated.item[0 ]; + +if (value == dspk->stereo_to_mono) +return 0 ; + + dspk->stereo_to_mono = value; + +return 1 ; +} +static int __maybe_unused tegra186_dspk_runtime_suspend (struct device *dev) {struct tegra186_dspk *dspk =dev_get_drvdata (dev);
@@ -278,17 +390,19 @@ static const struct soc_enum tegra186_dsstatic const struct snd_kcontrol_new tegrat186_dspk_controls[] = {SOC_SINGLE_EXT ("FIFO Threshold" ,SND_SOC_NOPM ,0 ,TEGRA186_DSPK_RX_FIFO_DEPTH -1 ,0 , - tegra186_dspk_get_control, tegra186_dspk_put_control), + tegra186_dspk_get_fifo_th, tegra186_dspk_put_fifo_th),SOC_ENUM_EXT ("OSR Value" , tegra186_dspk_osr_enum, - tegra186_dspk_get_control, tegra186_dspk_put_control), + tegra186_dspk_get_osr_val, tegra186_dspk_put_osr_val),SOC_ENUM_EXT ("LR Polarity Select" , tegra186_dspk_lrsel_enum, - tegra186_dspk_get_control, tegra186_dspk_put_control), + tegra186_dspk_get_pol_sel, tegra186_dspk_put_pol_sel),SOC_ENUM_EXT ("Channel Select" , tegra186_dspk_ch_sel_enum, - tegra186_dspk_get_control, tegra186_dspk_put_control), + tegra186_dspk_get_ch_sel, tegra186_dspk_put_ch_sel),SOC_ENUM_EXT ("Mono To Stereo" , tegra186_dspk_mono_conv_enum, - tegra186_dspk_get_control, tegra186_dspk_put_control), + tegra186_dspk_get_mono_to_stereo, + tegra186_dspk_put_mono_to_stereo),SOC_ENUM_EXT ("Stereo To Mono" , tegra186_dspk_stereo_conv_enum, - tegra186_dspk_get_control, tegra186_dspk_put_control), + tegra186_dspk_get_stereo_to_mono, + tegra186_dspk_put_stereo_to_mono), };static const struct snd_soc_component_driver tegra186_dspk_cmpnt = {
Greg Kroah-Hartman
maintainerPATCH 123/207 ASoC: tegra: Fix kcontrol put callback in AHUB
In reply to Greg Kroah-HartmanFrom: Sameer Pujar <[email protected]>
commit a4e37950c9e9b126f9cbee79b8ab94a94646dcf1 upstream.
The kcontrol put callback is expected to return 1 when there is change in HW or when the update is acknowledged by driver. This would ensure that change notifications are sent to subscribed applications. Update the AHUB driver accordingly.
--- sound/soc/tegra/tegra210_ahub.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
sound/soc/tegra/tegra210_ahub.c +7 -4
@@ -62,6 +62,7 @@ static int tegra_ahub_put_value_enum(strunsigned int *item = uctl->value.enumerated.item;unsigned int value = e->values[item[0 ]];unsigned int i, bit_pos, reg_idx =0 , reg_val =0 ; +int change =0 ;if (item[0 ] >= e->items)return -EINVAL ;
@@ -86,12 +87,14 @@ static int tegra_ahub_put_value_enum(str/* Update widget power if state has changed */ if (snd_soc_component_test_bits (cmpnt, update[i].reg, - update[i].mask, update[i].val)) -snd_soc_dapm_mux_update_power (dapm, kctl, item[0 ], e, - &update[i]); + update[i].mask, + update[i].val)) + change |=snd_soc_dapm_mux_update_power (dapm, kctl, + item[0 ], e, + &update[i]); } -return 0 ; +return change; }static struct snd_soc_dai_driver tegra210_ahub_dais[] = {
Greg Kroah-Hartman
maintainerPATCH 124/207 rxrpc: Fix rxrpc_peer leak in rxrpc_look_up_bundle()
In reply to Greg Kroah-HartmanFrom: Eiichi Tsukata <[email protected]>
commit ca77fba821351190777b236ce749d7c4d353102e upstream.
Need to call rxrpc_put_peer() for bundle candidate before kfree() as it holds a ref to rxrpc_peer.
[DH: v2: Changed to abstract out the bundle freeing code into a function]
--- net/rxrpc/conn_client.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
net/rxrpc/conn_client.c +9 -5
@@ -135,16 +135,20 @@ struct rxrpc_bundle *rxrpc_get_bundle(streturn bundle; } +static void rxrpc_free_bundle (struct rxrpc_bundle *bundle) +{ +rxrpc_put_peer (bundle->params.peer); +kfree (bundle); +} +void rxrpc_put_bundle (struct rxrpc_bundle *bundle) {unsigned int d = bundle->debug_id;unsigned int u =atomic_dec_return (&bundle->usage);_debug ("PUT B=%x %u" , d, u); -if (u ==0 ) { -rxrpc_put_peer (bundle->params.peer); -kfree (bundle); - } +if (u ==0 ) +rxrpc_free_bundle (bundle); }/*
@@ -328,7 +332,7 @@ static struct rxrpc_bundle *rxrpc_look_ureturn candidate; found_bundle_free: -kfree (candidate); +rxrpc_free_bundle (candidate); found_bundle:rxrpc_get_bundle (bundle);spin_unlock (&local->client_bundles_lock);
Greg Kroah-Hartman
maintainerPATCH 125/207 rxrpc: Fix rxrpc_local leak in rxrpc_lookup_peer()
In reply to Greg Kroah-HartmanFrom: Eiichi Tsukata <[email protected]>
commit beacff50edbd6c9659a6f15fc7f6126909fade29 upstream.
Need to call rxrpc_put_local() for peer candidate before kfree() as it holds a ref to rxrpc_local.
[DH: v2: Changed to abstract the peer freeing code out into a function]
--- net/rxrpc/peer_object.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
net/rxrpc/peer_object.c +9 -5
@@ -299,6 +299,12 @@ static struct rxrpc_peer *rxrpc_create_preturn peer; } +static void rxrpc_free_peer (struct rxrpc_peer *peer) +{ +rxrpc_put_local (peer->local); +kfree_rcu (peer, rcu); +} +/* * Set up a new incoming peer. There shouldn't be any other matching peers * since we've already done a search in the list from the non-reentrant context
@@ -365,7 +371,7 @@ struct rxrpc_peer *rxrpc_lookup_peer(strspin_unlock_bh (&rxnet->peer_hash_lock);if (peer) -kfree (candidate); +rxrpc_free_peer (candidate);else peer = candidate; }
@@ -420,8 +426,7 @@ static void __rxrpc_put_peer(struct rxrplist_del_init (&peer->keepalive_link);spin_unlock_bh (&rxnet->peer_hash_lock); -rxrpc_put_local (peer->local); -kfree_rcu (peer, rcu); +rxrpc_free_peer (peer); }/*
@@ -457,8 +462,7 @@ void rxrpc_put_peer_locked(struct rxrpc_if (n ==0 ) {hash_del_rcu (&peer->hash_link);list_del_init (&peer->keepalive_link); -rxrpc_put_local (peer->local); -kfree_rcu (peer, rcu); +rxrpc_free_peer (peer); } }
Greg Kroah-Hartman
maintainerPATCH 126/207 ALSA: intel-dsp-config: add quirk for CML devices based on ES8336 codec
In reply to Greg Kroah-HartmanFrom: Pierre-Louis Bossart <[email protected]>
commit ae26c08e6c8071ba8febb0c7c0829da96c75248c upstream.
We've added quirks for ESS8336 but missed CML, add quirks for both LP and H versions.
--- sound/hda/intel-dsp-config.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
sound/hda/intel-dsp-config.c +10 -0
@@ -252,6 +252,11 @@ static const struct config_entry config_ .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, .device = 0x02c8, }, + { + .flags = FLAG_SOF, + .device = 0x02c8, + .codec_hid = "ESSX8336", + },/* Cometlake-H */ { .flags = FLAG_SOF,
@@ -276,6 +281,11 @@ static const struct config_entry config_ .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, .device = 0x06c8, }, + { + .flags = FLAG_SOF, + .device = 0x06c8, + .codec_hid = "ESSX8336", + },#endif /* Icelake */
Greg Kroah-Hartman
maintainerPATCH 127/207 net: stmmac: Avoid DMA_CHAN_CONTROL write if no Split Header support
In reply to Greg Kroah-HartmanFrom: Vincent Whitchurch <[email protected]>
commit f8e7dfd6fdabb831846ab1970a875746559d491b upstream.
The driver assumes that split headers can be enabled/disabled without stopping/starting the device, so it writes DMA_CHAN_CONTROL from stmmac_set_features(). However, on my system (IP v5.10a without Split Header support), simply writing DMA_CHAN_CONTROL when DMA is running (for example, with the commands below) leads to a TX watchdog timeout.
host$ socat TCP-LISTEN:1024,fork,reuseaddr - & device$ ethtool -K eth0 tso off
device$ ethtool -K eth0 tso on
device$ dd if=/dev/zero bs=1M count=10 | socat - TCP4:host:1024 <tx watchdog timeout>
Note that since my IP is configured without Split Header support, the driver always just reads and writes the same value to the DMA_CHAN_CONTROL register.
I don't have access to any platforms with Split Header support so I don't know if these writes to the DMA_CHAN_CONTROL while DMA is running actually work properly on such systems. I could not find anything in the databook that says that DMA_CHAN_CONTROL should not be written when the DMA is running.
But on systems without Split Header support, there is in any case no need to call enable_sph() in stmmac_set_features() at all since SPH can never be toggled, so we can avoid the watchdog timeout there by skipping this call.
--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +6 -5
@@ -5531,8 +5531,6 @@ static int stmmac_set_features(struct ne netdev_features_t features) {struct stmmac_priv *priv =netdev_priv (netdev); -bool sph_en; -u32 chan;/* Keep the COE Type in case of csum is supporting */ if (features &NETIF_F_RXCSUM )
@@ -5544,10 +5542,13 @@ static int stmmac_set_features(struct ne*/ stmmac_rx_ipc (priv, priv->hw); - sph_en = (priv->hw->rx_csum >0 ) && priv->sph; +if (priv->sph_cap) { +bool sph_en = (priv->hw->rx_csum >0 ) && priv->sph; +u32 chan; -for (chan =0 ; chan < priv->plat->rx_queues_to_use; chan++) -stmmac_enable_sph (priv, priv->ioaddr, sph_en, chan); +for (chan =0 ; chan < priv->plat->rx_queues_to_use; chan++) +stmmac_enable_sph (priv, priv->ioaddr, sph_en, chan); + }return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 128/207 net: usb: lan78xx: lan78xx_phy_init(): use PHY_POLL instead of "0" if no IRQ is available
In reply to Greg Kroah-HartmanFrom: Sven Schuchmann <[email protected]>
commit 817b653160db9852d5a0498a31f047e18ce27e5b upstream.
On most systems request for IRQ 0 will fail, phylib will print an error message and fall back to polling. To fix this set the phydev->irq to PHY_POLL if no IRQ is available.
--- drivers/net/usb/lan78xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/usb/lan78xx.c +1 -1
@@ -2228,7 +2228,7 @@ static int lan78xx_phy_init(struct lan78if (dev->domain_data.phyirq >0 ) phydev->irq = dev->domain_data.phyirq;else - phydev->irq =0 ; + phydev->irq =PHY_POLL ;netdev_dbg (dev->net,"phydev->irq = %d\n" , phydev->irq);/* set to AUTOMDIX */
Greg Kroah-Hartman
maintainerPATCH 129/207 net: marvell: mvpp2: Fix the computation of shared CPUs
In reply to Greg Kroah-HartmanFrom: Christophe JAILLET <[email protected]>
commit b83f5ac7d922e69a109261f5f940eebbd4e514c4 upstream.
'bitmap_fill()' fills a bitmap one 'long' at a time. It is likely that an exact number of bits is expected.
Use 'bitmap_set()' instead in order not to set unexpected bits.
--- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +1 -1
@@ -7457,7 +7457,7 @@ static int mvpp2_probe(struct platform_d shared =num_present_cpus () - priv->nthreads;if (shared >0 ) -bitmap_fill (&priv->lock_map, +bitmap_set (&priv->lock_map,0 ,min_t (int, shared,MVPP2_MAX_THREADS ));for (i =0 ; i <MVPP2_MAX_THREADS ; i++) {
Greg Kroah-Hartman
maintainerPATCH 130/207 dpaa2-eth: destroy workqueue at the end of remove function
In reply to Greg Kroah-HartmanFrom: Dongliang Mu <[email protected]>
commit f4a8adbfe4841491b60c14fe610571e1422359f9 upstream.
The commit c55211892f46 ("dpaa2-eth: support PTP Sync packet one-step timestamping") forgets to destroy workqueue at the end of remove function.
Fix this by adding destroy_workqueue before fsl_mc_portal_free and free_netdev.
--- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +2 -0
@@ -4538,6 +4538,8 @@ static int dpaa2_eth_remove(struct fsl_mfsl_mc_portal_free (priv->mc_io); +destroy_workqueue (priv->dpaa2_ptp_wq); +dev_dbg (net_dev->dev.parent,"Removed interface %s\n" , net_dev->name);free_netdev (net_dev);
Greg Kroah-Hartman
maintainerPATCH 131/207 octeontx2-af: Fix a memleak bug in rvu_mbox_init()
In reply to Greg Kroah-HartmanFrom: Zhou Qingyang <[email protected]>
commit e07a097b4986afb8f925d0bb32612e1d3e88ce15 upstream.
In rvu_mbox_init(), mbox_regions is not freed or passed out under the switch-default region, which could lead to a memory leak.
Fix this bug by changing 'return err' to 'goto free_regions'.
This bug was found by a static analyzer. The analysis employs differential checking to identify inconsistent security operations (e.g., checks or kfrees) between two code paths and confirms that the inconsistent operations are not recovered in the current function or the callers, so they constitute bugs.
Note that, as a bug found by static analysis, it can be a false positive or hard to trigger. Multiple researchers have cross-reviewed the bug.
Builds with CONFIG_OCTEONTX2_AF=y show no new warnings, and our static analyzer no longer warns about this code.
--- drivers/net/ethernet/marvell/octeontx2/af/rvu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/marvell/octeontx2/af/rvu.c +1 -1
@@ -2281,7 +2281,7 @@ static int rvu_mbox_init(struct rvu *rvu goto free_regions;break ;default : -return err; + goto free_regions; } mw->mbox_wq = alloc_workqueue(name,
Greg Kroah-Hartman
maintainerPATCH 132/207 net: annotate data-races on txq->xmit_lock_owner
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
commit 7a10d8c810cfad3e79372d7d1c77899d86cd6662 upstream.
syzbot found that __dev_queue_xmit() is reading txq->xmit_lock_owner without annotations.
No serious issue there, let's document what is happening there.
BUG: KCSAN: data-race in __dev_queue_xmit / __dev_queue_xmit
write to 0xffff888139d09484 of 4 bytes by interrupt on cpu 0:
__netif_tx_unlock include/linux/netdevice.h:4437 [inline] __dev_queue_xmit+0x948/0xf70 net/core/dev.c:4229 dev_queue_xmit_accel+0x19/0x20 net/core/dev.c:4265 macvlan_queue_xmit drivers/net/macvlan.c:543 [inline] macvlan_start_xmit+0x2b3/0x3d0 drivers/net/macvlan.c:567 __netdev_start_xmit include/linux/netdevice.h:4987 [inline] netdev_start_xmit include/linux/netdevice.h:5001 [inline] xmit_one+0x105/0x2f0 net/core/dev.c:3590 dev_hard_start_xmit+0x72/0x120 net/core/dev.c:3606 sch_direct_xmit+0x1b2/0x7c0 net/sched/sch_generic.c:342 __dev_xmit_skb+0x83d/0x1370 net/core/dev.c:3817 __dev_queue_xmit+0x590/0xf70 net/core/dev.c:4194 dev_queue_xmit+0x13/0x20 net/core/dev.c:4259 neigh_hh_output include/net/neighbour.h:511 [inline] neigh_output include/net/neighbour.h:525 [inline] ip6_finish_output2+0x995/0xbb0 net/ipv6/ip6_output.c:126 __ip6_finish_output net/ipv6/ip6_output.c:191 [inline] ip6_finish_output+0x444/0x4c0 net/ipv6/ip6_output.c:201 NF_HOOK_COND include/linux/netfilter.h:296 [inline] ip6_output+0x10e/0x210 net/ipv6/ip6_output.c:224 dst_output include/net/dst.h:450 [inline] NF_HOOK include/linux/netfilter.h:307 [inline] ndisc_send_skb+0x486/0x610 net/ipv6/ndisc.c:508 ndisc_send_rs+0x3b0/0x3e0 net/ipv6/ndisc.c:702 addrconf_rs_timer+0x370/0x540 net/ipv6/addrconf.c:3898 call_timer_fn+0x2e/0x240 kernel/time/timer.c:1421 expire_timers+0x116/0x240 kernel/time/timer.c:1466 __run_timers+0x368/0x410 kernel/time/timer.c:1734 run_timer_softirq+0x2e/0x60 kernel/time/timer.c:1747 __do_softirq+0x158/0x2de kernel/softirq.c:558 __irq_exit_rcu kernel/softirq.c:636 [inline] irq_exit_rcu+0x37/0x70 kernel/softirq.c:648 sysvec_apic_timer_interrupt+0x3e/0xb0 arch/x86/kernel/apic/apic.c:1097 asm_sysvec_apic_timer_interrupt+0x12/0x20
read to 0xffff888139d09484 of 4 bytes by interrupt on cpu 1:
__dev_queue_xmit+0x5e3/0xf70 net/core/dev.c:4213 dev_queue_xmit_accel+0x19/0x20 net/core/dev.c:4265 macvlan_queue_xmit drivers/net/macvlan.c:543 [inline] macvlan_start_xmit+0x2b3/0x3d0 drivers/net/macvlan.c:567 __netdev_start_xmit include/linux/netdevice.h:4987 [inline] netdev_start_xmit include/linux/netdevice.h:5001 [inline] xmit_one+0x105/0x2f0 net/core/dev.c:3590 dev_hard_start_xmit+0x72/0x120 net/core/dev.c:3606 sch_direct_xmit+0x1b2/0x7c0 net/sched/sch_generic.c:342 __dev_xmit_skb+0x83d/0x1370 net/core/dev.c:3817 __dev_queue_xmit+0x590/0xf70 net/core/dev.c:4194 dev_queue_xmit+0x13/0x20 net/core/dev.c:4259 neigh_resolve_output+0x3db/0x410 net/core/neighbour.c:1523 neigh_output include/net/neighbour.h:527 [inline] ip6_finish_output2+0x9be/0xbb0 net/ipv6/ip6_output.c:126 __ip6_finish_output net/ipv6/ip6_output.c:191 [inline] ip6_finish_output+0x444/0x4c0 net/ipv6/ip6_output.c:201 NF_HOOK_COND include/linux/netfilter.h:296 [inline] ip6_output+0x10e/0x210 net/ipv6/ip6_output.c:224 dst_output include/net/dst.h:450 [inline] NF_HOOK include/linux/netfilter.h:307 [inline] ndisc_send_skb+0x486/0x610 net/ipv6/ndisc.c:508 ndisc_send_rs+0x3b0/0x3e0 net/ipv6/ndisc.c:702 addrconf_rs_timer+0x370/0x540 net/ipv6/addrconf.c:3898 call_timer_fn+0x2e/0x240 kernel/time/timer.c:1421 expire_timers+0x116/0x240 kernel/time/timer.c:1466 __run_timers+0x368/0x410 kernel/time/timer.c:1734 run_timer_softirq+0x2e/0x60 kernel/time/timer.c:1747 __do_softirq+0x158/0x2de kernel/softirq.c:558 __irq_exit_rcu kernel/softirq.c:636 [inline] irq_exit_rcu+0x37/0x70 kernel/softirq.c:648 sysvec_apic_timer_interrupt+0x8d/0xb0 arch/x86/kernel/apic/apic.c:1097 asm_sysvec_apic_timer_interrupt+0x12/0x20 kcsan_setup_watchpoint+0x94/0x420 kernel/kcsan/core.c:443 folio_test_anon include/linux/page-flags.h:581 [inline] PageAnon include/linux/page-flags.h:586 [inline] zap_pte_range+0x5ac/0x10e0 mm/memory.c:1347 zap_pmd_range mm/memory.c:1467 [inline] zap_pud_range mm/memory.c:1496 [inline] zap_p4d_range mm/memory.c:1517 [inline] unmap_page_range+0x2dc/0x3d0 mm/memory.c:1538 unmap_single_vma+0x157/0x210 mm/memory.c:1583 unmap_vmas+0xd0/0x180 mm/memory.c:1615 exit_mmap+0x23d/0x470 mm/mmap.c:3170 __mmput+0x27/0x1b0 kernel/fork.c:1113 mmput+0x3d/0x50 kernel/fork.c:1134 exit_mm+0xdb/0x170 kernel/exit.c:507 do_exit+0x608/0x17a0 kernel/exit.c:819 do_group_exit+0xce/0x180 kernel/exit.c:929 get_signal+0xfc3/0x1550 kernel/signal.c:2852 arch_do_signal_or_restart+0x8c/0x2e0 arch/x86/kernel/signal.c:868 handle_signal_work kernel/entry/common.c:148 [inline] exit_to_user_mode_loop kernel/entry/common.c:172 [inline] exit_to_user_mode_prepare+0x113/0x190 kernel/entry/common.c:207 __syscall_exit_to_user_mode_work kernel/entry/common.c:289 [inline] syscall_exit_to_user_mode+0x20/0x40 kernel/entry/common.c:300 do_syscall_64+0x50/0xd0 arch/x86/entry/common.c:86 entry_SYSCALL_64_after_hwframe+0x44/0xae
value changed: 0x00000000 -> 0xffffffff
Reported by Kernel Concurrency Sanitizer on:
CPU: 1 PID: 28712 Comm: syz-executor.0 Tainted: G W 5.16.0-rc1-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
--- include/linux/netdevice.h | 19 +++++++++++++------ net/core/dev.c | 5 ++++- 2 files changed, 17 insertions(+), 7 deletions(-)
include/linux/netdevice.h +13 -6
@@ -4403,7 +4403,8 @@ static inline u32 netif_msg_init(int debstatic inline void __netif_tx_lock (struct netdev_queue *txq,int cpu) {spin_lock (&txq->_xmit_lock); - txq->xmit_lock_owner = cpu; +/* Pairs with READ_ONCE() in __dev_queue_xmit() */ +WRITE_ONCE (txq->xmit_lock_owner, cpu); }static inline bool __netif_tx_acquire (struct netdev_queue *txq)
@@ -4420,26 +4421,32 @@ static inline void __netif_tx_release(ststatic inline void __netif_tx_lock_bh (struct netdev_queue *txq) {spin_lock_bh (&txq->_xmit_lock); - txq->xmit_lock_owner =smp_processor_id (); +/* Pairs with READ_ONCE() in __dev_queue_xmit() */ +WRITE_ONCE (txq->xmit_lock_owner,smp_processor_id ()); }static inline bool __netif_tx_trylock (struct netdev_queue *txq) {bool ok =spin_trylock (&txq->_xmit_lock); -if (likely (ok)) - txq->xmit_lock_owner =smp_processor_id (); + +if (likely (ok)) { +/* Pairs with READ_ONCE() in __dev_queue_xmit() */ +WRITE_ONCE (txq->xmit_lock_owner,smp_processor_id ()); + }return ok; }static inline void __netif_tx_unlock (struct netdev_queue *txq) { - txq->xmit_lock_owner =-1 ; +/* Pairs with READ_ONCE() in __dev_queue_xmit() */ +WRITE_ONCE (txq->xmit_lock_owner,-1 );spin_unlock (&txq->_xmit_lock); }static inline void __netif_tx_unlock_bh (struct netdev_queue *txq) { - txq->xmit_lock_owner =-1 ; +/* Pairs with READ_ONCE() in __dev_queue_xmit() */ +WRITE_ONCE (txq->xmit_lock_owner,-1 );spin_unlock_bh (&txq->_xmit_lock); }
net/core/dev.c +4 -1
@@ -4195,7 +4195,10 @@ static int __dev_queue_xmit(struct sk_buif (dev->flags &IFF_UP ) {int cpu =smp_processor_id ();/* ok because BHs are off */ -if (txq->xmit_lock_owner != cpu) { +/* Other cpus might concurrently change txq->xmit_lock_owner +* to -1 or to their cpu id, but not to our id. +*/ +if (READ_ONCE (txq->xmit_lock_owner) != cpu) {if (dev_xmit_recursion ()) goto recursion_alert;
Greg Kroah-Hartman
maintainerPATCH 133/207 ipv4: convert fib_num_tclassid_users to atomic_t
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
commit 213f5f8f31f10aa1e83187ae20fb7fa4e626b724 upstream.
Before commit faa041a40b9f ("ipv4: Create cleanup helper for fib_nh") changes to net->ipv4.fib_num_tclassid_users were protected by RTNL.
After the change, this is no longer the case, as free_fib_info_rcu() runs after rcu grace period, without rtnl being held.
--- include/net/ip_fib.h | 2 +- include/net/netns/ipv4.h | 2 +- net/ipv4/fib_frontend.c | 2 +- net/ipv4/fib_rules.c | 4 ++-- net/ipv4/fib_semantics.c | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-)
include/net/ip_fib.h +1 -1
@@ -438,7 +438,7 @@ int fib_validate_source(struct sk_buff *#ifdef CONFIG_IP_ROUTE_CLASSID static inline int fib_num_tclassid_users (struct net *net) { -return net->ipv4.fib_num_tclassid_users; +return atomic_read (&net->ipv4.fib_num_tclassid_users); }#else static inline int fib_num_tclassid_users (struct net *net)
include/net/netns/ipv4.h +1 -1
@@ -65,7 +65,7 @@ struct netns_ipv4 {bool fib_has_custom_local_routes;bool fib_offload_disabled;#ifdef CONFIG_IP_ROUTE_CLASSID -int fib_num_tclassid_users; +atomic_t fib_num_tclassid_users;#endif struct hlist_head *fib_table_hash;struct sock *fibnl;
net/ipv4/fib_frontend.c +1 -1
@@ -1582,7 +1582,7 @@ static int __net_init fib_net_init(strucint error;#ifdef CONFIG_IP_ROUTE_CLASSID - net->ipv4.fib_num_tclassid_users =0 ; +atomic_set (&net->ipv4.fib_num_tclassid_users,0 );#endif error =ip_fib_net_init (net);if (error <0 )
net/ipv4/fib_rules.c +2 -2
@@ -264,7 +264,7 @@ static int fib4_rule_configure(struct fiif (tb[FRA_FLOW ]) { rule4->tclassid =nla_get_u32 (tb[FRA_FLOW ]);if (rule4->tclassid) - net->ipv4.fib_num_tclassid_users++; +atomic_inc (&net->ipv4.fib_num_tclassid_users); }#endif
@@ -296,7 +296,7 @@ static int fib4_rule_delete(struct fib_r#ifdef CONFIG_IP_ROUTE_CLASSID if (((struct fib4_rule *)rule)->tclassid) - net->ipv4.fib_num_tclassid_users--; +atomic_dec (&net->ipv4.fib_num_tclassid_users);#endif net->ipv4.fib_has_custom_rules = true;
net/ipv4/fib_semantics.c +2 -2
@@ -220,7 +220,7 @@ void fib_nh_release(struct net *net, str {#ifdef CONFIG_IP_ROUTE_CLASSID if (fib_nh->nh_tclassid) - net->ipv4.fib_num_tclassid_users--; +atomic_dec (&net->ipv4.fib_num_tclassid_users);#endif fib_nh_common_release (&fib_nh->nh_common); }
@@ -632,7 +632,7 @@ int fib_nh_init(struct net *net, struct#ifdef CONFIG_IP_ROUTE_CLASSID nh->nh_tclassid = cfg->fc_flow;if (nh->nh_tclassid) - net->ipv4.fib_num_tclassid_users++; +atomic_inc (&net->ipv4.fib_num_tclassid_users);#endif #ifdef CONFIG_IP_ROUTE_MULTIPATH nh->fib_nh_weight = nh_weight;
Greg Kroah-Hartman
maintainerPATCH 134/207 net/smc: fix wrong list_del in smc_lgr_cleanup_early
In reply to Greg Kroah-HartmanFrom: Dust Li <[email protected]>
commit 789b6cc2a5f9123b9c549b886fdc47c865cfe0ba upstream.
smc_lgr_cleanup_early() meant to delete the link
group from the link group list, but it deleted
the list head by mistake.
This may cause memory corruption since we didn't remove the real link group from the list and later memseted the link group structure.
We got a list corruption panic when testing:
[ 231.277259] list_del corruption. prev->next should be ffff8881398a8000, but was 0000000000000000 [ 231.278222] ------------[ cut here ]------------
[ 231.278726] kernel BUG at lib/list_debug.c:53!
[ 231.279326] invalid opcode: 0000 [#1] SMP NOPTI
[ 231.279803] CPU: 0 PID: 5 Comm: kworker/0:0 Not tainted 5.10.46+ #435
[ 231.280466] Hardware name: Alibaba Cloud ECS, BIOS 8c24b4c 04/01/2014
[ 231.281248] Workqueue: events smc_link_down_work
[ 231.281732] RIP: 0010:__list_del_entry_valid+0x70/0x90
[ 231.282258] Code: 4c 60 82 e8 7d cc 6a 00 0f 0b 48 89 fe 48 c7 c7 88 4c
60 82 e8 6c cc 6a 00 0f 0b 48 89 fe 48 c7 c7 c0 4c 60 82 e8 5b cc 6a 00 <0f>
0b 48 89 fe 48 c7 c7 00 4d 60 82 e8 4a cc 6a 00 0f 0b cc cc cc
[ 231.284146] RSP: 0018:ffffc90000033d58 EFLAGS: 00010292
[ 231.284685] RAX: 0000000000000054 RBX: ffff8881398a8000 RCX: 0000000000000000
[ 231.285415] RDX: 0000000000000001 RSI: ffff88813bc18040 RDI: ffff88813bc18040
[ 231.286141] RBP: ffffffff8305ad40 R08: 0000000000000003 R09: 0000000000000001
[ 231.286873] R10: ffffffff82803da0 R11: ffffc90000033b90 R12: 0000000000000001
[ 231.287606] R13: 0000000000000000 R14: ffff8881398a8000 R15: 0000000000000003
[ 231.288337] FS: 0000000000000000(0000) GS:ffff88813bc00000(0000) knlGS:0000000000000000 [ 231.289160] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 231.289754] CR2: 0000000000e72058 CR3: 000000010fa96006 CR4: 00000000003706f0
[ 231.290485] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 231.291211] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[ 231.291940] Call Trace:
[ 231.292211] smc_lgr_terminate_sched+0x53/0xa0
[ 231.292677] smc_switch_conns+0x75/0x6b0
[ 231.293085] ? update_load_avg+0x1a6/0x590
[ 231.293517] ? ttwu_do_wakeup+0x17/0x150
[ 231.293907] ? update_load_avg+0x1a6/0x590
[ 231.294317] ? newidle_balance+0xca/0x3d0
[ 231.294716] smcr_link_down+0x50/0x1a0
[ 231.295090] ? __wake_up_common_lock+0x77/0x90
[ 231.295534] smc_link_down_work+0x46/0x60
[ 231.295933] process_one_work+0x18b/0x350
--- net/smc/smc_core.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
net/smc/smc_core.c +3 -4
@@ -582,18 +582,17 @@ int smcd_nl_get_lgr(struct sk_buff *skb,void smc_lgr_cleanup_early (struct smc_connection *conn) {struct smc_link_group *lgr = conn->lgr; -struct list_head *lgr_list;spinlock_t *lgr_lock;if (!lgr)return ;smc_conn_free (conn); - lgr_list =smc_lgr_list_head (lgr, &lgr_lock); +smc_lgr_list_head (lgr, &lgr_lock);spin_lock_bh (lgr_lock);/* do not use this link group for new connections */ -if (!list_empty (lgr_list)) -list_del_init (lgr_list); +if (!list_empty (&lgr->list)) +list_del_init (&lgr->list);spin_unlock_bh (lgr_lock);__smc_lgr_terminate (lgr, true); }
Greg Kroah-Hartman
maintainerPATCH 135/207 net/rds: correct socket tunable error in rds_tcp_tune()
In reply to Greg Kroah-HartmanFrom: William Kucharski <[email protected]>
commit 19f36edf14bcdb783aef3af8217df96f76a8ce34 upstream.
Correct an error where setting /proc/sys/net/rds/tcp/rds_tcp_rcvbuf would instead modify the socket's sk_sndbuf and would leave sk_rcvbuf untouched.
--- net/rds/tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/rds/tcp.c +1 -1
@@ -500,7 +500,7 @@ void rds_tcp_tune(struct socket *sock) sk->sk_userlocks |=SOCK_SNDBUF_LOCK ; }if (rtn->rcvbuf_size >0 ) { - sk->sk_sndbuf = rtn->rcvbuf_size; + sk->sk_rcvbuf = rtn->rcvbuf_size; sk->sk_userlocks |=SOCK_RCVBUF_LOCK ; }release_sock (sk);
Greg Kroah-Hartman
maintainerPATCH 136/207 net/smc: Keep smc_close_final rc during active close
In reply to Greg Kroah-HartmanFrom: Tony Lu <[email protected]>
commit 00e158fb91dfaff3f94746f260d11f1a4853506e upstream.
When smc_close_final() returns error, the return code overwrites by kernel_sock_shutdown() in smc_close_active(). The return code of smc_close_final() is more important than kernel_sock_shutdown(), and it will pass to userspace directly.
Fix it by keeping both return codes, if smc_close_final() raises an error, return it or kernel_sock_shutdown()'s.
--- net/smc/smc_close.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
net/smc/smc_close.c +6 -2
@@ -195,6 +195,7 @@ int smc_close_active(struct smc_sock *smint old_state;long timeout;int rc =0 ; +int rc1 =0 ; timeout = current->flags &PF_EXITING ? 0 : sock_flag(sk, SOCK_LINGER) ?
@@ -232,8 +233,11 @@ again:/* actively shutdown clcsock before peer close it, * prevent peer from entering TIME_WAIT state. */ -if (smc->clcsock && smc->clcsock->sk) - rc =kernel_sock_shutdown (smc->clcsock,SHUT_RDWR ); +if (smc->clcsock && smc->clcsock->sk) { + rc1 =kernel_sock_shutdown (smc->clcsock, +SHUT_RDWR ); + rc = rc ? rc : rc1; + } }else {/* peer event has changed the state */ goto again;
Greg Kroah-Hartman
maintainerPATCH 137/207 drm/msm/a6xx: Allocate enough space for GMU registers
In reply to Greg Kroah-HartmanFrom: Douglas Anderson <[email protected]>
commit b4d25abf9720b69a03465b09d0d62d1998ed6708 upstream.
In commit 142639a52a01 ("drm/msm/a6xx: fix crashstate capture for A650") we changed a6xx_get_gmu_registers() to read 3 sets of registers. Unfortunately, we didn't change the memory allocation for the array. That leads to a KASAN warning (this was on the chromeos-5.4 kernel, which has the problematic commit backported to it):
BUG: KASAN: slab-out-of-bounds in _a6xx_get_gmu_registers+0x144/0x430 Write of size 8 at addr ffffff80c89432b0 by task A618-worker/209 CPU: 5 PID: 209 Comm: A618-worker Tainted: G W 5.4.156-lockdep #22 Hardware name: Google Lazor Limozeen without Touchscreen (rev5 - rev8) (DT) Call trace: dump_backtrace+0x0/0x248 show_stack+0x20/0x2c dump_stack+0x128/0x1ec print_address_description+0x88/0x4a0 __kasan_report+0xfc/0x120 kasan_report+0x10/0x18 __asan_report_store8_noabort+0x1c/0x24 _a6xx_get_gmu_registers+0x144/0x430 a6xx_gpu_state_get+0x330/0x25d4 msm_gpu_crashstate_capture+0xa0/0x84c recover_worker+0x328/0x838 kthread_worker_fn+0x32c/0x574 kthread+0x2dc/0x39c ret_from_fork+0x10/0x18 Allocated by task 209: __kasan_kmalloc+0xfc/0x1c4 kasan_kmalloc+0xc/0x14 kmem_cache_alloc_trace+0x1f0/0x2a0 a6xx_gpu_state_get+0x164/0x25d4 msm_gpu_crashstate_capture+0xa0/0x84c recover_worker+0x328/0x838 kthread_worker_fn+0x32c/0x574 kthread+0x2dc/0x39c ret_from_fork+0x10/0x18
--- drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +2 -2
@@ -777,12 +777,12 @@ static void a6xx_get_gmu_registers(strucstruct a6xx_gpu *a6xx_gpu =to_a6xx_gpu (adreno_gpu); a6xx_state->gmu_registers =state_kcalloc (a6xx_state, -2 ,sizeof (*a6xx_state->gmu_registers)); +3 ,sizeof (*a6xx_state->gmu_registers));if (!a6xx_state->gmu_registers)return ; - a6xx_state->nr_gmu_registers =2 ; + a6xx_state->nr_gmu_registers =3 ;/* Get the CX GMU registers from AHB */ _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[0],
Greg Kroah-Hartman
maintainerPATCH 138/207 drm/msm: Do hw_init() before capturing GPU state
In reply to Greg Kroah-HartmanFrom: Rob Clark <[email protected]>
commit e4840d537c2c6b1189d4de16ee0f4820e069dcea upstream.
In particular, we need to ensure all the necessary blocks are switched to 64b mode (a5xx+) otherwise the high bits of the address of the BO to snapshot state into will be ignored, resulting in:
*** gpu fault: ttbr0=0000000000000000 iova=0000000000012000 dir=READ type=TRANSLATION source=CP (0,0,0,0) platform 506a000.gmu: [drm:a6xx_gmu_set_oob] *ERROR* Timeout waiting for GMU OOB set BOOT_SLUMBER: 0x0
--- drivers/gpu/drm/msm/msm_debugfs.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/msm/msm_debugfs.c +1 -0
@@ -77,6 +77,7 @@ static int msm_gpu_open(struct inode *in goto free_priv;pm_runtime_get_sync (&gpu->pdev->dev); +msm_gpu_hw_init (gpu); show_priv->state = gpu->funcs->gpu_state_get (gpu);pm_runtime_put_sync (&gpu->pdev->dev);
Greg Kroah-Hartman
maintainerPATCH 139/207 drm/vc4: kms: Wait for the commit before increasing our clock rate
In reply to Greg Kroah-HartmanFrom: Maxime Ripard <[email protected]>
commit 0c980a006d3fbee86c4d0698f66d6f5381831787 upstream.
Several DRM/KMS atomic commits can run in parallel if they affect different CRTC. These commits share the global HVS state, so we have some code to make sure we run commits in sequence. This synchronization code is one of the first thing that runs in vc4_atomic_commit_tail().
Another constraints we have is that we need to make sure the HVS clock gets a boost during the commit. That code relies on clk_set_min_rate and will remove the old minimum and set a new one. We also need another, temporary, minimum for the duration of the commit.
The algorithm is thus to set a temporary minimum, drop the previous one, do the commit, and finally set the minimum for the current mode.
However, the part that sets the temporary minimum and drops the older one runs before the commit synchronization code.
Thus, under the proper conditions, we can end up mixing up the minimums and ending up with the wrong one for our current step.
To avoid it, let's move the clock setup in the protected section.
--- drivers/gpu/drm/vc4/vc4_kms.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/gpu/drm/vc4/vc4_kms.c +3 -3
@@ -353,9 +353,6 @@ static void vc4_atomic_commit_tail(strucvc4_hvs_mask_underrun (dev, vc4_crtc_state->assigned_channel); } -if (vc4->hvs->hvs5) -clk_set_min_rate (hvs->core_clk,500000000 ); - old_hvs_state =vc4_hvs_get_old_global_state (state);if (!old_hvs_state)return ;
@@ -377,6 +374,9 @@ static void vc4_atomic_commit_tail(strucdrm_err (dev,"Timed out waiting for commit\n" ); } +if (vc4->hvs->hvs5) +clk_set_min_rate (hvs->core_clk,500000000 ); +drm_atomic_helper_commit_modeset_disables (dev, state);vc4_ctm_commit (vc4, state);
Greg Kroah-Hartman
maintainerPATCH 140/207 drm/vc4: kms: Fix return code check
In reply to Greg Kroah-HartmanFrom: Maxime Ripard <[email protected]>
commit f927767978d201d4ac023fcd797adbb963a6565d upstream.
The HVS global state functions return an error pointer, but in most cases we check if it's NULL, possibly resulting in an invalid pointer dereference.
--- drivers/gpu/drm/vc4/vc4_kms.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/gpu/drm/vc4/vc4_kms.c +5 -5
@@ -354,7 +354,7 @@ static void vc4_atomic_commit_tail(struc } old_hvs_state =vc4_hvs_get_old_global_state (state); -if (!old_hvs_state) +if (IS_ERR (old_hvs_state))return ;for_each_old_crtc_in_state (state, crtc, old_crtc_state, i) {
@@ -410,8 +410,8 @@ static int vc4_atomic_commit_setup(strucunsigned int i; hvs_state =vc4_hvs_get_new_global_state (state); -if (!hvs_state) -return -EINVAL ; +if (WARN_ON (IS_ERR (hvs_state))) +return PTR_ERR (hvs_state);for_each_new_crtc_in_state (state, crtc, crtc_state, i) { struct vc4_crtc_state *vc4_crtc_state =
@@ -762,8 +762,8 @@ static int vc4_pv_muxing_atomic_check(stunsigned int i; hvs_new_state =vc4_hvs_get_global_state (state); -if (!hvs_new_state) -return -EINVAL ; +if (IS_ERR (hvs_new_state)) +return PTR_ERR (hvs_new_state);for (i =0 ; i <ARRAY_SIZE (hvs_new_state->fifo_state); i++)if (!hvs_new_state->fifo_state[i].in_use)