Skip to contentSkip to conversation

6.10.8-rc1 review

PATCH In review Greg Kroah-Hartman 8 participants 160 messages Sep 1, 2024 – Sep 3, 2024 Page 1 of 2

Subsystems (8)
lore
Share & tools
lore

Greg Kroah-Hartman

author maintainer
#0 lore raw

cover 6.10.8-rc1 review

This is the start of the stable review cycle for the 6.10.8 release. There are 149 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 Tue, 03 Sep 2024 16:07:34 +0000. Anything received after that time might be too late.

The whole patch series can be found in one patch at:

	https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.10.8-rc1.gz

or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.10.y
and the diffstat can be found below.

thanks,

greg k-h

-------------
Pseudo-Shortlog of commits:

Greg Kroah-Hartman <[email protected]>

    Linux 6.10.8-rc1

NeilBrown <[email protected]>
nfsd: fix nfsd4_deleg_getattr_conflict in presence of third party lease

Guenter Roeck <[email protected]>
apparmor: fix policy_unpack_test on big endian systems

Ben Hutchings <[email protected]>
scsi: aacraid: Fix double-free on probe failure

Steve Wilkins <[email protected]>
firmware: microchip: fix incorrect error report of programming:timeout on success

Markus Niebel <[email protected]>

    arm64: dts: freescale: imx93-tqma9352-mba93xxla: fix typo

Markus Niebel <[email protected]>
arm64: dts: freescale: imx93-tqma9352: fix CMA alloc-ranges

Shenwei Wang <[email protected]>
arm64: dts: imx93: update default value for snps,clk-csr

Adam Ford <[email protected]>
arm64: dts: imx8mp-beacon-kit: Fix Stereo Audio on WM8962

Sicelo A. Mhlongo <[email protected]>
ARM: dts: omap3-n900: correct the accelerometer orientation

Varadarajan Narayanan <[email protected]>
arm64: dts: qcom: ipq5332: Fix interrupt trigger type for usb

Bjorn Andersson <[email protected]>
usb: typec: ucsi: Move unregister out of atomic section

Pawel Laszczak <[email protected]>
usb: cdnsp: fix for Link TRB with TC

Pawel Laszczak <[email protected]>
usb: cdnsp: fix incorrect index in cdnsp_get_hw_deq function

Zijun Hu <[email protected]>
usb: core: sysfs: Unmerge @usb3_hardware_lpm_attr_group in remove_power_attributes()

Krzysztof Kozlowski <[email protected]>
usb: dwc3: st: add missing depopulate in probe error path

Krzysztof Kozlowski <[email protected]>
usb: dwc3: st: fix probed platform device ref count on probe error path

Selvarasu Ganesan <[email protected]>
usb: dwc3: core: Prevent USB core invalid event buffer address access

Krzysztof Kozlowski <[email protected]>
usb: dwc3: omap: add missing depopulate in probe error path

Krzysztof Kozlowski <[email protected]>
usb: dwc3: xilinx: add missing depopulate in probe error path

Michael Grzeschik <[email protected]>
usb: dwc3: ep0: Don't reset resource alloc flag (including ep0)

Michal Vokáč <[email protected]>
ARM: dts: imx6dl-yapp43: Increase LED current to match the yapp4 HW design

Johan Hovold <[email protected]>
arm64: dts: qcom: x1e80100: fix PCIe domain numbers

Johan Hovold <[email protected]>
arm64: dts: qcom: x1e80100: add missing PCIe minimum OPP

Johan Hovold <[email protected]>

    arm64: dts: qcom: x1e80100-qcp: fix PCIe4 PHY supply

Johan Hovold <[email protected]>

    arm64: dts: qcom: x1e80100-crd: fix PCIe4 PHY supply

Xu Yang <[email protected]>
usb: gadget: uvc: queue pump work in uvcg_video_enable()

ZHANG Yuntian <[email protected]>
USB: serial: option: add MeiG Smart SRM825L

Alexander Stein <[email protected]>
dt-bindings: usb: microchip,usb2514: Fix reference USB device schema

Yihang Li <[email protected]>
scsi: sd: Ignore command SYNCHRONIZE CACHE error if format in progress

Murali Nalajala <[email protected]>
firmware: qcom: scm: Mark get_wq_ctx() as atomic call

Luca Weiss <[email protected]>
usb: typec: fsa4480: Relax CHIP_ID check

Ian Ray <[email protected]>
cdc-acm: Add DISABLE_ECHO quirk for GE HealthCare UI Controller

Bjorn Andersson <[email protected]>
soc: qcom: pmic_glink: Fix race during initialization

Bjorn Andersson <[email protected]>
soc: qcom: pmic_glink: Actually communicate when remote goes down

Volodymyr Babchuk <[email protected]>
soc: qcom: cmd-db: Map shared memory as WC, not WB

Jens Axboe <[email protected]>
io_uring/kbuf: return correct iovec count from classic buffer peek

Karthik Poosa <[email protected]>
drm/xe/hwmon: Fix WRITE_I1 param from u32 to u16

Aleksandr Mishin <[email protected]>
nfc: pn533: Add poll mod list filling check

Eric Dumazet <[email protected]>
net: busy-poll: use ktime_get_ns() instead of local_clock()

Ma Ke <[email protected]>
drm/amd/display: avoid using null object of framebuffer

Ondrej Mosnacek <[email protected]>
sctp: fix association labeling in the duplicate COOKIE-ECHO case

Xueming Feng <[email protected]>
tcp: fix forever orphan socket caused by tcp_abort

Cong Wang <[email protected]>
gtp: fix a potential NULL pointer dereference

Jianbo Liu <[email protected]>
bonding: change ipsec_lock from spin lock to mutex

Jianbo Liu <[email protected]>
bonding: extract the use of real_device into local variable

Jianbo Liu <[email protected]>
bonding: implement xdo_dev_state_free and call it after deletion

Petr Machata <[email protected]>
selftests: forwarding: local_termination: Down ports on cleanup

Petr Machata <[email protected]>
selftests: forwarding: no_forwarding: Down ports on cleanup

Pablo Neira Ayuso <[email protected]>
netfilter: nf_tables_ipv6: consider network offset in netdev/egress validation

Eric Dumazet <[email protected]>
net_sched: sch_fq: fix incorrect behavior for small weights

Cosmo Chou <[email protected]>
hwmon: (pt5161l) Fix invalid temperature reading

Jamie Bainbridge <[email protected]>
ethtool: check device is present when getting link settings

Avraham Stern <[email protected]>
wifi: iwlwifi: mvm: allow 6 GHz channels in MLO scan

Anjaneyulu <[email protected]>
wifi: iwlwifi: fw: fix wgds rev 3 exact size

Emmanuel Grumbach <[email protected]>
wifi: iwlwifi: mvm: take the mutex before running link selection

Pablo Neira Ayuso <[email protected]>
netfilter: nf_tables: restore IP sanity checks for netdev/egress

Jason Gunthorpe <[email protected]>
iommu: Do not return 0 from map_pages if it doesn't do anything

Luiz Augusto von Dentz <[email protected]>
Bluetooth: hci_core: Fix not handling hibernation actions

Neeraj Sanjay Kale <[email protected]>
Bluetooth: btnxpuart: Fix random crash seen while removing driver

Neeraj Sanjay Kale <[email protected]>
Bluetooth: btnxpuart: Handle FW Download Abort scenario

Mario Limonciello <[email protected]>
cpufreq/amd-pstate-ut: Don't check for highest perf matching on prefcore

Eric Dumazet <[email protected]>
pktgen: use cpus_read_lock() in pg_net_init()

Kees Cook <[email protected]>
dmaengine: ti: omap-dma: Initialize sglen after allocation

Serge Semin <[email protected]>
dmaengine: dw: Add memory bus width verification

Serge Semin <[email protected]>
dmaengine: dw: Add peripheral bus width verification

Piyush Mehta <[email protected]>
phy: xilinx: phy-zynqmp: Fix SGMII linkup failure on resume

Abel Vesa <[email protected]>
phy: qcom: qmp-pcie: Fix X1E80100 PCIe Gen4 PHY initialisation

Mrinmay Sarkar <[email protected]>
dmaengine: dw-edma: Do not enable watermark interrupts for HDMA

Mrinmay Sarkar <[email protected]>
dmaengine: dw-edma: Fix unmasking STOP and ABORT interrupts for HDMA

Krzysztof Kozlowski <[email protected]>
soundwire: stream: fix programming slave ports for non-continous port maps

Xu Yang <[email protected]>
phy: fsl-imx8mq-usb: fix tuning parameter name

Jason Gunthorpe <[email protected]>
iommufd: Do not allow creating areas without READ or WRITE

Gautham R. Shenoy <[email protected]>
cpufreq/amd-pstate: Use topology_logical_package_id() instead of logical_die_id()

Scott Mayhew <[email protected]>
selinux,smack: don't bypass permissions check in inode_setsecctx hook

Jeff Layton <[email protected]>
fs/nfsd: fix update of inode attrs in CB_GETATTR

Jeff Layton <[email protected]>
nfsd: fix potential UAF in nfsd4_cb_getattr_release

Jeff Layton <[email protected]>
nfsd: hold reference to delegation when updating it for cb_getattr

David Howells <[email protected]>
cifs: Fix FALLOC_FL_PUNCH_HOLE support

Stefan Metzmacher <[email protected]>
smb/client: remove unused rq_iter_size from struct smb_rqst

David Howells <[email protected]>
netfs: Fix interaction of streaming writes with zero-point tracker

David Howells <[email protected]>
netfs: Fix missing iterator reset on retry of short read

David Howells <[email protected]>
netfs: Fix trimming of streaming-write folios in netfs_inval_folio()

David Howells <[email protected]>
netfs: Fix netfs_release_folio() to say no if folio dirty

David Howells <[email protected]>
afs: Fix post-setattr file edit to do truncation correctly

David Howells <[email protected]>
mm: Fix missing folio invalidation calls during truncation

Olga Kornievskaia <[email protected]>
nfsd: prevent panic for nfsv4.0 closed files in nfs4_show_open

Hal Feng <[email protected]>
pinctrl: starfive: jh7110: Correct the level trigger configuration of iev register

Konrad Dybcio <[email protected]>
pinctrl: qcom: x1e80100: Fix special pin offsets

Nícolas F. R. A. Prado <[email protected]>
pinctrl: mediatek: common-v2: Fix broken bias-disable for PULL_PU_PD_RSEL_TYPE

Ed Tsai <[email protected]>

    backing-file: convert to using fops->splice_write

Jeff Layton <[email protected]>
nfsd: ensure that nfsd4_fattr_args.context is zeroed out

Richard Fitzgerald <[email protected]>
ASoC: cs-amp-lib: Ignore empty UEFI calibration entries

Richard Fitzgerald <[email protected]>
ASoC: cs-amp-lib-test: Force test calibration blob entries to be valid

Simon Trimmer <[email protected]>
ALSA: hda: cs35l56: Don't use the device index as a calibration index

Vijendar Mukunda <[email protected]>
ASoC: SOF: amd: Fix for acp init sequence

Yuntao Liu <[email protected]>
ASoC: amd: acp: fix module autoloading

Vijendar Mukunda <[email protected]>
ASoC: SOF: amd: Fix for incorrect acp error register offsets

Vijendar Mukunda <[email protected]>
ASoC: SOF: amd: move iram-dram fence register programming sequence

Konrad Dybcio <[email protected]>
pinctrl: qcom: x1e80100: Update PDC hwirq map

Alex Deucher <[email protected]>
drm/amdgpu: fix eGPU hotplug regression

Victor Lu <[email protected]>
drm/amdgpu: Do not wait for MP0_C2PMSG_33 IFWI init in SRIOV

Matthew Auld <[email protected]>
drm/xe: prevent UAF around preempt fence

Francois Dugast <[email protected]>
drm/xe/exec_queue: Rename xe_exec_queue::compute to xe_exec_queue::lr

Thorsten Blum <[email protected]>
drm/xe/vm: Simplify if condition

Maarten Lankhorst <[email protected]>
drm/xe/display: Make display suspend/resume work on discrete

Rodrigo Vivi <[email protected]>
drm/xe: Prepare display for D3Cold

Alex Deucher <[email protected]>
video/aperture: optionally match the device in sysfb_disable()

Zack Rusin <[email protected]>
drm/vmwgfx: Disable coherent dumb buffers without 3d

Zack Rusin <[email protected]>
drm/vmwgfx: Fix prime with external buffers

Zack Rusin <[email protected]>
drm/vmwgfx: Prevent unmapping active read buffers

Alex Deucher <[email protected]>
drm/amdgpu/swsmu: always force a state reprogram on init

Alex Deucher <[email protected]>
drm/amdgpu: align pp_power_profile_mode with kernel docs

Imre Deak <[email protected]>
drm/i915/dp_mst: Fix MST state after a sink reset

Hans de Goede <[email protected]>
drm/i915/dsi: Make Lenovo Yoga Tab 3 X90F DMI match less strict

Tvrtko Ursulin <[email protected]>
drm/v3d: Disable preemption while updating GPU stats

Max Filippov <[email protected]>
binfmt_elf_fdpic: fix AUXV size calculation when ELF_HWCAP2 is defined

Matthieu Baerts (NGI0) <[email protected]>
selftests: mptcp: join: check re-re-adding ID 0 endp

Matthieu Baerts (NGI0) <[email protected]>
selftests: mptcp: join: no extra msg if no counter

Matthieu Baerts (NGI0) <[email protected]>
selftests: mptcp: join: check removing ID 0 endpoint

Matthieu Baerts (NGI0) <[email protected]>
selftests: mptcp: join: cannot rm sf if closed

Matthieu Baerts (NGI0) <[email protected]>
mptcp: pm: ADD_ADDR 0 is not a new address

Matthieu Baerts (NGI0) <[email protected]>
mptcp: avoid duplicated SUB_CLOSED events

Matthieu Baerts (NGI0) <[email protected]>
mptcp: pm: fix ID 0 endp usage after multiple re-creations

Matthieu Baerts (NGI0) <[email protected]>
mptcp: pm: do not remove already closed subflows

Matthieu Baerts (NGI0) <[email protected]>
mptcp: pm: fix RM_ADDR ID for the initial subflow

Matthieu Baerts (NGI0) <[email protected]>
mptcp: pm: send ACK on an active subflow

Matthieu Baerts (NGI0) <[email protected]>
mptcp: pm: reset MPC endp ID when re-added

Matthieu Baerts (NGI0) <[email protected]>
mptcp: pm: skip connecting to already established sf

Matthieu Baerts (NGI0) <[email protected]>
mptcp: pm: reuse ID 0 after delete and re-add

Matthieu Baerts (NGI0) <[email protected]>
mptcp: pr_debug: add missing \n at the end

Matthieu Baerts (NGI0) <[email protected]>
mptcp: sched: check both backup in retrans

Matthieu Baerts (NGI0) <[email protected]>
mptcp: close subflow when receiving TCP+FIN

Haiyang Zhang <[email protected]>
net: mana: Fix race of mana_hwc_post_rx_wqe and new hwc response

Sascha Hauer <[email protected]>
wifi: mwifiex: duplicate static structs used in driver instances

Alexander Sverdlin <[email protected]>
wifi: wfx: repair open network AP mode

David Howells <[email protected]>

    netfs, ceph: Partially revert "netfs: Replace PG_fscache by setting folio->private and marking dirty"

Ma Ke <[email protected]>
pinctrl: single: fix potential NULL dereference in pcs_get_function()

Huang-Huang Bao <[email protected]>
pinctrl: rockchip: correct RK3328 iomux width flag for GPIO2-B pins

Stefan Metzmacher <[email protected]>
smb/client: avoid dereferencing rdata=NULL in smb2_new_read_req()

Josef Bacik <[email protected]>
btrfs: run delayed iputs when flushing delalloc

Qu Wenruo <[email protected]>
btrfs: fix a use-after-free when hitting errors inside btrfs_submit_chunk()

Stefan Berger <[email protected]>
tpm: ibmvtpm: Call tpm2_sessions_init() to initialize session support

Tiezhu Yang <[email protected]>
LoongArch: Add ifdefs to fix LSX and LASX related warnings

Miao Wang <[email protected]>
LoongArch: Remove the unused dma-direct.h

Hendrik Borghorst <[email protected]>

    ALSA: hda/realtek: support HP Pavilion Aero 13-bg0xxx Mute LED

John Sweeney <[email protected]>

    ALSA: hda/realtek: Enable mute/micmute LEDs on HP Laptop 14-ey0xxx

Takashi Iwai <[email protected]>
ALSA: seq: Skip event type filtering for UMP events

Gao Xiang <[email protected]>
erofs: fix out-of-bound access when z_erofs_gbuf_growsize() partially fails

Jack Xiao <[email protected]>
drm/amdgpu/mes: fix mes ring buffer overflow

-------------

Diffstat:

 .../devicetree/bindings/usb/microchip,usb2514.yaml |   9 +-
 Makefile                                           |   4 +-
 .../arm/boot/dts/nxp/imx/imx6dl-yapp43-common.dtsi |  12 +-
 arch/arm/boot/dts/ti/omap/omap3-n900.dts           |   2 +-
 .../arm64/boot/dts/freescale/imx8mp-beacon-kit.dts |  12 +-
 .../dts/freescale/imx93-tqma9352-mba93xxla.dts     |   2 +-
 arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi  |   2 +-
 arch/arm64/boot/dts/freescale/imx93.dtsi           |   2 +-
 arch/arm64/boot/dts/qcom/ipq5332.dtsi              |   4 +-
 arch/arm64/boot/dts/qcom/x1e80100-crd.dts          |   2 +-
 arch/arm64/boot/dts/qcom/x1e80100-qcp.dts          |   2 +-
 arch/arm64/boot/dts/qcom/x1e80100.dtsi             |   6 +-
 arch/loongarch/include/asm/dma-direct.h            |  11 --
 arch/loongarch/kernel/fpu.S                        |   4 +
 arch/loongarch/kvm/switch.S                        |   4 +
 drivers/bluetooth/btnxpuart.c                      |  65 +++++++--
 drivers/char/tpm/tpm_ibmvtpm.c                     |   4 +
 drivers/cpufreq/amd-pstate-ut.c                    |  13 +-
 drivers/cpufreq/amd-pstate.c                       |   2 +-
 drivers/dma/dw-edma/dw-hdma-v0-core.c              |  26 ++--
 drivers/dma/dw/core.c                              |  89 +++++++++++-
 drivers/dma/ti/omap-dma.c                          |   6 +-
 drivers/firmware/microchip/mpfs-auto-update.c      |   2 +-
 drivers/firmware/qcom/qcom_scm-smc.c               |   2 +-
 drivers/firmware/sysfb.c                           |  19 ++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c      |  26 ++--
 drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c           |   2 +
 drivers/gpu/drm/amd/amdgpu/mes_v11_0.c             |  18 ++-
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c    |   9 +-
 drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c          |  21 +--
 drivers/gpu/drm/i915/display/intel_dp.c            |  12 ++
 drivers/gpu/drm/i915/display/intel_dp_mst.c        |  40 ++++++
 drivers/gpu/drm/i915/display/intel_dp_mst.h        |   1 +
 drivers/gpu/drm/i915/display/vlv_dsi.c             |   1 -
 drivers/gpu/drm/v3d/v3d_sched.c                    |   6 +
 drivers/gpu/drm/vmwgfx/vmwgfx_blit.c               | 114 ++++++++++++++-
 drivers/gpu/drm/vmwgfx/vmwgfx_bo.c                 |  13 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_bo.h                 |   3 +
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h                |   4 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c               |  12 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_surface.c            |   6 +-
 drivers/gpu/drm/xe/display/xe_display.c            |  33 ++++-
 drivers/gpu/drm/xe/display/xe_display.h            |   8 +-
 drivers/gpu/drm/xe/xe_exec_queue.c                 |   5 +-
 drivers/gpu/drm/xe/xe_exec_queue_types.h           |  14 +-
 drivers/gpu/drm/xe/xe_hwmon.c                      |   2 +-
 drivers/gpu/drm/xe/xe_pm.c                         |  20 ++-
 drivers/gpu/drm/xe/xe_preempt_fence.c              |   3 +-
 drivers/gpu/drm/xe/xe_preempt_fence_types.h        |   2 +
 drivers/gpu/drm/xe/xe_vm.c                         |  60 ++++----
 drivers/hwmon/pt5161l.c                            |   4 +-
 drivers/iommu/io-pgtable-arm-v7s.c                 |   3 +-
 drivers/iommu/io-pgtable-arm.c                     |   3 +-
 drivers/iommu/io-pgtable-dart.c                    |   3 +-
 drivers/iommu/iommufd/ioas.c                       |   8 ++
 drivers/net/bonding/bond_main.c                    | 159 ++++++++++++++-------
 drivers/net/ethernet/microsoft/mana/hw_channel.c   |  68 +++++----
 drivers/net/gtp.c                                  |   2 +-
 drivers/net/wireless/intel/iwlwifi/fw/acpi.c       |  13 +-
 drivers/net/wireless/intel/iwlwifi/mvm/ops.c       |   2 +
 drivers/net/wireless/intel/iwlwifi/mvm/scan.c      |  11 ++
 drivers/net/wireless/marvell/mwifiex/cfg80211.c    |  32 ++++-
 drivers/net/wireless/silabs/wfx/sta.c              |   5 +-
 drivers/nfc/pn533/pn533.c                          |   5 +
 drivers/of/platform.c                              |   2 +-
 drivers/phy/freescale/phy-fsl-imx8mq-usb.c         |   2 +-
 drivers/phy/qualcomm/phy-qcom-qmp-pcie.c           |  23 ++-
 drivers/phy/xilinx/phy-zynqmp.c                    |  56 ++++++++
 drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c   |  55 +++----
 drivers/pinctrl/pinctrl-rockchip.c                 |   2 +-
 drivers/pinctrl/pinctrl-single.c                   |   2 +
 drivers/pinctrl/qcom/pinctrl-x1e80100.c            |  35 ++---
 drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c |   4 +-
 drivers/power/supply/qcom_battmgr.c                |  16 ++-
 drivers/scsi/aacraid/comminit.c                    |   2 +
 drivers/scsi/sd.c                                  |  12 +-
 drivers/soc/qcom/cmd-db.c                          |   2 +-
 drivers/soc/qcom/pmic_glink.c                      |  40 ++++--
 drivers/soc/qcom/pmic_glink_altmode.c              |  17 ++-
 drivers/soundwire/stream.c                         |   8 +-
 drivers/usb/cdns3/cdnsp-gadget.h                   |   3 +
 drivers/usb/cdns3/cdnsp-ring.c                     |  30 +++-
 drivers/usb/class/cdc-acm.c                        |   3 +
 drivers/usb/core/sysfs.c                           |   1 +
 drivers/usb/dwc3/core.c                            |   8 ++
 drivers/usb/dwc3/dwc3-omap.c                       |   4 +-
 drivers/usb/dwc3/dwc3-st.c                         |  16 +--
 drivers/usb/dwc3/dwc3-xilinx.c                     |   7 +-
 drivers/usb/dwc3/ep0.c                             |   3 +-
 drivers/usb/gadget/function/uvc_video.c            |   1 +
 drivers/usb/serial/option.c                        |   5 +
 drivers/usb/typec/mux/fsa4480.c                    |   2 +-
 drivers/usb/typec/ucsi/ucsi_glink.c                |  43 ++++--
 drivers/video/aperture.c                           |  11 +-
 fs/afs/inode.c                                     |  11 +-
 fs/attr.c                                          |  14 +-
 fs/backing-file.c                                  |   5 +-
 fs/binfmt_elf_fdpic.c                              |   3 +
 fs/btrfs/bio.c                                     |  26 ++--
 fs/btrfs/qgroup.c                                  |   2 +
 fs/ceph/inode.c                                    |   1 +
 fs/erofs/zutil.c                                   |   3 +-
 fs/netfs/io.c                                      |   1 +
 fs/netfs/misc.c                                    |  60 ++++++--
 fs/netfs/write_collect.c                           |   7 +
 fs/nfsd/nfs4state.c                                |  62 +++++---
 fs/nfsd/nfs4xdr.c                                  |   6 +-
 fs/nfsd/state.h                                    |   2 +-
 fs/smb/client/cifsglob.h                           |   1 -
 fs/smb/client/cifssmb.c                            |   1 -
 fs/smb/client/smb2ops.c                            |  24 +++-
 fs/smb/client/smb2pdu.c                            |   4 +-
 include/linux/fs.h                                 |   1 +
 include/linux/soc/qcom/pmic_glink.h                |  11 +-
 include/linux/sysfb.h                              |   4 +-
 include/net/bonding.h                              |   2 +-
 include/net/busy_poll.h                            |   2 +-
 include/net/netfilter/nf_tables_ipv4.h             |  10 +-
 include/net/netfilter/nf_tables_ipv6.h             |   5 +-
 io_uring/kbuf.c                                    |   2 +-
 mm/truncate.c                                      |   4 +-
 net/bluetooth/hci_core.c                           |  10 +-
 net/core/net-sysfs.c                               |   2 +-
 net/core/pktgen.c                                  |   4 +-
 net/ethtool/ioctl.c                                |   3 +
 net/ipv4/tcp.c                                     |  18 ++-
 net/mptcp/fastopen.c                               |   4 +-
 net/mptcp/options.c                                |  50 +++----
 net/mptcp/pm.c                                     |  32 +++--
 net/mptcp/pm_netlink.c                             | 107 +++++++++-----
 net/mptcp/protocol.c                               |  65 +++++----
 net/mptcp/protocol.h                               |   9 +-
 net/mptcp/sched.c                                  |   4 +-
 net/mptcp/sockopt.c                                |   4 +-
 net/mptcp/subflow.c                                |  56 ++++----
 net/sched/sch_fq.c                                 |   4 +-
 net/sctp/sm_statefuns.c                            |  22 ++-
 security/apparmor/policy_unpack_test.c             |   6 +-
 security/selinux/hooks.c                           |   4 +-
 security/smack/smack_lsm.c                         |   4 +-
 sound/core/seq/seq_clientmgr.c                     |   3 +
 sound/pci/hda/cs35l56_hda.c                        |   2 +-
 sound/pci/hda/patch_realtek.c                      |   2 +
 sound/soc/amd/acp/acp-legacy-mach.c                |   2 +
 sound/soc/codecs/cs-amp-lib-test.c                 |   9 ++
 sound/soc/codecs/cs-amp-lib.c                      |   7 +-
 sound/soc/sof/amd/acp-dsp-offset.h                 |   6 +-
 sound/soc/sof/amd/acp.c                            |  52 ++++---
 sound/soc/sof/amd/acp.h                            |   9 +-
 sound/soc/sof/amd/pci-acp63.c                      |   2 +
 sound/soc/sof/amd/pci-rmb.c                        |   2 +
 sound/soc/sof/amd/pci-rn.c                         |   2 +
 tools/testing/selftests/iommu/iommufd.c            |   6 +-
 .../selftests/net/forwarding/local_termination.sh  |   4 +
 .../selftests/net/forwarding/no_forwarding.sh      |   3 +
 tools/testing/selftests/net/mptcp/mptcp_join.sh    |  57 +++++---
 156 files changed, 1613 insertions(+), 711 deletions(-)
author maintainer
#1 lore raw

PATCH 1/149 drm/amdgpu/mes: fix mes ring buffer overflow

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jack Xiao <[email protected]>

commit 11752c013f562a1124088a35bd314aa0e9f0e88f upstream.

wait memory room until enough before writing mes packets to avoid ring buffer overflow.

v2: squash in sched_hw_submission fix

Fixes de3246254156 ("drm/amdgpu: cleanup MES11 command submission")
Fixes fffe347e1478 ("drm/amdgpu: cleanup MES12 command submission")
(cherry picked from commit 34e087e8920e635c62e2ed6a758b0cd27f836d13)
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c |    2 ++
 drivers/gpu/drm/amd/amdgpu/mes_v11_0.c   |   18 ++++++++++++++----
 2 files changed, 16 insertions(+), 4 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +2 -0
@@ -212,6 +212,8 @@ int amdgpu_ring_init(struct amdgpu_devic
 	 */
 	if (ring->funcs->type == AMDGPU_RING_TYPE_KIQ)
 		sched_hw_submission = max(sched_hw_submission, 256);
+	if (ring->funcs->type == AMDGPU_RING_TYPE_MES)
+		sched_hw_submission = 8;
 	else if (ring == &adev->sdma.instance[0].page)
 		sched_hw_submission = 256;
 
drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +14 -4
@@ -163,7 +163,7 @@ static int mes_v11_0_submit_pkt_and_poll
 	const char *op_str, *misc_op_str;
 	unsigned long flags;
 	u64 status_gpu_addr;
-	u32 status_offset;
+	u32 seq, status_offset;
 	u64 *status_ptr;
 	signed long r;
 	int ret;
@@ -191,6 +191,13 @@ static int mes_v11_0_submit_pkt_and_poll
 	if (r)
 		goto error_unlock_free;
 
+	seq = ++ring->fence_drv.sync_seq;
+	r = amdgpu_fence_wait_polling(ring,
+				      seq - ring->fence_drv.num_fences_mask,
+				      timeout);
+	if (r < 1)
+		goto error_undo;
+
 	api_status = (struct MES_API_STATUS *)((char *)pkt + api_status_off);
 	api_status->api_completion_fence_addr = status_gpu_addr;
 	api_status->api_completion_fence_value = 1;
@@ -203,8 +210,7 @@ static int mes_v11_0_submit_pkt_and_poll
 	mes_status_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS;
 	mes_status_pkt.api_status.api_completion_fence_addr =
 		ring->fence_drv.gpu_addr;
-	mes_status_pkt.api_status.api_completion_fence_value =
-		++ring->fence_drv.sync_seq;
+	mes_status_pkt.api_status.api_completion_fence_value = seq;
 
 	amdgpu_ring_write_multiple(ring, &mes_status_pkt,
 				   sizeof(mes_status_pkt) / 4);
@@ -224,7 +230,7 @@ static int mes_v11_0_submit_pkt_and_poll
 		dev_dbg(adev->dev, "MES msg=%d was emitted\n",
 			x_pkt->header.opcode);
 
-	r = amdgpu_fence_wait_polling(ring, ring->fence_drv.sync_seq, timeout);
+	r = amdgpu_fence_wait_polling(ring, seq, timeout);
 	if (r < 1 || !*status_ptr) {
 
 		if (misc_op_str)
@@ -247,6 +253,10 @@ static int mes_v11_0_submit_pkt_and_poll
 	amdgpu_device_wb_free(adev, status_offset);
 	return 0;
 
+error_undo:
+	dev_err(adev->dev, "MES ring buffer is full.\n");
+	amdgpu_ring_undo(ring);
+
 error_unlock_free:
 	spin_unlock_irqrestore(&mes->ring_lock, flags);
 
author maintainer
#2 lore raw

PATCH 2/149 erofs: fix out-of-bound access when z_erofs_gbuf_growsize() partially fails

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Gao Xiang <[email protected]>

commit 0005e01e1e875c5e27130c5e2ed0189749d1e08a upstream.

If z_erofs_gbuf_growsize() partially fails on a global buffer due to memory allocation failure or fault injection (as reported by syzbot [1]), new pages need to be freed by comparing to the existing pages to avoid memory leaks.

However, the old gbuf->pages[] array may not be large enough, which can lead to null-ptr-deref or out-of-bound access.

Fix this by checking against gbuf->nrpages in advance.

[1] https://lore.kernel.org/r/[email protected]

Reported-by [email protected]
Fixes d6db47e571dc ("erofs: do not use pagepool in z_erofs_gbuf_growsize()")
Cc <[email protected]> # 6.10+
---
 fs/erofs/zutil.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
fs/erofs/zutil.c +2 -1
@@ -111,7 +111,8 @@ int z_erofs_gbuf_growsize(unsigned int n
 out:
 	if (i < z_erofs_gbuf_count && tmp_pages) {
 		for (j = 0; j < nrpages; ++j)
-			if (tmp_pages[j] && tmp_pages[j] != gbuf->pages[j])
+			if (tmp_pages[j] && (j >= gbuf->nrpages ||
+					     tmp_pages[j] != gbuf->pages[j]))
 				__free_page(tmp_pages[j]);
 		kfree(tmp_pages);
 	}
author maintainer
#3 lore raw

PATCH 3/149 ALSA: seq: Skip event type filtering for UMP events

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Takashi Iwai <[email protected]>

commit 32108c22ac619c32dd6db594319e259b63bfb387 upstream.

UMP events don't use the event type field, hence it's invalid to apply the filter, which may drop the events unexpectedly.
Skip the event filtering for UMP events, instead.

---
 sound/core/seq/seq_clientmgr.c |    3 +++
 1 file changed, 3 insertions(+)
sound/core/seq/seq_clientmgr.c +3 -0
@@ -537,6 +537,9 @@ static struct snd_seq_client *get_event_
 		return NULL;
 	if (! dest->accept_input)
 		goto __not_avail;
+	if (snd_seq_ev_is_ump(event))
+		return dest; /* ok - no filter checks */
+
 	if ((dest->filter & SNDRV_SEQ_FILTER_USE_EVENT) &&
 	    ! test_bit(event->type, dest->event_filter))
 		goto __not_avail;
author maintainer
#4 lore raw

PATCH 4/149 ALSA: hda/realtek: Enable mute/micmute LEDs on HP Laptop 14-ey0xxx

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: John Sweeney <[email protected]>

commit 56314c0d78d6f5a60c8804c517167991a879e14a upstream.

HP Pavilion Plus 14-ey0xxx needs existing quirk ALC245_FIXUP_HP_X360_MUTE_LEDS to enable its mute/micmute LEDs.

---
 sound/pci/hda/patch_realtek.c |    1 +
 1 file changed, 1 insertion(+)
sound/pci/hda/patch_realtek.c +1 -0
@@ -10221,6 +10221,7 @@ static const struct snd_pci_quirk alc269
 	SND_PCI_QUIRK(0x103c, 0x8c15, "HP Spectre x360 2-in-1 Laptop 14-eu0xxx", ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX),
 	SND_PCI_QUIRK(0x103c, 0x8c16, "HP Spectre 16", ALC287_FIXUP_CS35L41_I2C_2),
 	SND_PCI_QUIRK(0x103c, 0x8c17, "HP Spectre 16", ALC287_FIXUP_CS35L41_I2C_2),
+	SND_PCI_QUIRK(0x103c, 0x8c21, "HP Pavilion Plus Laptop 14-ey0XXX", ALC245_FIXUP_HP_X360_MUTE_LEDS),
 	SND_PCI_QUIRK(0x103c, 0x8c46, "HP EliteBook 830 G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
 	SND_PCI_QUIRK(0x103c, 0x8c47, "HP EliteBook 840 G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
 	SND_PCI_QUIRK(0x103c, 0x8c48, "HP EliteBook 860 G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
author maintainer
#5 lore raw

PATCH 5/149 ALSA: hda/realtek: support HP Pavilion Aero 13-bg0xxx Mute LED

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Hendrik Borghorst <[email protected]>

commit 2dc43c5e212036458ed7c5586fb82ee183fee504 upstream.

This patch adds the HP Pavilion Aero 13 (13-bg0xxx) (year 2024) to list of quirks for keyboard LED mute indication.

The laptop has two LEDs (one for speaker and one for mic mute). The pre-existing quirk ALC245_FIXUP_HP_X360_MUTE_LEDS chains both the quirk for mic and speaker mute.

Tested on 6.11.0-rc4 with the aforementioned laptop.

---
 sound/pci/hda/patch_realtek.c |    1 +
 1 file changed, 1 insertion(+)
sound/pci/hda/patch_realtek.c +1 -0
@@ -10260,6 +10260,7 @@ static const struct snd_pci_quirk alc269
 	SND_PCI_QUIRK(0x103c, 0x8ca2, "HP ZBook Power", ALC236_FIXUP_HP_GPIO_LED),
 	SND_PCI_QUIRK(0x103c, 0x8ca4, "HP ZBook Fury", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
 	SND_PCI_QUIRK(0x103c, 0x8ca7, "HP ZBook Fury", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
+	SND_PCI_QUIRK(0x103c, 0x8cbd, "HP Pavilion Aero Laptop 13-bg0xxx", ALC245_FIXUP_HP_X360_MUTE_LEDS),
 	SND_PCI_QUIRK(0x103c, 0x8cdd, "HP Spectre", ALC287_FIXUP_CS35L41_I2C_2),
 	SND_PCI_QUIRK(0x103c, 0x8cde, "HP Spectre", ALC287_FIXUP_CS35L41_I2C_2),
 	SND_PCI_QUIRK(0x103c, 0x8cdf, "HP SnowWhite", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
author maintainer
#6 lore raw

PATCH 6/149 LoongArch: Remove the unused dma-direct.h

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Miao Wang <[email protected]>

commit 58aec91efb93338d1cc7acc0a93242613a2a4e5f upstream.

dma-direct.h is introduced in commit d4b6f1562a3c3284 ("LoongArch: Add Non-Uniform Memory Access (NUMA) support"). In commit c78c43fe7d42524c ("LoongArch: Use acpi_arch_dma_setup() and remove ARCH_HAS_PHYS_TO_DMA"), ARCH_HAS_PHYS_TO_DMA was deselected and the coresponding phys_to_dma()/ dma_to_phys() functions were removed. However, the unused dma-direct.h was left behind, which is removed by this patch.

Fixes c78c43fe7d42 ("LoongArch: Use acpi_arch_dma_setup() and remove ARCH_HAS_PHYS_TO_DMA")
---
 arch/loongarch/include/asm/dma-direct.h |   11 -----------
 1 file changed, 11 deletions(-)
 delete mode 100644 arch/loongarch/include/asm/dma-direct.h
arch/loongarch/include/asm/dma-direct.h deleted +0 -11
@@ -1,11 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
- */
-#ifndef _LOONGARCH_DMA_DIRECT_H
-#define _LOONGARCH_DMA_DIRECT_H
-
-dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
-phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
-
-#endif /* _LOONGARCH_DMA_DIRECT_H */
author maintainer
#7 lore raw

PATCH 7/149 LoongArch: Add ifdefs to fix LSX and LASX related warnings

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Tiezhu Yang <[email protected]>

commit 80376323e2b6a4559f86b2b4d864848ac25cb054 upstream.

There exist some warnings when building kernel if CONFIG_CPU_HAS_LBT is set but CONFIG_CPU_HAS_LSX and CONFIG_CPU_HAS_LASX are not set. In this case, there are no definitions of _restore_lsx & _restore_lasx and there are also no definitions of kvm_restore_lsx & kvm_restore_lasx in fpu.S and switch.S respectively, just add some ifdefs to fix these warnings.

AS arch/loongarch/kernel/fpu.o
arch/loongarch/kernel/fpu.o: warning: objtool: unexpected relocation symbol type in .rela.discard.func_stack_frame_non_standard: 0 arch/loongarch/kernel/fpu.o: warning: objtool: unexpected relocation symbol type in .rela.discard.func_stack_frame_non_standard: 0

AS [M] arch/loongarch/kvm/switch.o
arch/loongarch/kvm/switch.o: warning: objtool: unexpected relocation symbol type in .rela.discard.func_stack_frame_non_standard: 0 arch/loongarch/kvm/switch.o: warning: objtool: unexpected relocation symbol type in .rela.discard.func_stack_frame_non_standard: 0

MODPOST Module.symvers
ERROR: modpost: "kvm_restore_lsx" [arch/loongarch/kvm/kvm.ko] undefined!
ERROR: modpost: "kvm_restore_lasx" [arch/loongarch/kvm/kvm.ko] undefined!

---
 arch/loongarch/kernel/fpu.S | 4 ++++
 arch/loongarch/kvm/switch.S | 4 ++++
 2 files changed, 8 insertions(+)
arch/loongarch/kernel/fpu.S +4 -0
index 69a85f2479fb..6ab640101457 100644
@@ -530,6 +530,10 @@ SYM_FUNC_END(_restore_lasx_context)
 
 #ifdef CONFIG_CPU_HAS_LBT
 STACK_FRAME_NON_STANDARD _restore_fp
+#ifdef CONFIG_CPU_HAS_LSX
 STACK_FRAME_NON_STANDARD _restore_lsx
+#endif
+#ifdef CONFIG_CPU_HAS_LASX
 STACK_FRAME_NON_STANDARD _restore_lasx
 #endif
+#endif
arch/loongarch/kvm/switch.S +4 -0
index 80e988985a6a..0c292f818492 100644
@@ -277,6 +277,10 @@ SYM_DATA(kvm_enter_guest_size, .quad kvm_enter_guest_end - kvm_enter_guest)
 
 #ifdef CONFIG_CPU_HAS_LBT
 STACK_FRAME_NON_STANDARD kvm_restore_fpu
+#ifdef CONFIG_CPU_HAS_LSX
 STACK_FRAME_NON_STANDARD kvm_restore_lsx
+#endif
+#ifdef CONFIG_CPU_HAS_LASX
 STACK_FRAME_NON_STANDARD kvm_restore_lasx
 #endif
+#endif
Signature · 1 line
2.46.0
author maintainer
#8 lore raw

PATCH 8/149 tpm: ibmvtpm: Call tpm2_sessions_init() to initialize session support

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Stefan Berger <[email protected]>

commit 08d08e2e9f0ad1af0044e4747723f66677c35ee9 upstream.

Commit d2add27cf2b8 ("tpm: Add NULL primary creation") introduced CONFIG_TCG_TPM2_HMAC. When this option is enabled on ppc64 then the following message appears in the kernel log due to a missing call to tpm2_sessions_init().

[    2.654549] tpm tpm0: auth session is not active

Add the missing call to tpm2_session_init() to the ibmvtpm driver to resolve this issue.

Cc [email protected] # v6.10+
Fixes d2add27cf2b8 ("tpm: Add NULL primary creation")
---
 drivers/char/tpm/tpm_ibmvtpm.c | 4 ++++
 1 file changed, 4 insertions(+)
drivers/char/tpm/tpm_ibmvtpm.c +4 -0
index d3989b257f42..1e5b107d1f3b 100644
@@ -698,6 +698,10 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
 		rc = tpm2_get_cc_attrs_tbl(chip);
 		if (rc)
 			goto init_irq_cleanup;
+
+		rc = tpm2_sessions_init(chip);
+		if (rc)
+			goto init_irq_cleanup;
 	}
 
 	return tpm_chip_register(chip);
Signature · 1 line
2.46.0
#9 lore raw

breaks ibmvtpm to be built as a module, since tpm2_sessions_init isn't

------------------

From 3e43cfa3466178ec7f4309031647e93565bc70bf Mon Sep 17 00:00:00 2001
From: Kexy Biscuit <[email protected]>
Date: Mon, 2 Sep 2024 08:26:38 +0800
Subject: [PATCH] tpm: export tpm2_sessions_init() to fix ibmvtpm building

Commit 08d08e2e9f0a ("tpm: ibmvtpm: Call tpm2_sessions_init() to initialize session support") adds call to tpm2_sessions_init() in ibmvtpm, which could be built as a module. However, tpm2_sessions_init() wasn't exported, causing libmvtpm to fail to build as a module:

ERROR: modpost: "tpm2_sessions_init" [drivers/char/tpm/tpm_ibmvtpm.ko] undefined!

Export tpm2_sessions_init() to resolve the issue.

---
 drivers/char/tpm/tpm2-sessions.c | 1 +
 1 file changed, 1 insertion(+)
drivers/char/tpm/tpm2-sessions.c +1 -0
index d3521aadd43ee..44f60730cff44 100644
@@ -1362,4 +1362,5 @@ int tpm2_sessions_init(struct tpm_chip *chip)
 
 	return rc;
 }
+EXPORT_SYMBOL(tpm2_sessions_init);
 #endif /* CONFIG_TCG_TPM2_HMAC */
Signature · 1 line
2.46.0
#10 lore raw

PATCH 1/1 tpm: export tpm2_sessions_init() to fix ibmvtpm building

In reply to Greg Kroah-Hartman

"tpm: ibmvtpm: Call tpm2_sessions_init() to initialize session support" breaks ibmvtpm to be built as a module, since tpm2_sessions_init isn't an exported symbol. Proposing the following patch to resolve the issue.

Also, please disregard for the previous incorrectly formatted email.
---

From 3e43cfa3466178ec7f4309031647e93565bc70bf Mon Sep 17 00:00:00 2001
From: Kexy Biscuit <[email protected]>
Date: Mon, 2 Sep 2024 08:26:38 +0800
Subject: [PATCH] tpm: export tpm2_sessions_init() to fix ibmvtpm building

Commit 08d08e2e9f0a ("tpm: ibmvtpm: Call tpm2_sessions_init() to initialize session support") adds call to tpm2_sessions_init() in ibmvtpm, which could be built as a module. However, tpm2_sessions_init() wasn't exported, causing libmvtpm to fail to build as a module:

ERROR: modpost: "tpm2_sessions_init" [drivers/char/tpm/tpm_ibmvtpm.ko] undefined!

Export tpm2_sessions_init() to resolve the issue.

---
 drivers/char/tpm/tpm2-sessions.c | 1 +
 1 file changed, 1 insertion(+)
drivers/char/tpm/tpm2-sessions.c +1 -0
index d3521aadd43ee..44f60730cff44 100644
@@ -1362,4 +1362,5 @@ int tpm2_sessions_init(struct tpm_chip *chip)
 
 	return rc;
 }
+EXPORT_SYMBOL(tpm2_sessions_init);
 #endif /* CONFIG_TCG_TPM2_HMAC */
Signature · 1 line
2.46.0
author maintainer
#11 lore raw

Re: [PATCH] tpm: export tpm2_sessions_init() to fix ibmvtpm building

Quoted 17 lines · Kexy Biscuit

"tpm: ibmvtpm: Call tpm2_sessions_init() to initialize session support" breaks ibmvtpm to be built as a module, since tpm2_sessions_init isn't an exported symbol. Proposing the following patch to resolve the issue.

Also, please disregard for the previous incorrectly formatted email.
---

Quoted 1 line

From 3e43cfa3466178ec7f4309031647e93565bc70bf Mon Sep 17 00:00:00 2001

From: Kexy Biscuit <[email protected]>
Date: Mon, 2 Sep 2024 08:26:38 +0800
Subject: [PATCH] tpm: export tpm2_sessions_init() to fix ibmvtpm building

Commit 08d08e2e9f0a ("tpm: ibmvtpm: Call tpm2_sessions_init() to initialize session support") adds call to tpm2_sessions_init() in ibmvtpm, which could be built as a module. However, tpm2_sessions_init() wasn't exported, causing libmvtpm to fail to build as a module:

Quoted 5 lines

ERROR: modpost: "tpm2_sessions_init" [drivers/char/tpm/tpm_ibmvtpm.ko] undefined!

Export tpm2_sessions_init() to resolve the issue.

Cc [email protected] # v6.10+

Put the git commit id in a Fixes: tag please?

Quoted 7 lines
---
 drivers/char/tpm/tpm2-sessions.c | 1 +
 1 file changed, 1 insertion(+)

For some reason this patch is attached, and that will not work. Please fix up and resend using 'git send-email' or some such tool so that it can be applied properly.

thanks,

greg k-h

#12 lore raw

PATCH v2 1/1 tpm: export tpm2_sessions_init() to fix ibmvtpm building

In reply to Greg Kroah-Hartman

Commit 08d08e2e9f0a ("tpm: ibmvtpm: Call tpm2_sessions_init() to initialize session support") adds call to tpm2_sessions_init() in ibmvtpm, which could be built as a module. However, tpm2_sessions_init() wasn't exported, causing libmvtpm to fail to build as a module:

ERROR: modpost: "tpm2_sessions_init" [drivers/char/tpm/tpm_ibmvtpm.ko] undefined!

Export tpm2_sessions_init() to resolve the issue.

Cc [email protected] # v6.10+
Fixes 08d08e2e9f0a ("tpm: ibmvtpm: Call tpm2_sessions_init() to initialize session support")

---
V1 -> V2: Added Fixes tag and fixed email format

 drivers/char/tpm/tpm2-sessions.c | 1 +
 1 file changed, 1 insertion(+)
drivers/char/tpm/tpm2-sessions.c +1 -0
index d3521aadd43e..44f60730cff4 100644
@@ -1362,4 +1362,5 @@ int tpm2_sessions_init(struct tpm_chip *chip)
 
 	return rc;
 }
+EXPORT_SYMBOL(tpm2_sessions_init);
 #endif /* CONFIG_TCG_TPM2_HMAC */
Signature · 1 line
2.46.0
author maintainer
#13 lore raw

PATCH 9/149 btrfs: fix a use-after-free when hitting errors inside btrfs_submit_chunk()

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Qu Wenruo <[email protected]>

commit 10d9d8c3512f16cad47b2ff81ec6fc4b27d8ee10 upstream.

[BUG]
There is an internal report that KASAN is reporting use-after-free, with the following backtrace:

  BUG: KASAN: slab-use-after-free in btrfs_check_read_bio+0xa68/0xb70 [btrfs]
  Read of size 4 at addr ffff8881117cec28 by task kworker/u16:2/45
  CPU: 1 UID: 0 PID: 45 Comm: kworker/u16:2 Not tainted 6.11.0-rc2-next-20240805-default+ #76
  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.2-3-gd478f380-rebuilt.opensuse.org 04/01/2014
  Workqueue: btrfs-endio btrfs_end_bio_work [btrfs]
  Call Trace:
   dump_stack_lvl+0x61/0x80
   print_address_description.constprop.0+0x5e/0x2f0
   print_report+0x118/0x216
   kasan_report+0x11d/0x1f0
   btrfs_check_read_bio+0xa68/0xb70 [btrfs]
   process_one_work+0xce0/0x12a0
   worker_thread+0x717/0x1250
   kthread+0x2e3/0x3c0
   ret_from_fork+0x2d/0x70
   ret_from_fork_asm+0x11/0x20

  Allocated by task 20917:
   kasan_save_stack+0x37/0x60
   kasan_save_track+0x10/0x30
   __kasan_slab_alloc+0x7d/0x80
   kmem_cache_alloc_noprof+0x16e/0x3e0
   mempool_alloc_noprof+0x12e/0x310
   bio_alloc_bioset+0x3f0/0x7a0
   btrfs_bio_alloc+0x2e/0x50 [btrfs]
   submit_extent_page+0x4d1/0xdb0 [btrfs]
   btrfs_do_readpage+0x8b4/0x12a0 [btrfs]
   btrfs_readahead+0x29a/0x430 [btrfs]
   read_pages+0x1a7/0xc60
   page_cache_ra_unbounded+0x2ad/0x560
   filemap_get_pages+0x629/0xa20
   filemap_read+0x335/0xbf0
   vfs_read+0x790/0xcb0
   ksys_read+0xfd/0x1d0
   do_syscall_64+0x6d/0x140
   entry_SYSCALL_64_after_hwframe+0x4b/0x53

  Freed by task 20917:
   kasan_save_stack+0x37/0x60
   kasan_save_track+0x10/0x30
   kasan_save_free_info+0x37/0x50
   __kasan_slab_free+0x4b/0x60
   kmem_cache_free+0x214/0x5d0
   bio_free+0xed/0x180
   end_bbio_data_read+0x1cc/0x580 [btrfs]
   btrfs_submit_chunk+0x98d/0x1880 [btrfs]
   btrfs_submit_bio+0x33/0x70 [btrfs]
   submit_one_bio+0xd4/0x130 [btrfs]
   submit_extent_page+0x3ea/0xdb0 [btrfs]
   btrfs_do_readpage+0x8b4/0x12a0 [btrfs]
   btrfs_readahead+0x29a/0x430 [btrfs]
   read_pages+0x1a7/0xc60
   page_cache_ra_unbounded+0x2ad/0x560
   filemap_get_pages+0x629/0xa20
   filemap_read+0x335/0xbf0
   vfs_read+0x790/0xcb0
   ksys_read+0xfd/0x1d0
   do_syscall_64+0x6d/0x140
   entry_SYSCALL_64_after_hwframe+0x4b/0x53

[CAUSE]
Although I cannot reproduce the error, the report itself is good enough to pin down the cause.

The call trace is the regular endio workqueue context, but the free-by-task trace is showing that during btrfs_submit_chunk() we already hit a critical error, and is calling btrfs_bio_end_io() to error out. And the original endio function called bio_put() to free the whole bio.

This means a double freeing thus causing use-after-free, e.g.:

1. Enter btrfs_submit_bio() with a read bio
The read bio length is 128K, crossing two 64K stripes.

2. The first run of btrfs_submit_chunk()

2.1 Call btrfs_map_block(), which returns 64K
2.2 Call btrfs_split_bio()
Now there are two bios, one referring to the first 64K, the other referring to the second 64K.
2.3 The first half is submitted.

3. The second run of btrfs_submit_chunk()

3.1 Call btrfs_map_block(), which by somehow failed
Now we call btrfs_bio_end_io() to handle the error

3.2 btrfs_bio_end_io() calls the original endio function
Which is end_bbio_data_read(), and it calls bio_put() for the original bio.

Now the original bio is freed.

4. The submitted first 64K bio finished
Now we call into btrfs_check_read_bio() and tries to advance the bio iter.
But since the original bio (thus its iter) is already freed, we trigger the above use-after free.

And even if the memory is not poisoned/corrupted, we will later call the original endio function, causing a double freeing.

[FIX]
Instead of calling btrfs_bio_end_io(), call btrfs_orig_bbio_end_io(), which has the extra check on split bios and do the proper refcounting for cloned bios.

Furthermore there is already one extra btrfs_cleanup_bio() call, but that is duplicated to btrfs_orig_bbio_end_io() call, so remove that label completely.

Fixes 852eee62d31a ("btrfs: allow btrfs_submit_bio to split bios")
---
 fs/btrfs/bio.c |   26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)
fs/btrfs/bio.c +18 -8
@@ -668,7 +668,6 @@ static bool btrfs_submit_chunk(struct bt
 {
 	struct btrfs_inode *inode = bbio->inode;
 	struct btrfs_fs_info *fs_info = bbio->fs_info;
-	struct btrfs_bio *orig_bbio = bbio;
 	struct bio *bio = &bbio->bio;
 	u64 logical = bio->bi_iter.bi_sector << SECTOR_SHIFT;
 	u64 length = bio->bi_iter.bi_size;
@@ -706,7 +705,7 @@ static bool btrfs_submit_chunk(struct bt
 		bbio->saved_iter = bio->bi_iter;
 		ret = btrfs_lookup_bio_sums(bbio);
 		if (ret)
-			goto fail_put_bio;
+			goto fail;
 	}
 
 	if (btrfs_op(bio) == BTRFS_MAP_WRITE) {
@@ -740,13 +739,13 @@ static bool btrfs_submit_chunk(struct bt
 
 			ret = btrfs_bio_csum(bbio);
 			if (ret)
-				goto fail_put_bio;
+				goto fail;
 		} else if (use_append ||
 			   (btrfs_is_zoned(fs_info) && inode &&
 			    inode->flags & BTRFS_INODE_NODATASUM)) {
 			ret = btrfs_alloc_dummy_sum(bbio);
 			if (ret)
-				goto fail_put_bio;
+				goto fail;
 		}
 	}
 
@@ -754,12 +753,23 @@ static bool btrfs_submit_chunk(struct bt
 done:
 	return map_length == length;
 
-fail_put_bio:
-	if (map_length < length)
-		btrfs_cleanup_bio(bbio);
 fail:
 	btrfs_bio_counter_dec(fs_info);
-	btrfs_bio_end_io(orig_bbio, ret);
+	/*
+	 * We have split the original bbio, now we have to end both the current
+	 * @bbio and remaining one, as the remaining one will never be submitted.
+	 */
+	if (map_length < length) {
+		struct btrfs_bio *remaining = bbio->private;
+
+		ASSERT(bbio->bio.bi_pool == &btrfs_clone_bioset);
+		ASSERT(remaining);
+
+		remaining->bio.bi_status = ret;
+		btrfs_orig_bbio_end_io(remaining);
+	}
+	bbio->bio.bi_status = ret;
+	btrfs_orig_bbio_end_io(bbio);
 	/* Do not submit another chunk */
 	return true;
 }
author maintainer
#14 lore raw

PATCH 10/149 btrfs: run delayed iputs when flushing delalloc

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Josef Bacik <[email protected]>

commit 2d3447261031503b181dacc549fe65ffe2d93d65 upstream.

We have transient failures with btrfs/301, specifically in the part where we do

for i in $(seq 0 10); do
write 50m to file
rm -f file
done

Sometimes this will result in a transient quota error, and it's because sometimes we start writeback on the file which results in a delayed iput, and thus the rm doesn't actually clean the file up. When we're flushing the quota space we need to run the delayed iputs to make sure all the unlinks that we think have completed have actually completed. This removes the small window where we could fail to find enough space in our quota.

---
 fs/btrfs/qgroup.c |    2 ++
 1 file changed, 2 insertions(+)
fs/btrfs/qgroup.c +2 -0
@@ -4100,6 +4100,8 @@ static int try_flush_qgroup(struct btrfs
 		return 0;
 	}
 
+	btrfs_run_delayed_iputs(root->fs_info);
+	btrfs_wait_on_delayed_iputs(root->fs_info);
 	ret = btrfs_start_delalloc_snapshot(root, true);
 	if (ret < 0)
 		goto out;
author maintainer
#15 lore raw

PATCH 11/149 smb/client: avoid dereferencing rdata=NULL in smb2_new_read_req()

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Stefan Metzmacher <[email protected]>

commit c724b2ab6a46435b4e7d58ad2fbbdb7a318823cf upstream.

This happens when called from SMB2_read() while using rdma and reaching the rdma_readwrite_threshold.

Fixes a6559cc1d35d ("cifs: split out smb3_use_rdma_offload() helper")
---
 fs/smb/client/smb2pdu.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/smb/client/smb2pdu.c +1 -1
@@ -4435,7 +4435,7 @@ smb2_new_read_req(void **buf, unsigned i
 	 * If we want to do a RDMA write, fill in and append
 	 * smbd_buffer_descriptor_v1 to the end of read request
 	 */
-	if (smb3_use_rdma_offload(io_parms)) {
+	if (rdata && smb3_use_rdma_offload(io_parms)) {
 		struct smbd_buffer_descriptor_v1 *v1;
 		bool need_invalidate = server->dialect == SMB30_PROT_ID;
 
author maintainer
#16 lore raw

PATCH 12/149 pinctrl: rockchip: correct RK3328 iomux width flag for GPIO2-B pins

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Huang-Huang Bao <[email protected]>

commit 128f71fe014fc91efa1407ce549f94a9a9f1072c upstream.

The base iomux offsets for each GPIO pin line are accumulatively calculated based off iomux width flag in rockchip_pinctrl_get_soc_data. If the iomux width flag is one of IOMUX_WIDTH_4BIT, IOMUX_WIDTH_3BIT or IOMUX_WIDTH_2BIT, the base offset for next pin line would increase by 8 bytes, otherwise it would increase by 4 bytes.

Despite most of GPIO2-B iomux have 2-bit data width, which can be fit into 4 bytes space with write mask, it actually take 8 bytes width for whole GPIO2-B line.

Commit e8448a6c817c ("pinctrl: rockchip: fix pinmux bits for RK3328 GPIO2-B pins") wrongly set iomux width flag to 0, causing all base iomux offset for line after GPIO2-B to be calculated wrong. Fix the iomux width flag to IOMUX_WIDTH_2BIT so the offset after GPIO2-B is correctly increased by 8, matching the actual width of GPIO2-B iomux.

---
 drivers/pinctrl/pinctrl-rockchip.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pinctrl/pinctrl-rockchip.c +1 -1
@@ -3800,7 +3800,7 @@ static struct rockchip_pin_bank rk3328_p
 	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", 0, 0, 0, 0),
 	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", 0, 0, 0, 0),
 	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0,
-			     0,
+			     IOMUX_WIDTH_2BIT,
 			     IOMUX_WIDTH_3BIT,
 			     0),
 	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3",
author maintainer
#17 lore raw

PATCH 13/149 pinctrl: single: fix potential NULL dereference in pcs_get_function()

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ma Ke <[email protected]>

commit 1c38a62f15e595346a1106025722869e87ffe044 upstream.

pinmux_generic_get_function() can return NULL and the pointer 'function' was dereferenced without checking against NULL. Add checking of pointer 'function' in pcs_get_function().

Found by code review.

Fixes 571aec4df5b7 ("pinctrl: single: Use generic pinmux helpers for managing functions")
---
 drivers/pinctrl/pinctrl-single.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/pinctrl/pinctrl-single.c +2 -0
@@ -345,6 +345,8 @@ static int pcs_get_function(struct pinct
 		return -ENOTSUPP;
 	fselector = setting->func;
 	function = pinmux_generic_get_function(pctldev, fselector);
+	if (!function)
+		return -EINVAL;
 	*func = function->data;
 	if (!(*func)) {
 		dev_err(pcs->dev, "%s could not find function%i\n",
author maintainer
#18 lore raw

PATCH 14/149 netfs, ceph: Partially revert "netfs: Replace PG_fscache by setting folio->private and marking dirty"

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: David Howells <[email protected]>

commit 92764e8822d4e7f8efb5ad959fac195a7f8ea0c6 upstream.

This partially reverts commit 2ff1e97587f4d398686f52c07afde3faf3da4e5c.

In addition to reverting the removal of PG_private_2 wrangling from the buffered read code[1][2], the removal of the waits for PG_private_2 from netfs_release_folio() and netfs_invalidate_folio() need reverting too.

It also adds a wait into ceph_evict_inode() to wait for netfs read and copy-to-cache ops to complete.

---
 fs/ceph/inode.c |    1 +
 fs/netfs/misc.c |    7 +++++++
 2 files changed, 8 insertions(+)
fs/ceph/inode.c +1 -0
@@ -697,6 +697,7 @@ void ceph_evict_inode(struct inode *inod
 
 	percpu_counter_dec(&mdsc->metric.total_inodes);
 
+	netfs_wait_for_outstanding_io(inode);
 	truncate_inode_pages_final(&inode->i_data);
 	if (inode->i_state & I_PINNING_NETFS_WB)
 		ceph_fscache_unuse_cookie(inode, true);
fs/netfs/misc.c +7 -0
@@ -101,6 +101,8 @@ void netfs_invalidate_folio(struct folio
 
 	kenter("{%lx},%zx,%zx", folio->index, offset, length);
 
+	folio_wait_private_2(folio); /* [DEPRECATED] */
+
 	if (!folio_test_private(folio))
 		return;
 
@@ -165,6 +167,11 @@ bool netfs_release_folio(struct folio *f
 
 	if (folio_test_private(folio))
 		return false;
+	if (unlikely(folio_test_private_2(folio))) { /* [DEPRECATED] */
+		if (current_is_kswapd() || !(gfp & __GFP_FS))
+			return false;
+		folio_wait_private_2(folio);
+	}
 	fscache_note_page_release(netfs_i_cookie(ctx));
 	return true;
 }
author maintainer
#19 lore raw

PATCH 15/149 wifi: wfx: repair open network AP mode

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alexander Sverdlin <[email protected]>

commit 6d30bb88f623526197c0e18a366e68a4254a2c83 upstream.

RSN IE missing in beacon is normal in open networks. Avoid returning -EINVAL in this case.

Steps to reproduce:

$ cat /etc/wpa_supplicant.conf
network={
	ssid="testNet"
	mode=2
	key_mgmt=NONE
}
$ wpa_supplicant -iwlan0 -c /etc/wpa_supplicant.conf
nl80211: Beacon set failed: -22 (Invalid argument)
Failed to set beacon parameters
Interface initialization failed
wlan0: interface state UNINITIALIZED->DISABLED
wlan0: AP-DISABLED
wlan0: Unable to setup interface.
Failed to initialize AP interface

After the change:

$ wpa_supplicant -iwlan0 -c /etc/wpa_supplicant.conf
Successfully initialized wpa_supplicant
wlan0: interface state UNINITIALIZED->ENABLED
wlan0: AP-ENABLED
Fixes fe0a7776d4d1 ("wifi: wfx: fix possible NULL pointer dereference in wfx_set_mfp_ap()")
---
 drivers/net/wireless/silabs/wfx/sta.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/wireless/silabs/wfx/sta.c +4 -1
@@ -352,8 +352,11 @@ static int wfx_set_mfp_ap(struct wfx_vif
 
 	ptr = (u16 *)cfg80211_find_ie(WLAN_EID_RSN, skb->data + ieoffset,
 				      skb->len - ieoffset);
-	if (unlikely(!ptr))
+	if (!ptr) {
+		/* No RSN IE is fine in open networks */
+		ret = 0;
 		goto free_skb;
+	}
 
 	ptr += pairwise_cipher_suite_count_offset;
 	if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb)))
author maintainer
#20 lore raw

PATCH 16/149 wifi: mwifiex: duplicate static structs used in driver instances

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sascha Hauer <[email protected]>

commit 27ec3c57fcadb43c79ed05b2ea31bc18c72d798a upstream.

mwifiex_band_2ghz and mwifiex_band_5ghz are statically allocated, but used and modified in driver instances. Duplicate them before using them in driver instances so that different driver instances do not influence each other.

This was observed on a board which has one PCIe and one SDIO mwifiex adapter. It blew up in mwifiex_setup_ht_caps(). This was called with the statically allocated struct which is modified in this function.

---
 drivers/net/wireless/marvell/mwifiex/cfg80211.c |   32 +++++++++++++++++++-----
 1 file changed, 26 insertions(+), 6 deletions(-)
drivers/net/wireless/marvell/mwifiex/cfg80211.c +26 -6
@@ -4363,11 +4363,27 @@ int mwifiex_register_cfg80211(struct mwi
 	if (ISSUPP_ADHOC_ENABLED(adapter->fw_cap_info))
 		wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
 
-	wiphy->bands[NL80211_BAND_2GHZ] = &mwifiex_band_2ghz;
-	if (adapter->config_bands & BAND_A)
-		wiphy->bands[NL80211_BAND_5GHZ] = &mwifiex_band_5ghz;
-	else
+	wiphy->bands[NL80211_BAND_2GHZ] = devm_kmemdup(adapter->dev,
+						       &mwifiex_band_2ghz,
+						       sizeof(mwifiex_band_2ghz),
+						       GFP_KERNEL);
+	if (!wiphy->bands[NL80211_BAND_2GHZ]) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	if (adapter->config_bands & BAND_A) {
+		wiphy->bands[NL80211_BAND_5GHZ] = devm_kmemdup(adapter->dev,
+							       &mwifiex_band_5ghz,
+							       sizeof(mwifiex_band_5ghz),
+							       GFP_KERNEL);
+		if (!wiphy->bands[NL80211_BAND_5GHZ]) {
+			ret = -ENOMEM;
+			goto err;
+		}
+	} else {
 		wiphy->bands[NL80211_BAND_5GHZ] = NULL;
+	}
 
 	if (adapter->drcs_enabled && ISSUPP_DRCS_ENABLED(adapter->fw_cap_info))
 		wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta_drcs;
@@ -4461,8 +4477,7 @@ int mwifiex_register_cfg80211(struct mwi
 	if (ret < 0) {
 		mwifiex_dbg(adapter, ERROR,
 			    "%s: wiphy_register failed: %d\n", __func__, ret);
-		wiphy_free(wiphy);
-		return ret;
+		goto err;
 	}
 
 	if (!adapter->regd) {
@@ -4504,4 +4519,9 @@ int mwifiex_register_cfg80211(struct mwi
 
 	adapter->wiphy = wiphy;
 	return ret;
+
+err:
+	wiphy_free(wiphy);
+
+	return ret;
 }
author maintainer
#21 lore raw

PATCH 17/149 net: mana: Fix race of mana_hwc_post_rx_wqe and new hwc response

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Haiyang Zhang <[email protected]>

commit 8af174ea863c72f25ce31cee3baad8a301c0cf0f upstream.

The mana_hwc_rx_event_handler() / mana_hwc_handle_resp() calls complete(&ctx->comp_event) before posting the wqe back. It's possible that other callers, like mana_create_txq(), start the next round of mana_hwc_send_request() before the posting of wqe. And if the HW is fast enough to respond, it can hit no_wqe error on the HW channel, then the response message is lost. The mana driver may fail to create queues and open, because of waiting for the HW response and timed out.
Sample dmesg:

[  528.610840] mana 39d4:00:02.0: HWC: Request timed out!
[  528.614452] mana 39d4:00:02.0: Failed to send mana message: -110, 0x0
[  528.618326] mana 39d4:00:02.0 enP14804s2: Failed to create WQ object: -110

To fix it, move posting of rx wqe before complete(&ctx->comp_event).

Fixes ca9c54d2d6a5 ("net: mana: Add a driver for Microsoft Azure Network Adapter (MANA)")
---
 drivers/net/ethernet/microsoft/mana/hw_channel.c |   62 ++++++++++++-----------
 1 file changed, 34 insertions(+), 28 deletions(-)
drivers/net/ethernet/microsoft/mana/hw_channel.c +34 -28
@@ -52,9 +52,33 @@ static int mana_hwc_verify_resp_msg(cons
 	return 0;
 }
 
+static int mana_hwc_post_rx_wqe(const struct hwc_wq *hwc_rxq,
+				struct hwc_work_request *req)
+{
+	struct device *dev = hwc_rxq->hwc->dev;
+	struct gdma_sge *sge;
+	int err;
+
+	sge = &req->sge;
+	sge->address = (u64)req->buf_sge_addr;
+	sge->mem_key = hwc_rxq->msg_buf->gpa_mkey;
+	sge->size = req->buf_len;
+
+	memset(&req->wqe_req, 0, sizeof(struct gdma_wqe_request));
+	req->wqe_req.sgl = sge;
+	req->wqe_req.num_sge = 1;
+	req->wqe_req.client_data_unit = 0;
+
+	err = mana_gd_post_and_ring(hwc_rxq->gdma_wq, &req->wqe_req, NULL);
+	if (err)
+		dev_err(dev, "Failed to post WQE on HWC RQ: %d\n", err);
+	return err;
+}
+
 static void mana_hwc_handle_resp(struct hw_channel_context *hwc, u32 resp_len,
-				 const struct gdma_resp_hdr *resp_msg)
+				 struct hwc_work_request *rx_req)
 {
+	const struct gdma_resp_hdr *resp_msg = rx_req->buf_va;
 	struct hwc_caller_ctx *ctx;
 	int err;
 
@@ -62,6 +86,7 @@ static void mana_hwc_handle_resp(struct
 		      hwc->inflight_msg_res.map)) {
 		dev_err(hwc->dev, "hwc_rx: invalid msg_id = %u\n",
 			resp_msg->response.hwc_msg_id);
+		mana_hwc_post_rx_wqe(hwc->rxq, rx_req);
 		return;
 	}
 
@@ -75,30 +100,13 @@ static void mana_hwc_handle_resp(struct
 	memcpy(ctx->output_buf, resp_msg, resp_len);
 out:
 	ctx->error = err;
-	complete(&ctx->comp_event);
-}
-
-static int mana_hwc_post_rx_wqe(const struct hwc_wq *hwc_rxq,
-				struct hwc_work_request *req)
-{
-	struct device *dev = hwc_rxq->hwc->dev;
-	struct gdma_sge *sge;
-	int err;
-
-	sge = &req->sge;
-	sge->address = (u64)req->buf_sge_addr;
-	sge->mem_key = hwc_rxq->msg_buf->gpa_mkey;
-	sge->size = req->buf_len;
 
-	memset(&req->wqe_req, 0, sizeof(struct gdma_wqe_request));
-	req->wqe_req.sgl = sge;
-	req->wqe_req.num_sge = 1;
-	req->wqe_req.client_data_unit = 0;
+	/* Must post rx wqe before complete(), otherwise the next rx may
+	 * hit no_wqe error.
+	 */
+	mana_hwc_post_rx_wqe(hwc->rxq, rx_req);
 
-	err = mana_gd_post_and_ring(hwc_rxq->gdma_wq, &req->wqe_req, NULL);
-	if (err)
-		dev_err(dev, "Failed to post WQE on HWC RQ: %d\n", err);
-	return err;
+	complete(&ctx->comp_event);
 }
 
 static void mana_hwc_init_event_handler(void *ctx, struct gdma_queue *q_self,
@@ -235,14 +243,12 @@ static void mana_hwc_rx_event_handler(vo
 		return;
 	}
 
-	mana_hwc_handle_resp(hwc, rx_oob->tx_oob_data_size, resp);
+	mana_hwc_handle_resp(hwc, rx_oob->tx_oob_data_size, rx_req);
 
-	/* Do no longer use 'resp', because the buffer is posted to the HW
-	 * in the below mana_hwc_post_rx_wqe().
+	/* Can no longer use 'resp', because the buffer is posted to the HW
+	 * in mana_hwc_handle_resp() above.
 	 */
 	resp = NULL;
-
-	mana_hwc_post_rx_wqe(hwc_rxq, rx_req);
 }
 
 static void mana_hwc_tx_event_handler(void *ctx, u32 gdma_txq_id,
author maintainer
#22 lore raw

PATCH 18/149 mptcp: close subflow when receiving TCP+FIN

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matthieu Baerts (NGI0) <[email protected]>

commit f09b0ad55a1196f5891663f8888463c0541059cb upstream.

When a peer decides to close one subflow in the middle of a connection having multiple subflows, the receiver of the first FIN should accept that, and close the subflow on its side as well. If not, the subflow will stay half closed, and would even continue to be used until the end of the MPTCP connection or a reset from the network.

The issue has not been seen before, probably because the in-kernel path-manager always sends a RM_ADDR before closing the subflow. Upon the reception of this RM_ADDR, the other peer will initiate the closure on its side as well. On the other hand, if the RM_ADDR is lost, or if the path-manager of the other peer only closes the subflow without sending a RM_ADDR, the subflow would switch to TCP_CLOSE_WAIT, but that's it, leaving the subflow half-closed.

So now, when the subflow switches to the TCP_CLOSE_WAIT state, and if the MPTCP connection has not been closed before with a DATA_FIN, the kernel owning the subflow schedules its worker to initiate the closure on its side as well.

This issue can be easily reproduced with packetdrill, as visible in [1], by creating an additional subflow, injecting a FIN+ACK before sending the DATA_FIN, and expecting a FIN+ACK in return.

---
 net/mptcp/protocol.c |    5 ++++-
 net/mptcp/subflow.c  |    8 ++++++--
 2 files changed, 10 insertions(+), 3 deletions(-)
net/mptcp/protocol.c +4 -1
@@ -2533,8 +2533,11 @@ static void __mptcp_close_subflow(struct
 
 	mptcp_for_each_subflow_safe(msk, subflow, tmp) {
 		struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
+		int ssk_state = inet_sk_state_load(ssk);
 
-		if (inet_sk_state_load(ssk) != TCP_CLOSE)
+		if (ssk_state != TCP_CLOSE &&
+		    (ssk_state != TCP_CLOSE_WAIT ||
+		     inet_sk_state_load(sk) != TCP_ESTABLISHED))
 			continue;
 
 		/* 'subflow_data_ready' will re-sched once rx queue is empty */
net/mptcp/subflow.c +6 -2
@@ -1255,12 +1255,16 @@ out:
 /* sched mptcp worker to remove the subflow if no more data is pending */
 static void subflow_sched_work_if_closed(struct mptcp_sock *msk, struct sock *ssk)
 {
-	if (likely(ssk->sk_state != TCP_CLOSE))
+	struct sock *sk = (struct sock *)msk;
+
+	if (likely(ssk->sk_state != TCP_CLOSE &&
+		   (ssk->sk_state != TCP_CLOSE_WAIT ||
+		    inet_sk_state_load(sk) != TCP_ESTABLISHED)))
 		return;
 
 	if (skb_queue_empty(&ssk->sk_receive_queue) &&
 	    !test_and_set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags))
-		mptcp_schedule_work((struct sock *)msk);
+		mptcp_schedule_work(sk);
 }
 
 static bool subflow_can_fallback(struct mptcp_subflow_context *subflow)
author maintainer
#23 lore raw

PATCH 19/149 mptcp: sched: check both backup in retrans

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matthieu Baerts (NGI0) <[email protected]>

commit 2a1f596ebb23eadc0f9b95a8012e18ef76295fc8 upstream.

The 'mptcp_subflow_context' structure has two items related to the backup flags:

- 'backup': the subflow has been marked as backup by the other peer

- 'request_bkup': the backup flag has been set by the host

Looking only at the 'backup' flag can make sense in some cases, but it is not the behaviour of the default packet scheduler when selecting paths.

As explained in the commit b6a66e521a20 ("mptcp: sched: check both directions for backup"), the packet scheduler should look at both flags, because that was the behaviour from the beginning: the 'backup' flag was set by accident instead of the 'request_bkup' one. Now that the latter has been fixed, get_retrans() needs to be adapted as well.

---
 net/mptcp/protocol.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/mptcp/protocol.c +1 -1
@@ -2326,7 +2326,7 @@ struct sock *mptcp_subflow_get_retrans(s
 			continue;
 		}
 
-		if (subflow->backup) {
+		if (subflow->backup || subflow->request_bkup) {
 			if (!backup)
 				backup = ssk;
 			continue;
author maintainer
#24 lore raw

PATCH 20/149 mptcp: pr_debug: add missing \n at the end

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matthieu Baerts (NGI0) <[email protected]>

commit cb41b195e634d3f1ecfcd845314e64fd4bb3c7aa upstream.

pr_debug() have been added in various places in MPTCP code to help developers to debug some situations. With the dynamic debug feature, it is easy to enable all or some of them, and asks users to reproduce issues with extra debug.

Many of these pr_debug() don't end with a new line, while no 'pr_cont()' are used in MPTCP code. So the goal was not to display multiple debug messages on one line: they were then not missing the '\n' on purpose. Not having the new line at the end causes these messages to be printed with a delay, when something else needs to be printed. This issue is not visible when many messages need to be printed, but it is annoying and confusing when only specific messages are expected, e.g.

  # echo "func mptcp_pm_add_addr_echoed +fmp" \
        > /sys/kernel/debug/dynamic_debug/control
  # ./mptcp_join.sh "signal address"; \
        echo "$(awk '{print $1}' /proc/uptime) - end"; \
        sleep 5s; \
        echo "$(awk '{print $1}' /proc/uptime) - restart"; \
        ./mptcp_join.sh "signal address"
  013 signal address
      (...)
  10.75 - end
  15.76 - restart
  013 signal address
  [  10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
      (...)

=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.

The 'Fixes' tag here below points to the first pr_debug() used without '\n' in net/mptcp. This patch could be split in many small ones, with different Fixes tag, but it doesn't seem worth it, because it is easy to re-generate this patch with this simple 'sed' command:

git grep -l pr_debug -- net/mptcp |

    xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"

So in case of conflicts, simply drop the modifications, and launch this command.

---
 net/mptcp/fastopen.c   |    4 +--
 net/mptcp/options.c    |   50 +++++++++++++++++++++++------------------------
 net/mptcp/pm.c         |   28 +++++++++++++-------------
 net/mptcp/pm_netlink.c |   20 +++++++++---------
 net/mptcp/protocol.c   |   52 ++++++++++++++++++++++++-------------------------
 net/mptcp/protocol.h   |    4 +--
 net/mptcp/sched.c      |    4 +--
 net/mptcp/sockopt.c    |    4 +--
 net/mptcp/subflow.c    |   48 ++++++++++++++++++++++-----------------------
 9 files changed, 107 insertions(+), 107 deletions(-)
net/mptcp/fastopen.c +2 -2
@@ -68,12 +68,12 @@ void __mptcp_fastopen_gen_msk_ackseq(str
 	skb = skb_peek_tail(&sk->sk_receive_queue);
 	if (skb) {
 		WARN_ON_ONCE(MPTCP_SKB_CB(skb)->end_seq);
-		pr_debug("msk %p moving seq %llx -> %llx end_seq %llx -> %llx", sk,
+		pr_debug("msk %p moving seq %llx -> %llx end_seq %llx -> %llx\n", sk,
 			 MPTCP_SKB_CB(skb)->map_seq, MPTCP_SKB_CB(skb)->map_seq + msk->ack_seq,
 			 MPTCP_SKB_CB(skb)->end_seq, MPTCP_SKB_CB(skb)->end_seq + msk->ack_seq);
 		MPTCP_SKB_CB(skb)->map_seq += msk->ack_seq;
 		MPTCP_SKB_CB(skb)->end_seq += msk->ack_seq;
 	}
 
-	pr_debug("msk=%p ack_seq=%llx", msk, msk->ack_seq);
+	pr_debug("msk=%p ack_seq=%llx\n", msk, msk->ack_seq);
 }
net/mptcp/options.c +25 -25

198 lines not on this page · raw message

net/mptcp/pm.c +14 -14
@@ -19,7 +19,7 @@ int mptcp_pm_announce_addr(struct mptcp_
 {
 	u8 add_addr = READ_ONCE(msk->pm.addr_signal);
 
-	pr_debug("msk=%p, local_id=%d, echo=%d", msk, addr->id, echo);
+	pr_debug("msk=%p, local_id=%d, echo=%d\n", msk, addr->id, echo);
 
 	lockdep_assert_held(&msk->pm.lock);
 
@@ -45,7 +45,7 @@ int mptcp_pm_remove_addr(struct mptcp_so
 {
 	u8 rm_addr = READ_ONCE(msk->pm.addr_signal);
 
-	pr_debug("msk=%p, rm_list_nr=%d", msk, rm_list->nr);
+	pr_debug("msk=%p, rm_list_nr=%d\n", msk, rm_list->nr);
 
 	if (rm_addr) {
 		MPTCP_ADD_STATS(sock_net((struct sock *)msk),
@@ -66,7 +66,7 @@ void mptcp_pm_new_connection(struct mptc
 {
 	struct mptcp_pm_data *pm = &msk->pm;
 
-	pr_debug("msk=%p, token=%u side=%d", msk, READ_ONCE(msk->token), server_side);
+	pr_debug("msk=%p, token=%u side=%d\n", msk, READ_ONCE(msk->token), server_side);
 
 	WRITE_ONCE(pm->server_side, server_side);
 	mptcp_event(MPTCP_EVENT_CREATED, msk, ssk, GFP_ATOMIC);
@@ -90,7 +90,7 @@ bool mptcp_pm_allow_new_subflow(struct m
 
 	subflows_max = mptcp_pm_get_subflows_max(msk);
 
-	pr_debug("msk=%p subflows=%d max=%d allow=%d", msk, pm->subflows,
+	pr_debug("msk=%p subflows=%d max=%d allow=%d\n", msk, pm->subflows,
 		 subflows_max, READ_ONCE(pm->accept_subflow));
 
 	/* try to avoid acquiring the lock below */
@@ -114,7 +114,7 @@ bool mptcp_pm_allow_new_subflow(struct m
 static bool mptcp_pm_schedule_work(struct mptcp_sock *msk,
 				   enum mptcp_pm_status new_status)
 {
-	pr_debug("msk=%p status=%x new=%lx", msk, msk->pm.status,
+	pr_debug("msk=%p status=%x new=%lx\n", msk, msk->pm.status,
 		 BIT(new_status));
 	if (msk->pm.status & BIT(new_status))
 		return false;
@@ -129,7 +129,7 @@ void mptcp_pm_fully_established(struct m
 	struct mptcp_pm_data *pm = &msk->pm;
 	bool announce = false;
 
-	pr_debug("msk=%p", msk);
+	pr_debug("msk=%p\n", msk);
 
 	spin_lock_bh(&pm->lock);
 
@@ -153,14 +153,14 @@ void mptcp_pm_fully_established(struct m
 
 void mptcp_pm_connection_closed(struct mptcp_sock *msk)
 {
-	pr_debug("msk=%p", msk);
+	pr_debug("msk=%p\n", msk);
 }
 
 void mptcp_pm_subflow_established(struct mptcp_sock *msk)
 {
 	struct mptcp_pm_data *pm = &msk->pm;
 
-	pr_debug("msk=%p", msk);
+	pr_debug("msk=%p\n", msk);
 
 	if (!READ_ONCE(pm->work_pending))
 		return;
@@ -212,7 +212,7 @@ void mptcp_pm_add_addr_received(const st
 	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
 	struct mptcp_pm_data *pm = &msk->pm;
 
-	pr_debug("msk=%p remote_id=%d accept=%d", msk, addr->id,
+	pr_debug("msk=%p remote_id=%d accept=%d\n", msk, addr->id,
 		 READ_ONCE(pm->accept_addr));
 
 	mptcp_event_addr_announced(ssk, addr);
@@ -243,7 +243,7 @@ void mptcp_pm_add_addr_echoed(struct mpt
 {
 	struct mptcp_pm_data *pm = &msk->pm;
 
-	pr_debug("msk=%p", msk);
+	pr_debug("msk=%p\n", msk);
 
 	spin_lock_bh(&pm->lock);
 
@@ -267,7 +267,7 @@ void mptcp_pm_rm_addr_received(struct mp
 	struct mptcp_pm_data *pm = &msk->pm;
 	u8 i;
 
-	pr_debug("msk=%p remote_ids_nr=%d", msk, rm_list->nr);
+	pr_debug("msk=%p remote_ids_nr=%d\n", msk, rm_list->nr);
 
 	for (i = 0; i < rm_list->nr; i++)
 		mptcp_event_addr_removed(msk, rm_list->ids[i]);
@@ -299,19 +299,19 @@ void mptcp_pm_mp_fail_received(struct so
 	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
 	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
 
-	pr_debug("fail_seq=%llu", fail_seq);
+	pr_debug("fail_seq=%llu\n", fail_seq);
 
 	if (!READ_ONCE(msk->allow_infinite_fallback))
 		return;
 
 	if (!subflow->fail_tout) {
-		pr_debug("send MP_FAIL response and infinite map");
+		pr_debug("send MP_FAIL response and infinite map\n");
 
 		subflow->send_mp_fail = 1;
 		subflow->send_infinite_map = 1;
 		tcp_send_ack(sk);
 	} else {
-		pr_debug("MP_FAIL response received");
+		pr_debug("MP_FAIL response received\n");
 		WRITE_ONCE(subflow->fail_tout, 0);
 	}
 }
net/mptcp/pm_netlink.c +10 -10
@@ -287,7 +287,7 @@ static void mptcp_pm_add_timer(struct ti
 	struct mptcp_sock *msk = entry->sock;
 	struct sock *sk = (struct sock *)msk;
 
-	pr_debug("msk=%p", msk);
+	pr_debug("msk=%p\n", msk);
 
 	if (!msk)
 		return;
@@ -306,7 +306,7 @@ static void mptcp_pm_add_timer(struct ti
 	spin_lock_bh(&msk->pm.lock);
 
 	if (!mptcp_pm_should_add_signal_addr(msk)) {
-		pr_debug("retransmit ADD_ADDR id=%d", entry->addr.id);
+		pr_debug("retransmit ADD_ADDR id=%d\n", entry->addr.id);
 		mptcp_pm_announce_addr(msk, &entry->addr, false);
 		mptcp_pm_add_addr_send_ack(msk);
 		entry->retrans_times++;
@@ -387,7 +387,7 @@ void mptcp_pm_free_anno_list(struct mptc
 	struct sock *sk = (struct sock *)msk;
 	LIST_HEAD(free_list);
 
-	pr_debug("msk=%p", msk);
+	pr_debug("msk=%p\n", msk);
 
 	spin_lock_bh(&msk->pm.lock);
 	list_splice_init(&msk->pm.anno_list, &free_list);
@@ -473,7 +473,7 @@ static void __mptcp_pm_send_ack(struct m
 	struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
 	bool slow;
 
-	pr_debug("send ack for %s",
+	pr_debug("send ack for %s\n",
 		 prio ? "mp_prio" : (mptcp_pm_should_add_signal(msk) ? "add_addr" : "rm_addr"));
 
 	slow = lock_sock_fast(ssk);
@@ -708,7 +708,7 @@ static void mptcp_pm_nl_add_addr_receive
 	add_addr_accept_max = mptcp_pm_get_add_addr_accept_max(msk);
 	subflows_max = mptcp_pm_get_subflows_max(msk);
 
-	pr_debug("accepted %d:%d remote family %d",
+	pr_debug("accepted %d:%d remote family %d\n",
 		 msk->pm.add_addr_accepted, add_addr_accept_max,
 		 msk->pm.remote.family);
 
@@ -767,7 +767,7 @@ int mptcp_pm_nl_mp_prio_send_ack(struct
 {
 	struct mptcp_subflow_context *subflow;
 
-	pr_debug("bkup=%d", bkup);
+	pr_debug("bkup=%d\n", bkup);
 
 	mptcp_for_each_subflow(msk, subflow) {
 		struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
@@ -803,7 +803,7 @@ static void mptcp_pm_nl_rm_addr_or_subfl
 	struct sock *sk = (struct sock *)msk;
 	u8 i;
 
-	pr_debug("%s rm_list_nr %d",
+	pr_debug("%s rm_list_nr %d\n",
 		 rm_type == MPTCP_MIB_RMADDR ? "address" : "subflow", rm_list->nr);
 
 	msk_owned_by_me(msk);
@@ -832,7 +832,7 @@ static void mptcp_pm_nl_rm_addr_or_subfl
 			if (rm_type == MPTCP_MIB_RMSUBFLOW && !mptcp_local_id_match(msk, id, rm_id))
 				continue;
 
-			pr_debug(" -> %s rm_list_ids[%d]=%u local_id=%u remote_id=%u mpc_id=%u",
+			pr_debug(" -> %s rm_list_ids[%d]=%u local_id=%u remote_id=%u mpc_id=%u\n",
 				 rm_type == MPTCP_MIB_RMADDR ? "address" : "subflow",
 				 i, rm_id, id, remote_id, msk->mpc_endpoint_id);
 			spin_unlock_bh(&msk->pm.lock);
@@ -889,7 +889,7 @@ void mptcp_pm_nl_work(struct mptcp_sock
 
 	spin_lock_bh(&msk->pm.lock);
 
-	pr_debug("msk=%p status=%x", msk, pm->status);
+	pr_debug("msk=%p status=%x\n", msk, pm->status);
 	if (pm->status & BIT(MPTCP_PM_ADD_ADDR_RECEIVED)) {
 		pm->status &= ~BIT(MPTCP_PM_ADD_ADDR_RECEIVED);
 		mptcp_pm_nl_add_addr_received(msk);
@@ -1476,7 +1476,7 @@ static int mptcp_nl_remove_subflow_and_s
 	long s_slot = 0, s_num = 0;
 	struct mptcp_sock *msk;
 
-	pr_debug("remove_id=%d", addr->id);
+	pr_debug("remove_id=%d\n", addr->id);
 
 	list.ids[list.nr++] = addr->id;
 
net/mptcp/protocol.c +26 -26

206 lines not on this page · raw message

net/mptcp/protocol.h +2 -2
@@ -1172,7 +1172,7 @@ static inline bool mptcp_check_fallback(
 static inline void __mptcp_do_fallback(struct mptcp_sock *msk)
 {
 	if (__mptcp_check_fallback(msk)) {
-		pr_debug("TCP fallback already done (msk=%p)", msk);
+		pr_debug("TCP fallback already done (msk=%p)\n", msk);
 		return;
 	}
 	set_bit(MPTCP_FALLBACK_DONE, &msk->flags);
@@ -1208,7 +1208,7 @@ static inline void mptcp_do_fallback(str
 	}
 }
 
-#define pr_fallback(a) pr_debug("%s:fallback to TCP (msk=%p)", __func__, a)
+#define pr_fallback(a) pr_debug("%s:fallback to TCP (msk=%p)\n", __func__, a)
 
 static inline bool mptcp_check_infinite_map(struct sk_buff *skb)
 {
net/mptcp/sched.c +2 -2
@@ -86,7 +86,7 @@ int mptcp_register_scheduler(struct mptc
 	list_add_tail_rcu(&sched->list, &mptcp_sched_list);
 	spin_unlock(&mptcp_sched_list_lock);
 
-	pr_debug("%s registered", sched->name);
+	pr_debug("%s registered\n", sched->name);
 	return 0;
 }
 
@@ -118,7 +118,7 @@ int mptcp_init_sched(struct mptcp_sock *
 	if (msk->sched->init)
 		msk->sched->init(msk);
 
-	pr_debug("sched=%s", msk->sched->name);
+	pr_debug("sched=%s\n", msk->sched->name);
 
 	return 0;
 }
net/mptcp/sockopt.c +2 -2
@@ -873,7 +873,7 @@ int mptcp_setsockopt(struct sock *sk, in
 	struct mptcp_sock *msk = mptcp_sk(sk);
 	struct sock *ssk;
 
-	pr_debug("msk=%p", msk);
+	pr_debug("msk=%p\n", msk);
 
 	if (level == SOL_SOCKET)
 		return mptcp_setsockopt_sol_socket(msk, optname, optval, optlen);
@@ -1453,7 +1453,7 @@ int mptcp_getsockopt(struct sock *sk, in
 	struct mptcp_sock *msk = mptcp_sk(sk);
 	struct sock *ssk;
 
-	pr_debug("msk=%p", msk);
+	pr_debug("msk=%p\n", msk);
 
 	/* @@ the meaning of setsockopt() when the socket is connected and
 	 * there are multiple subflows is not yet defined. It is up to the
net/mptcp/subflow.c +24 -24

192 lines not on this page · raw message

author maintainer
#25 lore raw

PATCH 21/149 mptcp: pm: reuse ID 0 after delete and re-add

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matthieu Baerts (NGI0) <[email protected]>

commit 8b8ed1b429f8fa7ebd5632555e7b047bc0620075 upstream.

When the endpoint used by the initial subflow is removed and re-added later, the PM has to force the ID 0, it is a special case imposed by the MPTCP specs.

Note that the endpoint should then need to be re-added reusing the same ID.

Fixes 3ad14f54bd74 ("mptcp: more accurate MPC endpoint tracking")
---
 net/mptcp/pm_netlink.c |   10 ++++++++++
 1 file changed, 10 insertions(+)
net/mptcp/pm_netlink.c +10 -0
@@ -585,6 +585,11 @@ static void mptcp_pm_create_subflow_or_s
 
 		__clear_bit(local.addr.id, msk->pm.id_avail_bitmap);
 		msk->pm.add_addr_signaled++;
+
+		/* Special case for ID0: set the correct ID */
+		if (local.addr.id == msk->mpc_endpoint_id)
+			local.addr.id = 0;
+
 		mptcp_pm_announce_addr(msk, &local.addr, false);
 		mptcp_pm_nl_addr_send_ack(msk);
 
@@ -609,6 +614,11 @@ subflow:
 
 		msk->pm.local_addr_used++;
 		__clear_bit(local.addr.id, msk->pm.id_avail_bitmap);
+
+		/* Special case for ID0: set the correct ID */
+		if (local.addr.id == msk->mpc_endpoint_id)
+			local.addr.id = 0;
+
 		nr = fill_remote_addresses_vec(msk, &local.addr, fullmesh, addrs);
 		if (nr == 0)
 			continue;
author maintainer
#26 lore raw

PATCH 22/149 mptcp: pm: skip connecting to already established sf

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matthieu Baerts (NGI0) <[email protected]>

commit bc19ff57637ff563d2bdf2b385b48c41e6509e0d upstream.

The lookup_subflow_by_daddr() helper checks if there is already a subflow connected to this address. But there could be a subflow that is closing, but taking time due to some reasons: latency, losses, data to process, etc.

If an ADD_ADDR is received while the endpoint is being closed, it is better to try connecting to it, instead of rejecting it: the peer which has sent the ADD_ADDR will not be notified that the ADD_ADDR has been rejected for this reason, and the expected subflow will not be created at the end.

This helper should then only look for subflows that are established, or going to be, but not the ones being closed.

Fixes d84ad04941c3 ("mptcp: skip connecting the connected address")
---
 net/mptcp/pm_netlink.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
net/mptcp/pm_netlink.c +6 -3
@@ -130,12 +130,15 @@ static bool lookup_subflow_by_daddr(cons
 {
 	struct mptcp_subflow_context *subflow;
 	struct mptcp_addr_info cur;
-	struct sock_common *skc;
 
 	list_for_each_entry(subflow, list, node) {
-		skc = (struct sock_common *)mptcp_subflow_tcp_sock(subflow);
+		struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
 
-		remote_address(skc, &cur);
+		if (!((1 << inet_sk_state_load(ssk)) &
+		      (TCPF_ESTABLISHED | TCPF_SYN_SENT | TCPF_SYN_RECV)))
+			continue;
+
+		remote_address((struct sock_common *)ssk, &cur);
 		if (mptcp_addresses_equal(&cur, daddr, daddr->port))
 			return true;
 	}
author maintainer
#27 lore raw

PATCH 23/149 mptcp: pm: reset MPC endp ID when re-added

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matthieu Baerts (NGI0) <[email protected]>

commit dce1c6d1e92535f165219695a826caedcca4e9b9 upstream.

The initial subflow has a special local ID: 0. It is specific per connection.

When a global endpoint is deleted and re-added later, it can have a different ID -- most services managing the endpoints automatically don't force the ID to be the same as before. It is then important to track these modifications to be consistent with the ID being used for the address used by the initial subflow, not to confuse the other peer or to send the ID 0 for the wrong address.

Now when removing an endpoint, msk->mpc_endpoint_id is reset if it corresponds to this endpoint. When adding a new endpoint, the same variable is updated if the address match the one of the initial subflow.

Fixes 3ad14f54bd74 ("mptcp: more accurate MPC endpoint tracking")
---
 net/mptcp/pm_netlink.c |   13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)
net/mptcp/pm_netlink.c +11 -2
@@ -1320,20 +1320,27 @@ static struct pm_nl_pernet *genl_info_pm
 	return pm_nl_get_pernet(genl_info_net(info));
 }
 
-static int mptcp_nl_add_subflow_or_signal_addr(struct net *net)
+static int mptcp_nl_add_subflow_or_signal_addr(struct net *net,
+					       struct mptcp_addr_info *addr)
 {
 	struct mptcp_sock *msk;
 	long s_slot = 0, s_num = 0;
 
 	while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
 		struct sock *sk = (struct sock *)msk;
+		struct mptcp_addr_info mpc_addr;
 
 		if (!READ_ONCE(msk->fully_established) ||
 		    mptcp_pm_is_userspace(msk))
 			goto next;
 
+		/* if the endp linked to the init sf is re-added with a != ID */
+		mptcp_local_address((struct sock_common *)msk, &mpc_addr);
+
 		lock_sock(sk);
 		spin_lock_bh(&msk->pm.lock);
+		if (mptcp_addresses_equal(addr, &mpc_addr, addr->port))
+			msk->mpc_endpoint_id = addr->id;
 		mptcp_pm_create_subflow_or_signal_addr(msk);
 		spin_unlock_bh(&msk->pm.lock);
 		release_sock(sk);
@@ -1406,7 +1413,7 @@ int mptcp_pm_nl_add_addr_doit(struct sk_
 		goto out_free;
 	}
 
-	mptcp_nl_add_subflow_or_signal_addr(sock_net(skb->sk));
+	mptcp_nl_add_subflow_or_signal_addr(sock_net(skb->sk), &entry->addr);
 	return 0;
 
 out_free:
@@ -1522,6 +1529,8 @@ static int mptcp_nl_remove_subflow_and_s
 			spin_unlock_bh(&msk->pm.lock);
 		}
 
+		if (msk->mpc_endpoint_id == entry->addr.id)
+			msk->mpc_endpoint_id = 0;
 		release_sock(sk);
 
 next:
author maintainer
#28 lore raw

PATCH 24/149 mptcp: pm: send ACK on an active subflow

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matthieu Baerts (NGI0) <[email protected]>

commit c07cc3ed895f9bfe0c53b5ed6be710c133b4271c upstream.

Taking the first one on the list doesn't work in some cases, e.g. if the initial subflow is being removed. Pick another one instead of not sending anything.

Fixes 84dfe3677a6f ("mptcp: send out dedicated ADD_ADDR packet")
---
 net/mptcp/pm_netlink.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
net/mptcp/pm_netlink.c +6 -3
@@ -768,9 +768,12 @@ void mptcp_pm_nl_addr_send_ack(struct mp
 	    !mptcp_pm_should_rm_signal(msk))
 		return;
 
-	subflow = list_first_entry_or_null(&msk->conn_list, typeof(*subflow), node);
-	if (subflow)
-		mptcp_pm_send_ack(msk, subflow, false, false);
+	mptcp_for_each_subflow(msk, subflow) {
+		if (__mptcp_subflow_active(subflow)) {
+			mptcp_pm_send_ack(msk, subflow, false, false);
+			break;
+		}
+	}
 }
 
 int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
author maintainer
#29 lore raw

PATCH 25/149 mptcp: pm: fix RM_ADDR ID for the initial subflow

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matthieu Baerts (NGI0) <[email protected]>

commit 87b5896f3f7848130095656739b05881904e2697 upstream.

The initial subflow has a special local ID: 0. When an endpoint is being deleted, it is then important to check if its address is not linked to the initial subflow to send the right ID.

If there was an endpoint linked to the initial subflow, msk's mpc_endpoint_id field will be set. We can then use this info when an endpoint is being removed to see if it is linked to the initial subflow.

So now, the correct IDs are passed to mptcp_pm_nl_rm_addr_or_subflow(), it is no longer needed to use mptcp_local_id_match().

Fixes 3ad14f54bd74 ("mptcp: more accurate MPC endpoint tracking")
---
 net/mptcp/pm_netlink.c |   28 +++++++++++++++-------------
 1 file changed, 15 insertions(+), 13 deletions(-)
net/mptcp/pm_netlink.c +15 -13
@@ -806,11 +806,6 @@ int mptcp_pm_nl_mp_prio_send_ack(struct
 	return -EINVAL;
 }
 
-static bool mptcp_local_id_match(const struct mptcp_sock *msk, u8 local_id, u8 id)
-{
-	return local_id == id || (!local_id && msk->mpc_endpoint_id == id);
-}
-
 static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk,
 					   const struct mptcp_rm_list *rm_list,
 					   enum linux_mptcp_mib_field rm_type)
@@ -845,7 +840,7 @@ static void mptcp_pm_nl_rm_addr_or_subfl
 
 			if (rm_type == MPTCP_MIB_RMADDR && remote_id != rm_id)
 				continue;
-			if (rm_type == MPTCP_MIB_RMSUBFLOW && !mptcp_local_id_match(msk, id, rm_id))
+			if (rm_type == MPTCP_MIB_RMSUBFLOW && id != rm_id)
 				continue;
 
 			pr_debug(" -> %s rm_list_ids[%d]=%u local_id=%u remote_id=%u mpc_id=%u\n",
@@ -1461,6 +1456,12 @@ static bool remove_anno_list_by_saddr(st
 	return false;
 }
 
+static u8 mptcp_endp_get_local_id(struct mptcp_sock *msk,
+				  const struct mptcp_addr_info *addr)
+{
+	return msk->mpc_endpoint_id == addr->id ? 0 : addr->id;
+}
+
 static bool mptcp_pm_remove_anno_addr(struct mptcp_sock *msk,
 				      const struct mptcp_addr_info *addr,
 				      bool force)
@@ -1468,7 +1469,7 @@ static bool mptcp_pm_remove_anno_addr(st
 	struct mptcp_rm_list list = { .nr = 0 };
 	bool ret;
 
-	list.ids[list.nr++] = addr->id;
+	list.ids[list.nr++] = mptcp_endp_get_local_id(msk, addr);
 
 	ret = remove_anno_list_by_saddr(msk, addr);
 	if (ret || force) {
@@ -1495,14 +1496,12 @@ static int mptcp_nl_remove_subflow_and_s
 						   const struct mptcp_pm_addr_entry *entry)
 {
 	const struct mptcp_addr_info *addr = &entry->addr;
-	struct mptcp_rm_list list = { .nr = 0 };
+	struct mptcp_rm_list list = { .nr = 1 };
 	long s_slot = 0, s_num = 0;
 	struct mptcp_sock *msk;
 
 	pr_debug("remove_id=%d\n", addr->id);
 
-	list.ids[list.nr++] = addr->id;
-
 	while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
 		struct sock *sk = (struct sock *)msk;
 		bool remove_subflow;
@@ -1520,6 +1519,7 @@ static int mptcp_nl_remove_subflow_and_s
 		mptcp_pm_remove_anno_addr(msk, addr, remove_subflow &&
 					  !(entry->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT));
 
+		list.ids[0] = mptcp_endp_get_local_id(msk, addr);
 		if (remove_subflow) {
 			spin_lock_bh(&msk->pm.lock);
 			mptcp_pm_nl_rm_subflow_received(msk, &list);
@@ -1628,6 +1628,7 @@ int mptcp_pm_nl_del_addr_doit(struct sk_
 	return ret;
 }
 
+/* Called from the userspace PM only */
 void mptcp_pm_remove_addrs(struct mptcp_sock *msk, struct list_head *rm_list)
 {
 	struct mptcp_rm_list alist = { .nr = 0 };
@@ -1656,6 +1657,7 @@ void mptcp_pm_remove_addrs(struct mptcp_
 	}
 }
 
+/* Called from the in-kernel PM only */
 static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk,
 					       struct list_head *rm_list)
 {
@@ -1665,11 +1667,11 @@ static void mptcp_pm_remove_addrs_and_su
 	list_for_each_entry(entry, rm_list, list) {
 		if (slist.nr < MPTCP_RM_IDS_MAX &&
 		    lookup_subflow_by_saddr(&msk->conn_list, &entry->addr))
-			slist.ids[slist.nr++] = entry->addr.id;
+			slist.ids[slist.nr++] = mptcp_endp_get_local_id(msk, &entry->addr);
 
 		if (alist.nr < MPTCP_RM_IDS_MAX &&
 		    remove_anno_list_by_saddr(msk, &entry->addr))
-			alist.ids[alist.nr++] = entry->addr.id;
+			alist.ids[alist.nr++] = mptcp_endp_get_local_id(msk, &entry->addr);
 	}
 
 	spin_lock_bh(&msk->pm.lock);
@@ -1966,7 +1968,7 @@ static void mptcp_pm_nl_fullmesh(struct
 {
 	struct mptcp_rm_list list = { .nr = 0 };
 
-	list.ids[list.nr++] = addr->id;
+	list.ids[list.nr++] = mptcp_endp_get_local_id(msk, addr);
 
 	spin_lock_bh(&msk->pm.lock);
 	mptcp_pm_nl_rm_subflow_received(msk, &list);
author maintainer
#30 lore raw

PATCH 26/149 mptcp: pm: do not remove already closed subflows

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matthieu Baerts (NGI0) <[email protected]>

commit 58e1b66b4e4b8a602d3f2843e8eba00a969ecce2 upstream.

It is possible to have in the list already closed subflows, e.g. the initial subflow has been already closed, but still in the list. No need to try to close it again, and increments the related counters again.

Fixes 0ee4261a3681 ("mptcp: implement mptcp_pm_remove_subflow")
---
 net/mptcp/pm_netlink.c |    2 ++
 1 file changed, 2 insertions(+)
net/mptcp/pm_netlink.c +2 -0
@@ -838,6 +838,8 @@ static void mptcp_pm_nl_rm_addr_or_subfl
 			int how = RCV_SHUTDOWN | SEND_SHUTDOWN;
 			u8 id = subflow_get_local_id(subflow);
 
+			if (inet_sk_state_load(ssk) == TCP_CLOSE)
+				continue;
 			if (rm_type == MPTCP_MIB_RMADDR && remote_id != rm_id)
 				continue;
 			if (rm_type == MPTCP_MIB_RMSUBFLOW && id != rm_id)
author maintainer
#31 lore raw

PATCH 27/149 mptcp: pm: fix ID 0 endp usage after multiple re-creations

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matthieu Baerts (NGI0) <[email protected]>

commit 9366922adc6a71378ca01f898c41be295309f044 upstream.

'local_addr_used' and 'add_addr_accepted' are decremented for addresses not related to the initial subflow (ID0), because the source and destination addresses of the initial subflows are known from the
beginning: they don't count as "additional local address being used" or "ADD_ADDR being accepted".

It is then required not to increment them when the entrypoint used by the initial subflow is removed and re-added during a connection. Without this modification, this entrypoint cannot be removed and re-added more than once.

---
 net/mptcp/pm_netlink.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
net/mptcp/pm_netlink.c +5 -2
@@ -615,12 +615,13 @@ subflow:
 
 		fullmesh = !!(local.flags & MPTCP_PM_ADDR_FLAG_FULLMESH);
 
-		msk->pm.local_addr_used++;
 		__clear_bit(local.addr.id, msk->pm.id_avail_bitmap);
 
 		/* Special case for ID0: set the correct ID */
 		if (local.addr.id == msk->mpc_endpoint_id)
 			local.addr.id = 0;
+		else /* local_addr_used is not decr for ID 0 */
+			msk->pm.local_addr_used++;
 
 		nr = fill_remote_addresses_vec(msk, &local.addr, fullmesh, addrs);
 		if (nr == 0)
@@ -750,7 +751,9 @@ static void mptcp_pm_nl_add_addr_receive
 	spin_lock_bh(&msk->pm.lock);
 
 	if (sf_created) {
-		msk->pm.add_addr_accepted++;
+		/* add_addr_accepted is not decr for ID 0 */
+		if (remote.id)
+			msk->pm.add_addr_accepted++;
 		if (msk->pm.add_addr_accepted >= add_addr_accept_max ||
 		    msk->pm.subflows >= subflows_max)
 			WRITE_ONCE(msk->pm.accept_addr, false);
author maintainer
#32 lore raw

PATCH 28/149 mptcp: avoid duplicated SUB_CLOSED events

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matthieu Baerts (NGI0) <[email protected]>

commit d82809b6c5f2676b382f77a5cbeb1a5d91ed2235 upstream.

The initial subflow might have already been closed, but still in the connection list. When the worker is instructed to close the subflows that have been marked as closed, it might then try to close the initial subflow again.

A consequence of that is that the SUB_CLOSED event can be seen twice:

  # ip mptcp endpoint
  1.1.1.1 id 1 subflow dev eth0
  2.2.2.2 id 2 subflow dev eth1
  # ip mptcp monitor &
  [         CREATED] remid=0 locid=0 saddr4=1.1.1.1 daddr4=9.9.9.9
  [     ESTABLISHED] remid=0 locid=0 saddr4=1.1.1.1 daddr4=9.9.9.9
  [  SF_ESTABLISHED] remid=0 locid=2 saddr4=2.2.2.2 daddr4=9.9.9.9
  # ip mptcp endpoint delete id 1
  [       SF_CLOSED] remid=0 locid=0 saddr4=1.1.1.1 daddr4=9.9.9.9
  [       SF_CLOSED] remid=0 locid=0 saddr4=1.1.1.1 daddr4=9.9.9.9

The first one is coming from mptcp_pm_nl_rm_subflow_received(), and the second one from __mptcp_close_subflow().

To avoid doing the post-closed processing twice, the subflow is now marked as closed the first time.

Note that it is not enough to check if we are dealing with the first subflow and check its sk_state: the subflow might have been reset or closed before calling mptcp_close_ssk().

---
 net/mptcp/protocol.c |    6 ++++++
 net/mptcp/protocol.h |    3 ++-
 2 files changed, 8 insertions(+), 1 deletion(-)
net/mptcp/protocol.c +6 -0
@@ -2508,6 +2508,12 @@ out:
 void mptcp_close_ssk(struct sock *sk, struct sock *ssk,
 		     struct mptcp_subflow_context *subflow)
 {
+	/* The first subflow can already be closed and still in the list */
+	if (subflow->close_event_done)
+		return;
+
+	subflow->close_event_done = true;
+
 	if (sk->sk_state == TCP_ESTABLISHED)
 		mptcp_event(MPTCP_EVENT_SUB_CLOSED, mptcp_sk(sk), ssk, GFP_KERNEL);
 
net/mptcp/protocol.h +2 -1
@@ -519,7 +519,8 @@ struct mptcp_subflow_context {
 		stale : 1,	    /* unable to snd/rcv data, do not use for xmit */
 		valid_csum_seen : 1,        /* at least one csum validated */
 		is_mptfo : 1,	    /* subflow is doing TFO */
-		__unused : 10;
+		close_event_done : 1,       /* has done the post-closed part */
+		__unused : 9;
 	bool	data_avail;
 	bool	scheduled;
 	u32	remote_nonce;
author maintainer
#33 lore raw

PATCH 29/149 mptcp: pm: ADD_ADDR 0 is not a new address

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matthieu Baerts (NGI0) <[email protected]>

commit 57f86203b41c98b322119dfdbb1ec54ce5e3369b upstream.

The ADD_ADDR 0 with the address from the initial subflow should not be considered as a new address: this is not something new. If the host receives it, it simply means that the address is available again.

When receiving an ADD_ADDR for the ID 0, the PM already doesn't consider it as new by not incrementing the 'add_addr_accepted' counter. But the 'accept_addr' might not be set if the limit has already been reached:
this can be bypassed in this case. But before, it is important to check that this ADD_ADDR for the ID 0 is for the same address as the initial subflow. If not, it is not something that should happen, and the ADD_ADDR can be ignored.

Note that if an ADD_ADDR is received while there is already a subflow opened using the same address, this ADD_ADDR is ignored as well. It means that if multiple ADD_ADDR for ID 0 are received, there will not be any duplicated subflows created by the client.

Fixes d0876b2284cf ("mptcp: add the incoming RM_ADDR support")
---
 net/mptcp/pm.c         |    4 +++-
 net/mptcp/pm_netlink.c |    9 +++++++++
 net/mptcp/protocol.h   |    2 ++
 3 files changed, 14 insertions(+), 1 deletion(-)
net/mptcp/pm.c +3 -1
@@ -226,7 +226,9 @@ void mptcp_pm_add_addr_received(const st
 		} else {
 			__MPTCP_INC_STATS(sock_net((struct sock *)msk), MPTCP_MIB_ADDADDRDROP);
 		}
-	} else if (!READ_ONCE(pm->accept_addr)) {
+	/* id0 should not have a different address */
+	} else if ((addr->id == 0 && !mptcp_pm_nl_is_init_remote_addr(msk, addr)) ||
+		   (addr->id > 0 && !READ_ONCE(pm->accept_addr))) {
 		mptcp_pm_announce_addr(msk, addr, true);
 		mptcp_pm_add_addr_send_ack(msk);
 	} else if (mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_RECEIVED)) {
net/mptcp/pm_netlink.c +9 -0
@@ -760,6 +760,15 @@ static void mptcp_pm_nl_add_addr_receive
 	}
 }
 
+bool mptcp_pm_nl_is_init_remote_addr(struct mptcp_sock *msk,
+				     const struct mptcp_addr_info *remote)
+{
+	struct mptcp_addr_info mpc_remote;
+
+	remote_address((struct sock_common *)msk, &mpc_remote);
+	return mptcp_addresses_equal(&mpc_remote, remote, remote->port);
+}
+
 void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk)
 {
 	struct mptcp_subflow_context *subflow;
net/mptcp/protocol.h +2 -0
@@ -988,6 +988,8 @@ void mptcp_pm_add_addr_received(const st
 void mptcp_pm_add_addr_echoed(struct mptcp_sock *msk,
 			      const struct mptcp_addr_info *addr);
 void mptcp_pm_add_addr_send_ack(struct mptcp_sock *msk);
+bool mptcp_pm_nl_is_init_remote_addr(struct mptcp_sock *msk,
+				     const struct mptcp_addr_info *remote);
 void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk);
 void mptcp_pm_rm_addr_received(struct mptcp_sock *msk,
 			       const struct mptcp_rm_list *rm_list);
author maintainer
#34 lore raw

PATCH 30/149 selftests: mptcp: join: cannot rm sf if closed

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matthieu Baerts (NGI0) <[email protected]>

commit e93681afcb96864ec26c3b2ce94008ce93577373 upstream.

Thanks to the previous commit, the MPTCP subflows are now closed on both directions even when only the MPTCP path-manager of one peer asks for their closure.

In the two tests modified here -- "userspace pm add & remove address" and "userspace pm create destroy subflow" -- one peer is controlled by the userspace PM, and the other one by the in-kernel PM. When the userspace PM sends a RM_ADDR notification, the in-kernel PM will automatically react by closing all subflows using this address. Now, thanks to the previous commit, the subflows are properly closed on both directions, the userspace PM can then no longer closes the same subflows if they are already closed. Before, it was OK to do that, because the subflows were still half-opened, still OK to send a RM_ADDR.

In other words, thanks to the previous commit closing the subflows, an error will be returned to the userspace if it tries to close a subflow that has already been closed. So no need to run this command, which mean that the linked counters will then not be incremented.

These tests are then no longer sending both a RM_ADDR, then closing the linked subflow just after. The test with the userspace PM on the server side is now removing one subflow linked to one address, then sending a RM_ADDR for another address. The test with the userspace PM on the client side is now only removing the subflow that was previously created.

---
 tools/testing/selftests/net/mptcp/mptcp_join.sh |   11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)
tools/testing/selftests/net/mptcp/mptcp_join.sh +4 -7
@@ -3429,14 +3429,12 @@ userspace_tests()
 			"signal"
 		userspace_pm_chk_get_addr "${ns1}" "10" "id 10 flags signal 10.0.2.1"
 		userspace_pm_chk_get_addr "${ns1}" "20" "id 20 flags signal 10.0.3.1"
-		userspace_pm_rm_addr $ns1 10
 		userspace_pm_rm_sf $ns1 "::ffff:10.0.2.1" $MPTCP_LIB_EVENT_SUB_ESTABLISHED
 		userspace_pm_chk_dump_addr "${ns1}" \
-			"id 20 flags signal 10.0.3.1" "after rm_addr 10"
+			"id 20 flags signal 10.0.3.1" "after rm_sf 10"
 		userspace_pm_rm_addr $ns1 20
-		userspace_pm_rm_sf $ns1 10.0.3.1 $MPTCP_LIB_EVENT_SUB_ESTABLISHED
 		userspace_pm_chk_dump_addr "${ns1}" "" "after rm_addr 20"
-		chk_rm_nr 2 2 invert
+		chk_rm_nr 1 1 invert
 		chk_mptcp_info subflows 0 subflows 0
 		chk_subflows_total 1 1
 		kill_events_pids
@@ -3460,12 +3458,11 @@ userspace_tests()
 			"id 20 flags subflow 10.0.3.2" \
 			"subflow"
 		userspace_pm_chk_get_addr "${ns2}" "20" "id 20 flags subflow 10.0.3.2"
-		userspace_pm_rm_addr $ns2 20
 		userspace_pm_rm_sf $ns2 10.0.3.2 $MPTCP_LIB_EVENT_SUB_ESTABLISHED
 		userspace_pm_chk_dump_addr "${ns2}" \
 			"" \
-			"after rm_addr 20"
-		chk_rm_nr 1 1
+			"after rm_sf 20"
+		chk_rm_nr 0 1
 		chk_mptcp_info subflows 0 subflows 0
 		chk_subflows_total 1 1
 		kill_events_pids
author maintainer
#35 lore raw

PATCH 31/149 selftests: mptcp: join: check removing ID 0 endpoint

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matthieu Baerts (NGI0) <[email protected]>

commit 5f94b08c001290acda94d9d8868075590931c198 upstream.

Removing the endpoint linked to the initial subflow should trigger a RM_ADDR for the right ID, and the removal of the subflow. That's what is now being verified in the "delete and re-add" test.

Note that removing the initial subflow will not decrement the 'subflows' counters, which corresponds to the *additional* subflows. On the other hand, when the same endpoint is re-added, it will increment this counter, as it will be seen as an additional subflow this time.

The 'Fixes' tag here below is the same as the one from the previous
commit: this patch here is not fixing anything wrong in the selftests, but it validates the previous fix for an issue introduced by this commit ID.

Fixes 3ad14f54bd74 ("mptcp: more accurate MPC endpoint tracking")
---
 tools/testing/selftests/net/mptcp/mptcp_join.sh |   25 +++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)
tools/testing/selftests/net/mptcp/mptcp_join.sh +18 -7
@@ -3572,8 +3572,9 @@ endpoint_tests()
 
 	if reset_with_tcp_filter "delete and re-add" ns2 10.0.3.2 REJECT OUTPUT &&
 	   mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then
-		pm_nl_set_limits $ns1 0 2
-		pm_nl_set_limits $ns2 0 2
+		pm_nl_set_limits $ns1 0 3
+		pm_nl_set_limits $ns2 0 3
+		pm_nl_add_endpoint $ns2 10.0.1.2 id 1 dev ns2eth1 flags subflow
 		pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow
 		test_linkfail=4 speed=20 \
 			run_tests $ns1 $ns2 10.0.1.1 &
@@ -3582,17 +3583,17 @@ endpoint_tests()
 		wait_mpj $ns2
 		pm_nl_check_endpoint "creation" \
 			$ns2 10.0.2.2 id 2 flags subflow dev ns2eth2
-		chk_subflow_nr "before delete" 2
+		chk_subflow_nr "before delete id 2" 2
 		chk_mptcp_info subflows 1 subflows 1
 
 		pm_nl_del_endpoint $ns2 2 10.0.2.2
 		sleep 0.5
-		chk_subflow_nr "after delete" 1
+		chk_subflow_nr "after delete id 2" 1
 		chk_mptcp_info subflows 0 subflows 0
 
 		pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow
 		wait_mpj $ns2
-		chk_subflow_nr "after re-add" 2
+		chk_subflow_nr "after re-add id 2" 2
 		chk_mptcp_info subflows 1 subflows 1
 
 		pm_nl_add_endpoint $ns2 10.0.3.2 id 3 flags subflow
@@ -3607,10 +3608,20 @@ endpoint_tests()
 		chk_subflow_nr "after no reject" 3
 		chk_mptcp_info subflows 2 subflows 2
 
+		pm_nl_del_endpoint $ns2 1 10.0.1.2
+		sleep 0.5
+		chk_subflow_nr "after delete id 0" 2
+		chk_mptcp_info subflows 2 subflows 2 # only decr for additional sf
+
+		pm_nl_add_endpoint $ns2 10.0.1.2 id 1 dev ns2eth1 flags subflow
+		wait_mpj $ns2
+		chk_subflow_nr "after re-add id 0" 3
+		chk_mptcp_info subflows 3 subflows 3
+
 		mptcp_lib_kill_wait $tests_pid
 
-		chk_join_nr 3 3 3
-		chk_rm_nr 1 1
+		chk_join_nr 4 4 4
+		chk_rm_nr 2 2
 	fi
 }
 
author maintainer
#36 lore raw

PATCH 32/149 selftests: mptcp: join: no extra msg if no counter

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matthieu Baerts (NGI0) <[email protected]>

commit 76a2d8394cc183df872adf04bf636eaf42746449 upstream.

The checksum and fail counters might not be available. Then no need to display an extra message with missing info.

While at it, fix the indentation around, which is wrong since the same commit.

Fixes 47867f0a7e83 ("selftests: mptcp: join: skip check if MIB counter not supported")
---
 tools/testing/selftests/net/mptcp/mptcp_join.sh |   16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)
tools/testing/selftests/net/mptcp/mptcp_join.sh +8 -8
@@ -1112,26 +1112,26 @@ chk_csum_nr()
 
 	print_check "sum"
 	count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtDataCsumErr")
-	if [ "$count" != "$csum_ns1" ]; then
+	if [ -n "$count" ] && [ "$count" != "$csum_ns1" ]; then
 		extra_msg+=" ns1=$count"
 	fi
 	if [ -z "$count" ]; then
 		print_skip
 	elif { [ "$count" != $csum_ns1 ] && [ $allow_multi_errors_ns1 -eq 0 ]; } ||
-	   { [ "$count" -lt $csum_ns1 ] && [ $allow_multi_errors_ns1 -eq 1 ]; }; then
+	     { [ "$count" -lt $csum_ns1 ] && [ $allow_multi_errors_ns1 -eq 1 ]; }; then
 		fail_test "got $count data checksum error[s] expected $csum_ns1"
 	else
 		print_ok
 	fi
 	print_check "csum"
 	count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtDataCsumErr")
-	if [ "$count" != "$csum_ns2" ]; then
+	if [ -n "$count" ] && [ "$count" != "$csum_ns2" ]; then
 		extra_msg+=" ns2=$count"
 	fi
 	if [ -z "$count" ]; then
 		print_skip
 	elif { [ "$count" != $csum_ns2 ] && [ $allow_multi_errors_ns2 -eq 0 ]; } ||
-	   { [ "$count" -lt $csum_ns2 ] && [ $allow_multi_errors_ns2 -eq 1 ]; }; then
+	     { [ "$count" -lt $csum_ns2 ] && [ $allow_multi_errors_ns2 -eq 1 ]; }; then
 		fail_test "got $count data checksum error[s] expected $csum_ns2"
 	else
 		print_ok
@@ -1169,13 +1169,13 @@ chk_fail_nr()
 
 	print_check "ftx"
 	count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPFailTx")
-	if [ "$count" != "$fail_tx" ]; then
+	if [ -n "$count" ] && [ "$count" != "$fail_tx" ]; then
 		extra_msg+=",tx=$count"
 	fi
 	if [ -z "$count" ]; then
 		print_skip
 	elif { [ "$count" != "$fail_tx" ] && [ $allow_tx_lost -eq 0 ]; } ||
-	   { [ "$count" -gt "$fail_tx" ] && [ $allow_tx_lost -eq 1 ]; }; then
+	     { [ "$count" -gt "$fail_tx" ] && [ $allow_tx_lost -eq 1 ]; }; then
 		fail_test "got $count MP_FAIL[s] TX expected $fail_tx"
 	else
 		print_ok
@@ -1183,13 +1183,13 @@ chk_fail_nr()
 
 	print_check "failrx"
 	count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtMPFailRx")
-	if [ "$count" != "$fail_rx" ]; then
+	if [ -n "$count" ] && [ "$count" != "$fail_rx" ]; then
 		extra_msg+=",rx=$count"
 	fi
 	if [ -z "$count" ]; then
 		print_skip
 	elif { [ "$count" != "$fail_rx" ] && [ $allow_rx_lost -eq 0 ]; } ||
-	   { [ "$count" -gt "$fail_rx" ] && [ $allow_rx_lost -eq 1 ]; }; then
+	     { [ "$count" -gt "$fail_rx" ] && [ $allow_rx_lost -eq 1 ]; }; then
 		fail_test "got $count MP_FAIL[s] RX expected $fail_rx"
 	else
 		print_ok
author maintainer
#37 lore raw

PATCH 33/149 selftests: mptcp: join: check re-re-adding ID 0 endp

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matthieu Baerts (NGI0) <[email protected]>

commit d397d7246c11ca36c33c932bc36d38e3a79e9aa0 upstream.

This test extends "delete and re-add" to validate the previous commit:
when the endpoint linked to the initial subflow (ID 0) is re-added multiple times, it was no longer being used, because the internal linked counters are not decremented for this special endpoint: it is not an additional endpoint.

Here, the "del/add id 0" steps are done 3 times to unsure this case is validated.

The 'Fixes' tag here below is the same as the one from the previous
commit: this patch here is not fixing anything wrong in the selftests, but it validates the previous fix for an issue introduced by this commit ID.

Fixes 3ad14f54bd74 ("mptcp: more accurate MPC endpoint tracking")
---
 tools/testing/selftests/net/mptcp/mptcp_join.sh |   27 +++++++++++++-----------
 1 file changed, 15 insertions(+), 12 deletions(-)
tools/testing/selftests/net/mptcp/mptcp_join.sh +15 -12
@@ -3576,7 +3576,7 @@ endpoint_tests()
 		pm_nl_set_limits $ns2 0 3
 		pm_nl_add_endpoint $ns2 10.0.1.2 id 1 dev ns2eth1 flags subflow
 		pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow
-		test_linkfail=4 speed=20 \
+		test_linkfail=4 speed=5 \
 			run_tests $ns1 $ns2 10.0.1.1 &
 		local tests_pid=$!
 
@@ -3608,20 +3608,23 @@ endpoint_tests()
 		chk_subflow_nr "after no reject" 3
 		chk_mptcp_info subflows 2 subflows 2
 
-		pm_nl_del_endpoint $ns2 1 10.0.1.2
-		sleep 0.5
-		chk_subflow_nr "after delete id 0" 2
-		chk_mptcp_info subflows 2 subflows 2 # only decr for additional sf
-
-		pm_nl_add_endpoint $ns2 10.0.1.2 id 1 dev ns2eth1 flags subflow
-		wait_mpj $ns2
-		chk_subflow_nr "after re-add id 0" 3
-		chk_mptcp_info subflows 3 subflows 3
+		local i
+		for i in $(seq 3); do
+			pm_nl_del_endpoint $ns2 1 10.0.1.2
+			sleep 0.5
+			chk_subflow_nr "after delete id 0 ($i)" 2
+			chk_mptcp_info subflows 2 subflows 2 # only decr for additional sf
+
+			pm_nl_add_endpoint $ns2 10.0.1.2 id 1 dev ns2eth1 flags subflow
+			wait_mpj $ns2
+			chk_subflow_nr "after re-add id 0 ($i)" 3
+			chk_mptcp_info subflows 3 subflows 3
+		done
 
 		mptcp_lib_kill_wait $tests_pid
 
-		chk_join_nr 4 4 4
-		chk_rm_nr 2 2
+		chk_join_nr 6 6 6
+		chk_rm_nr 4 4
 	fi
 }
 
author maintainer
#38 lore raw

PATCH 34/149 binfmt_elf_fdpic: fix AUXV size calculation when ELF_HWCAP2 is defined

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Max Filippov <[email protected]>

commit c6a09e342f8e6d3cac7f7c5c14085236aca284b9 upstream.

create_elf_fdpic_tables() does not correctly account the space for the AUX vector when an architecture has ELF_HWCAP2 defined. Prior to the commit 10e29251be0e ("binfmt_elf_fdpic: fix /proc/<pid>/auxv") it resulted in the last entry of the AUX vector being set to zero, but with that change it results in a kernel BUG.

Fix that by adding one to the number of AUXV entries (nitems) when ELF_HWCAP2 is defined.

---
 fs/binfmt_elf_fdpic.c |    3 +++
 1 file changed, 3 insertions(+)
fs/binfmt_elf_fdpic.c +3 -0
@@ -592,6 +592,9 @@ static int create_elf_fdpic_tables(struc
 
 	if (bprm->have_execfd)
 		nitems++;
+#ifdef ELF_HWCAP2
+	nitems++;
+#endif
 
 	csp = sp;
 	sp -= nitems * 2 * sizeof(unsigned long);
author maintainer
#39 lore raw

PATCH 35/149 drm/v3d: Disable preemption while updating GPU stats

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Tvrtko Ursulin <[email protected]>

commit 9d824c7fce58f59982228aa85b0376b113cdfa35 upstream.

We forgot to disable preemption around the write_seqcount_begin/end() pair while updating GPU stats:

[ ] WARNING: CPU: 2 PID: 12 at include/linux/seqlock.h:221 __seqprop_assert.isra.0+0x128/0x150 [v3d] [ ] Workqueue: v3d_bin drm_sched_run_job_work [gpu_sched]
<...snip...>
[ ] Call trace:

  [ ]  __seqprop_assert.isra.0+0x128/0x150 [v3d]
  [ ]  v3d_job_start_stats.isra.0+0x90/0x218 [v3d]
  [ ]  v3d_bin_job_run+0x23c/0x388 [v3d]
  [ ]  drm_sched_run_job_work+0x520/0x6d0 [gpu_sched]
  [ ]  process_one_work+0x62c/0xb48
  [ ]  worker_thread+0x468/0x5b0
  [ ]  kthread+0x1c4/0x1e0
  [ ]  ret_from_fork+0x10/0x20

Fix it.

Cc Maíra Canal <[email protected]>
Cc [email protected] # v6.10+
Fixes 6abe93b621ab ("drm/v3d: Fix race-condition between sysfs/fdinfo and interrupt handler")
---
 drivers/gpu/drm/v3d/v3d_sched.c | 6 ++++++
 1 file changed, 6 insertions(+)
drivers/gpu/drm/v3d/v3d_sched.c +6 -0
index b8682818bafa..ad1e6236ff6f 100644
@@ -134,6 +134,8 @@ v3d_job_start_stats(struct v3d_job *job, enum v3d_queue queue)
 	struct v3d_stats *local_stats = &file->stats[queue];
 	u64 now = local_clock();
 
+	preempt_disable();
+
 	write_seqcount_begin(&local_stats->lock);
 	local_stats->start_ns = now;
 	write_seqcount_end(&local_stats->lock);
@@ -141,6 +143,8 @@ v3d_job_start_stats(struct v3d_job *job, enum v3d_queue queue)
 	write_seqcount_begin(&global_stats->lock);
 	global_stats->start_ns = now;
 	write_seqcount_end(&global_stats->lock);
+
+	preempt_enable();
 }
 
 static void
@@ -162,8 +166,10 @@ v3d_job_update_stats(struct v3d_job *job, enum v3d_queue queue)
 	struct v3d_stats *local_stats = &file->stats[queue];
 	u64 now = local_clock();
 
+	preempt_disable();
 	v3d_stats_update(local_stats, now);
 	v3d_stats_update(global_stats, now);
+	preempt_enable();
 }
 
 static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
Signature · 1 line
2.46.0
author maintainer
#40 lore raw

PATCH 36/149 drm/i915/dsi: Make Lenovo Yoga Tab 3 X90F DMI match less strict

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Hans de Goede <[email protected]>

commit 7d058e6bac9afab6a406e34344ebbfd3068bb2d5 upstream.

There are 2G and 4G RAM versions of the Lenovo Yoga Tab 3 X90F and it turns out that the 2G version has a DMI product name of "CHERRYVIEW D1 PLATFORM" where as the 4G version has "CHERRYVIEW C0 PLATFORM". The sys-vendor + product-version check are unique enough that the product-name check is not necessary.

Drop the product-name check so that the existing DMI match for the 4G RAM version also matches the 2G RAM version.

Fixes f6f4a0862bde ("drm/i915/vlv_dsi: Add DMI quirk for backlight control issues on Lenovo Yoga Tab 3 (v2)")
(cherry picked from commit a4dbe45c4c14edc316ae94b9af86a28f8c5d8123)
---
 drivers/gpu/drm/i915/display/vlv_dsi.c |    1 -
 1 file changed, 1 deletion(-)
drivers/gpu/drm/i915/display/vlv_dsi.c +0 -1
@@ -1869,7 +1869,6 @@ static const struct dmi_system_id vlv_ds
 		/* Lenovo Yoga Tab 3 Pro YT3-X90F */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
 			DMI_MATCH(DMI_PRODUCT_VERSION, "Blade3-10A-001"),
 		},
 		.driver_data = (void *)vlv_dsi_lenovo_yoga_tab3_backlight_fixup,
author maintainer
#41 lore raw

PATCH 37/149 drm/i915/dp_mst: Fix MST state after a sink reset

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Imre Deak <[email protected]>

commit a2ccc33b88e2953a6bf0b309e7e8849cc5320018 upstream.

In some cases the sink can reset itself after it was configured into MST mode, without the driver noticing the disconnected state. For instance the reset may happen in the middle of a modeset, or the (long) HPD pulse generated may be not long enough for the encoder detect handler to observe the HPD's deasserted state. In this case the sink's DPCD register programmed to enable MST will be reset, while the driver still assumes MST is still enabled. Detect this condition, which will tear down and recreate/re-enable the MST topology.

v2:
- Add a code comment about adjusting the expected DP_MSTM_CTRL register value for SST + SideBand. (Suraj, Jani)
- Print a debug message about detecting the link reset. (Jani)
- Verify the DPCD MST state only if it wasn't already determined that the sink is disconnected.

---
 drivers/gpu/drm/i915/display/intel_dp.c     |   12 ++++++++
 drivers/gpu/drm/i915/display/intel_dp_mst.c |   40 ++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_dp_mst.h |    1 
 3 files changed, 53 insertions(+)
drivers/gpu/drm/i915/display/intel_dp.c +12 -0
@@ -5860,6 +5860,18 @@ intel_dp_detect(struct drm_connector *co
 	else
 		status = connector_status_disconnected;
 
+	if (status != connector_status_disconnected &&
+	    !intel_dp_mst_verify_dpcd_state(intel_dp))
+		/*
+		 * This requires retrying detection for instance to re-enable
+		 * the MST mode that got reset via a long HPD pulse. The retry
+		 * will happen either via the hotplug handler's retry logic,
+		 * ensured by setting the connector here to SST/disconnected,
+		 * or via a userspace connector probing in response to the
+		 * hotplug uevent sent when removing the MST connectors.
+		 */
+		status = connector_status_disconnected;
+
 	if (status == connector_status_disconnected) {
 		memset(&intel_dp->compliance, 0, sizeof(intel_dp->compliance));
 		memset(intel_connector->dp.dsc_dpcd, 0, sizeof(intel_connector->dp.dsc_dpcd));
drivers/gpu/drm/i915/display/intel_dp_mst.c +40 -0
@@ -1986,3 +1986,43 @@ bool intel_dp_mst_crtc_needs_modeset(str
 
 	return false;
 }
+
+/*
+ * intel_dp_mst_verify_dpcd_state - verify the MST SW enabled state wrt. the DPCD
+ * @intel_dp: DP port object
+ *
+ * Verify if @intel_dp's MST enabled SW state matches the corresponding DPCD
+ * state. A long HPD pulse - not long enough to be detected as a disconnected
+ * state - could've reset the DPCD state, which requires tearing
+ * down/recreating the MST topology.
+ *
+ * Returns %true if the SW MST enabled and DPCD states match, %false
+ * otherwise.
+ */
+bool intel_dp_mst_verify_dpcd_state(struct intel_dp *intel_dp)
+{
+	struct intel_display *display = to_intel_display(intel_dp);
+	struct intel_connector *connector = intel_dp->attached_connector;
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	struct intel_encoder *encoder = &dig_port->base;
+	int ret;
+	u8 val;
+
+	if (!intel_dp->is_mst)
+		return true;
+
+	ret = drm_dp_dpcd_readb(intel_dp->mst_mgr.aux, DP_MSTM_CTRL, &val);
+
+	/* Adjust the expected register value for SST + SideBand. */
+	if (ret < 0 || val != (DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC)) {
+		drm_dbg_kms(display->drm,
+			    "[CONNECTOR:%d:%s][ENCODER:%d:%s] MST mode got reset, removing topology (ret=%d, ctrl=0x%02x)\n",
+			    connector->base.base.id, connector->base.name,
+			    encoder->base.base.id, encoder->base.name,
+			    ret, val);
+
+		return false;
+	}
+
+	return true;
+}
drivers/gpu/drm/i915/display/intel_dp_mst.h +1 -0
@@ -27,5 +27,6 @@ int intel_dp_mst_atomic_check_link(struc
 				   struct intel_link_bw_limits *limits);
 bool intel_dp_mst_crtc_needs_modeset(struct intel_atomic_state *state,
 				     struct intel_crtc *crtc);
+bool intel_dp_mst_verify_dpcd_state(struct intel_dp *intel_dp);
 
 #endif /* __INTEL_DP_MST_H__ */
author maintainer
#42 lore raw

PATCH 38/149 drm/amdgpu: align pp_power_profile_mode with kernel docs

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alex Deucher <[email protected]>

commit 8f614469de248a4bc55fb07e55d5f4c340c75b11 upstream.

The kernel doc says you need to select manual mode to adjust this, but the code only allows you to adjust it when manual mode is not selected. Remove the manual mode check.

(cherry picked from commit bbb05f8a9cd87f5046d05a0c596fddfb714ee457)
---
 drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c |    6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +2 -4
@@ -2256,8 +2256,7 @@ static int smu_adjust_power_state_dynami
 		smu_dpm_ctx->dpm_level = level;
 	}
 
-	if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL &&
-		smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM) {
+	if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM) {
 		index = fls(smu->workload_mask);
 		index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
 		workload[0] = smu->workload_setting[index];
@@ -2334,8 +2333,7 @@ static int smu_switch_power_profile(void
 		workload[0] = smu->workload_setting[index];
 	}
 
-	if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL &&
-		smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM)
+	if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM)
 		smu_bump_power_profile_mode(smu, workload, 0);
 
 	return 0;
author maintainer
#43 lore raw

PATCH 39/149 drm/amdgpu/swsmu: always force a state reprogram on init

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alex Deucher <[email protected]>

commit d420c857d85777663e8d16adfc24463f5d5c2dbc upstream.

Always reprogram the hardware state on init. This ensures the PMFW state is explicitly programmed and we are not relying on the default PMFW state.

(cherry picked from commit c50fe289ed7207f71df3b5f1720512a9620e84fb)
---
 drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c |   15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +9 -6
@@ -2215,8 +2215,9 @@ static int smu_bump_power_profile_mode(s
 }
 
 static int smu_adjust_power_state_dynamic(struct smu_context *smu,
-				   enum amd_dpm_forced_level level,
-				   bool skip_display_settings)
+					  enum amd_dpm_forced_level level,
+					  bool skip_display_settings,
+					  bool force_update)
 {
 	int ret = 0;
 	int index = 0;
@@ -2245,7 +2246,7 @@ static int smu_adjust_power_state_dynami
 		}
 	}
 
-	if (smu_dpm_ctx->dpm_level != level) {
+	if (force_update || smu_dpm_ctx->dpm_level != level) {
 		ret = smu_asic_set_performance_level(smu, level);
 		if (ret) {
 			dev_err(smu->adev->dev, "Failed to set performance level!");
@@ -2261,7 +2262,7 @@ static int smu_adjust_power_state_dynami
 		index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
 		workload[0] = smu->workload_setting[index];
 
-		if (smu->power_profile_mode != workload[0])
+		if (force_update || smu->power_profile_mode != workload[0])
 			smu_bump_power_profile_mode(smu, workload, 0);
 	}
 
@@ -2282,11 +2283,13 @@ static int smu_handle_task(struct smu_co
 		ret = smu_pre_display_config_changed(smu);
 		if (ret)
 			return ret;
-		ret = smu_adjust_power_state_dynamic(smu, level, false);
+		ret = smu_adjust_power_state_dynamic(smu, level, false, false);
 		break;
 	case AMD_PP_TASK_COMPLETE_INIT:
+		ret = smu_adjust_power_state_dynamic(smu, level, true, true);
+		break;
 	case AMD_PP_TASK_READJUST_POWER_STATE:
-		ret = smu_adjust_power_state_dynamic(smu, level, true);
+		ret = smu_adjust_power_state_dynamic(smu, level, true, false);
 		break;
 	default:
 		break;
author maintainer
#44 lore raw

PATCH 40/149 drm/vmwgfx: Prevent unmapping active read buffers

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Zack Rusin <[email protected]>

commit aba07b9a0587f50e5d3346eaa19019cf3f86c0ea upstream.

The kms paths keep a persistent map active to read and compare the cursor buffer. These maps can race with each other in simple scenario where:
a) buffer "a" mapped for update
b) buffer "a" mapped for compare
c) do the compare
d) unmap "a" for compare
e) update the cursor
f) unmap "a" for update
At step "e" the buffer has been unmapped and the read contents is bogus.

Prevent unmapping of active read buffers by simply keeping a count of how many paths have currently active maps and unmap only when the count reaches 0.

Fixes 485d98d472d5 ("drm/vmwgfx: Add support for CursorMob and CursorBypass 4")
Cc Broadcom internal kernel review list <[email protected]>
Cc <[email protected]> # v5.19+
---
 drivers/gpu/drm/vmwgfx/vmwgfx_bo.c |   13 +++++++++++--
 drivers/gpu/drm/vmwgfx/vmwgfx_bo.h |    3 +++
 2 files changed, 14 insertions(+), 2 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +11 -2
@@ -360,6 +360,8 @@ void *vmw_bo_map_and_cache_size(struct v
 	void *virtual;
 	int ret;
 
+	atomic_inc(&vbo->map_count);
+
 	virtual = ttm_kmap_obj_virtual(&vbo->map, &not_used);
 	if (virtual)
 		return virtual;
@@ -383,11 +385,17 @@ void *vmw_bo_map_and_cache_size(struct v
  */
 void vmw_bo_unmap(struct vmw_bo *vbo)
 {
+	int map_count;
+
 	if (vbo->map.bo == NULL)
 		return;
 
-	ttm_bo_kunmap(&vbo->map);
-	vbo->map.bo = NULL;
+	map_count = atomic_dec_return(&vbo->map_count);
+
+	if (!map_count) {
+		ttm_bo_kunmap(&vbo->map);
+		vbo->map.bo = NULL;
+	}
 }
 
 
@@ -421,6 +429,7 @@ static int vmw_bo_init(struct vmw_privat
 	vmw_bo->tbo.priority = 3;
 	vmw_bo->res_tree = RB_ROOT;
 	xa_init(&vmw_bo->detached_resources);
+	atomic_set(&vmw_bo->map_count, 0);
 
 	params->size = ALIGN(params->size, PAGE_SIZE);
 	drm_gem_private_object_init(vdev, &vmw_bo->tbo.base, params->size);
drivers/gpu/drm/vmwgfx/vmwgfx_bo.h +3 -0
@@ -71,6 +71,8 @@ struct vmw_bo_params {
  * @map: Kmap object for semi-persistent mappings
  * @res_tree: RB tree of resources using this buffer object as a backing MOB
  * @res_prios: Eviction priority counts for attached resources
+ * @map_count: The number of currently active maps. Will differ from the
+ * cpu_writers because it includes kernel maps.
  * @cpu_writers: Number of synccpu write grabs. Protected by reservation when
  * increased. May be decreased without reservation.
  * @dx_query_ctx: DX context if this buffer object is used as a DX query MOB
@@ -90,6 +92,7 @@ struct vmw_bo {
 	u32 res_prios[TTM_MAX_BO_PRIORITY];
 	struct xarray detached_resources;
 
+	atomic_t map_count;
 	atomic_t cpu_writers;
 	/* Not ref-counted.  Protected by binding_mutex */
 	struct vmw_resource *dx_query_ctx;
author maintainer
#45 lore raw

PATCH 41/149 drm/vmwgfx: Fix prime with external buffers

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Zack Rusin <[email protected]>

commit 50f1199250912568606b3778dc56646c10cb7b04 upstream.

Make sure that for external buffers mapping goes through the dma_buf interface instead of trying to access pages directly.

External buffers might not provide direct access to readable/writable pages so to make sure the bo's created from external dma_bufs can be read dma_buf interface has to be used.

Fixes crashes in IGT's kms_prime with vgem. Regular desktop usage won't trigger this due to the fact that virtual machines will not have multiple GPUs but it enables better test coverage in IGT.

Fixes b32233acceff ("drm/vmwgfx: Fix prime import/export")
Cc <[email protected]> # v6.6+
Cc Broadcom internal kernel review list <[email protected]>
Cc <[email protected]> # v6.9+
---
 drivers/gpu/drm/vmwgfx/vmwgfx_blit.c |  114 +++++++++++++++++++++++++++++++++--
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h  |    4 -
 drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c |   12 +--
 3 files changed, 118 insertions(+), 12 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_blit.c +110 -4
@@ -27,6 +27,8 @@
  **************************************************************************/
 
 #include "vmwgfx_drv.h"
+
+#include "vmwgfx_bo.h"
 #include <linux/highmem.h>
 
 /*
@@ -420,13 +422,105 @@ static int vmw_bo_cpu_blit_line(struct v
 	return 0;
 }
 
+static void *map_external(struct vmw_bo *bo, struct iosys_map *map)
+{
+	struct vmw_private *vmw =
+		container_of(bo->tbo.bdev, struct vmw_private, bdev);
+	void *ptr = NULL;
+	int ret;
+
+	if (bo->tbo.base.import_attach) {
+		ret = dma_buf_vmap(bo->tbo.base.dma_buf, map);
+		if (ret) {
+			drm_dbg_driver(&vmw->drm,
+				       "Wasn't able to map external bo!\n");
+			goto out;
+		}
+		ptr = map->vaddr;
+	} else {
+		ptr = vmw_bo_map_and_cache(bo);
+	}
+
+out:
+	return ptr;
+}
+
+static void unmap_external(struct vmw_bo *bo, struct iosys_map *map)
+{
+	if (bo->tbo.base.import_attach)
+		dma_buf_vunmap(bo->tbo.base.dma_buf, map);
+	else
+		vmw_bo_unmap(bo);
+}
+
+static int vmw_external_bo_copy(struct vmw_bo *dst, u32 dst_offset,
+				u32 dst_stride, struct vmw_bo *src,
+				u32 src_offset, u32 src_stride,
+				u32 width_in_bytes, u32 height,
+				struct vmw_diff_cpy *diff)
+{
+	struct vmw_private *vmw =
+		container_of(dst->tbo.bdev, struct vmw_private, bdev);
+	size_t dst_size = dst->tbo.resource->size;
+	size_t src_size = src->tbo.resource->size;
+	struct iosys_map dst_map = {0};
+	struct iosys_map src_map = {0};
+	int ret, i;
+	int x_in_bytes;
+	u8 *vsrc;
+	u8 *vdst;
+
+	vsrc = map_external(src, &src_map);
+	if (!vsrc) {
+		drm_dbg_driver(&vmw->drm, "Wasn't able to map src\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	vdst = map_external(dst, &dst_map);
+	if (!vdst) {
+		drm_dbg_driver(&vmw->drm, "Wasn't able to map dst\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	vsrc += src_offset;
+	vdst += dst_offset;
+	if (src_stride == dst_stride) {
+		dst_size -= dst_offset;
+		src_size -= src_offset;
+		memcpy(vdst, vsrc,
+		       min(dst_stride * height, min(dst_size, src_size)));
+	} else {
+		WARN_ON(dst_stride < width_in_bytes);
+		for (i = 0; i < height; ++i) {
+			memcpy(vdst, vsrc, width_in_bytes);
+			vsrc += src_stride;
+			vdst += dst_stride;
+		}
+	}
+
+	x_in_bytes = (dst_offset % dst_stride);
+	diff->rect.x1 =  x_in_bytes / diff->cpp;
+	diff->rect.y1 = ((dst_offset - x_in_bytes) / dst_stride);
+	diff->rect.x2 = diff->rect.x1 + width_in_bytes / diff->cpp;
+	diff->rect.y2 = diff->rect.y1 + height;
+
+	ret = 0;
+out:
+	unmap_external(src, &src_map);
+	unmap_external(dst, &dst_map);
+
+	return ret;
+}
+
 /**
  * vmw_bo_cpu_blit - in-kernel cpu blit.
  *
- * @dst: Destination buffer object.
+ * @vmw_dst: Destination buffer object.
  * @dst_offset: Destination offset of blit start in bytes.
  * @dst_stride: Destination stride in bytes.
- * @src: Source buffer object.
+ * @vmw_src: Source buffer object.
  * @src_offset: Source offset of blit start in bytes.
  * @src_stride: Source stride in bytes.
  * @w: Width of blit.
@@ -444,13 +538,15 @@ static int vmw_bo_cpu_blit_line(struct v
  * Neither of the buffer objects may be placed in PCI memory
  * (Fixed memory in TTM terminology) when using this function.
  */
-int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
+int vmw_bo_cpu_blit(struct vmw_bo *vmw_dst,
 		    u32 dst_offset, u32 dst_stride,
-		    struct ttm_buffer_object *src,
+		    struct vmw_bo *vmw_src,
 		    u32 src_offset, u32 src_stride,
 		    u32 w, u32 h,
 		    struct vmw_diff_cpy *diff)
 {
+	struct ttm_buffer_object *src = &vmw_src->tbo;
+	struct ttm_buffer_object *dst = &vmw_dst->tbo;
 	struct ttm_operation_ctx ctx = {
 		.interruptible = false,
 		.no_wait_gpu = false
@@ -460,6 +556,11 @@ int vmw_bo_cpu_blit(struct ttm_buffer_ob
 	int ret = 0;
 	struct page **dst_pages = NULL;
 	struct page **src_pages = NULL;
+	bool src_external = (src->ttm->page_flags & TTM_TT_FLAG_EXTERNAL) != 0;
+	bool dst_external = (dst->ttm->page_flags & TTM_TT_FLAG_EXTERNAL) != 0;
+
+	if (WARN_ON(dst == src))
+		return -EINVAL;
 
 	/* Buffer objects need to be either pinned or reserved: */
 	if (!(dst->pin_count))
@@ -479,6 +580,11 @@ int vmw_bo_cpu_blit(struct ttm_buffer_ob
 			return ret;
 	}
 
+	if (src_external || dst_external)
+		return vmw_external_bo_copy(vmw_dst, dst_offset, dst_stride,
+					    vmw_src, src_offset, src_stride,
+					    w, h, diff);
+
 	if (!src->ttm->pages && src->ttm->sg) {
 		src_pages = kvmalloc_array(src->ttm->num_pages,
 					   sizeof(struct page *), GFP_KERNEL);
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +2 -2
@@ -1353,9 +1353,9 @@ void vmw_diff_memcpy(struct vmw_diff_cpy
 
 void vmw_memcpy(struct vmw_diff_cpy *diff, u8 *dest, const u8 *src, size_t n);
 
-int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
+int vmw_bo_cpu_blit(struct vmw_bo *dst,
 		    u32 dst_offset, u32 dst_stride,
-		    struct ttm_buffer_object *src,
+		    struct vmw_bo *src,
 		    u32 src_offset, u32 src_stride,
 		    u32 w, u32 h,
 		    struct vmw_diff_cpy *diff);
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +6 -6
@@ -502,7 +502,7 @@ static void vmw_stdu_bo_cpu_commit(struc
 		container_of(dirty->unit, typeof(*stdu), base);
 	s32 width, height;
 	s32 src_pitch, dst_pitch;
-	struct ttm_buffer_object *src_bo, *dst_bo;
+	struct vmw_bo *src_bo, *dst_bo;
 	u32 src_offset, dst_offset;
 	struct vmw_diff_cpy diff = VMW_CPU_BLIT_DIFF_INITIALIZER(stdu->cpp);
 
@@ -517,11 +517,11 @@ static void vmw_stdu_bo_cpu_commit(struc
 
 	/* Assume we are blitting from Guest (bo) to Host (display_srf) */
 	src_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp;
-	src_bo = &stdu->display_srf->res.guest_memory_bo->tbo;
+	src_bo = stdu->display_srf->res.guest_memory_bo;
 	src_offset = ddirty->top * src_pitch + ddirty->left * stdu->cpp;
 
 	dst_pitch = ddirty->pitch;
-	dst_bo = &ddirty->buf->tbo;
+	dst_bo = ddirty->buf;
 	dst_offset = ddirty->fb_top * dst_pitch + ddirty->fb_left * stdu->cpp;
 
 	(void) vmw_bo_cpu_blit(dst_bo, dst_offset, dst_pitch,
@@ -1170,7 +1170,7 @@ vmw_stdu_bo_populate_update_cpu(struct v
 	struct vmw_diff_cpy diff = VMW_CPU_BLIT_DIFF_INITIALIZER(0);
 	struct vmw_stdu_update_gb_image *cmd_img = cmd;
 	struct vmw_stdu_update *cmd_update;
-	struct ttm_buffer_object *src_bo, *dst_bo;
+	struct vmw_bo *src_bo, *dst_bo;
 	u32 src_offset, dst_offset;
 	s32 src_pitch, dst_pitch;
 	s32 width, height;
@@ -1184,11 +1184,11 @@ vmw_stdu_bo_populate_update_cpu(struct v
 
 	diff.cpp = stdu->cpp;
 
-	dst_bo = &stdu->display_srf->res.guest_memory_bo->tbo;
+	dst_bo = stdu->display_srf->res.guest_memory_bo;
 	dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp;
 	dst_offset = bb->y1 * dst_pitch + bb->x1 * stdu->cpp;
 
-	src_bo = &vfbbo->buffer->tbo;
+	src_bo = vfbbo->buffer;
 	src_pitch = update->vfb->base.pitches[0];
 	src_offset = bo_update->fb_top * src_pitch + bo_update->fb_left *
 		stdu->cpp;
author maintainer
#46 lore raw

PATCH 42/149 drm/vmwgfx: Disable coherent dumb buffers without 3d

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Zack Rusin <[email protected]>

commit e9fd436bb8fb9b9d31fdf07bbcdba6d30290c5e4 upstream.

Coherent surfaces make only sense if the host renders to them using accelerated apis. Without 3d the entire content of dumb buffers stays in the guest making all of the extra work they're doing to synchronize between guest and host useless.

Configurations without 3d also tend to run with very low graphics memory limits. The pinned console fb, mob cursors and graphical login manager tend to run out of 16MB graphics memory that those guests use.

Fix it by making sure the coherent dumb buffers are only used on configs with 3d enabled.

---
 drivers/gpu/drm/vmwgfx/vmwgfx_surface.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +4 -2
@@ -2283,9 +2283,11 @@ int vmw_dumb_create(struct drm_file *fil
 	/*
 	 * Without mob support we're just going to use raw memory buffer
 	 * because we wouldn't be able to support full surface coherency
-	 * without mobs
+	 * without mobs. There also no reason to support surface coherency
+	 * without 3d (i.e. gpu usage on the host) because then all the
+	 * contents is going to be rendered guest side.
 	 */
-	if (!dev_priv->has_mob) {
+	if (!dev_priv->has_mob || !vmw_supports_3d(dev_priv)) {
 		int cpp = DIV_ROUND_UP(args->bpp, 8);
 
 		switch (cpp) {
author maintainer
#47 lore raw

PATCH 43/149 video/aperture: optionally match the device in sysfb_disable()

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alex Deucher <[email protected]>

commit b49420d6a1aeb399e5b107fc6eb8584d0860fbd7 upstream.

In aperture_remove_conflicting_pci_devices(), we currently only call sysfb_disable() on vga class devices. This leads to the following problem when the pimary device is not VGA compatible:

1. A PCI device with a non-VGA class is the boot display
2. That device is probed first and it is not a VGA device so sysfb_disable() is not called, but the device resources are freed by aperture_detach_platform_device()
3. Non-primary GPU has a VGA class and it ends up calling sysfb_disable()
4. NULL pointer dereference via sysfb_disable() since the resources have already been freed by aperture_detach_platform_device() when it was called by the other device.

Fix this by passing a device pointer to sysfb_disable() and checking the device to determine if we should execute it or not.

v2: Fix build when CONFIG_SCREEN_INFO is not set
v3: Move device check into the mutex
Drop primary variable in aperture_remove_conflicting_pci_devices() Drop __init on pci sysfb_pci_dev_is_enabled()

Fixes 5ae3716cfdcd ("video/aperture: Only remove sysfb on the default vga pci device")
Cc Javier Martinez Canillas <[email protected]>
Cc Thomas Zimmermann <[email protected]>
Cc Helge Deller <[email protected]>
Cc Sam Ravnborg <[email protected]>
Cc Daniel Vetter <[email protected]>
---
 drivers/firmware/sysfb.c |   19 +++++++++++++------
 drivers/of/platform.c    |    2 +-
 drivers/video/aperture.c |   11 +++--------
 include/linux/sysfb.h    |    4 ++--
 4 files changed, 19 insertions(+), 17 deletions(-)
drivers/firmware/sysfb.c +13 -6
@@ -39,6 +39,8 @@ static struct platform_device *pd;
 static DEFINE_MUTEX(disable_lock);
 static bool disabled;
 
+static struct device *sysfb_parent_dev(const struct screen_info *si);
+
 static bool sysfb_unregister(void)
 {
 	if (IS_ERR_OR_NULL(pd))
@@ -52,6 +54,7 @@ static bool sysfb_unregister(void)
 
 /**
  * sysfb_disable() - disable the Generic System Framebuffers support
+ * @dev:	the device to check if non-NULL
  *
  * This disables the registration of system framebuffer devices that match the
  * generic drivers that make use of the system framebuffer set up by firmware.
@@ -61,17 +64,21 @@ static bool sysfb_unregister(void)
  * Context: The function can sleep. A @disable_lock mutex is acquired to serialize
  *          against sysfb_init(), that registers a system framebuffer device.
  */
-void sysfb_disable(void)
+void sysfb_disable(struct device *dev)
 {
+	struct screen_info *si = &screen_info;
+
 	mutex_lock(&disable_lock);
-	sysfb_unregister();
-	disabled = true;
+	if (!dev || dev == sysfb_parent_dev(si)) {
+		sysfb_unregister();
+		disabled = true;
+	}
 	mutex_unlock(&disable_lock);
 }
 EXPORT_SYMBOL_GPL(sysfb_disable);
 
 #if defined(CONFIG_PCI)
-static __init bool sysfb_pci_dev_is_enabled(struct pci_dev *pdev)
+static bool sysfb_pci_dev_is_enabled(struct pci_dev *pdev)
 {
 	/*
 	 * TODO: Try to integrate this code into the PCI subsystem
@@ -87,13 +94,13 @@ static __init bool sysfb_pci_dev_is_enab
 	return true;
 }
 #else
-static __init bool sysfb_pci_dev_is_enabled(struct pci_dev *pdev)
+static bool sysfb_pci_dev_is_enabled(struct pci_dev *pdev)
 {
 	return false;
 }
 #endif
 
-static __init struct device *sysfb_parent_dev(const struct screen_info *si)
+static struct device *sysfb_parent_dev(const struct screen_info *si)
 {
 	struct pci_dev *pdev;
 
drivers/of/platform.c +1 -1
@@ -592,7 +592,7 @@ static int __init of_platform_default_po
 			 * This can happen for example on DT systems that do EFI
 			 * booting and may provide a GOP handle to the EFI stub.
 			 */
-			sysfb_disable();
+			sysfb_disable(NULL);
 			of_platform_device_create(node, NULL, NULL);
 			of_node_put(node);
 		}
drivers/video/aperture.c +3 -8
@@ -293,7 +293,7 @@ int aperture_remove_conflicting_devices(
 	 * ask for this, so let's assume that a real driver for the display
 	 * was already probed and prevent sysfb to register devices later.
 	 */
-	sysfb_disable();
+	sysfb_disable(NULL);
 
 	aperture_detach_devices(base, size);
 
@@ -346,15 +346,10 @@ EXPORT_SYMBOL(__aperture_remove_legacy_v
  */
 int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *name)
 {
-	bool primary = false;
 	resource_size_t base, size;
 	int bar, ret = 0;
 
-	if (pdev == vga_default_device())
-		primary = true;
-
-	if (primary)
-		sysfb_disable();
+	sysfb_disable(&pdev->dev);
 
 	for (bar = 0; bar < PCI_STD_NUM_BARS; ++bar) {
 		if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM))
@@ -370,7 +365,7 @@ int aperture_remove_conflicting_pci_devi
 	 * that consumes the VGA framebuffer I/O range. Remove this
 	 * device as well.
 	 */
-	if (primary)
+	if (pdev == vga_default_device())
 		ret = __aperture_remove_legacy_vga_devices(pdev);
 
 	return ret;
include/linux/sysfb.h +2 -2
@@ -58,11 +58,11 @@ struct efifb_dmi_info {
 
 #ifdef CONFIG_SYSFB
 
-void sysfb_disable(void);
+void sysfb_disable(struct device *dev);
 
 #else /* CONFIG_SYSFB */
 
-static inline void sysfb_disable(void)
+static inline void sysfb_disable(struct device *dev)
 {
 }
 
author maintainer
#48 lore raw

PATCH 44/149 drm/xe: Prepare display for D3Cold

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Rodrigo Vivi <[email protected]>

[ Upstream commit e7b180b22022f52e3f5fca695cc75d63bddc5a1c ]

Prepare power-well and DC handling for a full power lost during D3Cold, then sanitize it upon D3->D0. Otherwise we get a bunch of state mismatch.

Ideally we could leave DC9 enabled and wouldn't need to move DC9->DC0 on every runtime resume, however, the disable_DC is part of the power-well checks and intrinsic to the dc_off power well. In the future that can be detangled so we can have even bigger power savings. But for now, let's focus on getting a D3Cold, which saves much more power by itself.

v2: create new functions to avoid full-suspend-resume path, which would result in a deadlock between xe_gem_fault and the modeset-ioctl.

v3: Only avoid the full modeset to avoid the race, for a more robust suspend-resume.

Stable-dep-of: ddf6492e0e50 ("drm/xe/display: Make display suspend/resume work on discrete")

---
 drivers/gpu/drm/xe/display/xe_display.c | 10 ++++++----
 drivers/gpu/drm/xe/display/xe_display.h |  8 ++++----
 drivers/gpu/drm/xe/xe_pm.c              | 15 ++++++++++++---
 3 files changed, 22 insertions(+), 11 deletions(-)
drivers/gpu/drm/xe/display/xe_display.c +6 -4
index 7cdc03dc40ed9..79d33d592093c 100644
@@ -302,7 +302,7 @@ static bool suspend_to_idle(void)
 	return false;
 }
 
-void xe_display_pm_suspend(struct xe_device *xe)
+void xe_display_pm_suspend(struct xe_device *xe, bool runtime)
 {
 	bool s2idle = suspend_to_idle();
 	if (!xe->info.enable_display)
@@ -316,7 +316,8 @@ void xe_display_pm_suspend(struct xe_device *xe)
 	if (has_display(xe))
 		drm_kms_helper_poll_disable(&xe->drm);
 
-	intel_display_driver_suspend(xe);
+	if (!runtime)
+		intel_display_driver_suspend(xe);
 
 	intel_dp_mst_suspend(xe);
 
@@ -352,7 +353,7 @@ void xe_display_pm_resume_early(struct xe_device *xe)
 	intel_power_domains_resume(xe);
 }
 
-void xe_display_pm_resume(struct xe_device *xe)
+void xe_display_pm_resume(struct xe_device *xe, bool runtime)
 {
 	if (!xe->info.enable_display)
 		return;
@@ -367,7 +368,8 @@ void xe_display_pm_resume(struct xe_device *xe)
 
 	/* MST sideband requires HPD interrupts enabled */
 	intel_dp_mst_resume(xe);
-	intel_display_driver_resume(xe);
+	if (!runtime)
+		intel_display_driver_resume(xe);
 
 	intel_hpd_poll_disable(xe);
 	if (has_display(xe))
drivers/gpu/drm/xe/display/xe_display.h +4 -4
index 710e56180b52d..93d1f779b9788 100644
@@ -34,10 +34,10 @@ void xe_display_irq_enable(struct xe_device *xe, u32 gu_misc_iir);
 void xe_display_irq_reset(struct xe_device *xe);
 void xe_display_irq_postinstall(struct xe_device *xe, struct xe_gt *gt);
 
-void xe_display_pm_suspend(struct xe_device *xe);
+void xe_display_pm_suspend(struct xe_device *xe, bool runtime);
 void xe_display_pm_suspend_late(struct xe_device *xe);
 void xe_display_pm_resume_early(struct xe_device *xe);
-void xe_display_pm_resume(struct xe_device *xe);
+void xe_display_pm_resume(struct xe_device *xe, bool runtime);
 
 #else
 
@@ -63,10 +63,10 @@ static inline void xe_display_irq_enable(struct xe_device *xe, u32 gu_misc_iir)
 static inline void xe_display_irq_reset(struct xe_device *xe) {}
 static inline void xe_display_irq_postinstall(struct xe_device *xe, struct xe_gt *gt) {}
 
-static inline void xe_display_pm_suspend(struct xe_device *xe) {}
+static inline void xe_display_pm_suspend(struct xe_device *xe, bool runtime) {}
 static inline void xe_display_pm_suspend_late(struct xe_device *xe) {}
 static inline void xe_display_pm_resume_early(struct xe_device *xe) {}
-static inline void xe_display_pm_resume(struct xe_device *xe) {}
+static inline void xe_display_pm_resume(struct xe_device *xe, bool runtime) {}
 
 #endif /* CONFIG_DRM_XE_DISPLAY */
 #endif /* _XE_DISPLAY_H_ */
drivers/gpu/drm/xe/xe_pm.c +12 -3
index 37fbeda12d3bd..07615acd2c299 100644
@@ -96,12 +96,12 @@ int xe_pm_suspend(struct xe_device *xe)
 	if (err)
 		goto err;
 
-	xe_display_pm_suspend(xe);
+	xe_display_pm_suspend(xe, false);
 
 	for_each_gt(gt, xe, id) {
 		err = xe_gt_suspend(gt);
 		if (err) {
-			xe_display_pm_resume(xe);
+			xe_display_pm_resume(xe, false);
 			goto err;
 		}
 	}
@@ -151,7 +151,7 @@ int xe_pm_resume(struct xe_device *xe)
 
 	xe_irq_resume(xe);
 
-	xe_display_pm_resume(xe);
+	xe_display_pm_resume(xe, false);
 
 	for_each_gt(gt, xe, id)
 		xe_gt_resume(gt);
@@ -366,6 +366,7 @@ int xe_pm_runtime_suspend(struct xe_device *xe)
 		err = xe_bo_evict_all(xe);
 		if (err)
 			goto out;
+		xe_display_pm_suspend(xe, true);
 	}
 
 	for_each_gt(gt, xe, id) {
@@ -375,7 +376,12 @@ int xe_pm_runtime_suspend(struct xe_device *xe)
 	}
 
 	xe_irq_suspend(xe);
+
+	if (xe->d3cold.allowed)
+		xe_display_pm_suspend_late(xe);
 out:
+	if (err)
+		xe_display_pm_resume(xe, true);
 	lock_map_release(&xe_pm_runtime_lockdep_map);
 	xe_pm_write_callback_task(xe, NULL);
 	return err;
@@ -411,6 +417,8 @@ int xe_pm_runtime_resume(struct xe_device *xe)
 		if (err)
 			goto out;
 
+		xe_display_pm_resume_early(xe);
+
 		/*
 		 * This only restores pinned memory which is the memory
 		 * required for the GT(s) to resume.
@@ -426,6 +434,7 @@ int xe_pm_runtime_resume(struct xe_device *xe)
 		xe_gt_resume(gt);
 
 	if (xe->d3cold.allowed && xe->d3cold.power_lost) {
+		xe_display_pm_resume(xe, true);
 		err = xe_bo_restore_user(xe);
 		if (err)
 			goto out;
Signature · 1 line
2.43.0
author maintainer
#49 lore raw

PATCH 45/149 drm/xe/display: Make display suspend/resume work on discrete

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Maarten Lankhorst <[email protected]>

[ Upstream commit ddf6492e0e508b7c2b42c8d5a4ac82bd38ef0dd5 ]

We should unpin before evicting all memory, and repin after GT resume. This way, we preserve the contents of the framebuffers, and won't hang on resume due to migration engine not being restored yet.

Fixes dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs")
(cherry picked from commit cb8f81c1753187995b7a43e79c12959f14eb32d3)
---
 drivers/gpu/drm/xe/display/xe_display.c | 23 +++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_pm.c              | 11 ++++++-----
 2 files changed, 29 insertions(+), 5 deletions(-)
drivers/gpu/drm/xe/display/xe_display.c +23 -0
index 79d33d592093c..96835ffa5734e 100644
@@ -302,6 +302,27 @@ static bool suspend_to_idle(void)
 	return false;
 }
 
+static void xe_display_flush_cleanup_work(struct xe_device *xe)
+{
+	struct intel_crtc *crtc;
+
+	for_each_intel_crtc(&xe->drm, crtc) {
+		struct drm_crtc_commit *commit;
+
+		spin_lock(&crtc->base.commit_lock);
+		commit = list_first_entry_or_null(&crtc->base.commit_list,
+						  struct drm_crtc_commit, commit_entry);
+		if (commit)
+			drm_crtc_commit_get(commit);
+		spin_unlock(&crtc->base.commit_lock);
+
+		if (commit) {
+			wait_for_completion(&commit->cleanup_done);
+			drm_crtc_commit_put(commit);
+		}
+	}
+}
+
 void xe_display_pm_suspend(struct xe_device *xe, bool runtime)
 {
 	bool s2idle = suspend_to_idle();
@@ -319,6 +340,8 @@ void xe_display_pm_suspend(struct xe_device *xe, bool runtime)
 	if (!runtime)
 		intel_display_driver_suspend(xe);
 
+	xe_display_flush_cleanup_work(xe);
+
 	intel_dp_mst_suspend(xe);
 
 	intel_hpd_cancel_work(xe);
drivers/gpu/drm/xe/xe_pm.c +6 -5
index 07615acd2c299..cf80679ceb701 100644
@@ -91,13 +91,13 @@ int xe_pm_suspend(struct xe_device *xe)
 	for_each_gt(gt, xe, id)
 		xe_gt_suspend_prepare(gt);
 
+	xe_display_pm_suspend(xe, false);
+
 	/* FIXME: Super racey... */
 	err = xe_bo_evict_all(xe);
 	if (err)
 		goto err;
 
-	xe_display_pm_suspend(xe, false);
-
 	for_each_gt(gt, xe, id) {
 		err = xe_gt_suspend(gt);
 		if (err) {
@@ -151,11 +151,11 @@ int xe_pm_resume(struct xe_device *xe)
 
 	xe_irq_resume(xe);
 
-	xe_display_pm_resume(xe, false);
-
 	for_each_gt(gt, xe, id)
 		xe_gt_resume(gt);
 
+	xe_display_pm_resume(xe, false);
+
 	err = xe_bo_restore_user(xe);
 	if (err)
 		goto err;
@@ -363,10 +363,11 @@ int xe_pm_runtime_suspend(struct xe_device *xe)
 	mutex_unlock(&xe->mem_access.vram_userfault.lock);
 
 	if (xe->d3cold.allowed) {
+		xe_display_pm_suspend(xe, true);
+
 		err = xe_bo_evict_all(xe);
 		if (err)
 			goto out;
-		xe_display_pm_suspend(xe, true);
 	}
 
 	for_each_gt(gt, xe, id) {
Signature · 1 line
2.43.0
author maintainer
#50 lore raw

PATCH 46/149 drm/xe/vm: Simplify if condition

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Thorsten Blum <[email protected]>

[ Upstream commit b3181f433206a1432bc7093d1896fe36026f7fff ]

The if condition !A || A && B can be simplified to !A || B.

Fixes the following Coccinelle/coccicheck warning reported by excluded_middle.cocci:

	WARNING !A || A && B is equivalent to !A || B

Compile-tested only.

Stable-dep-of: 730b72480e29 ("drm/xe: prevent UAF around preempt fence")

---
 drivers/gpu/drm/xe/xe_vm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/xe/xe_vm.c +2 -2
index 4aa3943e6f292..3137cbbaabde0 100644
@@ -85,8 +85,8 @@ static bool preempt_fences_waiting(struct xe_vm *vm)
 
 	list_for_each_entry(q, &vm->preempt.exec_queues, compute.link) {
 		if (!q->compute.pfence ||
-		    (q->compute.pfence && test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
-						   &q->compute.pfence->flags))) {
+		    test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
+			     &q->compute.pfence->flags)) {
 			return true;
 		}
 	}
Signature · 1 line
2.43.0
author maintainer
#51 lore raw

PATCH 47/149 drm/xe/exec_queue: Rename xe_exec_queue::compute to xe_exec_queue::lr

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Francois Dugast <[email protected]>

[ Upstream commit 731e46c032281601756f08cfa7d8505fe41166a9 ]

The properties of this struct are used in long running context so make that clear by renaming it to lr, in alignment with the rest of the code.

Stable-dep-of: 730b72480e29 ("drm/xe: prevent UAF around preempt fence")

---
 drivers/gpu/drm/xe/xe_exec_queue.c       |  6 +--
 drivers/gpu/drm/xe/xe_exec_queue_types.h | 14 +++---
 drivers/gpu/drm/xe/xe_preempt_fence.c    |  2 +-
 drivers/gpu/drm/xe/xe_vm.c               | 58 ++++++++++++------------
 4 files changed, 40 insertions(+), 40 deletions(-)
drivers/gpu/drm/xe/xe_exec_queue.c +3 -3
index 2ae4420e29353..316731c5cce6d 100644
@@ -67,7 +67,7 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe,
 	q->fence_irq = &gt->fence_irq[hwe->class];
 	q->ring_ops = gt->ring_ops[hwe->class];
 	q->ops = gt->exec_queue_ops;
-	INIT_LIST_HEAD(&q->compute.link);
+	INIT_LIST_HEAD(&q->lr.link);
 	INIT_LIST_HEAD(&q->multi_gt_link);
 
 	q->sched_props.timeslice_us = hwe->eclass->sched_props.timeslice_us;
@@ -631,8 +631,8 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
 			return PTR_ERR(q);
 
 		if (xe_vm_in_preempt_fence_mode(vm)) {
-			q->compute.context = dma_fence_context_alloc(1);
-			spin_lock_init(&q->compute.lock);
+			q->lr.context = dma_fence_context_alloc(1);
+			spin_lock_init(&q->lr.lock);
 
 			err = xe_vm_add_compute_exec_queue(vm, q);
 			if (XE_IOCTL_DBG(xe, err))
drivers/gpu/drm/xe/xe_exec_queue_types.h +7 -7
index f0c40e8ad80a1..52a1965d91375 100644
@@ -115,19 +115,19 @@ struct xe_exec_queue {
 		enum xe_exec_queue_priority priority;
 	} sched_props;
 
-	/** @compute: compute exec queue state */
+	/** @lr: long-running exec queue state */
 	struct {
-		/** @compute.pfence: preemption fence */
+		/** @lr.pfence: preemption fence */
 		struct dma_fence *pfence;
-		/** @compute.context: preemption fence context */
+		/** @lr.context: preemption fence context */
 		u64 context;
-		/** @compute.seqno: preemption fence seqno */
+		/** @lr.seqno: preemption fence seqno */
 		u32 seqno;
-		/** @compute.link: link into VM's list of exec queues */
+		/** @lr.link: link into VM's list of exec queues */
 		struct list_head link;
-		/** @compute.lock: preemption fences lock */
+		/** @lr.lock: preemption fences lock */
 		spinlock_t lock;
-	} compute;
+	} lr;
 
 	/** @ops: submission backend exec queue operations */
 	const struct xe_exec_queue_ops *ops;
drivers/gpu/drm/xe/xe_preempt_fence.c +1 -1
index 5b243b7feb59d..e8b8ae5c6485e 100644
@@ -129,7 +129,7 @@ xe_preempt_fence_arm(struct xe_preempt_fence *pfence, struct xe_exec_queue *q,
 	list_del_init(&pfence->link);
 	pfence->q = xe_exec_queue_get(q);
 	dma_fence_init(&pfence->base, &preempt_fence_ops,
-		      &q->compute.lock, context, seqno);
+		      &q->lr.lock, context, seqno);
 
 	return &pfence->base;
 }
drivers/gpu/drm/xe/xe_vm.c +29 -29

132 lines not on this page · raw message

Signature · 1 line
2.43.0
author maintainer
#52 lore raw

PATCH 48/149 drm/xe: prevent UAF around preempt fence

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matthew Auld <[email protected]>

[ Upstream commit 730b72480e29f63fd644f5fa57c9d46109428953 ]

The fence lock is part of the queue, therefore in the current design anything locking the fence should then also hold a ref to the queue to prevent the queue from being freed.

However, currently it looks like we signal the fence and then drop the queue ref, but if something is waiting on the fence, the waiter is kicked to wake up at some later point, where upon waking up it first grabs the lock before checking the fence state. But if we have already dropped the queue ref, then the lock might already be freed as part of the queue, leading to uaf.

To prevent this, move the fence lock into the fence itself so we don't run into lifetime issues. Alternative might be to have device level lock, or only release the queue in the fence release callback, however that might require pushing to another worker to avoid locking issues.

Fixes dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs")

References: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2454
References: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2342
References: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2020

Cc Matthew Brost <[email protected]>
Cc <[email protected]> # v6.8+
(cherry picked from commit 7116c35aacedc38be6d15bd21b2fc936eed0008b)
---
 drivers/gpu/drm/xe/xe_exec_queue.c          | 1 -
 drivers/gpu/drm/xe/xe_exec_queue_types.h    | 2 --
 drivers/gpu/drm/xe/xe_preempt_fence.c       | 3 ++-
 drivers/gpu/drm/xe/xe_preempt_fence_types.h | 2 ++
 4 files changed, 4 insertions(+), 4 deletions(-)
drivers/gpu/drm/xe/xe_exec_queue.c +0 -1
index 316731c5cce6d..ba7013f82c8b6 100644
@@ -632,7 +632,6 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
 
 		if (xe_vm_in_preempt_fence_mode(vm)) {
 			q->lr.context = dma_fence_context_alloc(1);
-			spin_lock_init(&q->lr.lock);
 
 			err = xe_vm_add_compute_exec_queue(vm, q);
 			if (XE_IOCTL_DBG(xe, err))
drivers/gpu/drm/xe/xe_exec_queue_types.h +0 -2
index 52a1965d91375..a5aa43942d8cf 100644
@@ -125,8 +125,6 @@ struct xe_exec_queue {
 		u32 seqno;
 		/** @lr.link: link into VM's list of exec queues */
 		struct list_head link;
-		/** @lr.lock: preemption fences lock */
-		spinlock_t lock;
 	} lr;
 
 	/** @ops: submission backend exec queue operations */
drivers/gpu/drm/xe/xe_preempt_fence.c +2 -1
index e8b8ae5c6485e..c453f45328b1c 100644
@@ -128,8 +128,9 @@ xe_preempt_fence_arm(struct xe_preempt_fence *pfence, struct xe_exec_queue *q,
 {
 	list_del_init(&pfence->link);
 	pfence->q = xe_exec_queue_get(q);
+	spin_lock_init(&pfence->lock);
 	dma_fence_init(&pfence->base, &preempt_fence_ops,
-		      &q->lr.lock, context, seqno);
+		      &pfence->lock, context, seqno);
 
 	return &pfence->base;
 }
drivers/gpu/drm/xe/xe_preempt_fence_types.h +2 -0
index b54b5c29b5331..312c3372a49f9 100644
@@ -25,6 +25,8 @@ struct xe_preempt_fence {
 	struct xe_exec_queue *q;
 	/** @preempt_work: work struct which issues preemption */
 	struct work_struct preempt_work;
+	/** @lock: dma-fence fence lock */
+	spinlock_t lock;
 	/** @error: preempt fence is in error state */
 	int error;
 };
Signature · 1 line
2.43.0
author maintainer
#53 lore raw

PATCH 49/149 drm/amdgpu: Do not wait for MP0_C2PMSG_33 IFWI init in SRIOV

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Victor Lu <[email protected]>

[ Upstream commit b32563859d6f61265222ec0f27d394964a8f7669 ]

SRIOV does not need to wait for IFWI init, and MP0_C2PMSG_33 is blocked for VF access.

Stable-dep-of: 9cead81eff63 ("drm/amdgpu: fix eGPU hotplug regression")

---
 drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 26 ++++++++++---------
 1 file changed, 14 insertions(+), 12 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +14 -12
index 0e31bdb4b7cb6..ea5223388cff2 100644
@@ -256,19 +256,21 @@ static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev,
 	u32 msg;
 	int i, ret = 0;
 
-	/* It can take up to a second for IFWI init to complete on some dGPUs,
-	 * but generally it should be in the 60-100ms range.  Normally this starts
-	 * as soon as the device gets power so by the time the OS loads this has long
-	 * completed.  However, when a card is hotplugged via e.g., USB4, we need to
-	 * wait for this to complete.  Once the C2PMSG is updated, we can
-	 * continue.
-	 */
+	if (!amdgpu_sriov_vf(adev)) {
+		/* It can take up to a second for IFWI init to complete on some dGPUs,
+		 * but generally it should be in the 60-100ms range.  Normally this starts
+		 * as soon as the device gets power so by the time the OS loads this has long
+		 * completed.  However, when a card is hotplugged via e.g., USB4, we need to
+		 * wait for this to complete.  Once the C2PMSG is updated, we can
+		 * continue.
+		 */
 
-	for (i = 0; i < 1000; i++) {
-		msg = RREG32(mmMP0_SMN_C2PMSG_33);
-		if (msg & 0x80000000)
-			break;
-		usleep_range(1000, 1100);
+		for (i = 0; i < 1000; i++) {
+			msg = RREG32(mmMP0_SMN_C2PMSG_33);
+			if (msg & 0x80000000)
+				break;
+			usleep_range(1000, 1100);
+		}
 	}
 
 	vram_size = (uint64_t)RREG32(mmRCC_CONFIG_MEMSIZE) << 20;
Signature · 1 line
2.43.0
author maintainer
#54 lore raw

PATCH 50/149 drm/amdgpu: fix eGPU hotplug regression

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alex Deucher <[email protected]>

[ Upstream commit 9cead81eff635e3b3cbce51b40228f3bdc6f2b8c ]

The driver needs to wait for the on board firmware
to finish its initialization before probing the card.
Commit 959056982a9b ("drm/amdgpu: Fix discovery initialization failure during pci rescan") switched from using msleep() to using usleep_range() which
seems to have caused init failures on some navi1x boards. Switch
back to msleep().

Fixes 959056982a9b ("drm/amdgpu: Fix discovery initialization failure during pci rescan")
Cc Ma Jun <[email protected]>
(cherry picked from commit c69b07f7bbc905022491c45097923d3487479529)
Cc [email protected] # 6.10.x
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +1 -1
index ea5223388cff2..f1b08893765cf 100644
@@ -269,7 +269,7 @@ static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev,
 			msg = RREG32(mmMP0_SMN_C2PMSG_33);
 			if (msg & 0x80000000)
 				break;
-			usleep_range(1000, 1100);
+			msleep(1);
 		}
 	}
 
Signature · 1 line
2.43.0
author maintainer
#55 lore raw

PATCH 51/149 pinctrl: qcom: x1e80100: Update PDC hwirq map

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Konrad Dybcio <[email protected]>

[ Upstream commit b7fd10333713e9984cc9b9c04f3681f80efdc809 ]

The current map seems to be out of sync (and includes a duplicate entry for GPIO193..).

Replace it with the map present in shipping devices' ACPI tables.

This new one seems more complete, as it e.g. contains GPIO145 (PCIE6a WAKE#)

---
 drivers/pinctrl/qcom/pinctrl-x1e80100.c | 27 ++++++++++++++-----------
 1 file changed, 15 insertions(+), 12 deletions(-)
drivers/pinctrl/qcom/pinctrl-x1e80100.c +15 -12
index e30e938403574..6cd4d10e6fd6f 100644
@@ -1813,18 +1813,21 @@ static const struct msm_pingroup x1e80100_groups[] = {
 
 static const struct msm_gpio_wakeirq_map x1e80100_pdc_map[] = {
 	{ 0, 72 }, { 2, 70 }, { 3, 71 }, { 6, 123 }, { 7, 67 }, { 11, 85 },
-	{ 15, 68 }, { 18, 122 }, { 19, 69 }, { 21, 158 }, { 23, 143 }, { 26, 129 },
-	{ 27, 144 }, { 28, 77 }, { 29, 78 }, { 30, 92 }, { 32, 145 }, { 33, 115 },
-	{ 34, 130 }, { 35, 146 }, { 36, 147 }, { 39, 80 }, { 43, 148 }, { 47, 149 },
-	{ 51, 79 }, { 53, 89 }, { 59, 87 }, { 64, 90 }, { 65, 106 }, { 66, 142 },
-	{ 67, 88 }, { 71, 91 }, { 75, 152 }, { 79, 153 }, { 80, 125 }, { 81, 128 },
-	{ 84, 137 }, { 85, 155 }, { 87, 156 }, { 91, 157 }, { 92, 138 }, { 94, 140 },
-	{ 95, 141 }, { 113, 84 }, { 121, 73 }, { 123, 74 }, { 129, 76 }, { 131, 82 },
-	{ 134, 83 }, { 141, 93 }, { 144, 94 }, { 147, 96 }, { 148, 97 }, { 150, 102 },
-	{ 151, 103 }, { 153, 104 }, { 156, 105 }, { 157, 107 }, { 163, 98 }, { 166, 112 },
-	{ 172, 99 }, { 181, 101 }, { 184, 116 }, { 193, 40 }, { 193, 117 }, { 196, 108 },
-	{ 203, 133 }, { 212, 120 }, { 213, 150 }, { 214, 121 }, { 215, 118 }, { 217, 109 },
-	{ 220, 110 }, { 221, 111 }, { 222, 124 }, { 224, 131 }, { 225, 132 },
+	{ 13, 86 }, { 15, 68 }, { 18, 122 }, { 19, 69 }, { 21, 158 }, { 23, 143 },
+	{ 24, 126 }, { 26, 129 }, { 27, 144 }, { 28, 77 }, { 29, 78 }, { 30, 92 },
+	{ 31, 159 }, { 32, 145 }, { 33, 115 }, { 34, 130 }, { 35, 146 }, { 36, 147 },
+	{ 38, 113 }, { 39, 80 }, { 43, 148 }, { 47, 149 }, { 51, 79 }, { 53, 89 },
+	{ 55, 81 }, { 59, 87 }, { 64, 90 }, { 65, 106 }, { 66, 142 }, { 67, 88 },
+	{ 68, 151 }, { 71, 91 }, { 75, 152 }, { 79, 153 }, { 80, 125 }, { 81, 128 },
+	{ 83, 154 }, { 84, 137 }, { 85, 155 }, { 87, 156 }, { 91, 157 }, { 92, 138 },
+	{ 93, 139 }, { 94, 140 }, { 95, 141 }, { 113, 84 }, { 121, 73 }, { 123, 74 },
+	{ 125, 75 }, { 129, 76 }, { 131, 82 }, { 134, 83 }, { 141, 93 }, { 144, 94 },
+	{ 145, 95 }, { 147, 96 }, { 148, 97 }, { 150, 102 }, { 151, 103 }, { 153, 104 },
+	{ 154, 100 }, { 156, 105 }, { 157, 107 }, { 163, 98 }, { 166, 112 }, { 172, 99 },
+	{ 175, 114 }, { 181, 101 }, { 184, 116 }, { 193, 117 }, { 196, 108 }, { 203, 133 },
+	{ 208, 134 }, { 212, 120 }, { 213, 150 }, { 214, 121 }, { 215, 118 }, { 217, 109 },
+	{ 219, 119 }, { 220, 110 }, { 221, 111 }, { 222, 124 }, { 224, 131 }, { 225, 132 },
+	{ 228, 135 }, { 230, 136 }, { 232, 162 },
 };
 
 static const struct msm_pinctrl_soc_data x1e80100_pinctrl = {
Signature · 1 line
2.43.0
author maintainer
#56 lore raw

PATCH 52/149 ASoC: SOF: amd: move iram-dram fence register programming sequence

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Vijendar Mukunda <[email protected]>

[ Upstream commit c56ba3e44784527fd6efe5eb7a4fa6c9f6969a58 ]

The existing code modifies IRAM and DRAM size after sha dma start for vangogh platform. The problem with this sequence is that it might cause sha dma failure when firmware code binary size is greater than the default IRAM size. To fix this issue, Move the iram-dram fence register sequence prior to sha dma start.

Fixes 094d11768f74 ("ASoC: SOF: amd: Skip IRAM/DRAM size modification for Steam Deck OLED")
---
 sound/soc/sof/amd/acp.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)
sound/soc/sof/amd/acp.c +11 -11
index 74fd5f2b148b8..9123427fab4e3 100644
@@ -263,6 +263,17 @@ int configure_and_run_sha_dma(struct acp_dev_data *adata, void *image_addr,
 	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SHA_DMA_STRT_ADDR, start_addr);
 	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SHA_DMA_DESTINATION_ADDR, dest_addr);
 	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SHA_MSG_LENGTH, image_length);
+
+	/* psp_send_cmd only required for vangogh platform (rev - 5) */
+	if (desc->rev == 5 && !(adata->quirks && adata->quirks->skip_iram_dram_size_mod)) {
+		/* Modify IRAM and DRAM size */
+		ret = psp_send_cmd(adata, MBOX_ACP_IRAM_DRAM_FENCE_COMMAND | IRAM_DRAM_FENCE_2);
+		if (ret)
+			return ret;
+		ret = psp_send_cmd(adata, MBOX_ACP_IRAM_DRAM_FENCE_COMMAND | MBOX_ISREADY_FLAG);
+		if (ret)
+			return ret;
+	}
 	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SHA_DMA_CMD, ACP_SHA_RUN);
 
 	ret = snd_sof_dsp_read_poll_timeout(sdev, ACP_DSP_BAR, ACP_SHA_TRANSFER_BYTE_CNT,
@@ -280,17 +291,6 @@ int configure_and_run_sha_dma(struct acp_dev_data *adata, void *image_addr,
 			return ret;
 	}
 
-	/* psp_send_cmd only required for vangogh platform (rev - 5) */
-	if (desc->rev == 5 && !(adata->quirks && adata->quirks->skip_iram_dram_size_mod)) {
-		/* Modify IRAM and DRAM size */
-		ret = psp_send_cmd(adata, MBOX_ACP_IRAM_DRAM_FENCE_COMMAND | IRAM_DRAM_FENCE_2);
-		if (ret)
-			return ret;
-		ret = psp_send_cmd(adata, MBOX_ACP_IRAM_DRAM_FENCE_COMMAND | MBOX_ISREADY_FLAG);
-		if (ret)
-			return ret;
-	}
-
 	ret = snd_sof_dsp_read_poll_timeout(sdev, ACP_DSP_BAR, ACP_SHA_DSP_FW_QUALIFIER,
 					    fw_qualifier, fw_qualifier & DSP_FW_RUN_ENABLE,
 					    ACP_REG_POLL_INTERVAL, ACP_DMA_COMPLETE_TIMEOUT_US);
Signature · 1 line
2.43.0
author maintainer
#57 lore raw

PATCH 53/149 ASoC: SOF: amd: Fix for incorrect acp error register offsets

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Vijendar Mukunda <[email protected]>

[ Upstream commit 897e91e995b338002b00454fd0018af26a098148 ]

Addition of 'dsp_intr_base' to ACP error register offsets points to wrong register offsets in irq handler. Correct the acp error register offsets. ACP error status register offset and acp error reason register offset got changed from ACP6.0 onwards. Add 'acp_error_stat' and 'acp_sw0_i2s_err_reason' as descriptor fields in sof_amd_acp_desc structure and update the values based on the ACP variant.

Quoted 1 line

From Rembrandt platform onwards, errors related to SW1 Soundwire manager

instance/I2S controller connected on P1 power tile is reported with ACP_SW1_I2S_ERROR_REASON register. Add conditional check for the same.

Fixes 96eb81851012 ("ASoC: SOF: amd: add interrupt handling for SoundWire manager devices")
---
 sound/soc/sof/amd/acp-dsp-offset.h |  6 ++++--
 sound/soc/sof/amd/acp.c            | 11 +++++++----
 sound/soc/sof/amd/acp.h            |  2 ++
 sound/soc/sof/amd/pci-acp63.c      |  2 ++
 sound/soc/sof/amd/pci-rmb.c        |  2 ++
 sound/soc/sof/amd/pci-rn.c         |  2 ++
 6 files changed, 19 insertions(+), 6 deletions(-)
sound/soc/sof/amd/acp-dsp-offset.h +4 -2
index 59afbe2e0f420..072b703f9b3f3 100644
@@ -76,13 +76,15 @@
 #define DSP_SW_INTR_CNTL_OFFSET			0x0
 #define DSP_SW_INTR_STAT_OFFSET			0x4
 #define DSP_SW_INTR_TRIG_OFFSET			0x8
-#define ACP_ERROR_STATUS			0x18C4
+#define ACP3X_ERROR_STATUS			0x18C4
+#define ACP6X_ERROR_STATUS			0x1A4C
 #define ACP3X_AXI2DAGB_SEM_0			0x1880
 #define ACP5X_AXI2DAGB_SEM_0			0x1884
 #define ACP6X_AXI2DAGB_SEM_0			0x1874
 
 /* ACP common registers to report errors related to I2S & SoundWire interfaces */
-#define ACP_SW0_I2S_ERROR_REASON		0x18B4
+#define ACP3X_SW_I2S_ERROR_REASON		0x18C8
+#define ACP6X_SW0_I2S_ERROR_REASON		0x18B4
 #define ACP_SW1_I2S_ERROR_REASON		0x1A50
 
 /* Registers from ACP_SHA block */
sound/soc/sof/amd/acp.c +7 -4
index 9123427fab4e3..d95f865669a69 100644
@@ -92,6 +92,7 @@ static int config_dma_channel(struct acp_dev_data *adata, unsigned int ch,
 			      unsigned int idx, unsigned int dscr_count)
 {
 	struct snd_sof_dev *sdev = adata->dev;
+	const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
 	unsigned int val, status;
 	int ret;
 
@@ -102,7 +103,7 @@ static int config_dma_channel(struct acp_dev_data *adata, unsigned int ch,
 					    val & (1 << ch), ACP_REG_POLL_INTERVAL,
 					    ACP_REG_POLL_TIMEOUT_US);
 	if (ret < 0) {
-		status = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_ERROR_STATUS);
+		status = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->acp_error_stat);
 		val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_DMA_ERR_STS_0 + ch * sizeof(u32));
 
 		dev_err(sdev->dev, "ACP_DMA_ERR_STS :0x%x ACP_ERROR_STATUS :0x%x\n", val, status);
@@ -402,9 +403,11 @@ static irqreturn_t acp_irq_handler(int irq, void *dev_id)
 
 	if (val & ACP_ERROR_IRQ_MASK) {
 		snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_stat, ACP_ERROR_IRQ_MASK);
-		snd_sof_dsp_write(sdev, ACP_DSP_BAR, base + ACP_SW0_I2S_ERROR_REASON, 0);
-		snd_sof_dsp_write(sdev, ACP_DSP_BAR, base + ACP_SW1_I2S_ERROR_REASON, 0);
-		snd_sof_dsp_write(sdev, ACP_DSP_BAR, base + ACP_ERROR_STATUS, 0);
+		snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->acp_sw0_i2s_err_reason, 0);
+		/* ACP_SW1_I2S_ERROR_REASON is newly added register from rmb platform onwards */
+		if (desc->rev >= 6)
+			snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SW1_I2S_ERROR_REASON, 0);
+		snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->acp_error_stat, 0);
 		irq_flag = 1;
 	}
 
sound/soc/sof/amd/acp.h +2 -0
index 87e79d500865a..1af86b5b28db8 100644
@@ -203,6 +203,8 @@ struct sof_amd_acp_desc {
 	u32 probe_reg_offset;
 	u32 reg_start_addr;
 	u32 reg_end_addr;
+	u32 acp_error_stat;
+	u32 acp_sw0_i2s_err_reason;
 	u32 sdw_max_link_count;
 	u64 sdw_acpi_dev_addr;
 };
sound/soc/sof/amd/pci-acp63.c +2 -0
index fc89844473657..986f5928caedd 100644
@@ -35,6 +35,8 @@ static const struct sof_amd_acp_desc acp63_chip_info = {
 	.ext_intr_cntl = ACP6X_EXTERNAL_INTR_CNTL,
 	.ext_intr_stat	= ACP6X_EXT_INTR_STAT,
 	.ext_intr_stat1	= ACP6X_EXT_INTR_STAT1,
+	.acp_error_stat = ACP6X_ERROR_STATUS,
+	.acp_sw0_i2s_err_reason = ACP6X_SW0_I2S_ERROR_REASON,
 	.dsp_intr_base	= ACP6X_DSP_SW_INTR_BASE,
 	.sram_pte_offset = ACP6X_SRAM_PTE_OFFSET,
 	.hw_semaphore_offset = ACP6X_AXI2DAGB_SEM_0,
sound/soc/sof/amd/pci-rmb.c +2 -0
index 4bc30951f8b0d..a366f904e6f31 100644
@@ -33,6 +33,8 @@ static const struct sof_amd_acp_desc rembrandt_chip_info = {
 	.pgfsm_base	= ACP6X_PGFSM_BASE,
 	.ext_intr_stat	= ACP6X_EXT_INTR_STAT,
 	.dsp_intr_base	= ACP6X_DSP_SW_INTR_BASE,
+	.acp_error_stat = ACP6X_ERROR_STATUS,
+	.acp_sw0_i2s_err_reason = ACP6X_SW0_I2S_ERROR_REASON,
 	.sram_pte_offset = ACP6X_SRAM_PTE_OFFSET,
 	.hw_semaphore_offset = ACP6X_AXI2DAGB_SEM_0,
 	.fusion_dsp_offset = ACP6X_DSP_FUSION_RUNSTALL,
sound/soc/sof/amd/pci-rn.c +2 -0
index e08875bdfa8b1..2b7c53470ce82 100644
@@ -33,6 +33,8 @@ static const struct sof_amd_acp_desc renoir_chip_info = {
 	.pgfsm_base	= ACP3X_PGFSM_BASE,
 	.ext_intr_stat	= ACP3X_EXT_INTR_STAT,
 	.dsp_intr_base	= ACP3X_DSP_SW_INTR_BASE,
+	.acp_error_stat = ACP3X_ERROR_STATUS,
+	.acp_sw0_i2s_err_reason = ACP3X_SW_I2S_ERROR_REASON,
 	.sram_pte_offset = ACP3X_SRAM_PTE_OFFSET,
 	.hw_semaphore_offset = ACP3X_AXI2DAGB_SEM_0,
 	.acp_clkmux_sel	= ACP3X_CLKMUX_SEL,
Signature · 1 line
2.43.0
author maintainer
#58 lore raw

PATCH 54/149 ASoC: amd: acp: fix module autoloading

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Yuntao Liu <[email protected]>

[ Upstream commit 164199615ae230ace4519141285f06766d6d8036 ]

Add MODULE_DEVICE_TABLE(), so modules could be properly autoloaded based on the alias from platform_device_id table.

Fixes 9d8a7be88b336 ("ASoC: amd: acp: Add legacy sound card support for Chrome audio")
---
 sound/soc/amd/acp/acp-legacy-mach.c | 2 ++
 1 file changed, 2 insertions(+)
sound/soc/amd/acp/acp-legacy-mach.c +2 -0
index 47c3b5f167f59..0d529e32e552b 100644
@@ -227,6 +227,8 @@ static const struct platform_device_id board_ids[] = {
 	},
 	{ }
 };
+MODULE_DEVICE_TABLE(platform, board_ids);
+
 static struct platform_driver acp_asoc_audio = {
 	.driver = {
 		.pm = &snd_soc_pm_ops,
Signature · 1 line
2.43.0
author maintainer
#59 lore raw

PATCH 55/149 ASoC: SOF: amd: Fix for acp init sequence

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Vijendar Mukunda <[email protected]>

[ Upstream commit a42db293e5983aa1508d12644f23d73f0553b32c ]

When ACP is not powered on by default, acp power on sequence explicitly invoked by programming pgfsm control mask. The existing implementation checks the same PGFSM status mask and programs the same PGFSM control mask in all ACP variants which breaks acp power on sequence for ACP6.0 and ACP6.3 variants. So to fix this issue, update ACP pgfsm control mask and status mask based on acp descriptor rev field, which will vary based on acp variant.

Fixes 846aef1d7cc0 ("ASoC: SOF: amd: Add Renoir ACP HW support")
---
 sound/soc/sof/amd/acp.c | 19 +++++++++++++++++--
 sound/soc/sof/amd/acp.h |  7 +++++--
 2 files changed, 22 insertions(+), 4 deletions(-)
sound/soc/sof/amd/acp.c +17 -2
index d95f865669a69..85b58c8ccd0da 100644
@@ -433,6 +433,7 @@ static int acp_power_on(struct snd_sof_dev *sdev)
 	const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
 	unsigned int base = desc->pgfsm_base;
 	unsigned int val;
+	unsigned int acp_pgfsm_status_mask, acp_pgfsm_cntl_mask;
 	int ret;
 
 	val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, base + PGFSM_STATUS_OFFSET);
@@ -440,9 +441,23 @@ static int acp_power_on(struct snd_sof_dev *sdev)
 	if (val == ACP_POWERED_ON)
 		return 0;
 
-	if (val & ACP_PGFSM_STATUS_MASK)
+	switch (desc->rev) {
+	case 3:
+	case 5:
+		acp_pgfsm_status_mask = ACP3X_PGFSM_STATUS_MASK;
+		acp_pgfsm_cntl_mask = ACP3X_PGFSM_CNTL_POWER_ON_MASK;
+		break;
+	case 6:
+		acp_pgfsm_status_mask = ACP6X_PGFSM_STATUS_MASK;
+		acp_pgfsm_cntl_mask = ACP6X_PGFSM_CNTL_POWER_ON_MASK;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (val & acp_pgfsm_status_mask)
 		snd_sof_dsp_write(sdev, ACP_DSP_BAR, base + PGFSM_CONTROL_OFFSET,
-				  ACP_PGFSM_CNTL_POWER_ON_MASK);
+				  acp_pgfsm_cntl_mask);
 
 	ret = snd_sof_dsp_read_poll_timeout(sdev, ACP_DSP_BAR, base + PGFSM_STATUS_OFFSET, val,
 					    !val, ACP_REG_POLL_INTERVAL, ACP_REG_POLL_TIMEOUT_US);
sound/soc/sof/amd/acp.h +5 -2
index 1af86b5b28db8..61b28df8c9081 100644
@@ -25,8 +25,11 @@
 #define ACP_REG_POLL_TIMEOUT_US                 2000
 #define ACP_DMA_COMPLETE_TIMEOUT_US		5000
 
-#define ACP_PGFSM_CNTL_POWER_ON_MASK		0x01
-#define ACP_PGFSM_STATUS_MASK			0x03
+#define ACP3X_PGFSM_CNTL_POWER_ON_MASK		0x01
+#define ACP3X_PGFSM_STATUS_MASK			0x03
+#define ACP6X_PGFSM_CNTL_POWER_ON_MASK		0x07
+#define ACP6X_PGFSM_STATUS_MASK			0x0F
+
 #define ACP_POWERED_ON				0x00
 #define ACP_ASSERT_RESET			0x01
 #define ACP_RELEASE_RESET			0x00
Signature · 1 line
2.43.0
author maintainer
#60 lore raw

PATCH 56/149 ALSA: hda: cs35l56: Dont use the device index as a calibration index

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Simon Trimmer <[email protected]>

[ Upstream commit 91191a6e50a2ff752da244493171037663536768 ]

The HDA driver cannot assume that the order that the devices are specified in the cirrus,dev-index matches the order of calibration entries.

Only a calibration entry with a matching silicon id will be used.

Fixes cfa43aaa7948 ("ALSA: hda: cs35l56: Apply amp calibration from EFI data")
---
 sound/pci/hda/cs35l56_hda.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
sound/pci/hda/cs35l56_hda.c +1 -1
index e134ede6c5aa5..357fd59aa49e4 100644
@@ -980,7 +980,7 @@ int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int hid, int id)
 		goto err;
 	}
 
-	cs35l56->base.cal_index = cs35l56->index;
+	cs35l56->base.cal_index = -1;
 
 	cs35l56_init_cs_dsp(&cs35l56->base, &cs35l56->cs_dsp);
 	cs35l56->cs_dsp.client_ops = &cs35l56_hda_client_ops;
Signature · 1 line
2.43.0
author maintainer
#61 lore raw

PATCH 57/149 ASoC: cs-amp-lib-test: Force test calibration blob entries to be valid

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Richard Fitzgerald <[email protected]>

[ Upstream commit bff980d8d9ca537fd5f3c0e9a99876c1e3713e81 ]

For a normal calibration blob the calTarget values must be non-zero and unique, and the calTime values must be non-zero. Don't rely on get_random_bytes() to be random enough to guarantee this. Force the calTarget and calTime values to be valid while retaining randomness in the values.

Fixes 177862317a98 ("ASoC: cs-amp-lib: Add KUnit test for calibration helpers")
---
 sound/soc/codecs/cs-amp-lib-test.c | 9 +++++++++
 1 file changed, 9 insertions(+)
sound/soc/codecs/cs-amp-lib-test.c +9 -0
index 15f991b2e16e2..8169ec88a8ba8 100644
@@ -38,6 +38,7 @@ static void cs_amp_lib_test_init_dummy_cal_blob(struct kunit *test, int num_amps
 {
 	struct cs_amp_lib_test_priv *priv = test->priv;
 	unsigned int blob_size;
+	int i;
 
 	blob_size = offsetof(struct cirrus_amp_efi_data, data) +
 		    sizeof(struct cirrus_amp_cal_data) * num_amps;
@@ -49,6 +50,14 @@ static void cs_amp_lib_test_init_dummy_cal_blob(struct kunit *test, int num_amps
 	priv->cal_blob->count = num_amps;
 
 	get_random_bytes(priv->cal_blob->data, sizeof(struct cirrus_amp_cal_data) * num_amps);
+
+	/* Ensure all timestamps are non-zero to mark the entry valid. */
+	for (i = 0; i < num_amps; i++)
+		priv->cal_blob->data[i].calTime[0] |= 1;
+
+	/* Ensure that all UIDs are non-zero and unique. */
+	for (i = 0; i < num_amps; i++)
+		*(u8 *)&priv->cal_blob->data[i].calTarget[0] = i + 1;
 }
 
 static u64 cs_amp_lib_test_get_target_uid(struct kunit *test)
Signature · 1 line
2.43.0
author maintainer
#62 lore raw

PATCH 58/149 ASoC: cs-amp-lib: Ignore empty UEFI calibration entries

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Richard Fitzgerald <[email protected]>

[ Upstream commit bb4485562f5907708f1c218b5d70dce04165d1e1 ]

If the timestamp of a calibration entry is 0 it is an unused entry and must be ignored.

Some end-products reserve EFI space for calibration entries by shipping with a zero-filled EFI file. When searching the file for calibration data the driver must skip the empty entries. The timestamp of a valid entry is always non-zero.

Fixes 1cad8725f2b9 ("ASoC: cs-amp-lib: Add helpers for factory calibration data")
---
 sound/soc/codecs/cs-amp-lib.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
sound/soc/codecs/cs-amp-lib.c +6 -1
index 605964af8afad..51b128c806718 100644
@@ -182,6 +182,10 @@ static int _cs_amp_get_efi_calibration_data(struct device *dev, u64 target_uid,
 		for (i = 0; i < efi_data->count; ++i) {
 			u64 cal_target = cs_amp_cal_target_u64(&efi_data->data[i]);
 
+			/* Skip empty entries */
+			if (!efi_data->data[i].calTime[0] && !efi_data->data[i].calTime[1])
+				continue;
+
 			/* Skip entries with unpopulated silicon ID */
 			if (cal_target == 0)
 				continue;
@@ -193,7 +197,8 @@ static int _cs_amp_get_efi_calibration_data(struct device *dev, u64 target_uid,
 		}
 	}
 
-	if (!cal && (amp_index >= 0) && (amp_index < efi_data->count)) {
+	if (!cal && (amp_index >= 0) && (amp_index < efi_data->count) &&
+	    (efi_data->data[amp_index].calTime[0] || efi_data->data[amp_index].calTime[1])) {
 		u64 cal_target = cs_amp_cal_target_u64(&efi_data->data[amp_index]);
 
 		/*
Signature · 1 line
2.43.0
author maintainer
#63 lore raw

PATCH 59/149 nfsd: ensure that nfsd4_fattr_args.context is zeroed out

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jeff Layton <[email protected]>

[ Upstream commit f58bab6fd4063913bd8321e99874b8239e9ba726 ]

If nfsd4_encode_fattr4 ends up doing a "goto out" before we get to checking for the security label, then args.context will be set to uninitialized junk on the stack, which we'll then try to free. Initialize it early.

Fixes f59388a579c6 ("NFSD: Add nfsd4_encode_fattr4_sec_label()")
---
 fs/nfsd/nfs4xdr.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
fs/nfsd/nfs4xdr.c +3 -1
index c7bfd2180e3f2..8a7bc2b58e721 100644
@@ -3545,6 +3545,9 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 	args.dentry = dentry;
 	args.ignore_crossmnt = (ignore_crossmnt != 0);
 	args.acl = NULL;
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+	args.context = NULL;
+#endif
 
 	/*
 	 * Make a local copy of the attribute bitmap that can be modified.
@@ -3617,7 +3620,6 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 	args.contextsupport = false;
 
 #ifdef CONFIG_NFSD_V4_SECURITY_LABEL
-	args.context = NULL;
 	if ((attrmask[2] & FATTR4_WORD2_SECURITY_LABEL) ||
 	     attrmask[0] & FATTR4_WORD0_SUPPORTED_ATTRS) {
 		if (exp->ex_flags & NFSEXP_SECURITY_LABEL)
Signature · 1 line
2.43.0
author maintainer
#64 lore raw

PATCH 60/149 backing-file: convert to using fops->splice_write

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ed Tsai <[email protected]>

[ Upstream commit 996b37da1e0f51314d4186b326742c2a95a9f0dd ]

Filesystems may define their own splice write. Therefore, use the file fops instead of invoking iter_file_splice_write() directly.

Fixes 5ca73468612d ("fuse: implement splice read/write passthrough")
---
 fs/backing-file.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
fs/backing-file.c +4 -1
index afb557446c27c..8860dac58c37e 100644
@@ -303,13 +303,16 @@ ssize_t backing_file_splice_write(struct pipe_inode_info *pipe,
 	if (WARN_ON_ONCE(!(out->f_mode & FMODE_BACKING)))
 		return -EIO;
 
+	if (!out->f_op->splice_write)
+		return -EINVAL;
+
 	ret = file_remove_privs(ctx->user_file);
 	if (ret)
 		return ret;
 
 	old_cred = override_creds(ctx->cred);
 	file_start_write(out);
-	ret = iter_file_splice_write(pipe, out, ppos, len, flags);
+	ret = out->f_op->splice_write(pipe, out, ppos, len, flags);
 	file_end_write(out);
 	revert_creds(old_cred);
 
Signature · 1 line
2.43.0
author maintainer
#65 lore raw

PATCH 61/149 pinctrl: mediatek: common-v2: Fix broken bias-disable for PULL_PU_PD_RSEL_TYPE

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Nícolas F. R. A. Prado <[email protected]>

[ Upstream commit 166bf8af91225576f85208a31eaedbadd182d1ea ]

Despite its name, commit fed74d75277d ("pinctrl: mediatek: common-v2:
Fix bias-disable for PULL_PU_PD_RSEL_TYPE") actually broke bias-disable for PULL_PU_PD_RSEL_TYPE.

mtk_pinconf_bias_set_combo() tries every bias method supported by the pin until one succeeds. For PULL_PU_PD_RSEL_TYPE pins, before the breaking commit, mtk_pinconf_bias_set_rsel() would be called first to try and set the RSEL value (as well as PU and PD), and if that failed, the only other valid option was that bias-disable was specified, which would then be handled by calling mtk_pinconf_bias_set_pu_pd() and disabling both PU and PD.

The breaking commit misunderstood this logic and added an early "return 0" in mtk_pinconf_bias_set_rsel(). The result was that in the bias-disable case, the bias was left unchanged, since by returning success, mtk_pinconf_bias_set_combo() no longer tried calling mtk_pinconf_bias_set_pu_pd() to disable the bias.

Since the logic for configuring bias-disable on PULL_PU_PD_RSEL_TYPE pins required mtk_pinconf_bias_set_rsel() to fail first, in that case, an error was printed to the log, eg:

mt8195-pinctrl 10005000.pinctrl: Not support rsel value 0 Ohm for pin = 29 (GPIO29)

This is what the breaking commit actually got rid of, and likely part of the reason why that commit was thought to be fixing functionality, while in reality it was breaking it.

Instead of simply reverting that commit, restore the functionality but in a way that avoids the error from being printed and makes the code less confusing:
* Return 0 explicitly if a bias method was successful
* Introduce an extra function mtk_pinconf_bias_set_pu_pd_rsel() that calls both mtk_pinconf_bias_set_rsel() (only if needed) and mtk_pinconf_bias_set_pu_pd()
* And analogously for the corresponding getters

Fixes fed74d75277d ("pinctrl: mediatek: common-v2: Fix bias-disable for PULL_PU_PD_RSEL_TYPE")
---
 .../pinctrl/mediatek/pinctrl-mtk-common-v2.c  | 55 ++++++++++---------
 1 file changed, 29 insertions(+), 26 deletions(-)
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c +29 -26
index b7921b59eb7b1..54301fbba524a 100644
@@ -709,32 +709,35 @@ static int mtk_pinconf_bias_set_rsel(struct mtk_pinctrl *hw,
 {
 	int err, rsel_val;
 
-	if (!pullup && arg == MTK_DISABLE)
-		return 0;
-
 	if (hw->rsel_si_unit) {
 		/* find pin rsel_index from pin_rsel array*/
 		err = mtk_hw_pin_rsel_lookup(hw, desc, pullup, arg, &rsel_val);
 		if (err)
-			goto out;
+			return err;
 	} else {
-		if (arg < MTK_PULL_SET_RSEL_000 ||
-		    arg > MTK_PULL_SET_RSEL_111) {
-			err = -EINVAL;
-			goto out;
-		}
+		if (arg < MTK_PULL_SET_RSEL_000 || arg > MTK_PULL_SET_RSEL_111)
+			return -EINVAL;
 
 		rsel_val = arg - MTK_PULL_SET_RSEL_000;
 	}
 
-	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_RSEL, rsel_val);
-	if (err)
-		goto out;
+	return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_RSEL, rsel_val);
+}
 
-	err = mtk_pinconf_bias_set_pu_pd(hw, desc, pullup, MTK_ENABLE);
+static int mtk_pinconf_bias_set_pu_pd_rsel(struct mtk_pinctrl *hw,
+					   const struct mtk_pin_desc *desc,
+					   u32 pullup, u32 arg)
+{
+	u32 enable = arg == MTK_DISABLE ? MTK_DISABLE : MTK_ENABLE;
+	int err;
 
-out:
-	return err;
+	if (arg != MTK_DISABLE) {
+		err = mtk_pinconf_bias_set_rsel(hw, desc, pullup, arg);
+		if (err)
+			return err;
+	}
+
+	return mtk_pinconf_bias_set_pu_pd(hw, desc, pullup, enable);
 }
 
 int mtk_pinconf_bias_set_combo(struct mtk_pinctrl *hw,
@@ -750,22 +753,22 @@ int mtk_pinconf_bias_set_combo(struct mtk_pinctrl *hw,
 		try_all_type = MTK_PULL_TYPE_MASK;
 
 	if (try_all_type & MTK_PULL_RSEL_TYPE) {
-		err = mtk_pinconf_bias_set_rsel(hw, desc, pullup, arg);
+		err = mtk_pinconf_bias_set_pu_pd_rsel(hw, desc, pullup, arg);
 		if (!err)
-			return err;
+			return 0;
 	}
 
 	if (try_all_type & MTK_PULL_PU_PD_TYPE) {
 		err = mtk_pinconf_bias_set_pu_pd(hw, desc, pullup, arg);
 		if (!err)
-			return err;
+			return 0;
 	}
 
 	if (try_all_type & MTK_PULL_PULLSEL_TYPE) {
 		err = mtk_pinconf_bias_set_pullsel_pullen(hw, desc,
 							  pullup, arg);
 		if (!err)
-			return err;
+			return 0;
 	}
 
 	if (try_all_type & MTK_PULL_PUPD_R1R0_TYPE)
@@ -803,9 +806,9 @@ static int mtk_rsel_get_si_unit(struct mtk_pinctrl *hw,
 	return 0;
 }
 
-static int mtk_pinconf_bias_get_rsel(struct mtk_pinctrl *hw,
-				     const struct mtk_pin_desc *desc,
-				     u32 *pullup, u32 *enable)
+static int mtk_pinconf_bias_get_pu_pd_rsel(struct mtk_pinctrl *hw,
+					   const struct mtk_pin_desc *desc,
+					   u32 *pullup, u32 *enable)
 {
 	int pu, pd, rsel, err;
 
@@ -939,22 +942,22 @@ int mtk_pinconf_bias_get_combo(struct mtk_pinctrl *hw,
 		try_all_type = MTK_PULL_TYPE_MASK;
 
 	if (try_all_type & MTK_PULL_RSEL_TYPE) {
-		err = mtk_pinconf_bias_get_rsel(hw, desc, pullup, enable);
+		err = mtk_pinconf_bias_get_pu_pd_rsel(hw, desc, pullup, enable);
 		if (!err)
-			return err;
+			return 0;
 	}
 
 	if (try_all_type & MTK_PULL_PU_PD_TYPE) {
 		err = mtk_pinconf_bias_get_pu_pd(hw, desc, pullup, enable);
 		if (!err)
-			return err;
+			return 0;
 	}
 
 	if (try_all_type & MTK_PULL_PULLSEL_TYPE) {
 		err = mtk_pinconf_bias_get_pullsel_pullen(hw, desc,
 							  pullup, enable);
 		if (!err)
-			return err;
+			return 0;
 	}
 
 	if (try_all_type & MTK_PULL_PUPD_R1R0_TYPE)
Signature · 1 line
2.43.0
author maintainer
#66 lore raw

PATCH 62/149 pinctrl: qcom: x1e80100: Fix special pin offsets

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Konrad Dybcio <[email protected]>

[ Upstream commit d3692d95cc4d88114b070ee63cffc976f00f207f ]

Remove the erroneus 0x100000 offset to prevent the boards from crashing on pin state setting, as well as for the intended state changes to take effect.

---
 drivers/pinctrl/qcom/pinctrl-x1e80100.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/pinctrl/qcom/pinctrl-x1e80100.c +4 -4
index 6cd4d10e6fd6f..65ed933f05ce1 100644
@@ -1805,10 +1805,10 @@ static const struct msm_pingroup x1e80100_groups[] = {
 	[235] = PINGROUP(235, aon_cci, qdss_gpio, _, _, _, _, _, _, _),
 	[236] = PINGROUP(236, aon_cci, qdss_gpio, _, _, _, _, _, _, _),
 	[237] = PINGROUP(237, _, _, _, _, _, _, _, _, _),
-	[238] = UFS_RESET(ufs_reset, 0x1f9000),
-	[239] = SDC_QDSD_PINGROUP(sdc2_clk, 0x1f2000, 14, 6),
-	[240] = SDC_QDSD_PINGROUP(sdc2_cmd, 0x1f2000, 11, 3),
-	[241] = SDC_QDSD_PINGROUP(sdc2_data, 0x1f2000, 9, 0),
+	[238] = UFS_RESET(ufs_reset, 0xf9000),
+	[239] = SDC_QDSD_PINGROUP(sdc2_clk, 0xf2000, 14, 6),
+	[240] = SDC_QDSD_PINGROUP(sdc2_cmd, 0xf2000, 11, 3),
+	[241] = SDC_QDSD_PINGROUP(sdc2_data, 0xf2000, 9, 0),
 };
 
 static const struct msm_gpio_wakeirq_map x1e80100_pdc_map[] = {
Signature · 1 line
2.43.0
author maintainer
#67 lore raw

PATCH 63/149 pinctrl: starfive: jh7110: Correct the level trigger configuration of iev register

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Hal Feng <[email protected]>

[ Upstream commit 639766ca10d1e218e257ae7eabe76814bae6ab89 ]

A mistake was made in level trigger register configuration. Correct it.

Fixes 447976ab62c5 ("pinctrl: starfive: Add StarFive JH7110 sys controller driver")
---
 drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c +2 -2
index 9609eb1ecc3d8..7637de7452b91 100644
@@ -795,12 +795,12 @@ static int jh7110_irq_set_type(struct irq_data *d, unsigned int trigger)
 	case IRQ_TYPE_LEVEL_HIGH:
 		irq_type  = 0;    /* 0: level triggered */
 		edge_both = 0;    /* 0: ignored */
-		polarity  = mask; /* 1: high level */
+		polarity  = 0;    /* 0: high level */
 		break;
 	case IRQ_TYPE_LEVEL_LOW:
 		irq_type  = 0;    /* 0: level triggered */
 		edge_both = 0;    /* 0: ignored */
-		polarity  = 0;    /* 0: low level */
+		polarity  = mask; /* 1: low level */
 		break;
 	default:
 		return -EINVAL;
Signature · 1 line
2.43.0
author maintainer
#68 lore raw

PATCH 64/149 nfsd: prevent panic for nfsv4.0 closed files in nfs4_show_open

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Olga Kornievskaia <[email protected]>

[ Upstream commit a204501e1743d695ca2930ed25a2be9f8ced96d3 ]

Prior to commit 3f29cc82a84c ("nfsd: split sc_status out of sc_type") states_show() relied on sc_type field to be of valid type before calling into a subfunction to show content of a particular stateid. From that commit, we split the validity of the stateid into sc_status and no longer changed sc_type to 0 while unhashing the stateid. This resulted in kernel oopsing for nfsv4.0 opens that stay around and in nfs4_show_open() would derefence sc_file which was NULL.

Instead, for closed open stateids forgo displaying information that relies of having a valid sc_file.

To reproduce: mount the server with 4.0, read and close a file and then on the server cat /proc/fs/nfsd/clients/2/states

[  513.590804] Call trace:
[  513.590925]  _raw_spin_lock+0xcc/0x160
[  513.591119]  nfs4_show_open+0x78/0x2c0 [nfsd]
[  513.591412]  states_show+0x44c/0x488 [nfsd]
[  513.591681]  seq_read_iter+0x5d8/0x760
[  513.591896]  seq_read+0x188/0x208
[  513.592075]  vfs_read+0x148/0x470
[  513.592241]  ksys_read+0xcc/0x178
Fixes 3f29cc82a84c ("nfsd: split sc_status out of sc_type")
---
 fs/nfsd/nfs4state.c | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)
fs/nfsd/nfs4state.c +12 -9
index a20c2c9d7d457..dafff707e23a4 100644
@@ -2789,15 +2789,18 @@ static int nfs4_show_open(struct seq_file *s, struct nfs4_stid *st)
 		deny & NFS4_SHARE_ACCESS_READ ? "r" : "-",
 		deny & NFS4_SHARE_ACCESS_WRITE ? "w" : "-");
 
-	spin_lock(&nf->fi_lock);
-	file = find_any_file_locked(nf);
-	if (file) {
-		nfs4_show_superblock(s, file);
-		seq_puts(s, ", ");
-		nfs4_show_fname(s, file);
-		seq_puts(s, ", ");
-	}
-	spin_unlock(&nf->fi_lock);
+	if (nf) {
+		spin_lock(&nf->fi_lock);
+		file = find_any_file_locked(nf);
+		if (file) {
+			nfs4_show_superblock(s, file);
+			seq_puts(s, ", ");
+			nfs4_show_fname(s, file);
+			seq_puts(s, ", ");
+		}
+		spin_unlock(&nf->fi_lock);
+	} else
+		seq_puts(s, "closed, ");
 	nfs4_show_owner(s, oo);
 	if (st->sc_status & SC_STATUS_ADMIN_REVOKED)
 		seq_puts(s, ", admin-revoked");
Signature · 1 line
2.43.0
author maintainer
#69 lore raw

PATCH 65/149 mm: Fix missing folio invalidation calls during truncation

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: David Howells <[email protected]>

[ Upstream commit 0aa2e1b2fb7a75aa4b5b4347055ccfea6f091769 ]

When AS_RELEASE_ALWAYS is set on a mapping, the ->release_folio() and ->invalidate_folio() calls should be invoked even if PG_private and PG_private_2 aren't set. This is used by netfslib to keep track of the point above which reads can be skipped in favour of just zeroing pagecache locally.

There are a couple of places in truncation in which invalidation is only called when folio_has_private() is true. Fix these to check folio_needs_release() instead.

Without this, the generic/075 and generic/112 xfstests (both fsx-based tests) fail with minimum folio size patches applied[1].

---
 mm/truncate.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
mm/truncate.c +2 -2
index e99085bf3d34d..a2af7f088407f 100644
@@ -174,7 +174,7 @@ static void truncate_cleanup_folio(struct folio *folio)
 	if (folio_mapped(folio))
 		unmap_mapping_folio(folio);
 
-	if (folio_has_private(folio))
+	if (folio_needs_release(folio))
 		folio_invalidate(folio, 0, folio_size(folio));
 
 	/*
@@ -235,7 +235,7 @@ bool truncate_inode_partial_folio(struct folio *folio, loff_t start, loff_t end)
 	 */
 	folio_zero_range(folio, offset, length);
 
-	if (folio_has_private(folio))
+	if (folio_needs_release(folio))
 		folio_invalidate(folio, offset, length);
 	if (!folio_test_large(folio))
 		return true;
Signature · 1 line
2.43.0
author maintainer
#70 lore raw

PATCH 66/149 afs: Fix post-setattr file edit to do truncation correctly

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: David Howells <[email protected]>

[ Upstream commit a74ee0e878e262c0276966528d72d4e887174410 ]

At the end of an kAFS RPC operation, there is an "edit" phase (originally intended for post-directory modification ops to edit the local image) that the setattr VFS op uses to fix up the pagecache if the RPC that requested truncation of a file was successful.

afs_setattr_edit_file() calls truncate_setsize() which sets i_size, expands the pagecache if needed and truncates the pagecache. The first two of those, however, are redundant as they've already been done by afs_setattr_success() under the io_lock and the first is also done under the callback lock (cb_lock).

Fix afs_setattr_edit_file() to call truncate_pagecache() instead (which is called by truncate_setsize(), thereby skipping the redundant parts.

Fixes 100ccd18bb41 ("netfs: Optimise away reads above the point at which there can be no data")
cc Matthew Wilcox (Oracle) <[email protected]>
cc Pankaj Raghav <[email protected]>
cc Jeff Layton <[email protected]>
cc Marc Dionne <[email protected]>
---
 fs/afs/inode.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)
fs/afs/inode.c +8 -3
index 3acf5e0500728..a95e77670b494 100644
@@ -695,13 +695,18 @@ static void afs_setattr_edit_file(struct afs_operation *op)
 {
 	struct afs_vnode_param *vp = &op->file[0];
 	struct afs_vnode *vnode = vp->vnode;
+	struct inode *inode = &vnode->netfs.inode;
 
 	if (op->setattr.attr->ia_valid & ATTR_SIZE) {
 		loff_t size = op->setattr.attr->ia_size;
-		loff_t i_size = op->setattr.old_i_size;
+		loff_t old = op->setattr.old_i_size;
+
+		/* Note: inode->i_size was updated by afs_apply_status() inside
+		 * the I/O and callback locks.
+		 */
 
-		if (size != i_size) {
-			truncate_setsize(&vnode->netfs.inode, size);
+		if (size != old) {
+			truncate_pagecache(inode, size);
 			netfs_resize_file(&vnode->netfs, size, true);
 			fscache_resize_cookie(afs_vnode_cache(vnode), size);
 		}
Signature · 1 line
2.43.0
author maintainer
#71 lore raw

PATCH 67/149 netfs: Fix netfs_release_folio() to say no if folio dirty

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: David Howells <[email protected]>

[ Upstream commit 7dfc8f0c6144c290dbeb01835a67e81b34dda8cd ]

Fix netfs_release_folio() to say no (ie. return false) if the folio is dirty (analogous with iomap's behaviour). Without this, it will say yes to the release of a dirty page by split_huge_page_to_list_to_order(), which will result in the loss of untruncated data in the folio.

Without this, the generic/075 and generic/112 xfstests (both fsx-based tests) fail with minimum folio size patches applied[1].

---
 fs/netfs/misc.c | 3 +++
 1 file changed, 3 insertions(+)
fs/netfs/misc.c +3 -0
index 607a1972f4563..21acf4b092a46 100644
@@ -161,6 +161,9 @@ bool netfs_release_folio(struct folio *folio, gfp_t gfp)
 	struct netfs_inode *ctx = netfs_inode(folio_inode(folio));
 	unsigned long long end;
 
+	if (folio_test_dirty(folio))
+		return false;
+
 	end = folio_pos(folio) + folio_size(folio);
 	if (end > ctx->zero_point)
 		ctx->zero_point = end;
Signature · 1 line
2.43.0
author maintainer
#72 lore raw

PATCH 68/149 netfs: Fix trimming of streaming-write folios in netfs_inval_folio()

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: David Howells <[email protected]>

[ Upstream commit cce6bfa6ca0e30af9927b0074c97fe6a92f28092 ]

When netfslib writes to a folio that it doesn't have data for, but that data exists on the server, it will make a 'streaming write' whereby it stores data in a folio that is marked dirty, but not uptodate. When it does this, it attaches a record to folio->private to track the dirty region.

When truncate() or fallocate() wants to invalidate part of such a folio, it will call into ->invalidate_folio(), specifying the part of the folio that is to be invalidated. netfs_invalidate_folio(), on behalf of the filesystem, must then determine how to trim the streaming write record. In a couple of cases, however, it does this incorrectly (the reduce-length and move-start cases are switched over and don't, in any case, calculate the value correctly).

Fix this by making the logic tree more obvious and fixing the cases.

Fixes 9ebff83e6481 ("netfs: Prep to use folio->private for write grouping and streaming write")
cc Matthew Wilcox (Oracle) <[email protected]>
cc Pankaj Raghav <[email protected]>
cc Jeff Layton <[email protected]>
cc Marc Dionne <[email protected]>
---
 fs/netfs/misc.c | 50 ++++++++++++++++++++++++++++++++++---------------
 1 file changed, 35 insertions(+), 15 deletions(-)
fs/netfs/misc.c +35 -15
index 21acf4b092a46..a46bf569303fc 100644
@@ -97,10 +97,20 @@ EXPORT_SYMBOL(netfs_clear_inode_writeback);
 void netfs_invalidate_folio(struct folio *folio, size_t offset, size_t length)
 {
 	struct netfs_folio *finfo;
+	struct netfs_inode *ctx = netfs_inode(folio_inode(folio));
 	size_t flen = folio_size(folio);
 
 	kenter("{%lx},%zx,%zx", folio->index, offset, length);
 
+	if (offset == 0 && length == flen) {
+		unsigned long long i_size = i_size_read(&ctx->inode);
+		unsigned long long fpos = folio_pos(folio), end;
+
+		end = umin(fpos + flen, i_size);
+		if (fpos < i_size && end > ctx->zero_point)
+			ctx->zero_point = end;
+	}
+
 	folio_wait_private_2(folio); /* [DEPRECATED] */
 
 	if (!folio_test_private(folio))
@@ -115,18 +125,34 @@ void netfs_invalidate_folio(struct folio *folio, size_t offset, size_t length)
 		/* We have a partially uptodate page from a streaming write. */
 		unsigned int fstart = finfo->dirty_offset;
 		unsigned int fend = fstart + finfo->dirty_len;
-		unsigned int end = offset + length;
+		unsigned int iend = offset + length;
 
 		if (offset >= fend)
 			return;
-		if (end <= fstart)
+		if (iend <= fstart)
+			return;
+
+		/* The invalidation region overlaps the data.  If the region
+		 * covers the start of the data, we either move along the start
+		 * or just erase the data entirely.
+		 */
+		if (offset <= fstart) {
+			if (iend >= fend)
+				goto erase_completely;
+			/* Move the start of the data. */
+			finfo->dirty_len = fend - iend;
+			finfo->dirty_offset = offset;
+			return;
+		}
+
+		/* Reduce the length of the data if the invalidation region
+		 * covers the tail part.
+		 */
+		if (iend >= fend) {
+			finfo->dirty_len = offset - fstart;
 			return;
-		if (offset <= fstart && end >= fend)
-			goto erase_completely;
-		if (offset <= fstart && end > fstart)
-			goto reduce_len;
-		if (offset > fstart && end >= fend)
-			goto move_start;
+		}
+
 		/* A partial write was split.  The caller has already zeroed
 		 * it, so just absorb the hole.
 		 */
@@ -139,12 +165,6 @@ void netfs_invalidate_folio(struct folio *folio, size_t offset, size_t length)
 	folio_clear_uptodate(folio);
 	kfree(finfo);
 	return;
-reduce_len:
-	finfo->dirty_len = offset + length - finfo->dirty_offset;
-	return;
-move_start:
-	finfo->dirty_len -= offset - finfo->dirty_offset;
-	finfo->dirty_offset = offset;
 }
 EXPORT_SYMBOL(netfs_invalidate_folio);
 
@@ -164,7 +184,7 @@ bool netfs_release_folio(struct folio *folio, gfp_t gfp)
 	if (folio_test_dirty(folio))
 		return false;
 
-	end = folio_pos(folio) + folio_size(folio);
+	end = umin(folio_pos(folio) + folio_size(folio), i_size_read(&ctx->inode));
 	if (end > ctx->zero_point)
 		ctx->zero_point = end;
 
Signature · 1 line
2.43.0
author maintainer
#73 lore raw

PATCH 69/149 netfs: Fix missing iterator reset on retry of short read

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: David Howells <[email protected]>

[ Upstream commit 950b03d0f664a54389a555d79215348ed413161f ]

Fix netfs_rreq_perform_resubmissions() to reset before retrying a short read, otherwise the wrong part of the output buffer will be used.

Fixes 92b6cc5d1e7c ("netfs: Add iov_iters to (sub)requests to describe various buffers")
cc Steve French <[email protected]>
cc Paulo Alcantara <[email protected]>
cc Jeff Layton <[email protected]>
---
 fs/netfs/io.c | 1 +
 1 file changed, 1 insertion(+)
fs/netfs/io.c +1 -0
index f3abc5dfdbc0c..c96431d3da6d8 100644
@@ -313,6 +313,7 @@ static bool netfs_rreq_perform_resubmissions(struct netfs_io_request *rreq)
 			netfs_reset_subreq_iter(rreq, subreq);
 			netfs_read_from_server(rreq, subreq);
 		} else if (test_bit(NETFS_SREQ_SHORT_IO, &subreq->flags)) {
+			netfs_reset_subreq_iter(rreq, subreq);
 			netfs_rreq_short_read(rreq, subreq);
 		}
 	}
Signature · 1 line
2.43.0
author maintainer
#74 lore raw

PATCH 70/149 netfs: Fix interaction of streaming writes with zero-point tracker

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: David Howells <[email protected]>

[ Upstream commit e00e99ba6c6b8e5239e75cd6684a6827d93c39a2 ]

When a folio that is marked for streaming write (dirty, but not uptodate, with partial content specified in the private data) is written back, the folio is effectively switched to the blank state upon completion of the write. This means that if we want to read it in future, we need to reread the whole folio.

However, if the folio is above the zero_point position, when it is read back, it will just be cleared and the read skipped, leading to apparent local corruption.

Fix this by increasing the zero_point to the end of the dirty data in the folio when clearing the folio state after writeback. This is analogous to the folio having ->release_folio() called upon it.

This was causing the config.log generated by configuring a cpython tree on a cifs share to get corrupted because the scripts involved were appending text to the file in small pieces.

---
 fs/netfs/write_collect.c | 7 +++++++
 1 file changed, 7 insertions(+)
fs/netfs/write_collect.c +7 -0
index 488147439fe0f..a2b697b4aa401 100644
@@ -33,6 +33,7 @@
 int netfs_folio_written_back(struct folio *folio)
 {
 	enum netfs_folio_trace why = netfs_folio_trace_clear;
+	struct netfs_inode *ictx = netfs_inode(folio->mapping->host);
 	struct netfs_folio *finfo;
 	struct netfs_group *group = NULL;
 	int gcount = 0;
@@ -41,6 +42,12 @@ int netfs_folio_written_back(struct folio *folio)
 		/* Streaming writes cannot be redirtied whilst under writeback,
 		 * so discard the streaming record.
 		 */
+		unsigned long long fend;
+
+		fend = folio_pos(folio) + finfo->dirty_offset + finfo->dirty_len;
+		if (fend > ictx->zero_point)
+			ictx->zero_point = fend;
+
 		folio_detach_private(folio);
 		group = finfo->netfs_group;
 		gcount++;
Signature · 1 line
2.43.0
author maintainer
#75 lore raw

PATCH 71/149 smb/client: remove unused rq_iter_size from struct smb_rqst

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Stefan Metzmacher <[email protected]>

[ Upstream commit b608e2c318789aeba49055747166e13bee57df4a ]

Fixes d08089f649a0 ("cifs: Change the I/O paths to use an iterator rather than a page list")
---
 fs/smb/client/cifsglob.h | 1 -
 fs/smb/client/cifssmb.c  | 1 -
 fs/smb/client/smb2ops.c  | 2 --
 fs/smb/client/smb2pdu.c  | 2 --
 4 files changed, 6 deletions(-)
fs/smb/client/cifsglob.h +0 -1
index 0a271b9fbc622..1e4da268de3b4 100644
@@ -254,7 +254,6 @@ struct cifs_open_info_data {
 struct smb_rqst {
 	struct kvec	*rq_iov;	/* array of kvecs */
 	unsigned int	rq_nvec;	/* number of kvecs in array */
-	size_t		rq_iter_size;	/* Amount of data in ->rq_iter */
 	struct iov_iter	rq_iter;	/* Data iterator */
 	struct xarray	rq_buffer;	/* Page buffer for encryption */
 };
fs/smb/client/cifssmb.c +0 -1
index 595c4b673707e..6dce70f172082 100644
@@ -1713,7 +1713,6 @@ cifs_async_writev(struct cifs_io_subrequest *wdata)
 	rqst.rq_iov = iov;
 	rqst.rq_nvec = 2;
 	rqst.rq_iter = wdata->subreq.io_iter;
-	rqst.rq_iter_size = iov_iter_count(&wdata->subreq.io_iter);
 
 	cifs_dbg(FYI, "async write at %llu %zu bytes\n",
 		 wdata->subreq.start, wdata->subreq.len);
fs/smb/client/smb2ops.c +0 -2
index 7fe59235f0901..cfbca3489ece1 100644
@@ -4428,7 +4428,6 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, int num_rqst,
 			}
 			iov_iter_xarray(&new->rq_iter, ITER_SOURCE,
 					buffer, 0, size);
-			new->rq_iter_size = size;
 		}
 	}
 
@@ -4474,7 +4473,6 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
 	rqst.rq_nvec = 2;
 	if (iter) {
 		rqst.rq_iter = *iter;
-		rqst.rq_iter_size = iov_iter_count(iter);
 		iter_size = iov_iter_count(iter);
 	}
 
fs/smb/client/smb2pdu.c +0 -2
index 52b95f33db57d..d262e70100c9c 100644
@@ -4517,7 +4517,6 @@ smb2_readv_callback(struct mid_q_entry *mid)
 
 	if (rdata->got_bytes) {
 		rqst.rq_iter	  = rdata->subreq.io_iter;
-		rqst.rq_iter_size = iov_iter_count(&rdata->subreq.io_iter);
 	}
 
 	WARN_ONCE(rdata->server != mid->server,
@@ -4969,7 +4968,6 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
 	rqst.rq_iov = iov;
 	rqst.rq_nvec = 1;
 	rqst.rq_iter = wdata->subreq.io_iter;
-	rqst.rq_iter_size = iov_iter_count(&rqst.rq_iter);
 	if (test_bit(NETFS_SREQ_RETRYING, &wdata->subreq.flags))
 		smb2_set_replay(server, &rqst);
 #ifdef CONFIG_CIFS_SMB_DIRECT
Signature · 1 line
2.43.0
author maintainer
#76 lore raw

PATCH 72/149 cifs: Fix FALLOC_FL_PUNCH_HOLE support

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: David Howells <[email protected]>

[ Upstream commit 416871f4fb84bc96822562e654941d5625a25bf8 ]

The cifs filesystem doesn't quite emulate FALLOC_FL_PUNCH_HOLE correctly (note that due to lack of protocol support, it can't actually implement it directly). Whilst it will (partially) invalidate dirty folios in the pagecache, it doesn't write them back first, and so the EOF marker on the server may be lower than inode->i_size.

This presents a problem, however, as if the punched hole invalidates the tail of the locally cached dirty data, writeback won't know it needs to move the EOF over to account for the hole punch (which isn't supposed to move the EOF). We could just write zeroes over the punched out region of the pagecache and write that back - but this is supposed to be a deallocatory operation.

Fix this by manually moving the EOF over on the server after the operation if the hole punched would corrupt it.

Note that the FSCTL_SET_ZERO_DATA RPC and the setting of the EOF should probably be compounded to stop a third party interfering (or, at least, massively reduce the chance).

This was reproducible occasionally by using fsx with the following script:

	truncate 0x0 0x375e2 0x0
	punch_hole 0x2f6d3 0x6ab5 0x375e2
	truncate 0x0 0x3a71f 0x375e2
	mapread 0xee05 0xcf12 0x3a71f
	write 0x2078e 0x5604 0x3a71f
	write 0x3ebdf 0x1421 0x3a71f *
	punch_hole 0x379d0 0x8630 0x40000 *
	mapread 0x2aaa2 0x85b 0x40000
	fallocate 0x1b401 0x9ada 0x40000
	read 0x15f2 0x7d32 0x40000
	read 0x32f37 0x7a3b 0x40000 *

The second "write" should extend the EOF to 0x40000, and the "punch_hole" should operate inside of that - but that depends on whether the VM gets in and writes back the data first. If it doesn't, the file ends up 0x3a71f in size, not 0x40000.

Fixes 31742c5a3317 ("enable fallocate punch hole ("fallocate -p") for SMB3")
cc Steve French <[email protected]>
cc Paulo Alcantara <[email protected]>
cc Shyam Prasad N <[email protected]>
cc Jeff Layton <[email protected]>
---
 fs/smb/client/smb2ops.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)
fs/smb/client/smb2ops.c +22 -0
index cfbca3489ece1..f44f5f2494006 100644
@@ -3287,6 +3287,7 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
 	struct inode *inode = file_inode(file);
 	struct cifsFileInfo *cfile = file->private_data;
 	struct file_zero_data_information fsctl_buf;
+	unsigned long long end = offset + len, i_size, remote_i_size;
 	long rc;
 	unsigned int xid;
 	__u8 set_sparse = 1;
@@ -3318,6 +3319,27 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
 			(char *)&fsctl_buf,
 			sizeof(struct file_zero_data_information),
 			CIFSMaxBufSize, NULL, NULL);
+
+	if (rc)
+		goto unlock;
+
+	/* If there's dirty data in the buffer that would extend the EOF if it
+	 * were written, then we need to move the EOF marker over to the lower
+	 * of the high end of the hole and the proposed EOF.  The problem is
+	 * that we locally hole-punch the tail of the dirty data, the proposed
+	 * EOF update will end up in the wrong place.
+	 */
+	i_size = i_size_read(inode);
+	remote_i_size = netfs_inode(inode)->remote_i_size;
+	if (end > remote_i_size && i_size > remote_i_size) {
+		unsigned long long extend_to = umin(end, i_size);
+		rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
+				  cfile->fid.volatile_fid, cfile->pid, extend_to);
+		if (rc >= 0)
+			netfs_inode(inode)->remote_i_size = extend_to;
+	}
+
+unlock:
 	filemap_invalidate_unlock(inode->i_mapping);
 out:
 	inode_unlock(inode);
Signature · 1 line
2.43.0
author maintainer
#77 lore raw

PATCH 73/149 nfsd: hold reference to delegation when updating it for cb_getattr

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jeff Layton <[email protected]>

[ Upstream commit da05ba23d4c8d3e8a45846b952e53dd76c4b5e36 ]

Once we've dropped the flc_lock, there is nothing that ensures that the delegation that was found will still be around later. Take a reference to it while holding the lock and then drop it when we've finished with the delegation.

Fixes c5967721e106 ("NFSD: handle GETATTR conflict with write delegation")
---
 fs/nfsd/nfs4state.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
fs/nfsd/nfs4state.c +7 -3
index dafff707e23a4..19d39872be325 100644
@@ -8837,7 +8837,6 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode,
 	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 	struct file_lock_context *ctx;
 	struct file_lease *fl;
-	struct nfs4_delegation *dp;
 	struct iattr attrs;
 	struct nfs4_cb_fattr *ncf;
 
@@ -8862,7 +8861,8 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode,
 			goto break_lease;
 		}
 		if (type == F_WRLCK) {
-			dp = fl->c.flc_owner;
+			struct nfs4_delegation *dp = fl->c.flc_owner;
+
 			if (dp->dl_recall.cb_clp == *(rqstp->rq_lease_breaker)) {
 				spin_unlock(&ctx->flc_lock);
 				return 0;
@@ -8870,6 +8870,7 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode,
 break_lease:
 			nfsd_stats_wdeleg_getattr_inc(nn);
 			dp = fl->c.flc_owner;
+			refcount_inc(&dp->dl_stid.sc_count);
 			ncf = &dp->dl_cb_fattr;
 			nfs4_cb_getattr(&dp->dl_cb_fattr);
 			spin_unlock(&ctx->flc_lock);
@@ -8879,8 +8880,10 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode,
 				/* Recall delegation only if client didn't respond */
 				status = nfserrno(nfsd_open_break_lease(inode, NFSD_MAY_READ));
 				if (status != nfserr_jukebox ||
-						!nfsd_wait_for_delegreturn(rqstp, inode))
+						!nfsd_wait_for_delegreturn(rqstp, inode)) {
+					nfs4_put_stid(&dp->dl_stid);
 					return status;
+				}
 			}
 			if (!ncf->ncf_file_modified &&
 					(ncf->ncf_initial_cinfo != ncf->ncf_cb_change ||
@@ -8900,6 +8903,7 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode,
 				*size = ncf->ncf_cur_fsize;
 				*modified = true;
 			}
+			nfs4_put_stid(&dp->dl_stid);
 			return 0;
 		}
 		break;
Signature · 1 line
2.43.0
author maintainer
#78 lore raw

PATCH 74/149 nfsd: fix potential UAF in nfsd4_cb_getattr_release

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jeff Layton <[email protected]>

[ Upstream commit 1116e0e372eb16dd907ec571ce5d4af325c55c10 ]

Once we drop the delegation reference, the fields embedded in it are no longer safe to access. Do that last.

Fixes c5967721e106 ("NFSD: handle GETATTR conflict with write delegation")
---
 fs/nfsd/nfs4state.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfsd/nfs4state.c +1 -1
index 19d39872be325..02d43f95146ee 100644
@@ -3078,9 +3078,9 @@ nfsd4_cb_getattr_release(struct nfsd4_callback *cb)
 	struct nfs4_delegation *dp =
 			container_of(ncf, struct nfs4_delegation, dl_cb_fattr);
 
-	nfs4_put_stid(&dp->dl_stid);
 	clear_bit(CB_GETATTR_BUSY, &ncf->ncf_cb_flags);
 	wake_up_bit(&ncf->ncf_cb_flags, CB_GETATTR_BUSY);
+	nfs4_put_stid(&dp->dl_stid);
 }
 
 static const struct nfsd4_callback_ops nfsd4_cb_recall_any_ops = {
Signature · 1 line
2.43.0
author maintainer
#79 lore raw

PATCH 75/149 fs/nfsd: fix update of inode attrs in CB_GETATTR

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jeff Layton <[email protected]>

[ Upstream commit 7e8ae8486e4471513e2111aba6ac29f2357bed2a ]

Currently, we copy the mtime and ctime to the in-core inode and then mark the inode dirty. This is fine for certain types of filesystems, but not all. Some require a real setattr to properly change these values (e.g. ceph or reexported NFS).

Fix this code to call notify_change() instead, which is the proper way to effect a setattr. There is one problem though:

In this case, the client is holding a write delegation and has sent us attributes to update our cache. We don't want to break the delegation for this since that would defeat the purpose. Add a new ATTR_DELEG flag that makes notify_change bypass the try_break_deleg call.

Fixes c5967721e106 ("NFSD: handle GETATTR conflict with write delegation")
---
 fs/attr.c           | 14 +++++++++++---
 fs/nfsd/nfs4state.c | 18 +++++++++++++-----
 fs/nfsd/nfs4xdr.c   |  2 +-
 fs/nfsd/state.h     |  2 +-
 include/linux/fs.h  |  1 +
 5 files changed, 27 insertions(+), 10 deletions(-)
fs/attr.c +11 -3
index 960a310581ebb..0dbf43b6555c8 100644
@@ -489,9 +489,17 @@ int notify_change(struct mnt_idmap *idmap, struct dentry *dentry,
 	error = security_inode_setattr(idmap, dentry, attr);
 	if (error)
 		return error;
-	error = try_break_deleg(inode, delegated_inode);
-	if (error)
-		return error;
+
+	/*
+	 * If ATTR_DELEG is set, then these attributes are being set on
+	 * behalf of the holder of a write delegation. We want to avoid
+	 * breaking the delegation in this case.
+	 */
+	if (!(ia_valid & ATTR_DELEG)) {
+		error = try_break_deleg(inode, delegated_inode);
+		if (error)
+			return error;
+	}
 
 	if (inode->i_op->setattr)
 		error = inode->i_op->setattr(idmap, dentry, attr);
fs/nfsd/nfs4state.c +13 -5
index 02d43f95146ee..07f2496850c4c 100644
@@ -8815,7 +8815,7 @@ nfsd4_get_writestateid(struct nfsd4_compound_state *cstate,
 /**
  * nfsd4_deleg_getattr_conflict - Recall if GETATTR causes conflict
  * @rqstp: RPC transaction context
- * @inode: file to be checked for a conflict
+ * @dentry: dentry of inode to be checked for a conflict
  * @modified: return true if file was modified
  * @size: new size of file if modified is true
  *
@@ -8830,7 +8830,7 @@ nfsd4_get_writestateid(struct nfsd4_compound_state *cstate,
  * code is returned.
  */
 __be32
-nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode,
+nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct dentry *dentry,
 				bool *modified, u64 *size)
 {
 	__be32 status;
@@ -8839,6 +8839,7 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode,
 	struct file_lease *fl;
 	struct iattr attrs;
 	struct nfs4_cb_fattr *ncf;
+	struct inode *inode = d_inode(dentry);
 
 	*modified = false;
 	ctx = locks_inode_context(inode);
@@ -8890,15 +8891,22 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode,
 					ncf->ncf_cur_fsize != ncf->ncf_cb_fsize))
 				ncf->ncf_file_modified = true;
 			if (ncf->ncf_file_modified) {
+				int err;
+
 				/*
 				 * Per section 10.4.3 of RFC 8881, the server would
 				 * not update the file's metadata with the client's
 				 * modified size
 				 */
 				attrs.ia_mtime = attrs.ia_ctime = current_time(inode);
-				attrs.ia_valid = ATTR_MTIME | ATTR_CTIME;
-				setattr_copy(&nop_mnt_idmap, inode, &attrs);
-				mark_inode_dirty(inode);
+				attrs.ia_valid = ATTR_MTIME | ATTR_CTIME | ATTR_DELEG;
+				inode_lock(inode);
+				err = notify_change(&nop_mnt_idmap, dentry, &attrs, NULL);
+				inode_unlock(inode);
+				if (err) {
+					nfs4_put_stid(&dp->dl_stid);
+					return nfserrno(err);
+				}
 				ncf->ncf_cur_fsize = ncf->ncf_cb_fsize;
 				*size = ncf->ncf_cur_fsize;
 				*modified = true;
fs/nfsd/nfs4xdr.c +1 -1
index 8a7bc2b58e721..0869062280ccc 100644
@@ -3565,7 +3565,7 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 	}
 	args.size = 0;
 	if (attrmask[0] & (FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE)) {
-		status = nfsd4_deleg_getattr_conflict(rqstp, d_inode(dentry),
+		status = nfsd4_deleg_getattr_conflict(rqstp, dentry,
 					&file_modified, &size);
 		if (status)
 			goto out;
fs/nfsd/state.h +1 -1
index ffc217099d191..ec4559ecd193b 100644
@@ -781,5 +781,5 @@ static inline bool try_to_expire_client(struct nfs4_client *clp)
 }
 
 extern __be32 nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp,
-		struct inode *inode, bool *file_modified, u64 *size);
+		struct dentry *dentry, bool *file_modified, u64 *size);
 #endif   /* NFSD4_STATE_H */
include/linux/fs.h +1 -0
index 36b9e87439221..5f07c1c377df6 100644
@@ -208,6 +208,7 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
 #define ATTR_OPEN	(1 << 15) /* Truncating from open(O_TRUNC) */
 #define ATTR_TIMES_SET	(1 << 16)
 #define ATTR_TOUCH	(1 << 17)
+#define ATTR_DELEG	(1 << 18) /* Delegated attrs. Don't break write delegations */
 
 /*
  * Whiteout is represented by a char device.  The following constants define the
Signature · 1 line
2.43.0
author maintainer
#80 lore raw

PATCH 76/149 selinux,smack: dont bypass permissions check in inode_setsecctx hook

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Scott Mayhew <[email protected]>

commit 76a0e79bc84f466999fa501fce5bf7a07641b8a7 upstream.

Marek Gresko reports that the root user on an NFS client is able to change the security labels on files on an NFS filesystem that is exported with root squashing enabled.

The end of the kerneldoc comment for __vfs_setxattr_noperm() states:

 *  This function requires the caller to lock the inode's i_mutex before it
 *  is executed. It also assumes that the caller will make the appropriate
 *  permission checks.

nfsd_setattr() does do permissions checking via fh_verify() and nfsd_permission(), but those don't do all the same permissions checks that are done by security_inode_setxattr() and its related LSM hooks do.

Since nfsd_setattr() is the only consumer of security_inode_setsecctx(), simplest solution appears to be to replace the call to __vfs_setxattr_noperm() with a call to __vfs_setxattr_locked(). This fixes the above issue and has the added benefit of causing nfsd to recall conflicting delegations on a file when a client tries to change its security label.

---
 security/selinux/hooks.c   |    4 ++--
 security/smack/smack_lsm.c |    4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)
security/selinux/hooks.c +2 -2
@@ -6660,8 +6660,8 @@ static int selinux_inode_notifysecctx(st
  */
 static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
 {
-	return __vfs_setxattr_noperm(&nop_mnt_idmap, dentry, XATTR_NAME_SELINUX,
-				     ctx, ctxlen, 0);
+	return __vfs_setxattr_locked(&nop_mnt_idmap, dentry, XATTR_NAME_SELINUX,
+				     ctx, ctxlen, 0, NULL);
 }
 
 static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
security/smack/smack_lsm.c +2 -2
@@ -4874,8 +4874,8 @@ static int smack_inode_notifysecctx(stru
 
 static int smack_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
 {
-	return __vfs_setxattr_noperm(&nop_mnt_idmap, dentry, XATTR_NAME_SMACK,
-				     ctx, ctxlen, 0);
+	return __vfs_setxattr_locked(&nop_mnt_idmap, dentry, XATTR_NAME_SMACK,
+				     ctx, ctxlen, 0, NULL);
 }
 
 static int smack_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
author maintainer
#81 lore raw

PATCH 77/149 cpufreq/amd-pstate: Use topology_logical_package_id() instead of logical_die_id()

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Gautham R. Shenoy <[email protected]>

commit 0d8584d288a9b4132e945d76bcc04395d158b2e7 upstream.

After the commit 63edbaa48a57 ("x86/cpu/topology: Add support for the AMD 0x80000026 leaf"), the topolgy_logical_die_id() function returns the logical Core Chiplet Die (CCD) ID instead of the logical socket ID.

Since this is currently used to set MSR_AMD_CPPC_ENABLE, which needs to be set on any one of the threads of the socket, it is prudent to use topology_logical_package_id() in place of topology_logical_die_id().

---
 drivers/cpufreq/amd-pstate.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/cpufreq/amd-pstate.c +1 -1
@@ -329,7 +329,7 @@ static inline int pstate_enable(bool ena
 		return 0;
 
 	for_each_present_cpu(cpu) {
-		unsigned long logical_id = topology_logical_die_id(cpu);
+		unsigned long logical_id = topology_logical_package_id(cpu);
 
 		if (test_bit(logical_id, &logical_proc_id_mask))
 			continue;
author maintainer
#82 lore raw

PATCH 78/149 iommufd: Do not allow creating areas without READ or WRITE

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jason Gunthorpe <[email protected]>

commit 996dc53ac289b81957aa70d62ccadc6986d26a87 upstream.

This results in passing 0 or just IOMMU_CACHE to iommu_map(). Most of the page table formats don't like this:

amdv1 - -EINVAL
armv7s - returns 0, doesn't update mapped
arm-lpae - returns 0 doesn't update mapped
dart - returns 0, doesn't update mapped
VT-D - returns -EINVAL

Unfortunately the three formats that return 0 cause serious problems:

- Returning ret = but not uppdating mapped from domain->map_pages() causes an infinite loop in __iommu_map()

- Not writing ioptes means that VFIO/iommufd have no way to recover them and we will have memory leaks and worse during unmap

Since almost nothing can support this, and it is a useless thing to do, block it early in iommufd.

---
 drivers/iommu/iommufd/ioas.c            |    8 ++++++++
 tools/testing/selftests/iommu/iommufd.c |    6 +++---
 2 files changed, 11 insertions(+), 3 deletions(-)
drivers/iommu/iommufd/ioas.c +8 -0
@@ -213,6 +213,10 @@ int iommufd_ioas_map(struct iommufd_ucmd
 	if (cmd->iova >= ULONG_MAX || cmd->length >= ULONG_MAX)
 		return -EOVERFLOW;
 
+	if (!(cmd->flags &
+	      (IOMMU_IOAS_MAP_WRITEABLE | IOMMU_IOAS_MAP_READABLE)))
+		return -EINVAL;
+
 	ioas = iommufd_get_ioas(ucmd->ictx, cmd->ioas_id);
 	if (IS_ERR(ioas))
 		return PTR_ERR(ioas);
@@ -253,6 +257,10 @@ int iommufd_ioas_copy(struct iommufd_ucm
 	    cmd->dst_iova >= ULONG_MAX)
 		return -EOVERFLOW;
 
+	if (!(cmd->flags &
+	      (IOMMU_IOAS_MAP_WRITEABLE | IOMMU_IOAS_MAP_READABLE)))
+		return -EINVAL;
+
 	src_ioas = iommufd_get_ioas(ucmd->ictx, cmd->src_ioas_id);
 	if (IS_ERR(src_ioas))
 		return PTR_ERR(src_ioas);
tools/testing/selftests/iommu/iommufd.c +3 -3
@@ -803,7 +803,7 @@ TEST_F(iommufd_ioas, copy_area)
 {
 	struct iommu_ioas_copy copy_cmd = {
 		.size = sizeof(copy_cmd),
-		.flags = IOMMU_IOAS_MAP_FIXED_IOVA,
+		.flags = IOMMU_IOAS_MAP_FIXED_IOVA | IOMMU_IOAS_MAP_WRITEABLE,
 		.dst_ioas_id = self->ioas_id,
 		.src_ioas_id = self->ioas_id,
 		.length = PAGE_SIZE,
@@ -1296,7 +1296,7 @@ TEST_F(iommufd_ioas, copy_sweep)
 {
 	struct iommu_ioas_copy copy_cmd = {
 		.size = sizeof(copy_cmd),
-		.flags = IOMMU_IOAS_MAP_FIXED_IOVA,
+		.flags = IOMMU_IOAS_MAP_FIXED_IOVA | IOMMU_IOAS_MAP_WRITEABLE,
 		.src_ioas_id = self->ioas_id,
 		.dst_iova = MOCK_APERTURE_START,
 		.length = MOCK_PAGE_SIZE,
@@ -1586,7 +1586,7 @@ TEST_F(iommufd_mock_domain, user_copy)
 	};
 	struct iommu_ioas_copy copy_cmd = {
 		.size = sizeof(copy_cmd),
-		.flags = IOMMU_IOAS_MAP_FIXED_IOVA,
+		.flags = IOMMU_IOAS_MAP_FIXED_IOVA | IOMMU_IOAS_MAP_WRITEABLE,
 		.dst_ioas_id = self->ioas_id,
 		.dst_iova = MOCK_APERTURE_START,
 		.length = BUFFER_SIZE,
author maintainer
#83 lore raw

PATCH 79/149 phy: fsl-imx8mq-usb: fix tuning parameter name

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Xu Yang <[email protected]>

commit ce52c2532299c7ccfd34a52db8d071e890a78c59 upstream.

According to fsl,imx8mq-usb-phy.yaml, this tuning parameter should be fsl,phy-pcs-tx-deemph-3p5db-attenuation-db.

---
 drivers/phy/freescale/phy-fsl-imx8mq-usb.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/phy/freescale/phy-fsl-imx8mq-usb.c +1 -1
@@ -176,7 +176,7 @@ static void imx8m_get_phy_tuning_data(st
 		imx_phy->comp_dis_tune =
 			phy_comp_dis_tune_from_property(imx_phy->comp_dis_tune);
 
-	if (device_property_read_u32(dev, "fsl,pcs-tx-deemph-3p5db-attenuation-db",
+	if (device_property_read_u32(dev, "fsl,phy-pcs-tx-deemph-3p5db-attenuation-db",
 				     &imx_phy->pcs_tx_deemph_3p5db))
 		imx_phy->pcs_tx_deemph_3p5db = PHY_TUNE_DEFAULT;
 	else
author maintainer
#84 lore raw

PATCH 80/149 soundwire: stream: fix programming slave ports for non-continous port maps

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Krzysztof Kozlowski <[email protected]>

commit ab8d66d132bc8f1992d3eb6cab8d32dda6733c84 upstream.

Two bitmasks in 'struct sdw_slave_prop' - 'source_ports' and 'sink_ports' - define which ports to program in sdw_program_slave_port_params(). The masks are used to get the appropriate data port properties ('struct sdw_get_slave_dpn_prop') from an array.

Bitmasks can be non-continuous or can start from index different than 0, thus when looking for matching port property for given port, we must iterate over mask bits, not from 0 up to number of ports.

This fixes allocation and programming slave ports, when a source or sink masks start from further index.

---
 drivers/soundwire/stream.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/soundwire/stream.c +4 -4
@@ -1286,18 +1286,18 @@ struct sdw_dpn_prop *sdw_get_slave_dpn_p
 					    unsigned int port_num)
 {
 	struct sdw_dpn_prop *dpn_prop;
-	u8 num_ports;
+	unsigned long mask;
 	int i;
 
 	if (direction == SDW_DATA_DIR_TX) {
-		num_ports = hweight32(slave->prop.source_ports);
+		mask = slave->prop.source_ports;
 		dpn_prop = slave->prop.src_dpn_prop;
 	} else {
-		num_ports = hweight32(slave->prop.sink_ports);
+		mask = slave->prop.sink_ports;
 		dpn_prop = slave->prop.sink_dpn_prop;
 	}
 
-	for (i = 0; i < num_ports; i++) {
+	for_each_set_bit(i, &mask, 32) {
 		if (dpn_prop[i].num == port_num)
 			return &dpn_prop[i];
 	}
author maintainer
#85 lore raw

PATCH 81/149 dmaengine: dw-edma: Fix unmasking STOP and ABORT interrupts for HDMA

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Mrinmay Sarkar <[email protected]>

commit 383baf5c8f062091af34c63f28d37642a8f188ae upstream.

The current logic is enabling both STOP_INT_MASK and ABORT_INT_MASK bit. This is apparently masking those particular interrupts rather than unmasking the same. If the interrupts are masked, they would never get triggered.

So fix the issue by unmasking the STOP and ABORT interrupts properly.

---
 drivers/dma/dw-edma/dw-hdma-v0-core.c |    9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/dma/dw-edma/dw-hdma-v0-core.c +5 -4
@@ -247,10 +247,11 @@ static void dw_hdma_v0_core_start(struct
 	if (first) {
 		/* Enable engine */
 		SET_CH_32(dw, chan->dir, chan->id, ch_en, BIT(0));
-		/* Interrupt enable&unmask - done, abort */
-		tmp = GET_CH_32(dw, chan->dir, chan->id, int_setup) |
-		      HDMA_V0_STOP_INT_MASK | HDMA_V0_ABORT_INT_MASK |
-		      HDMA_V0_LOCAL_STOP_INT_EN | HDMA_V0_LOCAL_ABORT_INT_EN;
+		/* Interrupt unmask - stop, abort */
+		tmp = GET_CH_32(dw, chan->dir, chan->id, int_setup);
+		tmp &= ~(HDMA_V0_STOP_INT_MASK | HDMA_V0_ABORT_INT_MASK);
+		/* Interrupt enable - stop, abort */
+		tmp |= HDMA_V0_LOCAL_STOP_INT_EN | HDMA_V0_LOCAL_ABORT_INT_EN;
 		if (!(dw->chip->flags & DW_EDMA_CHIP_LOCAL))
 			tmp |= HDMA_V0_REMOTE_STOP_INT_EN | HDMA_V0_REMOTE_ABORT_INT_EN;
 		SET_CH_32(dw, chan->dir, chan->id, int_setup, tmp);
author maintainer
#86 lore raw

PATCH 82/149 dmaengine: dw-edma: Do not enable watermark interrupts for HDMA

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Mrinmay Sarkar <[email protected]>

commit 9f646ff25c09c52cebe726601db27a60f876f15e upstream.

DW_HDMA_V0_LIE and DW_HDMA_V0_RIE are initialized as BIT(3) and BIT(4) respectively in dw_hdma_control enum. But as per HDMA register these bits are corresponds to LWIE and RWIE bit i.e local watermark interrupt enable and remote watermarek interrupt enable. In linked list mode LWIE and RWIE bits only enable the local and remote watermark interrupt.

Since the watermark interrupts are not used but enabled, this leads to spurious interrupts getting generated. So remove the code that enables them to avoid generating spurious watermark interrupts.

And also rename DW_HDMA_V0_LIE to DW_HDMA_V0_LWIE and DW_HDMA_V0_RIE to DW_HDMA_V0_RWIE as there is no LIE and RIE bits in HDMA and those bits are corresponds to LWIE and RWIE bits.

---
 drivers/dma/dw-edma/dw-hdma-v0-core.c |   17 +++--------------
 1 file changed, 3 insertions(+), 14 deletions(-)
drivers/dma/dw-edma/dw-hdma-v0-core.c +3 -14
@@ -17,8 +17,8 @@ enum dw_hdma_control {
 	DW_HDMA_V0_CB					= BIT(0),
 	DW_HDMA_V0_TCB					= BIT(1),
 	DW_HDMA_V0_LLP					= BIT(2),
-	DW_HDMA_V0_LIE					= BIT(3),
-	DW_HDMA_V0_RIE					= BIT(4),
+	DW_HDMA_V0_LWIE					= BIT(3),
+	DW_HDMA_V0_RWIE					= BIT(4),
 	DW_HDMA_V0_CCS					= BIT(8),
 	DW_HDMA_V0_LLE					= BIT(9),
 };
@@ -195,25 +195,14 @@ static void dw_hdma_v0_write_ll_link(str
 static void dw_hdma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
 {
 	struct dw_edma_burst *child;
-	struct dw_edma_chan *chan = chunk->chan;
 	u32 control = 0, i = 0;
-	int j;
 
 	if (chunk->cb)
 		control = DW_HDMA_V0_CB;
 
-	j = chunk->bursts_alloc;
-	list_for_each_entry(child, &chunk->burst->list, list) {
-		j--;
-		if (!j) {
-			control |= DW_HDMA_V0_LIE;
-			if (!(chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL))
-				control |= DW_HDMA_V0_RIE;
-		}
-
+	list_for_each_entry(child, &chunk->burst->list, list)
 		dw_hdma_v0_write_ll_data(chunk, i++, control, child->sz,
 					 child->sar, child->dar);
-	}
 
 	control = DW_HDMA_V0_LLP | DW_HDMA_V0_TCB;
 	if (!chunk->cb)
author maintainer
#87 lore raw

PATCH 83/149 phy: qcom: qmp-pcie: Fix X1E80100 PCIe Gen4 PHY initialisation

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Abel Vesa <[email protected]>

[ Upstream commit 0e8a0504da59041e775a95db3ebc1a6211423593 ]

Update the PCIe Gen4 PHY init sequence with the latest based on internal Qualcomm documentation.

Fixes 606060ce8fd0 ("phy: qcom-qmp-pcie: Add support for X1E80100 g3x2 and g4x2 PCIE")
---
 drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)
drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +16 -7
index 8fcdcb193d241..e99cbcc378908 100644
@@ -1008,8 +1008,8 @@ static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_serdes_tbl[] = {
 static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_ln_shrd_tbl[] = {
 	QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RXCLK_DIV2_CTRL, 0x01),
 	QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_DFE_DAC_ENABLE1, 0x88),
-	QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH1, 0x00),
-	QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH2, 0x1f),
+	QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH1, 0x02),
+	QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH2, 0x0d),
 	QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B0, 0xd4),
 	QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B1, 0x12),
 	QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B2, 0xdb),
@@ -1026,6 +1026,7 @@ static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_ln_shrd_tbl[] = {
 	QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH4_RATE3, 0x1f),
 	QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH5_RATE3, 0x1f),
 	QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH6_RATE3, 0x1f),
+	QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_SUMMER_CAL_SPD_MODE, 0x5b),
 };
 
 static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_tx_tbl[] = {
@@ -1049,12 +1050,15 @@ static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_rx_tbl[] = {
 	QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_1, 0x01),
 	QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_2, 0x01),
 	QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_3, 0x45),
-	QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_VGA_CAL_MAN_VAL, 0x0b),
+	QMP_PHY_INIT_CFG_LANE(QSERDES_V6_20_RX_VGA_CAL_MAN_VAL, 0x0a, 1),
+	QMP_PHY_INIT_CFG_LANE(QSERDES_V6_20_RX_VGA_CAL_MAN_VAL, 0x0b, 2),
+	QMP_PHY_INIT_CFG(QSERDES_V6_20_VGA_CAL_CNTRL1, 0x00),
 	QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_GM_CAL, 0x0d),
 	QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_EQU_ADAPTOR_CNTRL4, 0x0b),
 	QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_SIGDET_ENABLES, 0x1c),
 	QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_PHPRE_CTRL, 0x20),
-	QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
+	QMP_PHY_INIT_CFG_LANE(QSERDES_V6_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x3a, 1),
+	QMP_PHY_INIT_CFG_LANE(QSERDES_V6_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38, 2),
 	QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_Q_PI_INTRINSIC_BIAS_RATE32, 0x39),
 	QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B0, 0x14),
 	QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B1, 0xb3),
@@ -1070,6 +1074,7 @@ static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_rx_tbl[] = {
 	QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B4, 0x4b),
 	QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B5, 0x76),
 	QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B6, 0xff),
+	QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_TX_ADPT_CTRL, 0x10),
 };
 
 static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_pcs_tbl[] = {
@@ -1077,6 +1082,8 @@ static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_pcs_tbl[] = {
 	QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_RX_SIGDET_LVL, 0xcc),
 	QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_EQ_CONFIG4, 0x00),
 	QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_EQ_CONFIG5, 0x22),
+	QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_TX_RX_CONFIG1, 0x04),
+	QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_TX_RX_CONFIG2, 0x02),
 };
 
 static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_pcs_misc_tbl[] = {
@@ -1087,11 +1094,13 @@ static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_pcs_misc_tbl[] = {
 	QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G4_PRE_GAIN, 0x2e),
 	QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_RX_MARGINING_CONFIG1, 0x03),
 	QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_RX_MARGINING_CONFIG3, 0x28),
+	QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G3_RXEQEVAL_TIME, 0x27),
+	QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G4_RXEQEVAL_TIME, 0x27),
 	QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_TX_RX_CONFIG, 0xc0),
 	QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_POWER_STATE_CONFIG2, 0x1d),
-	QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_RX_MARGINING_CONFIG5, 0x0f),
-	QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G3_FOM_EQ_CONFIG5, 0xf2),
-	QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G4_FOM_EQ_CONFIG5, 0xf2),
+	QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_RX_MARGINING_CONFIG5, 0x18),
+	QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G3_FOM_EQ_CONFIG5, 0x7a),
+	QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G4_FOM_EQ_CONFIG5, 0x8a),
 };
 
 static const struct qmp_phy_init_tbl sm8250_qmp_pcie_serdes_tbl[] = {
Signature · 1 line
2.43.0
author maintainer
#88 lore raw

PATCH 84/149 phy: xilinx: phy-zynqmp: Fix SGMII linkup failure on resume

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Piyush Mehta <[email protected]>

[ Upstream commit 5af9b304bc6010723c02f74de0bfd24ff19b1a10 ]

On a few Kria KR260 Robotics Starter Kit the PS-GEM SGMII linkup is not happening after the resume. This is because serdes registers are reset when FPD is off (in suspend state) and needs to be reprogrammed in the resume path with the same default initialization as done in the first stage bootloader psu_init routine.

To address the failure introduce a set of serdes registers to be saved in the suspend path and then restore it on resume.

Fixes 4a33bea00314 ("phy: zynqmp: Add PHY driver for the Xilinx ZynqMP Gigabit Transceiver")
---
 drivers/phy/xilinx/phy-zynqmp.c | 56 +++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)
drivers/phy/xilinx/phy-zynqmp.c +56 -0
index f2bff7f25f05a..d7d12cf3011a2 100644
@@ -166,6 +166,24 @@
 /* Timeout values */
 #define TIMEOUT_US			1000
 
+/* Lane 0/1/2/3 offset */
+#define DIG_8(n)		((0x4000 * (n)) + 0x1074)
+#define ILL13(n)		((0x4000 * (n)) + 0x1994)
+#define DIG_10(n)		((0x4000 * (n)) + 0x107c)
+#define RST_DLY(n)		((0x4000 * (n)) + 0x19a4)
+#define BYP_15(n)		((0x4000 * (n)) + 0x1038)
+#define BYP_12(n)		((0x4000 * (n)) + 0x102c)
+#define MISC3(n)		((0x4000 * (n)) + 0x19ac)
+#define EQ11(n)			((0x4000 * (n)) + 0x1978)
+
+static u32 save_reg_address[] = {
+	/* Lane 0/1/2/3 Register */
+	DIG_8(0), ILL13(0), DIG_10(0), RST_DLY(0), BYP_15(0), BYP_12(0), MISC3(0), EQ11(0),
+	DIG_8(1), ILL13(1), DIG_10(1), RST_DLY(1), BYP_15(1), BYP_12(1), MISC3(1), EQ11(1),
+	DIG_8(2), ILL13(2), DIG_10(2), RST_DLY(2), BYP_15(2), BYP_12(2), MISC3(2), EQ11(2),
+	DIG_8(3), ILL13(3), DIG_10(3), RST_DLY(3), BYP_15(3), BYP_12(3), MISC3(3), EQ11(3),
+};
+
 struct xpsgtr_dev;
 
 /**
@@ -214,6 +232,7 @@ struct xpsgtr_phy {
  * @tx_term_fix: fix for GT issue
  * @saved_icm_cfg0: stored value of ICM CFG0 register
  * @saved_icm_cfg1: stored value of ICM CFG1 register
+ * @saved_regs: registers to be saved/restored during suspend/resume
  */
 struct xpsgtr_dev {
 	struct device *dev;
@@ -226,6 +245,7 @@ struct xpsgtr_dev {
 	bool tx_term_fix;
 	unsigned int saved_icm_cfg0;
 	unsigned int saved_icm_cfg1;
+	u32 *saved_regs;
 };
 
 /*
@@ -299,6 +319,32 @@ static inline void xpsgtr_clr_set_phy(struct xpsgtr_phy *gtr_phy,
 	writel((readl(addr) & ~clr) | set, addr);
 }
 
+/**
+ * xpsgtr_save_lane_regs - Saves registers on suspend
+ * @gtr_dev: pointer to phy controller context structure
+ */
+static void xpsgtr_save_lane_regs(struct xpsgtr_dev *gtr_dev)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(save_reg_address); i++)
+		gtr_dev->saved_regs[i] = xpsgtr_read(gtr_dev,
+						     save_reg_address[i]);
+}
+
+/**
+ * xpsgtr_restore_lane_regs - Restores registers on resume
+ * @gtr_dev: pointer to phy controller context structure
+ */
+static void xpsgtr_restore_lane_regs(struct xpsgtr_dev *gtr_dev)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(save_reg_address); i++)
+		xpsgtr_write(gtr_dev, save_reg_address[i],
+			     gtr_dev->saved_regs[i]);
+}
+
 /*
  * Hardware Configuration
  */
@@ -839,6 +885,8 @@ static int xpsgtr_runtime_suspend(struct device *dev)
 	gtr_dev->saved_icm_cfg0 = xpsgtr_read(gtr_dev, ICM_CFG0);
 	gtr_dev->saved_icm_cfg1 = xpsgtr_read(gtr_dev, ICM_CFG1);
 
+	xpsgtr_save_lane_regs(gtr_dev);
+
 	return 0;
 }
 
@@ -849,6 +897,8 @@ static int xpsgtr_runtime_resume(struct device *dev)
 	unsigned int i;
 	bool skip_phy_init;
 
+	xpsgtr_restore_lane_regs(gtr_dev);
+
 	icm_cfg0 = xpsgtr_read(gtr_dev, ICM_CFG0);
 	icm_cfg1 = xpsgtr_read(gtr_dev, ICM_CFG1);
 
@@ -994,6 +1044,12 @@ static int xpsgtr_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	gtr_dev->saved_regs = devm_kmalloc(gtr_dev->dev,
+					   sizeof(save_reg_address),
+					   GFP_KERNEL);
+	if (!gtr_dev->saved_regs)
+		return -ENOMEM;
+
 	return 0;
 }
 
Signature · 1 line
2.43.0
author maintainer
#89 lore raw

PATCH 85/149 dmaengine: dw: Add peripheral bus width verification

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Serge Semin <[email protected]>

[ Upstream commit b336268dde75cb09bd795cb24893d52152a9191f ]

Currently the src_addr_width and dst_addr_width fields of the dma_slave_config structure are mapped to the CTLx.SRC_TR_WIDTH and CTLx.DST_TR_WIDTH fields of the peripheral bus side in order to have the properly aligned data passed to the target device. It's done just by converting the passed peripheral bus width to the encoded value using the __ffs() function. This implementation has several problematic sides:

1. __ffs() is undefined if no bit exist in the passed value. Thus if the specified addr-width is DMA_SLAVE_BUSWIDTH_UNDEFINED, __ffs() may return unexpected value depending on the platform-specific implementation.

2. DW AHB DMA-engine permits having the power-of-2 transfer width limited by the DMAH_Mk_HDATA_WIDTH IP-core synthesize parameter. Specifying bus-width out of that constraints scope will definitely cause unexpected result since the destination reg will be only partly touched than the client driver implied.

Let's fix all of that by adding the peripheral bus width verification method and calling it in dwc_config() which is supposed to be executed before preparing any transfer. The new method will make sure that the passed source or destination address width is valid and if undefined then the driver will just fallback to the 1-byte width transfer.

---
 drivers/dma/dw/core.c | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)
drivers/dma/dw/core.c +38 -0
index 5f7d690e3dbae..11e269a31a092 100644
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/log2.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -780,10 +781,43 @@ bool dw_dma_filter(struct dma_chan *chan, void *param)
 }
 EXPORT_SYMBOL_GPL(dw_dma_filter);
 
+static int dwc_verify_p_buswidth(struct dma_chan *chan)
+{
+	struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+	struct dw_dma *dw = to_dw_dma(chan->device);
+	u32 reg_width, max_width;
+
+	if (dwc->dma_sconfig.direction == DMA_MEM_TO_DEV)
+		reg_width = dwc->dma_sconfig.dst_addr_width;
+	else if (dwc->dma_sconfig.direction == DMA_DEV_TO_MEM)
+		reg_width = dwc->dma_sconfig.src_addr_width;
+	else /* DMA_MEM_TO_MEM */
+		return 0;
+
+	max_width = dw->pdata->data_width[dwc->dws.p_master];
+
+	/* Fall-back to 1-byte transfer width if undefined */
+	if (reg_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
+		reg_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	else if (!is_power_of_2(reg_width) || reg_width > max_width)
+		return -EINVAL;
+	else /* bus width is valid */
+		return 0;
+
+	/* Update undefined addr width value */
+	if (dwc->dma_sconfig.direction == DMA_MEM_TO_DEV)
+		dwc->dma_sconfig.dst_addr_width = reg_width;
+	else /* DMA_DEV_TO_MEM */
+		dwc->dma_sconfig.src_addr_width = reg_width;
+
+	return 0;
+}
+
 static int dwc_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
 {
 	struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
 	struct dw_dma *dw = to_dw_dma(chan->device);
+	int ret;
 
 	memcpy(&dwc->dma_sconfig, sconfig, sizeof(*sconfig));
 
@@ -792,6 +826,10 @@ static int dwc_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
 	dwc->dma_sconfig.dst_maxburst =
 		clamp(dwc->dma_sconfig.dst_maxburst, 0U, dwc->max_burst);
 
+	ret = dwc_verify_p_buswidth(chan);
+	if (ret)
+		return ret;
+
 	dw->encode_maxburst(dwc, &dwc->dma_sconfig.src_maxburst);
 	dw->encode_maxburst(dwc, &dwc->dma_sconfig.dst_maxburst);
 
Signature · 1 line
2.43.0
author maintainer
#90 lore raw

PATCH 86/149 dmaengine: dw: Add memory bus width verification

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Serge Semin <[email protected]>

[ Upstream commit d04b21bfa1c50a2ade4816cab6fdc91827b346b1 ]

Currently in case of the DEV_TO_MEM or MEM_TO_DEV DMA transfers the memory data width (single transfer width) is determined based on the buffer length, buffer base address or DMA master-channel max address width capability. It isn't enough in case of the channel disabling prior the block transfer is finished. Here is what DW AHB DMA IP-core databook says regarding the port suspension (DMA-transfer pause) implementation in the controller:

"When CTLx.SRC_TR_WIDTH < CTLx.DST_TR_WIDTH and the CFGx.CH_SUSP bit is high, the CFGx.FIFO_EMPTY is asserted once the contents of the FIFO do not permit a single word of CTLx.DST_TR_WIDTH to be formed. However, there may still be data in the channel FIFO, but not enough to form a single transfer of CTLx.DST_TR_WIDTH. In this scenario, once the channel is disabled, the remaining data in the channel FIFO is not transferred to the destination peripheral."

So in case if the port gets to be suspended and then disabled it's possible to have the data silently discarded even though the controller reported that FIFO is empty and the CTLx.BLOCK_TS indicated the dropped data already received from the source device. This looks as if the data somehow got lost on a way from the peripheral device to memory and causes problems for instance in the DW APB UART driver, which pauses and disables the DMA-transfer as soon as the recv data timeout happens. Here is the way it looks:

Memory <------- DMA FIFO <------ UART FIFO <---------------- UART

  DST_TR_WIDTH -+--------|       |         |
                |        |       |         |                No more data
   Current lvl -+--------|       |---------+- DMA-burst lvl
                |        |       |---------+- Leftover data
                |        |       |---------+- SRC_TR_WIDTH
               -+--------+-------+---------+

In the example above: no more data is getting received over the UART port and BLOCK_TS is not even close to be fully received; some data is left in the UART FIFO, but not enough to perform a bursted DMA-xfer to the DMA FIFO; some data is left in the DMA FIFO, but not enough to be passed further to the system memory in a single transfer. In this situation the 8250 UART driver catches the recv timeout interrupt, pauses the DMA-transfer and terminates it completely, after which the IRQ handler manually fetches the leftover data from the UART FIFO into the recv-buffer. But since the DMA-channel has been disabled with the data left in the DMA FIFO, that data will be just discarded and the recv-buffer will have a gap of the "current lvl" size in the recv-buffer at the tail of the lately received data portion. So the data will be lost just due to the misconfigured DMA transfer.

Note this is only relevant for the case of the transfer suspension and _disabling_. No problem will happen if the transfer will be re-enabled afterwards or the block transfer is fully completed. In the later case the "FIFO flush mode" will be executed at the transfer final stage in order to push out the data left in the DMA FIFO.

In order to fix the denoted problem the DW AHB DMA-engine driver needs to make sure that the _bursted_ source transfer width is greater or equal to the single destination transfer (note the HW databook describes more strict constraint than actually required). Since the peripheral-device side is prescribed by the client driver logic, the memory-side can be only used for that. The solution can be easily implemented for the DEV_TO_MEM transfers just by adjusting the memory-channel address width. Sadly it's not that easy for the MEM_TO_DEV transfers since the mem-to-dma burst size is normally dynamically determined by the controller. So the only thing that can be done is to make sure that memory-side address width is greater than the peripheral device address width.

Fixes a09820043c9e ("dw_dmac: autoconfigure data_width or get it via platform data")
---
 drivers/dma/dw/core.c | 51 +++++++++++++++++++++++++++++++++++++------
 1 file changed, 44 insertions(+), 7 deletions(-)
drivers/dma/dw/core.c +44 -7
index 11e269a31a092..b341a6f1b0438 100644
@@ -622,12 +622,10 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 	struct dw_desc		*prev;
 	struct dw_desc		*first;
 	u32			ctllo, ctlhi;
-	u8			m_master = dwc->dws.m_master;
-	u8			lms = DWC_LLP_LMS(m_master);
+	u8			lms = DWC_LLP_LMS(dwc->dws.m_master);
 	dma_addr_t		reg;
 	unsigned int		reg_width;
 	unsigned int		mem_width;
-	unsigned int		data_width = dw->pdata->data_width[m_master];
 	unsigned int		i;
 	struct scatterlist	*sg;
 	size_t			total_len = 0;
@@ -661,7 +659,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 			mem = sg_dma_address(sg);
 			len = sg_dma_len(sg);
 
-			mem_width = __ffs(data_width | mem | len);
+			mem_width = __ffs(sconfig->src_addr_width | mem | len);
 
 slave_sg_todev_fill_desc:
 			desc = dwc_desc_get(dwc);
@@ -721,7 +719,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 			lli_write(desc, sar, reg);
 			lli_write(desc, dar, mem);
 			lli_write(desc, ctlhi, ctlhi);
-			mem_width = __ffs(data_width | mem);
+			mem_width = __ffs(sconfig->dst_addr_width | mem);
 			lli_write(desc, ctllo, ctllo | DWC_CTLL_DST_WIDTH(mem_width));
 			desc->len = dlen;
 
@@ -813,6 +811,41 @@ static int dwc_verify_p_buswidth(struct dma_chan *chan)
 	return 0;
 }
 
+static int dwc_verify_m_buswidth(struct dma_chan *chan)
+{
+	struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+	struct dw_dma *dw = to_dw_dma(chan->device);
+	u32 reg_width, reg_burst, mem_width;
+
+	mem_width = dw->pdata->data_width[dwc->dws.m_master];
+
+	/*
+	 * It's possible to have a data portion locked in the DMA FIFO in case
+	 * of the channel suspension. Subsequent channel disabling will cause
+	 * that data silent loss. In order to prevent that maintain the src and
+	 * dst transfer widths coherency by means of the relation:
+	 * (CTLx.SRC_TR_WIDTH * CTLx.SRC_MSIZE >= CTLx.DST_TR_WIDTH)
+	 * Look for the details in the commit message that brings this change.
+	 *
+	 * Note the DMA configs utilized in the calculations below must have
+	 * been verified to have correct values by this method call.
+	 */
+	if (dwc->dma_sconfig.direction == DMA_MEM_TO_DEV) {
+		reg_width = dwc->dma_sconfig.dst_addr_width;
+		if (mem_width < reg_width)
+			return -EINVAL;
+
+		dwc->dma_sconfig.src_addr_width = mem_width;
+	} else if (dwc->dma_sconfig.direction == DMA_DEV_TO_MEM) {
+		reg_width = dwc->dma_sconfig.src_addr_width;
+		reg_burst = rounddown_pow_of_two(dwc->dma_sconfig.src_maxburst);
+
+		dwc->dma_sconfig.dst_addr_width = min(mem_width, reg_width * reg_burst);
+	}
+
+	return 0;
+}
+
 static int dwc_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
 {
 	struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
@@ -822,14 +855,18 @@ static int dwc_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
 	memcpy(&dwc->dma_sconfig, sconfig, sizeof(*sconfig));
 
 	dwc->dma_sconfig.src_maxburst =
-		clamp(dwc->dma_sconfig.src_maxburst, 0U, dwc->max_burst);
+		clamp(dwc->dma_sconfig.src_maxburst, 1U, dwc->max_burst);
 	dwc->dma_sconfig.dst_maxburst =
-		clamp(dwc->dma_sconfig.dst_maxburst, 0U, dwc->max_burst);
+		clamp(dwc->dma_sconfig.dst_maxburst, 1U, dwc->max_burst);
 
 	ret = dwc_verify_p_buswidth(chan);
 	if (ret)
 		return ret;
 
+	ret = dwc_verify_m_buswidth(chan);
+	if (ret)
+		return ret;
+
 	dw->encode_maxburst(dwc, &dwc->dma_sconfig.src_maxburst);
 	dw->encode_maxburst(dwc, &dwc->dma_sconfig.dst_maxburst);
 
Signature · 1 line
2.43.0
author maintainer
#91 lore raw

PATCH 87/149 dmaengine: ti: omap-dma: Initialize sglen after allocation

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Kees Cook <[email protected]>

[ Upstream commit 5e5c793c7fc47219998465361d94510fdf55d83f ]

With the new __counted_by annocation, the "sglen" struct member must be set before accessing the "sg" array. This initialization was done in other places where a new struct omap_desc is allocated, but these cases were missed. Set "sglen" after allocation.

Fixes b85178611c11 ("dmaengine: ti: omap-dma: Annotate struct omap_desc with __counted_by")
---
 drivers/dma/ti/omap-dma.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/dma/ti/omap-dma.c +3 -3
index b9e0e22383b72..984fbec2c4bae 100644
@@ -1186,10 +1186,10 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
 	d->dev_addr = dev_addr;
 	d->fi = burst;
 	d->es = es;
+	d->sglen = 1;
 	d->sg[0].addr = buf_addr;
 	d->sg[0].en = period_len / es_bytes[es];
 	d->sg[0].fn = buf_len / period_len;
-	d->sglen = 1;
 
 	d->ccr = c->ccr;
 	if (dir == DMA_DEV_TO_MEM)
@@ -1258,10 +1258,10 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_memcpy(
 	d->dev_addr = src;
 	d->fi = 0;
 	d->es = data_type;
+	d->sglen = 1;
 	d->sg[0].en = len / BIT(data_type);
 	d->sg[0].fn = 1;
 	d->sg[0].addr = dest;
-	d->sglen = 1;
 	d->ccr = c->ccr;
 	d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_POSTINC;
 
@@ -1309,6 +1309,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_interleaved(
 	if (data_type > CSDP_DATA_TYPE_32)
 		data_type = CSDP_DATA_TYPE_32;
 
+	d->sglen = 1;
 	sg = &d->sg[0];
 	d->dir = DMA_MEM_TO_MEM;
 	d->dev_addr = xt->src_start;
@@ -1316,7 +1317,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_interleaved(
 	sg->en = xt->sgl[0].size / BIT(data_type);
 	sg->fn = xt->numf;
 	sg->addr = xt->dst_start;
-	d->sglen = 1;
 	d->ccr = c->ccr;
 
 	src_icg = dmaengine_get_src_icg(xt, &xt->sgl[0]);
Signature · 1 line
2.43.0
author maintainer
#92 lore raw

PATCH 88/149 pktgen: use cpus_read_lock() in pg_net_init()

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <[email protected]>

[ Upstream commit 979b581e4c69257acab1af415ddad6b2d78a2fa5 ]

I have seen the WARN_ON(smp_processor_id() != cpu) firing in pktgen_thread_worker() during tests.

We must use cpus_read_lock()/cpus_read_unlock() around the for_each_online_cpu(cpu) loop.

While we are at it use WARN_ON_ONCE() to avoid a possible syslog flood.

---
 net/core/pktgen.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
net/core/pktgen.c +3 -1
index ea55a758a475a..197a50ef8e2e1 100644
@@ -3654,7 +3654,7 @@ static int pktgen_thread_worker(void *arg)
 	struct pktgen_dev *pkt_dev = NULL;
 	int cpu = t->cpu;
 
-	WARN_ON(smp_processor_id() != cpu);
+	WARN_ON_ONCE(smp_processor_id() != cpu);
 
 	init_waitqueue_head(&t->queue);
 	complete(&t->start_done);
@@ -3989,6 +3989,7 @@ static int __net_init pg_net_init(struct net *net)
 		goto remove;
 	}
 
+	cpus_read_lock();
 	for_each_online_cpu(cpu) {
 		int err;
 
@@ -3997,6 +3998,7 @@ static int __net_init pg_net_init(struct net *net)
 			pr_warn("Cannot create thread for cpu %d (%d)\n",
 				   cpu, err);
 	}
+	cpus_read_unlock();
 
 	if (list_empty(&pn->pktgen_threads)) {
 		pr_err("Initialization failed for all threads\n");
Signature · 1 line
2.43.0
author maintainer
#93 lore raw

PATCH 89/149 cpufreq/amd-pstate-ut: Dont check for highest perf matching on prefcore

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Mario Limonciello <[email protected]>

[ Upstream commit 9983a9cd4d429dc9ca01770083c4c1f366214b65 ]

If a system is using preferred cores the highest perf will be inconsistent as it can change from system events.

Skip the checks for it.

Fixes e571a5e2068e ("cpufreq: amd-pstate: Update amd-pstate preferred core ranking dynamically")
---
 drivers/cpufreq/amd-pstate-ut.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/cpufreq/amd-pstate-ut.c +8 -5
index 66b73c308ce67..b7318669485e4 100644
@@ -160,14 +160,17 @@ static void amd_pstate_ut_check_perf(u32 index)
 			lowest_perf = AMD_CPPC_LOWEST_PERF(cap1);
 		}
 
-		if ((highest_perf != READ_ONCE(cpudata->highest_perf)) ||
-			(nominal_perf != READ_ONCE(cpudata->nominal_perf)) ||
+		if (highest_perf != READ_ONCE(cpudata->highest_perf) && !cpudata->hw_prefcore) {
+			pr_err("%s cpu%d highest=%d %d highest perf doesn't match\n",
+				__func__, cpu, highest_perf, cpudata->highest_perf);
+			goto skip_test;
+		}
+		if ((nominal_perf != READ_ONCE(cpudata->nominal_perf)) ||
 			(lowest_nonlinear_perf != READ_ONCE(cpudata->lowest_nonlinear_perf)) ||
 			(lowest_perf != READ_ONCE(cpudata->lowest_perf))) {
 			amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL;
-			pr_err("%s cpu%d highest=%d %d nominal=%d %d lowest_nonlinear=%d %d lowest=%d %d, they should be equal!\n",
-				__func__, cpu, highest_perf, cpudata->highest_perf,
-				nominal_perf, cpudata->nominal_perf,
+			pr_err("%s cpu%d nominal=%d %d lowest_nonlinear=%d %d lowest=%d %d, they should be equal!\n",
+				__func__, cpu, nominal_perf, cpudata->nominal_perf,
 				lowest_nonlinear_perf, cpudata->lowest_nonlinear_perf,
 				lowest_perf, cpudata->lowest_perf);
 			goto skip_test;
Signature · 1 line
2.43.0
author maintainer
#94 lore raw

PATCH 90/149 Bluetooth: btnxpuart: Handle FW Download Abort scenario

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Neeraj Sanjay Kale <[email protected]>

[ Upstream commit e3c4891098c875a63ab0c3b31d584f6d4f1895fd ]

This adds a new flag BTNXPUART_FW_DOWNLOAD_ABORT which handles the situation where driver is removed while firmware download is in progress.

logs:
modprobe btnxpuart

[65239.230431] Bluetooth: hci0: ChipID: 7601, Version: 0
[65239.236670] Bluetooth: hci0: Request Firmware: nxp/uartspi_n61x_v1.bin.se
rmmod btnxpuart
[65241.425300] Bluetooth: hci0: FW Download Aborted

Stable-dep-of: 35237475384a ("Bluetooth: btnxpuart: Fix random crash seen while removing driver")

---
 drivers/bluetooth/btnxpuart.c | 47 ++++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 14 deletions(-)
drivers/bluetooth/btnxpuart.c +33 -14
index d310b525fbf00..1bb97747c4836 100644
@@ -29,6 +29,7 @@
 #define BTNXPUART_CHECK_BOOT_SIGNATURE	3
 #define BTNXPUART_SERDEV_OPEN		4
 #define BTNXPUART_IR_IN_PROGRESS	5
+#define BTNXPUART_FW_DOWNLOAD_ABORT	6
 
 /* NXP HW err codes */
 #define BTNXPUART_IR_HW_ERR		0xb0
@@ -159,6 +160,7 @@ struct btnxpuart_dev {
 	u8 fw_name[MAX_FW_FILE_NAME_LEN];
 	u32 fw_dnld_v1_offset;
 	u32 fw_v1_sent_bytes;
+	u32 fw_dnld_v3_offset;
 	u32 fw_v3_offset_correction;
 	u32 fw_v1_expected_len;
 	u32 boot_reg_offset;
@@ -566,6 +568,7 @@ static int nxp_download_firmware(struct hci_dev *hdev)
 	nxpdev->fw_v1_sent_bytes = 0;
 	nxpdev->fw_v1_expected_len = HDR_LEN;
 	nxpdev->boot_reg_offset = 0;
+	nxpdev->fw_dnld_v3_offset = 0;
 	nxpdev->fw_v3_offset_correction = 0;
 	nxpdev->baudrate_changed = false;
 	nxpdev->timeout_changed = false;
@@ -580,14 +583,23 @@ static int nxp_download_firmware(struct hci_dev *hdev)
 					       !test_bit(BTNXPUART_FW_DOWNLOADING,
 							 &nxpdev->tx_state),
 					       msecs_to_jiffies(60000));
+
+	release_firmware(nxpdev->fw);
+	memset(nxpdev->fw_name, 0, sizeof(nxpdev->fw_name));
+
 	if (err == 0) {
-		bt_dev_err(hdev, "FW Download Timeout.");
+		bt_dev_err(hdev, "FW Download Timeout. offset: %d",
+				nxpdev->fw_dnld_v1_offset ?
+				nxpdev->fw_dnld_v1_offset :
+				nxpdev->fw_dnld_v3_offset);
 		return -ETIMEDOUT;
 	}
+	if (test_bit(BTNXPUART_FW_DOWNLOAD_ABORT, &nxpdev->tx_state)) {
+		bt_dev_err(hdev, "FW Download Aborted");
+		return -EINTR;
+	}
 
 	serdev_device_set_flow_control(nxpdev->serdev, true);
-	release_firmware(nxpdev->fw);
-	memset(nxpdev->fw_name, 0, sizeof(nxpdev->fw_name));
 
 	/* Allow the downloaded FW to initialize */
 	msleep(1200);
@@ -998,8 +1010,9 @@ static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
 		goto free_skb;
 	}
 
-	serdev_device_write_buf(nxpdev->serdev, nxpdev->fw->data + offset -
-				nxpdev->fw_v3_offset_correction, len);
+	nxpdev->fw_dnld_v3_offset = offset - nxpdev->fw_v3_offset_correction;
+	serdev_device_write_buf(nxpdev->serdev, nxpdev->fw->data +
+				nxpdev->fw_dnld_v3_offset, len);
 
 free_skb:
 	kfree_skb(skb);
@@ -1429,16 +1442,22 @@ static void nxp_serdev_remove(struct serdev_device *serdev)
 	struct btnxpuart_dev *nxpdev = serdev_device_get_drvdata(serdev);
 	struct hci_dev *hdev = nxpdev->hdev;
 
-	/* Restore FW baudrate to fw_init_baudrate if changed.
-	 * This will ensure FW baudrate is in sync with
-	 * driver baudrate in case this driver is re-inserted.
-	 */
-	if (nxpdev->current_baudrate != nxpdev->fw_init_baudrate) {
-		nxpdev->new_baudrate = nxpdev->fw_init_baudrate;
-		nxp_set_baudrate_cmd(hdev, NULL);
+	if (is_fw_downloading(nxpdev)) {
+		set_bit(BTNXPUART_FW_DOWNLOAD_ABORT, &nxpdev->tx_state);
+		clear_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
+		wake_up_interruptible(&nxpdev->check_boot_sign_wait_q);
+		wake_up_interruptible(&nxpdev->fw_dnld_done_wait_q);
+	} else {
+		/* Restore FW baudrate to fw_init_baudrate if changed.
+		 * This will ensure FW baudrate is in sync with
+		 * driver baudrate in case this driver is re-inserted.
+		 */
+		if (nxpdev->current_baudrate != nxpdev->fw_init_baudrate) {
+			nxpdev->new_baudrate = nxpdev->fw_init_baudrate;
+			nxp_set_baudrate_cmd(hdev, NULL);
+		}
+		ps_cancel_timer(nxpdev);
 	}
-
-	ps_cancel_timer(nxpdev);
 	hci_unregister_dev(hdev);
 	hci_free_dev(hdev);
 }
Signature · 1 line
2.43.0
author maintainer
#95 lore raw

PATCH 91/149 Bluetooth: btnxpuart: Fix random crash seen while removing driver

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Neeraj Sanjay Kale <[email protected]>

[ Upstream commit 35237475384ab3622f63c3c09bdf6af6dacfe9c3 ]

This fixes the random kernel crash seen while removing the driver, when running the load/unload test over multiple iterations.

1) modprobe btnxpuart
2) hciconfig hci0 reset
3) hciconfig (check hci0 interface up with valid BD address)
4) modprobe -r btnxpuart
Repeat steps 1 to 4

The ps_wakeup() call in btnxpuart_close() schedules the psdata->work(), which gets scheduled after module is removed, causing a kernel crash.

This hidden issue got highlighted after enabling Power Save by default in 4183a7be7700 (Bluetooth: btnxpuart: Enable Power Save feature on startup)

The new ps_cleanup() deasserts UART break immediately while closing serdev device, cancels any scheduled ps_work and destroys the ps_lock mutex.

[   85.884604] Unable to handle kernel paging request at virtual address ffffd4a61638f258
[   85.884624] Mem abort info:
[   85.884625]   ESR = 0x0000000086000007
[   85.884628]   EC = 0x21: IABT (current EL), IL = 32 bits
[   85.884633]   SET = 0, FnV = 0
[   85.884636]   EA = 0, S1PTW = 0
[   85.884638]   FSC = 0x07: level 3 translation fault
[   85.884642] swapper pgtable: 4k pages, 48-bit VAs, pgdp=0000000041dd0000
[   85.884646] [ffffd4a61638f258] pgd=1000000095fff003, p4d=1000000095fff003, pud=100000004823d003, pmd=100000004823e003, pte=0000000000000000
[   85.884662] Internal error: Oops: 0000000086000007 [#1] PREEMPT SMP
[   85.890932] Modules linked in: algif_hash algif_skcipher af_alg overlay fsl_jr_uio caam_jr caamkeyblob_desc caamhash_desc caamalg_desc crypto_engine authenc libdes crct10dif_ce polyval_ce polyval_generic snd_soc_imx_spdif snd_soc_imx_card snd_soc_ak5558 snd_soc_ak4458 caam secvio error snd_soc_fsl_spdif snd_soc_fsl_micfil snd_soc_fsl_sai snd_soc_fsl_utils gpio_ir_recv rc_core fuse [last unloaded: btnxpuart(O)]
[   85.927297] CPU: 1 PID: 67 Comm: kworker/1:3 Tainted: G           O       6.1.36+g937b1be4345a #1
[   85.936176] Hardware name: FSL i.MX8MM EVK board (DT)
[   85.936182] Workqueue: events 0xffffd4a61638f380
[   85.936198] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[   85.952817] pc : 0xffffd4a61638f258
[   85.952823] lr : 0xffffd4a61638f258
[   85.952827] sp : ffff8000084fbd70
[   85.952829] x29: ffff8000084fbd70 x28: 0000000000000000 x27: 0000000000000000
[   85.963112] x26: ffffd4a69133f000 x25: ffff4bf1c8540990 x24: ffff4bf215b87305
[   85.963119] x23: ffff4bf215b87300 x22: ffff4bf1c85409d0 x21: ffff4bf1c8540970
[   85.977382] x20: 0000000000000000 x19: ffff4bf1c8540880 x18: 0000000000000000
[   85.977391] x17: 0000000000000000 x16: 0000000000000133 x15: 0000ffffe2217090
[   85.977399] x14: 0000000000000001 x13: 0000000000000133 x12: 0000000000000139
[   85.977407] x11: 0000000000000001 x10: 0000000000000a60 x9 : ffff8000084fbc50
[   85.977417] x8 : ffff4bf215b7d000 x7 : ffff4bf215b83b40 x6 : 00000000000003e8
[   85.977424] x5 : 00000000410fd030 x4 : 0000000000000000 x3 : 0000000000000000
[   85.977432] x2 : 0000000000000000 x1 : ffff4bf1c4265880 x0 : 0000000000000000
[   85.977443] Call trace:
[   85.977446]  0xffffd4a61638f258
[   85.977451]  0xffffd4a61638f3e8
[   85.977455]  process_one_work+0x1d4/0x330
[   85.977464]  worker_thread+0x6c/0x430
[   85.977471]  kthread+0x108/0x10c
[   85.977476]  ret_from_fork+0x10/0x20
[   85.977488] Code: bad PC value
[   85.977491] ---[ end trace 0000000000000000 ]---

Preset since v6.9.11

Fixes 86d55f124b52 ("Bluetooth: btnxpuart: Deasset UART break before closing serdev device")
---
 drivers/bluetooth/btnxpuart.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)
drivers/bluetooth/btnxpuart.c +18 -2
index 1bb97747c4836..eeba2d26d1cb9 100644
@@ -438,6 +438,23 @@ static bool ps_wakeup(struct btnxpuart_dev *nxpdev)
 	return false;
 }
 
+static void ps_cleanup(struct btnxpuart_dev *nxpdev)
+{
+	struct ps_data *psdata = &nxpdev->psdata;
+	u8 ps_state;
+
+	mutex_lock(&psdata->ps_lock);
+	ps_state = psdata->ps_state;
+	mutex_unlock(&psdata->ps_lock);
+
+	if (ps_state != PS_STATE_AWAKE)
+		ps_control(psdata->hdev, PS_STATE_AWAKE);
+
+	ps_cancel_timer(nxpdev);
+	cancel_work_sync(&psdata->work);
+	mutex_destroy(&psdata->ps_lock);
+}
+
 static int send_ps_cmd(struct hci_dev *hdev, void *data)
 {
 	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
@@ -1307,7 +1324,6 @@ static int btnxpuart_close(struct hci_dev *hdev)
 {
 	struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
 
-	ps_wakeup(nxpdev);
 	serdev_device_close(nxpdev->serdev);
 	skb_queue_purge(&nxpdev->txq);
 	kfree_skb(nxpdev->rx_skb);
@@ -1456,8 +1472,8 @@ static void nxp_serdev_remove(struct serdev_device *serdev)
 			nxpdev->new_baudrate = nxpdev->fw_init_baudrate;
 			nxp_set_baudrate_cmd(hdev, NULL);
 		}
-		ps_cancel_timer(nxpdev);
 	}
+	ps_cleanup(nxpdev);
 	hci_unregister_dev(hdev);
 	hci_free_dev(hdev);
 }
Signature · 1 line
2.43.0
author maintainer
#96 lore raw

PATCH 92/149 Bluetooth: hci_core: Fix not handling hibernation actions

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Luiz Augusto von Dentz <[email protected]>

[ Upstream commit 18b3256db76bd1130965acd99fbd38f87c3e6950 ]

This fixes not handling hibernation actions on suspend notifier so they are treated in the same way as regular suspend actions.

Fixes 9952d90ea288 ("Bluetooth: Handle PM_SUSPEND_PREPARE and PM_POST_SUSPEND")
---
 net/bluetooth/hci_core.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
net/bluetooth/hci_core.c +8 -2
index b488d0742c966..9493966cf389f 100644
@@ -2431,10 +2431,16 @@ static int hci_suspend_notifier(struct notifier_block *nb, unsigned long action,
 	/* To avoid a potential race with hci_unregister_dev. */
 	hci_dev_hold(hdev);
 
-	if (action == PM_SUSPEND_PREPARE)
+	switch (action) {
+	case PM_HIBERNATION_PREPARE:
+	case PM_SUSPEND_PREPARE:
 		ret = hci_suspend_dev(hdev);
-	else if (action == PM_POST_SUSPEND)
+		break;
+	case PM_POST_HIBERNATION:
+	case PM_POST_SUSPEND:
 		ret = hci_resume_dev(hdev);
+		break;
+	}
 
 	if (ret)
 		bt_dev_err(hdev, "Suspend notifier action (%lu) failed: %d",
Signature · 1 line
2.43.0
author maintainer
#97 lore raw

PATCH 93/149 iommu: Do not return 0 from map_pages if it doesnt do anything

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jason Gunthorpe <[email protected]>

[ Upstream commit 6093cd582f8e027117a8d4ad5d129a1aacdc53d2 ]

These three implementations of map_pages() all succeed if a mapping is requested with no read or write. Since they return back to __iommu_map() leaving the mapped output as 0 it triggers an infinite loop. Therefore nothing is using no-access protection bits.

Further, VFIO and iommufd rely on iommu_iova_to_phys() to get back PFNs stored by map, if iommu_map() succeeds but iommu_iova_to_phys() fails that will create serious bugs.

Thus remove this never used "nothing to do" concept and just fail map immediately.

Fixes e5fc9753b1a8 ("iommu/io-pgtable: Add ARMv7 short descriptor support")
Fixes e1d3c0fd701d ("iommu: add ARM LPAE page table allocator")
Fixes 745ef1092bcf ("iommu/io-pgtable: Move Apple DART support to its own file")
---
 drivers/iommu/io-pgtable-arm-v7s.c | 3 +--
 drivers/iommu/io-pgtable-arm.c     | 3 +--
 drivers/iommu/io-pgtable-dart.c    | 3 +--
 3 files changed, 3 insertions(+), 6 deletions(-)
drivers/iommu/io-pgtable-arm-v7s.c +1 -2
index 75f244a3e12df..06ffc683b28fe 100644
@@ -552,9 +552,8 @@ static int arm_v7s_map_pages(struct io_pgtable_ops *ops, unsigned long iova,
 		    paddr >= (1ULL << data->iop.cfg.oas)))
 		return -ERANGE;
 
-	/* If no access, then nothing to do */
 	if (!(prot & (IOMMU_READ | IOMMU_WRITE)))
-		return 0;
+		return -EINVAL;
 
 	while (pgcount--) {
 		ret = __arm_v7s_map(data, iova, paddr, pgsize, prot, 1, data->pgd,
drivers/iommu/io-pgtable-arm.c +1 -2
index 3d23b924cec16..07c9b90eab2ed 100644
@@ -495,9 +495,8 @@ static int arm_lpae_map_pages(struct io_pgtable_ops *ops, unsigned long iova,
 	if (WARN_ON(iaext || paddr >> cfg->oas))
 		return -ERANGE;
 
-	/* If no access, then nothing to do */
 	if (!(iommu_prot & (IOMMU_READ | IOMMU_WRITE)))
-		return 0;
+		return -EINVAL;
 
 	prot = arm_lpae_prot_to_pte(data, iommu_prot);
 	ret = __arm_lpae_map(data, iova, paddr, pgsize, pgcount, prot, lvl,
drivers/iommu/io-pgtable-dart.c +1 -2
index ad28031e1e93d..c004640640ee5 100644
@@ -245,9 +245,8 @@ static int dart_map_pages(struct io_pgtable_ops *ops, unsigned long iova,
 	if (WARN_ON(paddr >> cfg->oas))
 		return -ERANGE;
 
-	/* If no access, then nothing to do */
 	if (!(iommu_prot & (IOMMU_READ | IOMMU_WRITE)))
-		return 0;
+		return -EINVAL;
 
 	tbl = dart_get_table(data, iova);
 
Signature · 1 line
2.43.0
author maintainer
#98 lore raw

PATCH 94/149 netfilter: nf_tables: restore IP sanity checks for netdev/egress

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Pablo Neira Ayuso <[email protected]>

[ Upstream commit 5fd0628918977a0afdc2e6bc562d8751b5d3b8c5 ]

Subtract network offset to skb->len before performing IPv4 header sanity checks, then adjust transport offset from offset from mac header.

Jorge Ortiz says:

When small UDP packets (< 4 bytes payload) are sent from eth0, meta l4proto udp condition is not met because NFT_PKTINFO_L4PROTO is not set. This happens because there is a comparison that checks if the transport header offset exceeds the total length. This comparison does not take into account the fact that the skb network offset might be non-zero in egress mode (e.g., 14 bytes for Ethernet header).

Fixes 0ae8e4cca787 ("netfilter: nf_tables: set transport offset from mac header for netdev/egress")
---
 include/net/netfilter/nf_tables_ipv4.h | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)
include/net/netfilter/nf_tables_ipv4.h +6 -4
index 60a7d0ce30804..fcf967286e37c 100644
@@ -19,7 +19,7 @@ static inline void nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt)
 static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt)
 {
 	struct iphdr *iph, _iph;
-	u32 len, thoff;
+	u32 len, thoff, skb_len;
 
 	iph = skb_header_pointer(pkt->skb, skb_network_offset(pkt->skb),
 				 sizeof(*iph), &_iph);
@@ -30,8 +30,10 @@ static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt)
 		return -1;
 
 	len = iph_totlen(pkt->skb, iph);
-	thoff = skb_network_offset(pkt->skb) + (iph->ihl * 4);
-	if (pkt->skb->len < len)
+	thoff = iph->ihl * 4;
+	skb_len = pkt->skb->len - skb_network_offset(pkt->skb);
+
+	if (skb_len < len)
 		return -1;
 	else if (len < thoff)
 		return -1;
@@ -40,7 +42,7 @@ static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt)
 
 	pkt->flags = NFT_PKTINFO_L4PROTO;
 	pkt->tprot = iph->protocol;
-	pkt->thoff = thoff;
+	pkt->thoff = skb_network_offset(pkt->skb) + thoff;
 	pkt->fragoff = ntohs(iph->frag_off) & IP_OFFSET;
 
 	return 0;
Signature · 1 line
2.43.0
author maintainer
#99 lore raw

PATCH 95/149 wifi: iwlwifi: mvm: take the mutex before running link selection

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Emmanuel Grumbach <[email protected]>

[ Upstream commit cd6f46c2fdb82e80ca248549c1f3ebe08b4a63ab ]

iwl_mvm_select_links is called by the link selection worker and it requires the mutex.
Take it in the link selection worker.
This logic used to run from iwl_mvm_rx_umac_scan_complete_notif which had the mvm->mutex held. This was changed to run in a worker holding the wiphy mutex, but we also need the mvm->mutex.

---
 drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/net/wireless/intel/iwlwifi/mvm/ops.c +2 -0
index d343432474db0..1380ae5155f35 100644
@@ -1190,10 +1190,12 @@ static void iwl_mvm_trig_link_selection(struct wiphy *wiphy,
 	struct iwl_mvm *mvm =
 		container_of(wk, struct iwl_mvm, trig_link_selection_wk);
 
+	mutex_lock(&mvm->mutex);
 	ieee80211_iterate_active_interfaces(mvm->hw,
 					    IEEE80211_IFACE_ITER_NORMAL,
 					    iwl_mvm_find_link_selection_vif,
 					    NULL);
+	mutex_unlock(&mvm->mutex);
 }
 
 static struct iwl_op_mode *
Signature · 1 line
2.43.0
author maintainer
#100 lore raw

PATCH 96/149 wifi: iwlwifi: fw: fix wgds rev 3 exact size

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Anjaneyulu <[email protected]>

[ Upstream commit 3ee22f07a35b76939c5b8d17d6af292f5fafb509 ]

Check size of WGDS revision 3 is equal to 8 entries size with some header, but doesn't depend on the number of used entries. Check that used entries are between min and max but allow more to be present than are used to fix operation with some BIOSes that have such data.

---
 drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/net/wireless/intel/iwlwifi/fw/acpi.c +8 -5
index fa339791223b8..ba9e656037a20 100644
@@ -724,22 +724,25 @@ int iwl_acpi_get_wgds_table(struct iwl_fw_runtime *fwrt)
 				entry = &wifi_pkg->package.elements[entry_idx];
 				entry_idx++;
 				if (entry->type != ACPI_TYPE_INTEGER ||
-				    entry->integer.value > num_profiles) {
+				    entry->integer.value > num_profiles ||
+				    entry->integer.value <
+					rev_data[idx].min_profiles) {
 					ret = -EINVAL;
 					goto out_free;
 				}
-				num_profiles = entry->integer.value;
 
 				/*
-				 * this also validates >= min_profiles since we
-				 * otherwise wouldn't have gotten the data when
-				 * looking up in ACPI
+				 * Check to see if we received package count
+				 * same as max # of profiles
 				 */
 				if (wifi_pkg->package.count !=
 				    hdr_size + profile_size * num_profiles) {
 					ret = -EINVAL;
 					goto out_free;
 				}
+
+				/* Number of valid profiles */
+				num_profiles = entry->integer.value;
 			}
 			goto read_table;
 		}
Signature · 1 line
2.43.0
author maintainer
#101 lore raw

PATCH 97/149 wifi: iwlwifi: mvm: allow 6 GHz channels in MLO scan

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Avraham Stern <[email protected]>

[ Upstream commit 454f6306a31248cf972f5f16d4c145ad5b33bfdc ]

MLO internal scan may include 6 GHz channels. Since the 6 GHz scan indication is not set, the channel flags are set incorrectly, which leads to a firmware assert.
Since the MLO scan may include 6 GHz and non 6 GHz channels in one request, add support for non-PSC 6 GHz channels (PSC channels are already supported) when the 6 GHz indication is not set.

---
 drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 11 +++++++++++
 1 file changed, 11 insertions(+)
drivers/net/wireless/intel/iwlwifi/mvm/scan.c +11 -0
index e975f5ff17b5d..7615c91a55c62 100644
@@ -1659,6 +1659,17 @@ iwl_mvm_umac_scan_cfg_channels_v7(struct iwl_mvm *mvm,
 		cfg->v2.channel_num = channels[i]->hw_value;
 		if (cfg80211_channel_is_psc(channels[i]))
 			cfg->flags = 0;
+
+		if (band == NL80211_BAND_6GHZ) {
+			/* 6 GHz channels should only appear in a scan request
+			 * that has scan_6ghz set. The only exception is MLO
+			 * scan, which has to be passive.
+			 */
+			WARN_ON_ONCE(cfg->flags != 0);
+			cfg->flags =
+				cpu_to_le32(IWL_UHB_CHAN_CFG_FLAG_FORCE_PASSIVE);
+		}
+
 		cfg->v2.iter_count = 1;
 		cfg->v2.iter_interval = 0;
 		if (version < 17)
Signature · 1 line
2.43.0
author maintainer
#102 lore raw

PATCH 98/149 ethtool: check device is present when getting link settings

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jamie Bainbridge <[email protected]>

[ Upstream commit a699781c79ecf6cfe67fb00a0331b4088c7c8466 ]

A sysfs reader can race with a device reset or removal, attempting to read device state when the device is not actually present. eg:

[exception RIP: qed_get_current_link+17]
#8 [ffffb9e4f2907c48] qede_get_link_ksettings at ffffffffc07a994a [qede] #9 [ffffb9e4f2907cd8] __rh_call_get_link_ksettings at ffffffff992b01a3
#10 [ffffb9e4f2907d38] __ethtool_get_link_ksettings at ffffffff992b04e4 #11 [ffffb9e4f2907d90] duplex_show at ffffffff99260300
#12 [ffffb9e4f2907e38] dev_attr_show at ffffffff9905a01c
#13 [ffffb9e4f2907e50] sysfs_kf_seq_show at ffffffff98e0145b #14 [ffffb9e4f2907e68] seq_read at ffffffff98d902e3
#15 [ffffb9e4f2907ec8] vfs_read at ffffffff98d657d1
#16 [ffffb9e4f2907f00] ksys_read at ffffffff98d65c3f
#17 [ffffb9e4f2907f38] do_syscall_64 at ffffffff98a052fb

crash> struct net_device.state ffff9a9d21336000

    state = 5,

state 5 is __LINK_STATE_START (0b1) and __LINK_STATE_NOCARRIER (0b100). The device is not present, note lack of __LINK_STATE_PRESENT (0b10).

This is the same sort of panic as observed in commit 4224cfd7fb65 ("net-sysfs: add check for netdevice being present to speed_show").

There are many other callers of __ethtool_get_link_ksettings() which don't have a device presence check.

Move this check into ethtool to protect all callers.

Fixes d519e17e2d01 ("net: export device speed and duplex via sysfs")
Fixes 4224cfd7fb65 ("net-sysfs: add check for netdevice being present to speed_show")
---
 net/core/net-sysfs.c | 2 +-
 net/ethtool/ioctl.c  | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)
net/core/net-sysfs.c +1 -1
index 4c27a360c2948..dc91921da4ea0 100644
@@ -235,7 +235,7 @@ static ssize_t speed_show(struct device *dev,
 	if (!rtnl_trylock())
 		return restart_syscall();
 
-	if (netif_running(netdev) && netif_device_present(netdev)) {
+	if (netif_running(netdev)) {
 		struct ethtool_link_ksettings cmd;
 
 		if (!__ethtool_get_link_ksettings(netdev, &cmd))
net/ethtool/ioctl.c +3 -0
index fcc3dbef8b503..f99fd564d0ee5 100644
@@ -441,6 +441,9 @@ int __ethtool_get_link_ksettings(struct net_device *dev,
 	if (!dev->ethtool_ops->get_link_ksettings)
 		return -EOPNOTSUPP;
 
+	if (!netif_device_present(dev))
+		return -ENODEV;
+
 	memset(link_ksettings, 0, sizeof(*link_ksettings));
 	return dev->ethtool_ops->get_link_ksettings(dev, link_ksettings);
 }
Signature · 1 line
2.43.0
author maintainer
#103 lore raw

PATCH 99/149 hwmon: (pt5161l) Fix invalid temperature reading

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Cosmo Chou <[email protected]>

[ Upstream commit 7bbc079531fc38d401e1c4088d4981435a8828e3 ]

The temperature reading function was using a signed long for the ADC code, which could lead to mishandling of invalid codes on 32-bit platforms. This allowed out-of-range ADC codes to be incorrectly interpreted as valid values and used in temperature calculations.

Change adc_code to u32 to ensure that invalid ADC codes are correctly identified on all platforms.

Fixes 1b2ca93cd059 ("hwmon: Add driver for Astera Labs PT5161L retimer")

Message-ID: <[email protected]>

---
 drivers/hwmon/pt5161l.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/hwmon/pt5161l.c +2 -2
index b0d58a26d499d..a9f0b23f9e76e 100644
@@ -427,7 +427,7 @@ static int pt5161l_read(struct device *dev, enum hwmon_sensor_types type,
 	struct pt5161l_data *data = dev_get_drvdata(dev);
 	int ret;
 	u8 buf[8];
-	long adc_code;
+	u32 adc_code;
 
 	switch (attr) {
 	case hwmon_temp_input:
@@ -449,7 +449,7 @@ static int pt5161l_read(struct device *dev, enum hwmon_sensor_types type,
 
 		adc_code = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0];
 		if (adc_code == 0 || adc_code >= 0x3ff) {
-			dev_dbg(dev, "Invalid adc_code %lx\n", adc_code);
+			dev_dbg(dev, "Invalid adc_code %x\n", adc_code);
 			return -EIO;
 		}
 
Signature · 1 line
2.43.0
author maintainer
#104 lore raw

PATCH 100/149 net_sched: sch_fq: fix incorrect behavior for small weights

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <[email protected]>

[ Upstream commit bc21000e99f92a6b5540d7267c6b22806c5c33d3 ]

fq_dequeue() has a complex logic to find packets in one of the 3 bands.

As Neal found out, it is possible that one band has a deficit smaller than its weight. fq_dequeue() can return NULL while some packets are elligible for immediate transmit.

In this case, more than one iteration is needed to refill pband->credit.

With default parameters (weights 589824 196608 65536) bug can trigger if large BIG TCP packets are sent to the lowest priority band.

---
 net/sched/sch_fq.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
net/sched/sch_fq.c +3 -1
index 2389747256793..19a49af5a9e52 100644
@@ -663,7 +663,9 @@ static struct sk_buff *fq_dequeue(struct Qdisc *sch)
 			pband = &q->band_flows[q->band_nr];
 			pband->credit = min(pband->credit + pband->quantum,
 					    pband->quantum);
-			goto begin;
+			if (pband->credit > 0)
+				goto begin;
+			retry = 0;
 		}
 		if (q->time_next_delayed_flow != ~0ULL)
 			qdisc_watchdog_schedule_range_ns(&q->watchdog,
Signature · 1 line
2.43.0
author maintainer
#105 lore raw

PATCH 101/149 netfilter: nf_tables_ipv6: consider network offset in netdev/egress validation

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Pablo Neira Ayuso <[email protected]>

[ Upstream commit 70c261d500951cf3ea0fcf32651aab9a65a91471 ]

Quoted 1 line

From netdev/egress, skb->len can include the ethernet header, therefore,

subtract network offset from skb->len when validating IPv6 packet length.

Fixes 42df6e1d221d ("netfilter: Introduce egress hook")
---
 include/net/netfilter/nf_tables_ipv6.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
include/net/netfilter/nf_tables_ipv6.h +3 -2
index 467d59b9e5334..a0633eeaec977 100644
@@ -31,8 +31,8 @@ static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt)
 	struct ipv6hdr *ip6h, _ip6h;
 	unsigned int thoff = 0;
 	unsigned short frag_off;
+	u32 pkt_len, skb_len;
 	int protohdr;
-	u32 pkt_len;
 
 	ip6h = skb_header_pointer(pkt->skb, skb_network_offset(pkt->skb),
 				  sizeof(*ip6h), &_ip6h);
@@ -43,7 +43,8 @@ static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt)
 		return -1;
 
 	pkt_len = ntohs(ip6h->payload_len);
-	if (pkt_len + sizeof(*ip6h) > pkt->skb->len)
+	skb_len = pkt->skb->len - skb_network_offset(pkt->skb);
+	if (pkt_len + sizeof(*ip6h) > skb_len)
 		return -1;
 
 	protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
Signature · 1 line
2.43.0
author maintainer
#106 lore raw

PATCH 102/149 selftests: forwarding: no_forwarding: Down ports on cleanup

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Petr Machata <[email protected]>

[ Upstream commit e8497d6951ee8541d73784f9aac9942a7f239980 ]

This test neglects to put ports down on cleanup. Fix it.

---
 tools/testing/selftests/net/forwarding/no_forwarding.sh | 3 +++
 1 file changed, 3 insertions(+)
tools/testing/selftests/net/forwarding/no_forwarding.sh +3 -0
index af3b398d13f01..9e677aa64a06a 100755
@@ -233,6 +233,9 @@ cleanup()
 {
 	pre_cleanup
 
+	ip link set dev $swp2 down
+	ip link set dev $swp1 down
+
 	h2_destroy
 	h1_destroy
 
Signature · 1 line
2.43.0
author maintainer
#107 lore raw

PATCH 103/149 selftests: forwarding: local_termination: Down ports on cleanup

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Petr Machata <[email protected]>

[ Upstream commit 65a3cce43d5b4c53cf16b0be1a03991f665a0806 ]

This test neglects to put ports down on cleanup. Fix it.

---
 tools/testing/selftests/net/forwarding/local_termination.sh | 4 ++++
 1 file changed, 4 insertions(+)
tools/testing/selftests/net/forwarding/local_termination.sh +4 -0
index 4b364cdf3ef0c..656b1a82d1dca 100755
@@ -284,6 +284,10 @@ bridge()
 cleanup()
 {
 	pre_cleanup
+
+	ip link set $h2 down
+	ip link set $h1 down
+
 	vrf_cleanup
 }
 
Signature · 1 line
2.43.0
author maintainer
#108 lore raw

PATCH 104/149 bonding: implement xdo_dev_state_free and call it after deletion

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jianbo Liu <[email protected]>

[ Upstream commit ec13009472f4a756288eb4e18e20a7845da98d10 ]

Add this implementation for bonding, so hardware resources can be freed from the active slave after xfrm state is deleted. The netdev used to invoke xdo_dev_state_free callback, is saved in the xfrm state (xs->xso.real_dev), which is also the bond's active slave. To prevent it from being freed, acquire netdev reference before leaving RCU read-side critical section, and release it after callback is done.

And call it when deleting all SAs from old active real interface while switching current active slave.

---
 drivers/net/bonding/bond_main.c | 36 +++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)
drivers/net/bonding/bond_main.c +36 -0
index b257504a85347..232e592389638 100644
@@ -581,12 +581,47 @@ static void bond_ipsec_del_sa_all(struct bonding *bond)
 				   __func__);
 		} else {
 			slave->dev->xfrmdev_ops->xdo_dev_state_delete(ipsec->xs);
+			if (slave->dev->xfrmdev_ops->xdo_dev_state_free)
+				slave->dev->xfrmdev_ops->xdo_dev_state_free(ipsec->xs);
 		}
 	}
 	spin_unlock_bh(&bond->ipsec_lock);
 	rcu_read_unlock();
 }
 
+static void bond_ipsec_free_sa(struct xfrm_state *xs)
+{
+	struct net_device *bond_dev = xs->xso.dev;
+	struct net_device *real_dev;
+	netdevice_tracker tracker;
+	struct bonding *bond;
+	struct slave *slave;
+
+	if (!bond_dev)
+		return;
+
+	rcu_read_lock();
+	bond = netdev_priv(bond_dev);
+	slave = rcu_dereference(bond->curr_active_slave);
+	real_dev = slave ? slave->dev : NULL;
+	netdev_hold(real_dev, &tracker, GFP_ATOMIC);
+	rcu_read_unlock();
+
+	if (!slave)
+		goto out;
+
+	if (!xs->xso.real_dev)
+		goto out;
+
+	WARN_ON(xs->xso.real_dev != real_dev);
+
+	if (real_dev && real_dev->xfrmdev_ops &&
+	    real_dev->xfrmdev_ops->xdo_dev_state_free)
+		real_dev->xfrmdev_ops->xdo_dev_state_free(xs);
+out:
+	netdev_put(real_dev, &tracker);
+}
+
 /**
  * bond_ipsec_offload_ok - can this packet use the xfrm hw offload
  * @skb: current data packet
@@ -627,6 +662,7 @@ static bool bond_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs)
 static const struct xfrmdev_ops bond_xfrmdev_ops = {
 	.xdo_dev_state_add = bond_ipsec_add_sa,
 	.xdo_dev_state_delete = bond_ipsec_del_sa,
+	.xdo_dev_state_free = bond_ipsec_free_sa,
 	.xdo_dev_offload_ok = bond_ipsec_offload_ok,
 };
 #endif /* CONFIG_XFRM_OFFLOAD */
Signature · 1 line
2.43.0
author maintainer
#109 lore raw

PATCH 105/149 bonding: extract the use of real_device into local variable

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jianbo Liu <[email protected]>

[ Upstream commit 907ed83a7583e8ffede88c5ac088392701a7d458 ]

Add a local variable for slave->dev, to prepare for the lock change in the next patch. There is no functionality change.

---
 drivers/net/bonding/bond_main.c | 58 +++++++++++++++++++--------------
 1 file changed, 33 insertions(+), 25 deletions(-)
drivers/net/bonding/bond_main.c +33 -25
index 232e592389638..e6416bbaf1bf6 100644
@@ -427,6 +427,7 @@ static int bond_ipsec_add_sa(struct xfrm_state *xs,
 			     struct netlink_ext_ack *extack)
 {
 	struct net_device *bond_dev = xs->xso.dev;
+	struct net_device *real_dev;
 	struct bond_ipsec *ipsec;
 	struct bonding *bond;
 	struct slave *slave;
@@ -443,9 +444,10 @@ static int bond_ipsec_add_sa(struct xfrm_state *xs,
 		return -ENODEV;
 	}
 
-	if (!slave->dev->xfrmdev_ops ||
-	    !slave->dev->xfrmdev_ops->xdo_dev_state_add ||
-	    netif_is_bond_master(slave->dev)) {
+	real_dev = slave->dev;
+	if (!real_dev->xfrmdev_ops ||
+	    !real_dev->xfrmdev_ops->xdo_dev_state_add ||
+	    netif_is_bond_master(real_dev)) {
 		NL_SET_ERR_MSG_MOD(extack, "Slave does not support ipsec offload");
 		rcu_read_unlock();
 		return -EINVAL;
@@ -456,9 +458,9 @@ static int bond_ipsec_add_sa(struct xfrm_state *xs,
 		rcu_read_unlock();
 		return -ENOMEM;
 	}
-	xs->xso.real_dev = slave->dev;
 
-	err = slave->dev->xfrmdev_ops->xdo_dev_state_add(xs, extack);
+	xs->xso.real_dev = real_dev;
+	err = real_dev->xfrmdev_ops->xdo_dev_state_add(xs, extack);
 	if (!err) {
 		ipsec->xs = xs;
 		INIT_LIST_HEAD(&ipsec->list);
@@ -475,6 +477,7 @@ static int bond_ipsec_add_sa(struct xfrm_state *xs,
 static void bond_ipsec_add_sa_all(struct bonding *bond)
 {
 	struct net_device *bond_dev = bond->dev;
+	struct net_device *real_dev;
 	struct bond_ipsec *ipsec;
 	struct slave *slave;
 
@@ -483,12 +486,13 @@ static void bond_ipsec_add_sa_all(struct bonding *bond)
 	if (!slave)
 		goto out;
 
-	if (!slave->dev->xfrmdev_ops ||
-	    !slave->dev->xfrmdev_ops->xdo_dev_state_add ||
-	    netif_is_bond_master(slave->dev)) {
+	real_dev = slave->dev;
+	if (!real_dev->xfrmdev_ops ||
+	    !real_dev->xfrmdev_ops->xdo_dev_state_add ||
+	    netif_is_bond_master(real_dev)) {
 		spin_lock_bh(&bond->ipsec_lock);
 		if (!list_empty(&bond->ipsec_list))
-			slave_warn(bond_dev, slave->dev,
+			slave_warn(bond_dev, real_dev,
 				   "%s: no slave xdo_dev_state_add\n",
 				   __func__);
 		spin_unlock_bh(&bond->ipsec_lock);
@@ -497,9 +501,9 @@ static void bond_ipsec_add_sa_all(struct bonding *bond)
 
 	spin_lock_bh(&bond->ipsec_lock);
 	list_for_each_entry(ipsec, &bond->ipsec_list, list) {
-		ipsec->xs->xso.real_dev = slave->dev;
-		if (slave->dev->xfrmdev_ops->xdo_dev_state_add(ipsec->xs, NULL)) {
-			slave_warn(bond_dev, slave->dev, "%s: failed to add SA\n", __func__);
+		ipsec->xs->xso.real_dev = real_dev;
+		if (real_dev->xfrmdev_ops->xdo_dev_state_add(ipsec->xs, NULL)) {
+			slave_warn(bond_dev, real_dev, "%s: failed to add SA\n", __func__);
 			ipsec->xs->xso.real_dev = NULL;
 		}
 	}
@@ -515,6 +519,7 @@ static void bond_ipsec_add_sa_all(struct bonding *bond)
 static void bond_ipsec_del_sa(struct xfrm_state *xs)
 {
 	struct net_device *bond_dev = xs->xso.dev;
+	struct net_device *real_dev;
 	struct bond_ipsec *ipsec;
 	struct bonding *bond;
 	struct slave *slave;
@@ -532,16 +537,17 @@ static void bond_ipsec_del_sa(struct xfrm_state *xs)
 	if (!xs->xso.real_dev)
 		goto out;
 
-	WARN_ON(xs->xso.real_dev != slave->dev);
+	real_dev = slave->dev;
+	WARN_ON(xs->xso.real_dev != real_dev);
 
-	if (!slave->dev->xfrmdev_ops ||
-	    !slave->dev->xfrmdev_ops->xdo_dev_state_delete ||
-	    netif_is_bond_master(slave->dev)) {
-		slave_warn(bond_dev, slave->dev, "%s: no slave xdo_dev_state_delete\n", __func__);
+	if (!real_dev->xfrmdev_ops ||
+	    !real_dev->xfrmdev_ops->xdo_dev_state_delete ||
+	    netif_is_bond_master(real_dev)) {
+		slave_warn(bond_dev, real_dev, "%s: no slave xdo_dev_state_delete\n", __func__);
 		goto out;
 	}
 
-	slave->dev->xfrmdev_ops->xdo_dev_state_delete(xs);
+	real_dev->xfrmdev_ops->xdo_dev_state_delete(xs);
 out:
 	spin_lock_bh(&bond->ipsec_lock);
 	list_for_each_entry(ipsec, &bond->ipsec_list, list) {
@@ -558,6 +564,7 @@ static void bond_ipsec_del_sa(struct xfrm_state *xs)
 static void bond_ipsec_del_sa_all(struct bonding *bond)
 {
 	struct net_device *bond_dev = bond->dev;
+	struct net_device *real_dev;
 	struct bond_ipsec *ipsec;
 	struct slave *slave;
 
@@ -568,21 +575,22 @@ static void bond_ipsec_del_sa_all(struct bonding *bond)
 		return;
 	}
 
+	real_dev = slave->dev;
 	spin_lock_bh(&bond->ipsec_lock);
 	list_for_each_entry(ipsec, &bond->ipsec_list, list) {
 		if (!ipsec->xs->xso.real_dev)
 			continue;
 
-		if (!slave->dev->xfrmdev_ops ||
-		    !slave->dev->xfrmdev_ops->xdo_dev_state_delete ||
-		    netif_is_bond_master(slave->dev)) {
-			slave_warn(bond_dev, slave->dev,
+		if (!real_dev->xfrmdev_ops ||
+		    !real_dev->xfrmdev_ops->xdo_dev_state_delete ||
+		    netif_is_bond_master(real_dev)) {
+			slave_warn(bond_dev, real_dev,
 				   "%s: no slave xdo_dev_state_delete\n",
 				   __func__);
 		} else {
-			slave->dev->xfrmdev_ops->xdo_dev_state_delete(ipsec->xs);
-			if (slave->dev->xfrmdev_ops->xdo_dev_state_free)
-				slave->dev->xfrmdev_ops->xdo_dev_state_free(ipsec->xs);
+			real_dev->xfrmdev_ops->xdo_dev_state_delete(ipsec->xs);
+			if (real_dev->xfrmdev_ops->xdo_dev_state_free)
+				real_dev->xfrmdev_ops->xdo_dev_state_free(ipsec->xs);
 		}
 	}
 	spin_unlock_bh(&bond->ipsec_lock);
Signature · 1 line
2.43.0
author maintainer
#110 lore raw

PATCH 106/149 bonding: change ipsec_lock from spin lock to mutex

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jianbo Liu <[email protected]>

[ Upstream commit 2aeeef906d5a526dc60cf4af92eda69836c39b1f ]

In the cited commit, bond->ipsec_lock is added to protect ipsec_list, hence xdo_dev_state_add and xdo_dev_state_delete are called inside this lock. As ipsec_lock is a spin lock and such xfrmdev ops may sleep, "scheduling while atomic" will be triggered when changing bond's active slave.

[  101.055189] BUG: scheduling while atomic: bash/902/0x00000200
[  101.055726] Modules linked in:
[  101.058211] CPU: 3 PID: 902 Comm: bash Not tainted 6.9.0-rc4+ #1
[  101.058760] Hardware name:
[  101.059434] Call Trace:
[  101.059436]  <TASK>
[  101.060873]  dump_stack_lvl+0x51/0x60
[  101.061275]  __schedule_bug+0x4e/0x60
[  101.061682]  __schedule+0x612/0x7c0
[  101.062078]  ? __mod_timer+0x25c/0x370
[  101.062486]  schedule+0x25/0xd0
[  101.062845]  schedule_timeout+0x77/0xf0
[  101.063265]  ? asm_common_interrupt+0x22/0x40
[  101.063724]  ? __bpf_trace_itimer_state+0x10/0x10
[  101.064215]  __wait_for_common+0x87/0x190
[  101.064648]  ? usleep_range_state+0x90/0x90
[  101.065091]  cmd_exec+0x437/0xb20 [mlx5_core]
[  101.065569]  mlx5_cmd_do+0x1e/0x40 [mlx5_core]
[  101.066051]  mlx5_cmd_exec+0x18/0x30 [mlx5_core]
[  101.066552]  mlx5_crypto_create_dek_key+0xea/0x120 [mlx5_core]
[  101.067163]  ? bonding_sysfs_store_option+0x4d/0x80 [bonding]
[  101.067738]  ? kmalloc_trace+0x4d/0x350
[  101.068156]  mlx5_ipsec_create_sa_ctx+0x33/0x100 [mlx5_core]
[  101.068747]  mlx5e_xfrm_add_state+0x47b/0xaa0 [mlx5_core]
[  101.069312]  bond_change_active_slave+0x392/0x900 [bonding]
[  101.069868]  bond_option_active_slave_set+0x1c2/0x240 [bonding]
[  101.070454]  __bond_opt_set+0xa6/0x430 [bonding]
[  101.070935]  __bond_opt_set_notify+0x2f/0x90 [bonding]
[  101.071453]  bond_opt_tryset_rtnl+0x72/0xb0 [bonding]
[  101.071965]  bonding_sysfs_store_option+0x4d/0x80 [bonding]
[  101.072567]  kernfs_fop_write_iter+0x10c/0x1a0
[  101.073033]  vfs_write+0x2d8/0x400
[  101.073416]  ? alloc_fd+0x48/0x180
[  101.073798]  ksys_write+0x5f/0xe0
[  101.074175]  do_syscall_64+0x52/0x110
[  101.074576]  entry_SYSCALL_64_after_hwframe+0x4b/0x53

As bond_ipsec_add_sa_all and bond_ipsec_del_sa_all are only called from bond_change_active_slave, which requires holding the RTNL lock. And bond_ipsec_add_sa and bond_ipsec_del_sa are xfrm state xdo_dev_state_add and xdo_dev_state_delete APIs, which are in user context. So ipsec_lock doesn't have to be spin lock, change it to mutex, and thus the above issue can be resolved.

---
 drivers/net/bonding/bond_main.c | 79 ++++++++++++++++++---------------
 include/net/bonding.h           |  2 +-
 2 files changed, 44 insertions(+), 37 deletions(-)
drivers/net/bonding/bond_main.c +43 -36
index e6416bbaf1bf6..60db34095a255 100644
@@ -428,6 +428,7 @@ static int bond_ipsec_add_sa(struct xfrm_state *xs,
 {
 	struct net_device *bond_dev = xs->xso.dev;
 	struct net_device *real_dev;
+	netdevice_tracker tracker;
 	struct bond_ipsec *ipsec;
 	struct bonding *bond;
 	struct slave *slave;
@@ -439,24 +440,26 @@ static int bond_ipsec_add_sa(struct xfrm_state *xs,
 	rcu_read_lock();
 	bond = netdev_priv(bond_dev);
 	slave = rcu_dereference(bond->curr_active_slave);
-	if (!slave) {
-		rcu_read_unlock();
-		return -ENODEV;
+	real_dev = slave ? slave->dev : NULL;
+	netdev_hold(real_dev, &tracker, GFP_ATOMIC);
+	rcu_read_unlock();
+	if (!real_dev) {
+		err = -ENODEV;
+		goto out;
 	}
 
-	real_dev = slave->dev;
 	if (!real_dev->xfrmdev_ops ||
 	    !real_dev->xfrmdev_ops->xdo_dev_state_add ||
 	    netif_is_bond_master(real_dev)) {
 		NL_SET_ERR_MSG_MOD(extack, "Slave does not support ipsec offload");
-		rcu_read_unlock();
-		return -EINVAL;
+		err = -EINVAL;
+		goto out;
 	}
 
-	ipsec = kmalloc(sizeof(*ipsec), GFP_ATOMIC);
+	ipsec = kmalloc(sizeof(*ipsec), GFP_KERNEL);
 	if (!ipsec) {
-		rcu_read_unlock();
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto out;
 	}
 
 	xs->xso.real_dev = real_dev;
@@ -464,13 +467,14 @@ static int bond_ipsec_add_sa(struct xfrm_state *xs,
 	if (!err) {
 		ipsec->xs = xs;
 		INIT_LIST_HEAD(&ipsec->list);
-		spin_lock_bh(&bond->ipsec_lock);
+		mutex_lock(&bond->ipsec_lock);
 		list_add(&ipsec->list, &bond->ipsec_list);
-		spin_unlock_bh(&bond->ipsec_lock);
+		mutex_unlock(&bond->ipsec_lock);
 	} else {
 		kfree(ipsec);
 	}
-	rcu_read_unlock();
+out:
+	netdev_put(real_dev, &tracker);
 	return err;
 }
 
@@ -481,35 +485,35 @@ static void bond_ipsec_add_sa_all(struct bonding *bond)
 	struct bond_ipsec *ipsec;
 	struct slave *slave;
 
-	rcu_read_lock();
-	slave = rcu_dereference(bond->curr_active_slave);
-	if (!slave)
-		goto out;
+	slave = rtnl_dereference(bond->curr_active_slave);
+	real_dev = slave ? slave->dev : NULL;
+	if (!real_dev)
+		return;
 
-	real_dev = slave->dev;
+	mutex_lock(&bond->ipsec_lock);
 	if (!real_dev->xfrmdev_ops ||
 	    !real_dev->xfrmdev_ops->xdo_dev_state_add ||
 	    netif_is_bond_master(real_dev)) {
-		spin_lock_bh(&bond->ipsec_lock);
 		if (!list_empty(&bond->ipsec_list))
 			slave_warn(bond_dev, real_dev,
 				   "%s: no slave xdo_dev_state_add\n",
 				   __func__);
-		spin_unlock_bh(&bond->ipsec_lock);
 		goto out;
 	}
 
-	spin_lock_bh(&bond->ipsec_lock);
 	list_for_each_entry(ipsec, &bond->ipsec_list, list) {
+		/* If new state is added before ipsec_lock acquired */
+		if (ipsec->xs->xso.real_dev == real_dev)
+			continue;
+
 		ipsec->xs->xso.real_dev = real_dev;
 		if (real_dev->xfrmdev_ops->xdo_dev_state_add(ipsec->xs, NULL)) {
 			slave_warn(bond_dev, real_dev, "%s: failed to add SA\n", __func__);
 			ipsec->xs->xso.real_dev = NULL;
 		}
 	}
-	spin_unlock_bh(&bond->ipsec_lock);
 out:
-	rcu_read_unlock();
+	mutex_unlock(&bond->ipsec_lock);
 }
 
 /**
@@ -520,6 +524,7 @@ static void bond_ipsec_del_sa(struct xfrm_state *xs)
 {
 	struct net_device *bond_dev = xs->xso.dev;
 	struct net_device *real_dev;
+	netdevice_tracker tracker;
 	struct bond_ipsec *ipsec;
 	struct bonding *bond;
 	struct slave *slave;
@@ -530,6 +535,9 @@ static void bond_ipsec_del_sa(struct xfrm_state *xs)
 	rcu_read_lock();
 	bond = netdev_priv(bond_dev);
 	slave = rcu_dereference(bond->curr_active_slave);
+	real_dev = slave ? slave->dev : NULL;
+	netdev_hold(real_dev, &tracker, GFP_ATOMIC);
+	rcu_read_unlock();
 
 	if (!slave)
 		goto out;
@@ -537,7 +545,6 @@ static void bond_ipsec_del_sa(struct xfrm_state *xs)
 	if (!xs->xso.real_dev)
 		goto out;
 
-	real_dev = slave->dev;
 	WARN_ON(xs->xso.real_dev != real_dev);
 
 	if (!real_dev->xfrmdev_ops ||
@@ -549,7 +556,8 @@ static void bond_ipsec_del_sa(struct xfrm_state *xs)
 
 	real_dev->xfrmdev_ops->xdo_dev_state_delete(xs);
 out:
-	spin_lock_bh(&bond->ipsec_lock);
+	netdev_put(real_dev, &tracker);
+	mutex_lock(&bond->ipsec_lock);
 	list_for_each_entry(ipsec, &bond->ipsec_list, list) {
 		if (ipsec->xs == xs) {
 			list_del(&ipsec->list);
@@ -557,8 +565,7 @@ static void bond_ipsec_del_sa(struct xfrm_state *xs)
 			break;
 		}
 	}
-	spin_unlock_bh(&bond->ipsec_lock);
-	rcu_read_unlock();
+	mutex_unlock(&bond->ipsec_lock);
 }
 
 static void bond_ipsec_del_sa_all(struct bonding *bond)
@@ -568,15 +575,12 @@ static void bond_ipsec_del_sa_all(struct bonding *bond)
 	struct bond_ipsec *ipsec;
 	struct slave *slave;
 
-	rcu_read_lock();
-	slave = rcu_dereference(bond->curr_active_slave);
-	if (!slave) {
-		rcu_read_unlock();
+	slave = rtnl_dereference(bond->curr_active_slave);
+	real_dev = slave ? slave->dev : NULL;
+	if (!real_dev)
 		return;
-	}
 
-	real_dev = slave->dev;
-	spin_lock_bh(&bond->ipsec_lock);
+	mutex_lock(&bond->ipsec_lock);
 	list_for_each_entry(ipsec, &bond->ipsec_list, list) {
 		if (!ipsec->xs->xso.real_dev)
 			continue;
@@ -593,8 +597,7 @@ static void bond_ipsec_del_sa_all(struct bonding *bond)
 				real_dev->xfrmdev_ops->xdo_dev_state_free(ipsec->xs);
 		}
 	}
-	spin_unlock_bh(&bond->ipsec_lock);
-	rcu_read_unlock();
+	mutex_unlock(&bond->ipsec_lock);
 }
 
 static void bond_ipsec_free_sa(struct xfrm_state *xs)
@@ -5921,7 +5924,7 @@ void bond_setup(struct net_device *bond_dev)
 	/* set up xfrm device ops (only supported in active-backup right now) */
 	bond_dev->xfrmdev_ops = &bond_xfrmdev_ops;
 	INIT_LIST_HEAD(&bond->ipsec_list);
-	spin_lock_init(&bond->ipsec_lock);
+	mutex_init(&bond->ipsec_lock);
 #endif /* CONFIG_XFRM_OFFLOAD */
 
 	/* don't acquire bond device's netif_tx_lock when transmitting */
@@ -5970,6 +5973,10 @@ static void bond_uninit(struct net_device *bond_dev)
 		__bond_release_one(bond_dev, slave->dev, true, true);
 	netdev_info(bond_dev, "Released all slaves\n");
 
+#ifdef CONFIG_XFRM_OFFLOAD
+	mutex_destroy(&bond->ipsec_lock);
+#endif /* CONFIG_XFRM_OFFLOAD */
+
 	bond_set_slave_arr(bond, NULL, NULL);
 
 	list_del_rcu(&bond->bond_list);
include/net/bonding.h +1 -1
index b61fb1aa3a56b..8bb5f016969f1 100644
@@ -260,7 +260,7 @@ struct bonding {
 #ifdef CONFIG_XFRM_OFFLOAD
 	struct list_head ipsec_list;
 	/* protecting ipsec_list */
-	spinlock_t ipsec_lock;
+	struct mutex ipsec_lock;
 #endif /* CONFIG_XFRM_OFFLOAD */
 	struct bpf_prog *xdp_prog;
 };
Signature · 1 line
2.43.0
author maintainer
#111 lore raw

PATCH 107/149 gtp: fix a potential NULL pointer dereference

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Cong Wang <[email protected]>

[ Upstream commit defd8b3c37b0f9cb3e0f60f47d3d78d459d57fda ]

When sockfd_lookup() fails, gtp_encap_enable_socket() returns a NULL pointer, but its callers only check for error pointers thus miss the NULL pointer case.

Fix it by returning an error pointer with the error code carried from sockfd_lookup().

(I found this bug during code inspection.)

Fixes 1e3a3abd8b28 ("gtp: make GTP sockets in gtp_newlink optional")
Cc Andreas Schultz <[email protected]>
Cc Harald Welte <[email protected]>
---
 drivers/net/gtp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/gtp.c +1 -1
index 0696faf60013e..2e94d10348cce 100644
@@ -1653,7 +1653,7 @@ static struct sock *gtp_encap_enable_socket(int fd, int type,
 	sock = sockfd_lookup(fd, &err);
 	if (!sock) {
 		pr_debug("gtp socket fd=%d not found\n", fd);
-		return NULL;
+		return ERR_PTR(err);
 	}
 
 	sk = sock->sk;
Signature · 1 line
2.43.0
author maintainer
#112 lore raw

PATCH 108/149 tcp: fix forever orphan socket caused by tcp_abort

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Xueming Feng <[email protected]>

[ Upstream commit bac76cf89816bff06c4ec2f3df97dc34e150a1c4 ]

We have some problem closing zero-window fin-wait-1 tcp sockets in our environment. This patch come from the investigation.

Previously tcp_abort only sends out reset and calls tcp_done when the socket is not SOCK_DEAD, aka orphan. For orphan socket, it will only purging the write queue, but not close the socket and left it to the timer.

While purging the write queue, tp->packets_out and sk->sk_write_queue is cleared along the way. However tcp_retransmit_timer have early return based on !tp->packets_out and tcp_probe_timer have early return based on !sk->sk_write_queue.

This caused ICSK_TIME_RETRANS and ICSK_TIME_PROBE0 not being resched and socket not being killed by the timers, converting a zero-windowed orphan into a forever orphan.

This patch removes the SOCK_DEAD check in tcp_abort, making it send reset to peer and close the socket accordingly. Preventing the timer-less orphan from happening.

According to Lorenzo's email in the v1 thread, the check was there to prevent force-closing the same socket twice. That situation is handled by testing for TCP_CLOSE inside lock, and returning -ENOENT if it is already closed.

The -ENOENT code comes from the associate patch Lorenzo made for iproute2-ss; link attached below, which also conform to RFC 9293.

At the end of the patch, tcp_write_queue_purge(sk) is removed because it was already called in tcp_done_with_error().

p.s. This is the same patch with v2. Resent due to mis-labeled "changes requested" on patchwork.kernel.org.

---
 net/ipv4/tcp.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)
net/ipv4/tcp.c +11 -7
index ec6911034138f..2edbd5b181e29 100644
@@ -4573,6 +4573,13 @@ int tcp_abort(struct sock *sk, int err)
 		/* Don't race with userspace socket closes such as tcp_close. */
 		lock_sock(sk);
 
+	/* Avoid closing the same socket twice. */
+	if (sk->sk_state == TCP_CLOSE) {
+		if (!has_current_bpf_ctx())
+			release_sock(sk);
+		return -ENOENT;
+	}
+
 	if (sk->sk_state == TCP_LISTEN) {
 		tcp_set_state(sk, TCP_CLOSE);
 		inet_csk_listen_stop(sk);
@@ -4582,16 +4589,13 @@ int tcp_abort(struct sock *sk, int err)
 	local_bh_disable();
 	bh_lock_sock(sk);
 
-	if (!sock_flag(sk, SOCK_DEAD)) {
-		if (tcp_need_reset(sk->sk_state))
-			tcp_send_active_reset(sk, GFP_ATOMIC,
-					      SK_RST_REASON_NOT_SPECIFIED);
-		tcp_done_with_error(sk, err);
-	}
+	if (tcp_need_reset(sk->sk_state))
+		tcp_send_active_reset(sk, GFP_ATOMIC,
+				      SK_RST_REASON_NOT_SPECIFIED);
+	tcp_done_with_error(sk, err);
 
 	bh_unlock_sock(sk);
 	local_bh_enable();
-	tcp_write_queue_purge(sk);
 	if (!has_current_bpf_ctx())
 		release_sock(sk);
 	return 0;
Signature · 1 line
2.43.0
author maintainer
#113 lore raw

PATCH 109/149 sctp: fix association labeling in the duplicate COOKIE-ECHO case

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ondrej Mosnacek <[email protected]>

[ Upstream commit 3a0504d54b3b57f0d7bf3d9184a00c9f8887f6d7 ]

sctp_sf_do_5_2_4_dupcook() currently calls security_sctp_assoc_request() on new_asoc, but as it turns out, this association is always discarded and the LSM labels never get into the final association (asoc).

This can be reproduced by having two SCTP endpoints try to initiate an association with each other at approximately the same time and then peel off the association into a new socket, which exposes the unitialized labels and triggers SELinux denials.

Fix it by calling security_sctp_assoc_request() on asoc instead of new_asoc. Xin Long also suggested limit calling the hook only to cases A, B, and D, since in cases C and E the COOKIE ECHO chunk is discarded and the association doesn't enter the ESTABLISHED state, so rectify that as well.

One related caveat with SELinux and peer labeling: When an SCTP connection is set up simultaneously in this way, we will end up with an association that is initialized with security_sctp_assoc_request() on both sides, so the MLS component of the security context of the association will get swapped between the peers, instead of just one side setting it to the other's MLS component. However, at that point security_sctp_assoc_request() had already been called on both sides in sctp_sf_do_unexpected_init() (on a temporary association) and thus if the exchange didn't fail before due to MLS, it won't fail now either (most likely both endpoints have the same MLS range).

Tested by:
- reproducer from https://src.fedoraproject.org/tests/selinux/pull-request/530
- selinux-testsuite (https://github.com/SELinuxProject/selinux-testsuite/)
- sctp-tests (https://github.com/sctp/sctp-tests) - no tests failed that wouldn't fail also without the patch applied

---
 net/sctp/sm_statefuns.c | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)
net/sctp/sm_statefuns.c +16 -6
index 5adf0c0a6c1ac..7d315a18612ba 100644
@@ -2260,12 +2260,6 @@ enum sctp_disposition sctp_sf_do_5_2_4_dupcook(
 		}
 	}
 
-	/* Update socket peer label if first association. */
-	if (security_sctp_assoc_request(new_asoc, chunk->head_skb ?: chunk->skb)) {
-		sctp_association_free(new_asoc);
-		return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
-	}
-
 	/* Set temp so that it won't be added into hashtable */
 	new_asoc->temp = 1;
 
@@ -2274,6 +2268,22 @@ enum sctp_disposition sctp_sf_do_5_2_4_dupcook(
 	 */
 	action = sctp_tietags_compare(new_asoc, asoc);
 
+	/* In cases C and E the association doesn't enter the ESTABLISHED
+	 * state, so there is no need to call security_sctp_assoc_request().
+	 */
+	switch (action) {
+	case 'A': /* Association restart. */
+	case 'B': /* Collision case B. */
+	case 'D': /* Collision case D. */
+		/* Update socket peer label if first association. */
+		if (security_sctp_assoc_request((struct sctp_association *)asoc,
+						chunk->head_skb ?: chunk->skb)) {
+			sctp_association_free(new_asoc);
+			return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+		}
+		break;
+	}
+
 	switch (action) {
 	case 'A': /* Association restart. */
 		retval = sctp_sf_do_dupcook_a(net, ep, asoc, chunk, commands,
Signature · 1 line
2.43.0
author maintainer
#114 lore raw

PATCH 110/149 drm/amd/display: avoid using null object of framebuffer

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ma Ke <[email protected]>

[ Upstream commit 3b9a33235c773c7a3768060cf1d2cf8a9153bc37 ]

Instead of using state->fb->obj[0] directly, get object from framebuffer by calling drm_gem_fb_get_obj() and return error code when object is null to avoid using null object of framebuffer.

Fixes 5d945cbcd4b1 ("drm/amd/display: Create a file dedicated to planes")
(cherry picked from commit 73dd0ad9e5dad53766ea3e631303430116f834b3)
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +7 -2
index 311c62d2d1ebb..70e45d980bb93 100644
@@ -28,6 +28,7 @@
 #include <drm/drm_blend.h>
 #include <drm/drm_gem_atomic_helper.h>
 #include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_fourcc.h>
 
 #include "amdgpu.h"
@@ -854,10 +855,14 @@ static int amdgpu_dm_plane_helper_prepare_fb(struct drm_plane *plane,
 	}
 
 	afb = to_amdgpu_framebuffer(new_state->fb);
-	obj = new_state->fb->obj[0];
+	obj = drm_gem_fb_get_obj(new_state->fb, 0);
+	if (!obj) {
+		DRM_ERROR("Failed to get obj from framebuffer\n");
+		return -EINVAL;
+	}
+
 	rbo = gem_to_amdgpu_bo(obj);
 	adev = amdgpu_ttm_adev(rbo->tbo.bdev);
-
 	r = amdgpu_bo_reserve(rbo, true);
 	if (r) {
 		dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
Signature · 1 line
2.43.0
author maintainer
#115 lore raw

PATCH 111/149 net: busy-poll: use ktime_get_ns() instead of local_clock()

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <[email protected]>

[ Upstream commit 0870b0d8b393dde53106678a1e2cec9dfa52f9b7 ]

Typically, busy-polling durations are below 100 usec.

When/if the busy-poller thread migrates to another cpu, local_clock() can be off by +/-2msec or more for small values of HZ, depending on the platform.

Use ktimer_get_ns() to ensure deterministic behavior, which is the whole point of busy-polling.

Fixes 060212928670 ("net: add low latency socket poll")
Fixes 9a3c71aa8024 ("net: convert low latency sockets to sched_clock()")
Fixes 37089834528b ("sched, net: Fixup busy_loop_us_clock()")
Cc Mina Almasry <[email protected]>
Cc Willem de Bruijn <[email protected]>
---
 include/net/busy_poll.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
include/net/busy_poll.h +1 -1
index 9b09acac538ee..522f1da8b747a 100644
@@ -68,7 +68,7 @@ static inline bool sk_can_busy_loop(struct sock *sk)
 static inline unsigned long busy_loop_current_time(void)
 {
 #ifdef CONFIG_NET_RX_BUSY_POLL
-	return (unsigned long)(local_clock() >> 10);
+	return (unsigned long)(ktime_get_ns() >> 10);
 #else
 	return 0;
 #endif
Signature · 1 line
2.43.0
author maintainer
#116 lore raw

PATCH 112/149 nfc: pn533: Add poll mod list filling check

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Aleksandr Mishin <[email protected]>

[ Upstream commit febccb39255f9df35527b88c953b2e0deae50e53 ]

In case of im_protocols value is 1 and tm_protocols value is 0 this combination successfully passes the check
'if (!im_protocols && !tm_protocols)' in the nfc_start_poll(). But then after pn533_poll_create_mod_list() call in pn533_start_poll() poll mod list will remain empty and dev->poll_mod_count will remain 0 which lead to division by zero.

Normally no im protocol has value 1 in the mask, so this combination is not expected by driver. But these protocol values actually come from userspace via Netlink interface (NFC_CMD_START_POLL operation). So a broken or malicious program may pass a message containing a "bad" combination of protocol parameter values so that dev->poll_mod_count is not incremented inside pn533_poll_create_mod_list(), thus leading to division by zero.
Call trace looks like:
nfc_genl_start_poll()
nfc_start_poll()

    ->start_poll()
    pn533_start_poll()

Add poll mod list filling check.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

---
 drivers/nfc/pn533/pn533.c | 5 +++++
 1 file changed, 5 insertions(+)
drivers/nfc/pn533/pn533.c +5 -0
index b19c39dcfbd93..e2bc67300a915 100644
@@ -1723,6 +1723,11 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev,
 	}
 
 	pn533_poll_create_mod_list(dev, im_protocols, tm_protocols);
+	if (!dev->poll_mod_count) {
+		nfc_err(dev->dev,
+			"Poll mod list is empty\n");
+		return -EINVAL;
+	}
 
 	/* Do not always start polling from the same modulation */
 	get_random_bytes(&rand_mod, sizeof(rand_mod));
Signature · 1 line
2.43.0
author maintainer
#117 lore raw

PATCH 113/149 drm/xe/hwmon: Fix WRITE_I1 param from u32 to u16

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Karthik Poosa <[email protected]>

[ Upstream commit 59d237c8a241168c7ae34c48244059b7bafaff38 ]

WRITE_I1 sub-command of the POWER_SETUP pcode command accepts a u16 parameter instead of u32. This change prevents potential illegal sub-command errors.

v2: Mask uval instead of changing the prototype. (Badal)

v3: Rephrase commit message. (Badal)

Fixes 92d44a422d0d ("drm/xe/hwmon: Expose card reactive critical power")
(cherry picked from commit a7f657097e96d8fa745c74bb1a239ebd5a8c971c)
---
 drivers/gpu/drm/xe/xe_hwmon.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/xe/xe_hwmon.c +1 -1
index d37f1dea9f8b8..bb815dbde63a6 100644
@@ -443,7 +443,7 @@ static int xe_hwmon_pcode_write_i1(struct xe_gt *gt, u32 uval)
 {
 	return xe_pcode_write(gt, PCODE_MBOX(PCODE_POWER_SETUP,
 			      POWER_SETUP_SUBCOMMAND_WRITE_I1, 0),
-			      uval);
+			      (uval & POWER_SETUP_I1_DATA_MASK));
 }
 
 static int xe_hwmon_power_curr_crit_read(struct xe_hwmon *hwmon, int channel,
Signature · 1 line
2.43.0
author maintainer
#118 lore raw

PATCH 114/149 io_uring/kbuf: return correct iovec count from classic buffer peek

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jens Axboe <[email protected]>

[ Upstream commit f274495aea7b15225b3d83837121b22ef96e560c ]

io_provided_buffers_select() returns 0 to indicate success, but it should be returning 1 to indicate that 1 vec was mapped. This causes peeking to fail with classic provided buffers, and while that's not a use case that anyone should use, it should still work correctly.

The end result is that no buffer will be selected, and hence a completion with '0' as the result will be posted, without a buffer attached.

Fixes 35c8711c8fc4 ("io_uring/kbuf: add helpers for getting/peeking multiple buffers")
---
 io_uring/kbuf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
io_uring/kbuf.c +1 -1
index 1af2bd56af44a..bdfa30b38321b 100644
@@ -129,7 +129,7 @@ static int io_provided_buffers_select(struct io_kiocb *req, size_t *len,
 
 	iov[0].iov_base = buf;
 	iov[0].iov_len = *len;
-	return 0;
+	return 1;
 }
 
 static struct io_uring_buf *io_ring_head_to_buf(struct io_uring_buf_ring *br,
Signature · 1 line
2.43.0
author maintainer
#119 lore raw

PATCH 115/149 soc: qcom: cmd-db: Map shared memory as WC, not WB

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Volodymyr Babchuk <[email protected]>

commit f9bb896eab221618927ae6a2f1d566567999839d upstream.

Linux does not write into cmd-db region. This region of memory is write protected by XPU. XPU may sometime falsely detect clean cache eviction as "write" into the write protected region leading to secure interrupt which causes an endless loop somewhere in Trust Zone.

The only reason it is working right now is because Qualcomm Hypervisor maps the same region as Non-Cacheable memory in Stage 2 translation tables. The issue manifests if we want to use another hypervisor (like Xen or KVM), which does not know anything about those specific mappings.

Changing the mapping of cmd-db memory from MEMREMAP_WB to MEMREMAP_WT/WC removes dependency on correct mappings in Stage 2 tables. This patch fixes the issue by updating the mapping to MEMREMAP_WC.

I tested this on SA8155P with Xen.

---
 drivers/soc/qcom/cmd-db.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/soc/qcom/cmd-db.c +1 -1
@@ -349,7 +349,7 @@ static int cmd_db_dev_probe(struct platf
 		return -EINVAL;
 	}
 
-	cmd_db_header = memremap(rmem->base, rmem->size, MEMREMAP_WB);
+	cmd_db_header = memremap(rmem->base, rmem->size, MEMREMAP_WC);
 	if (!cmd_db_header) {
 		ret = -ENOMEM;
 		cmd_db_header = NULL;
author maintainer
#120 lore raw

PATCH 116/149 soc: qcom: pmic_glink: Actually communicate when remote goes down

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Bjorn Andersson <[email protected]>

commit ad51126037a43c05f5f4af5eb262734e3e88ca59 upstream.

When the pmic_glink state is UP and we either receive a protection- domain (PD) notification indicating that the PD is going down, or that the whole remoteproc is going down, it's expected that the pmic_glink client instances are notified that their function has gone DOWN.

This is not what the code does, which results in the client state either not updating, or being wrong in many cases. So let's fix the conditions.

---
 drivers/soc/qcom/pmic_glink.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/soc/qcom/pmic_glink.c +1 -1
@@ -175,7 +175,7 @@ static void pmic_glink_state_notify_clie
 		if (pg->pdr_state == SERVREG_SERVICE_STATE_UP && pg->ept)
 			new_state = SERVREG_SERVICE_STATE_UP;
 	} else {
-		if (pg->pdr_state == SERVREG_SERVICE_STATE_UP && pg->ept)
+		if (pg->pdr_state == SERVREG_SERVICE_STATE_DOWN || !pg->ept)
 			new_state = SERVREG_SERVICE_STATE_DOWN;
 	}
 
author maintainer
#121 lore raw

PATCH 117/149 soc: qcom: pmic_glink: Fix race during initialization

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Bjorn Andersson <[email protected]>

commit 3568affcddd68743e25aa3ec1647d9b82797757b upstream.

As pointed out by Stephen Boyd it is possible that during initialization of the pmic_glink child drivers, the protection-domain notifiers fires, and the associated work is scheduled, before the client registration returns and as a result the local "client" pointer has been initialized.

The outcome of this is a NULL pointer dereference as the "client" pointer is blindly dereferenced.

Timeline provided by Stephen:
CPU0 CPU1
---- ----
ucsi->client = NULL; devm_pmic_glink_register_client()
client->pdr_notify(client->priv, pg->client_state)
pmic_glink_ucsi_pdr_notify()

    schedule_work(&ucsi->register_work)
    <schedule away>
                                    pmic_glink_ucsi_register()
                                     ucsi_register()
                                      pmic_glink_ucsi_read_version()
                                       pmic_glink_ucsi_read()
                                        pmic_glink_ucsi_read()
                                         pmic_glink_send(ucsi->client)
                                         <client is NULL BAD>

ucsi->client = client // Too late!

This code is identical across the altmode, battery manager and usci child drivers.

Resolve this by splitting the allocation of the "client" object and the registration thereof into two operations.

This only happens if the protection domain registry is populated at the time of registration, which by the introduction of commit '1ebcde047c54 ("soc: qcom: add pd-mapper implementation")' became much more likely.

---
 drivers/power/supply/qcom_battmgr.c   |   16 ++++++++++------
 drivers/soc/qcom/pmic_glink.c         |   28 ++++++++++++++++++----------
 drivers/soc/qcom/pmic_glink_altmode.c |   17 +++++++++++------
 drivers/usb/typec/ucsi/ucsi_glink.c   |   16 ++++++++++------
 include/linux/soc/qcom/pmic_glink.h   |   11 ++++++-----
 5 files changed, 55 insertions(+), 33 deletions(-)
drivers/power/supply/qcom_battmgr.c +10 -6
@@ -1384,12 +1384,16 @@ static int qcom_battmgr_probe(struct aux
 					     "failed to register wireless charing power supply\n");
 	}
 
-	battmgr->client = devm_pmic_glink_register_client(dev,
-							  PMIC_GLINK_OWNER_BATTMGR,
-							  qcom_battmgr_callback,
-							  qcom_battmgr_pdr_notify,
-							  battmgr);
-	return PTR_ERR_OR_ZERO(battmgr->client);
+	battmgr->client = devm_pmic_glink_client_alloc(dev, PMIC_GLINK_OWNER_BATTMGR,
+						       qcom_battmgr_callback,
+						       qcom_battmgr_pdr_notify,
+						       battmgr);
+	if (IS_ERR(battmgr->client))
+		return PTR_ERR(battmgr->client);
+
+	pmic_glink_client_register(battmgr->client);
+
+	return 0;
 }
 
 static const struct auxiliary_device_id qcom_battmgr_id_table[] = {
drivers/soc/qcom/pmic_glink.c +18 -10
@@ -66,15 +66,14 @@ static void _devm_pmic_glink_release_cli
 	spin_unlock_irqrestore(&pg->client_lock, flags);
 }
 
-struct pmic_glink_client *devm_pmic_glink_register_client(struct device *dev,
-							  unsigned int id,
-							  void (*cb)(const void *, size_t, void *),
-							  void (*pdr)(void *, int),
-							  void *priv)
+struct pmic_glink_client *devm_pmic_glink_client_alloc(struct device *dev,
+						       unsigned int id,
+						       void (*cb)(const void *, size_t, void *),
+						       void (*pdr)(void *, int),
+						       void *priv)
 {
 	struct pmic_glink_client *client;
 	struct pmic_glink *pg = dev_get_drvdata(dev->parent);
-	unsigned long flags;
 
 	client = devres_alloc(_devm_pmic_glink_release_client, sizeof(*client), GFP_KERNEL);
 	if (!client)
@@ -85,6 +84,18 @@ struct pmic_glink_client *devm_pmic_glin
 	client->cb = cb;
 	client->pdr_notify = pdr;
 	client->priv = priv;
+	INIT_LIST_HEAD(&client->node);
+
+	devres_add(dev, client);
+
+	return client;
+}
+EXPORT_SYMBOL_GPL(devm_pmic_glink_client_alloc);
+
+void pmic_glink_client_register(struct pmic_glink_client *client)
+{
+	struct pmic_glink *pg = client->pg;
+	unsigned long flags;
 
 	mutex_lock(&pg->state_lock);
 	spin_lock_irqsave(&pg->client_lock, flags);
@@ -95,11 +106,8 @@ struct pmic_glink_client *devm_pmic_glin
 	spin_unlock_irqrestore(&pg->client_lock, flags);
 	mutex_unlock(&pg->state_lock);
 
-	devres_add(dev, client);
-
-	return client;
 }
-EXPORT_SYMBOL_GPL(devm_pmic_glink_register_client);
+EXPORT_SYMBOL_GPL(pmic_glink_client_register);
 
 int pmic_glink_send(struct pmic_glink_client *client, void *data, size_t len)
 {
drivers/soc/qcom/pmic_glink_altmode.c +11 -6
@@ -520,12 +520,17 @@ static int pmic_glink_altmode_probe(stru
 			return ret;
 	}
 
-	altmode->client = devm_pmic_glink_register_client(dev,
-							  altmode->owner_id,
-							  pmic_glink_altmode_callback,
-							  pmic_glink_altmode_pdr_notify,
-							  altmode);
-	return PTR_ERR_OR_ZERO(altmode->client);
+	altmode->client = devm_pmic_glink_client_alloc(dev,
+						       altmode->owner_id,
+						       pmic_glink_altmode_callback,
+						       pmic_glink_altmode_pdr_notify,
+						       altmode);
+	if (IS_ERR(altmode->client))
+		return PTR_ERR(altmode->client);
+
+	pmic_glink_client_register(altmode->client);
+
+	return 0;
 }
 
 static const struct auxiliary_device_id pmic_glink_altmode_id_table[] = {
drivers/usb/typec/ucsi/ucsi_glink.c +10 -6
@@ -395,12 +395,16 @@ static int pmic_glink_ucsi_probe(struct
 		ucsi->port_orientation[port] = desc;
 	}
 
-	ucsi->client = devm_pmic_glink_register_client(dev,
-						       PMIC_GLINK_OWNER_USBC,
-						       pmic_glink_ucsi_callback,
-						       pmic_glink_ucsi_pdr_notify,
-						       ucsi);
-	return PTR_ERR_OR_ZERO(ucsi->client);
+	ucsi->client = devm_pmic_glink_client_alloc(dev, PMIC_GLINK_OWNER_USBC,
+						    pmic_glink_ucsi_callback,
+						    pmic_glink_ucsi_pdr_notify,
+						    ucsi);
+	if (IS_ERR(ucsi->client))
+		return PTR_ERR(ucsi->client);
+
+	pmic_glink_client_register(ucsi->client);
+
+	return 0;
 }
 
 static void pmic_glink_ucsi_remove(struct auxiliary_device *adev)
include/linux/soc/qcom/pmic_glink.h +6 -5
@@ -23,10 +23,11 @@ struct pmic_glink_hdr {
 
 int pmic_glink_send(struct pmic_glink_client *client, void *data, size_t len);
 
-struct pmic_glink_client *devm_pmic_glink_register_client(struct device *dev,
-							  unsigned int id,
-							  void (*cb)(const void *, size_t, void *),
-							  void (*pdr)(void *, int),
-							  void *priv);
+struct pmic_glink_client *devm_pmic_glink_client_alloc(struct device *dev,
+						       unsigned int id,
+						       void (*cb)(const void *, size_t, void *),
+						       void (*pdr)(void *, int),
+						       void *priv);
+void pmic_glink_client_register(struct pmic_glink_client *client);
 
 #endif
author maintainer
#122 lore raw

PATCH 118/149 cdc-acm: Add DISABLE_ECHO quirk for GE HealthCare UI Controller

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ian Ray <[email protected]>

commit 0b00583ecacb0b51712a5ecd34cf7e6684307c67 upstream.

USB_DEVICE(0x1901, 0x0006) may send data before cdc_acm is ready, which may be misinterpreted in the default N_TTY line discipline.

---
 drivers/usb/class/cdc-acm.c |    3 +++
 1 file changed, 3 insertions(+)
drivers/usb/class/cdc-acm.c +3 -0
@@ -1761,6 +1761,9 @@ static const struct usb_device_id acm_id
 	{ USB_DEVICE(0x11ca, 0x0201), /* VeriFone Mx870 Gadget Serial */
 	.driver_info = SINGLE_RX_URB,
 	},
+	{ USB_DEVICE(0x1901, 0x0006), /* GE Healthcare Patient Monitor UI Controller */
+	.driver_info = DISABLE_ECHO, /* DISABLE ECHO in termios flag */
+	},
 	{ USB_DEVICE(0x1965, 0x0018), /* Uniden UBC125XLT */
 	.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
 	},
author maintainer
#123 lore raw

PATCH 119/149 usb: typec: fsa4480: Relax CHIP_ID check

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Luca Weiss <[email protected]>

commit 4f83cae0edb2b13aabb82e8a4852092844d320aa upstream.

Some FSA4480-compatible chips like the OCP96011 used on Fairphone 5 return 0x00 from the CHIP_ID register. Handle that gracefully and only fail probe when the I2C read has failed.

With this the dev_dbg will print 0 but otherwise continue working.

  [    0.251581] fsa4480 1-0042: Found FSA4480 v0.0 (Vendor ID = 0)
---
 drivers/usb/typec/mux/fsa4480.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/typec/mux/fsa4480.c +1 -1
index cd235339834b..f71dba8bf07c 100644
@@ -274,7 +274,7 @@ static int fsa4480_probe(struct i2c_client *client)
 		return dev_err_probe(dev, PTR_ERR(fsa->regmap), "failed to initialize regmap\n");
 
 	ret = regmap_read(fsa->regmap, FSA4480_DEVICE_ID, &val);
-	if (ret || !val)
+	if (ret)
 		return dev_err_probe(dev, -ENODEV, "FSA4480 not found\n");
 
 	dev_dbg(dev, "Found FSA4480 v%lu.%lu (Vendor ID = %lu)\n",
Signature · 1 line
2.46.0
author maintainer
#124 lore raw

PATCH 120/149 firmware: qcom: scm: Mark get_wq_ctx() as atomic call

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Murali Nalajala <[email protected]>

commit 9960085a3a82c58d3323c1c20b991db6045063b0 upstream.

Currently get_wq_ctx() is wrongly configured as a standard call. When two SMC calls are in sleep and one SMC wakes up, it calls get_wq_ctx() to resume the corresponding sleeping thread. But if get_wq_ctx() is interrupted, goes to sleep and another SMC call is waiting to be allocated a waitq context, it leads to a deadlock.

To avoid this get_wq_ctx() must be an atomic call and can't be a standard SMC call. Hence mark get_wq_ctx() as a fast call.

---
 drivers/firmware/qcom/qcom_scm-smc.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/firmware/qcom/qcom_scm-smc.c +1 -1
@@ -71,7 +71,7 @@ int scm_get_wq_ctx(u32 *wq_ctx, u32 *fla
 	struct arm_smccc_res get_wq_res;
 	struct arm_smccc_args get_wq_ctx = {0};
 
-	get_wq_ctx.args[0] = ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL,
+	get_wq_ctx.args[0] = ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,
 				ARM_SMCCC_SMC_64, ARM_SMCCC_OWNER_SIP,
 				SCM_SMC_FNID(QCOM_SCM_SVC_WAITQ, QCOM_SCM_WAITQ_GET_WQ_CTX));
 
author maintainer
#125 lore raw

PATCH 121/149 scsi: sd: Ignore command SYNCHRONIZE CACHE error if format in progress

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Yihang Li <[email protected]>

commit 4f9eedfa27ae5806ed10906bcceee7bae49c8941 upstream.

If formatting a suspended disk (such as formatting with different DIF type), the disk will be resuming first, and then the format command will submit to the disk through SG_IO ioctl.

When the disk is processing the format command, the system does not submit other commands to the disk. Therefore, the system attempts to suspend the disk again and sends the SYNCHRONIZE CACHE command. However, the SYNCHRONIZE CACHE command will fail because the disk is in the formatting process. This will cause the runtime_status of the disk to error and it is difficult for user to recover it. Error info like:

[  669.925325] sd 6:0:6:0: [sdg] Synchronizing SCSI cache
[  670.202371] sd 6:0:6:0: [sdg] Synchronize Cache(10) failed: Result: hostbyte=0x00 driverbyte=DRIVER_OK
[  670.216300] sd 6:0:6:0: [sdg] Sense Key : 0x2 [current]
[  670.221860] sd 6:0:6:0: [sdg] ASC=0x4 ASCQ=0x4

To solve the issue, ignore the error and return success/0 when format is in progress.

---
 drivers/scsi/sd.c |   12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)
drivers/scsi/sd.c +7 -5
@@ -1711,13 +1711,15 @@ static int sd_sync_cache(struct scsi_dis
 			    (sshdr.asc == 0x74 && sshdr.ascq == 0x71))	/* drive is password locked */
 				/* this is no error here */
 				return 0;
+
 			/*
-			 * This drive doesn't support sync and there's not much
-			 * we can do because this is called during shutdown
-			 * or suspend so just return success so those operations
-			 * can proceed.
+			 * If a format is in progress or if the drive does not
+			 * support sync, there is not much we can do because
+			 * this is called during shutdown or suspend so just
+			 * return success so those operations can proceed.
 			 */
-			if (sshdr.sense_key == ILLEGAL_REQUEST)
+			if ((sshdr.asc == 0x04 && sshdr.ascq == 0x04) ||
+			    sshdr.sense_key == ILLEGAL_REQUEST)
 				return 0;
 		}
 
author maintainer
#126 lore raw

PATCH 122/149 dt-bindings: usb: microchip,usb2514: Fix reference USB device schema

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alexander Stein <[email protected]>

commit 5b235693ed2a1e4963625717a1598becf97759cc upstream.

An USB hub is not a HCD, but an USB device. Fix the referenced schema accordingly.

---
 Documentation/devicetree/bindings/usb/microchip,usb2514.yaml |    9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/usb/microchip,usb2514.yaml +8 -1
@@ -10,7 +10,7 @@ maintainers:
   - Fabio Estevam <[email protected]>
 
 allOf:
-  - $ref: usb-hcd.yaml#
+  - $ref: usb-device.yaml#
 
 properties:
   compatible:
@@ -35,6 +35,13 @@ required:
   - compatible
   - reg
 
+patternProperties:
+  "^.*@[0-9a-f]{1,2}$":
+    description: The hard wired USB devices
+    type: object
+    $ref: /schemas/usb/usb-device.yaml
+    additionalProperties: true
+
 unevaluatedProperties: false
 
 examples:
author maintainer
#127 lore raw

PATCH 123/149 USB: serial: option: add MeiG Smart SRM825L

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: ZHANG Yuntian <[email protected]>

commit 9a471de516c35219d1722c13367191ce1f120fe9 upstream.

Add support for MeiG Smart SRM825L which is based on Qualcomm 315 chip.

T:  Bus=04 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=5000 MxCh= 0
D:  Ver= 3.20 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 9 #Cfgs=  1
P:  Vendor=2dee ProdID=4d22 Rev= 4.14
S:  Manufacturer=MEIG
S:  Product=LTE-A Module
S:  SerialNumber=6f345e48
C:* #Ifs= 6 Cfg#= 1 Atr=80 MxPwr=896mA
I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option
E:  Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E:  Ad=01(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option
E:  Ad=83(I) Atr=03(Int.) MxPS=  10 Ivl=32ms
E:  Ad=82(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option
E:  Ad=85(I) Atr=03(Int.) MxPS=  10 Ivl=32ms
E:  Ad=84(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E:  Ad=03(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=60 Driver=option
E:  Ad=87(I) Atr=03(Int.) MxPS=  10 Ivl=32ms
E:  Ad=86(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E:  Ad=04(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I:* If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none)
E:  Ad=05(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E:  Ad=88(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I:* If#= 5 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=50 Driver=qmi_wwan
E:  Ad=89(I) Atr=03(Int.) MxPS=   8 Ivl=32ms
E:  Ad=8e(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E:  Ad=0f(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
---
 drivers/usb/serial/option.c |    5 +++++
 1 file changed, 5 insertions(+)
drivers/usb/serial/option.c +5 -0
@@ -619,6 +619,8 @@ static void option_instat_callback(struc
 
 /* MeiG Smart Technology products */
 #define MEIGSMART_VENDOR_ID			0x2dee
+/* MeiG Smart SRM825L based on Qualcomm 315 */
+#define MEIGSMART_PRODUCT_SRM825L		0x4d22
 /* MeiG Smart SLM320 based on UNISOC UIS8910 */
 #define MEIGSMART_PRODUCT_SLM320		0x4d41
 
@@ -2366,6 +2368,9 @@ static const struct usb_device_id option
 	{ USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SLM320, 0xff, 0, 0) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x30) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x40) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x60) },
 	{ } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
author maintainer
#128 lore raw

PATCH 124/149 usb: gadget: uvc: queue pump work in uvcg_video_enable()

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Xu Yang <[email protected]>

commit b52a07e07dead777517af3cbda851bb2cc157c9d upstream.

Since commit "6acba0345b68 usb:gadget:uvc Do not use worker thread to pump isoc usb requests", pump work could only be queued in uvc_video_complete() and uvc_v4l2_qbuf(). If VIDIOC_QBUF is executed before VIDIOC_STREAMON, we can only depend on uvc_video_complete() to queue pump work. However, this requires some free requests in req_ready list. If req_ready list is empty all the time, pump work will never be queued and video datas will never be pumped to usb controller. Actually, this situation could happen when run uvc-gadget with static image:

$ ./uvc-gadget -i 1080p.jpg uvc.0

When capture image from this device, the user app will always block there.

The issue is uvc driver has queued video buffer before streamon, but the req_ready list is empty all the time after streamon. This will queue pump work in uvcg_video_enable() to fill some request to req_ready list so the uvc device could work properly.

Fixes 6acba0345b68 ("usb:gadget:uvc Do not use worker thread to pump isoc usb requests")
---
 drivers/usb/gadget/function/uvc_video.c |    1 +
 1 file changed, 1 insertion(+)
drivers/usb/gadget/function/uvc_video.c +1 -0
@@ -753,6 +753,7 @@ int uvcg_video_enable(struct uvc_video *
 	video->req_int_count = 0;
 
 	uvc_video_ep_queue_initial_requests(video);
+	queue_work(video->async_wq, &video->pump);
 
 	return ret;
 }
author maintainer
#129 lore raw

PATCH 125/149 arm64: dts: qcom: x1e80100-crd: fix PCIe4 PHY supply

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit 30f593fa0088b89f479f7358640687b3cbca93d4 upstream.

The PCIe4 PHY is powered by vreg_l3i (not vreg_l3j).

Fixes d7e03cce0400 ("arm64: dts: qcom: x1e80100-crd: Enable more support")
---
 arch/arm64/boot/dts/qcom/x1e80100-crd.dts |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/boot/dts/qcom/x1e80100-crd.dts +1 -1
@@ -648,7 +648,7 @@
 };
 
 &pcie4_phy {
-	vdda-phy-supply = <&vreg_l3j_0p8>;
+	vdda-phy-supply = <&vreg_l3i_0p8>;
 	vdda-pll-supply = <&vreg_l3e_1p2>;
 
 	status = "okay";
author maintainer
#130 lore raw

PATCH 126/149 arm64: dts: qcom: x1e80100-qcp: fix PCIe4 PHY supply

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit f03dd49f884f428ba71efe23383ff842f4f15e0e upstream.

The PCIe4 PHY is powered by vreg_l3i (not vreg_l3j) on the CRD so assume the same applies to the QCP.

---
 arch/arm64/boot/dts/qcom/x1e80100-qcp.dts |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/boot/dts/qcom/x1e80100-qcp.dts +1 -1
@@ -459,7 +459,7 @@
 };
 
 &pcie4_phy {
-	vdda-phy-supply = <&vreg_l3j_0p8>;
+	vdda-phy-supply = <&vreg_l3i_0p8>;
 	vdda-pll-supply = <&vreg_l3e_1p2>;
 
 	status = "okay";
author maintainer
#131 lore raw

PATCH 127/149 arm64: dts: qcom: x1e80100: add missing PCIe minimum OPP

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit 98abf2fbd179017833c38edc9f3b587c69d07e2a upstream.

Add the missing PCIe CX performance level votes to avoid relying on other drivers (e.g. USB) to maintain the nominal performance level required for Gen3 speeds.

---
 arch/arm64/boot/dts/qcom/x1e80100.dtsi |    2 ++
 1 file changed, 2 insertions(+)
arch/arm64/boot/dts/qcom/x1e80100.dtsi +2 -0
@@ -2814,6 +2814,7 @@
 				      "link_down";
 
 			power-domains = <&gcc GCC_PCIE_6A_GDSC>;
+			required-opps = <&rpmhpd_opp_nom>;
 
 			phys = <&pcie6a_phy>;
 			phy-names = "pciephy";
@@ -2935,6 +2936,7 @@
 				      "link_down";
 
 			power-domains = <&gcc GCC_PCIE_4_GDSC>;
+			required-opps = <&rpmhpd_opp_nom>;
 
 			phys = <&pcie4_phy>;
 			phy-names = "pciephy";
author maintainer
#132 lore raw

PATCH 128/149 arm64: dts: qcom: x1e80100: fix PCIe domain numbers

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit f8fa1f2f6412bffa71972f9506b72992d0e6e485 upstream.

The current PCIe domain numbers are off by one and do not match the numbers that the UEFI firmware (and Windows) uses.

---
 arch/arm64/boot/dts/qcom/x1e80100.dtsi |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/qcom/x1e80100.dtsi +2 -2
@@ -2756,7 +2756,7 @@
 
 			dma-coherent;
 
-			linux,pci-domain = <7>;
+			linux,pci-domain = <6>;
 			num-lanes = <2>;
 
 			interrupts = <GIC_SPI 773 IRQ_TYPE_LEVEL_HIGH>,
@@ -2878,7 +2878,7 @@
 
 			dma-coherent;
 
-			linux,pci-domain = <5>;
+			linux,pci-domain = <4>;
 			num-lanes = <2>;
 
 			interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
author maintainer
#133 lore raw

PATCH 129/149 ARM: dts: imx6dl-yapp43: Increase LED current to match the yapp4 HW design

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Michal Vokáč <[email protected]>

commit 8512fbb64b0e599412da661412d10d4ba1cb003c upstream.

On the imx6dl-yapp4 revision based boards, the RGB LED is not driven directly by the LP5562 driver but through FET transistors. Hence the LED current is not determined by the driver but by the LED series resistors.

On the imx6dl-yapp43 revision based boards, we removed the FET transistors to drive the LED directly from the LP5562 but forgot to tune the output current to match the previous HW design.

Set the LED current on imx6dl-yapp43 based boards to the same values measured on the imx6dl-yapp4 boards and limit the maximum current to 20mA.

Fixes 7da4734751e0 ("ARM: dts: imx6dl-yapp43: Add support for new HW revision of the IOTA board")
---
 arch/arm/boot/dts/nxp/imx/imx6dl-yapp43-common.dtsi |   12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
arch/arm/boot/dts/nxp/imx/imx6dl-yapp43-common.dtsi +6 -6
@@ -274,24 +274,24 @@
 
 		led@0 {
 			chan-name = "R";
-			led-cur = /bits/ 8 <0x20>;
-			max-cur = /bits/ 8 <0x60>;
+			led-cur = /bits/ 8 <0x6e>;
+			max-cur = /bits/ 8 <0xc8>;
 			reg = <0>;
 			color = <LED_COLOR_ID_RED>;
 		};
 
 		led@1 {
 			chan-name = "G";
-			led-cur = /bits/ 8 <0x20>;
-			max-cur = /bits/ 8 <0x60>;
+			led-cur = /bits/ 8 <0xbe>;
+			max-cur = /bits/ 8 <0xc8>;
 			reg = <1>;
 			color = <LED_COLOR_ID_GREEN>;
 		};
 
 		led@2 {
 			chan-name = "B";
-			led-cur = /bits/ 8 <0x20>;
-			max-cur = /bits/ 8 <0x60>;
+			led-cur = /bits/ 8 <0xbe>;
+			max-cur = /bits/ 8 <0xc8>;
 			reg = <2>;
 			color = <LED_COLOR_ID_BLUE>;
 		};
author maintainer
#134 lore raw

PATCH 130/149 usb: dwc3: ep0: Dont reset resource alloc flag (including ep0)

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Michael Grzeschik <[email protected]>

commit 72fca8371f205d654f95b09cd023a71fd5307041 upstream.

The DWC3_EP_RESOURCE_ALLOCATED flag ensures that the resource of an endpoint is only assigned once. Unless the endpoint is reset, don't clear this flag. Otherwise we may set endpoint resource again, which prevents the driver from initiate transfer after handling a STALL or endpoint halt to the control endpoint.

Commit f2e0eee47038 ("usb: dwc3: ep0: Don't reset resource alloc flag") was fixing the initial issue, but did this only for physical ep1. Since the function dwc3_ep0_stall_and_restart is resetting the flags for both physical endpoints, this also has to be done for ep0.

---
 drivers/usb/dwc3/ep0.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/usb/dwc3/ep0.c +2 -1
index d96ffbe52039..c9533a99e47c 100644
@@ -232,7 +232,8 @@ void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
 	/* stall is always issued on EP0 */
 	dep = dwc->eps[0];
 	__dwc3_gadget_ep_set_halt(dep, 1, false);
-	dep->flags = DWC3_EP_ENABLED;
+	dep->flags &= DWC3_EP_RESOURCE_ALLOCATED;
+	dep->flags |= DWC3_EP_ENABLED;
 	dwc->delayed_status = false;
 
 	if (!list_empty(&dep->pending_list)) {
Signature · 1 line
2.46.0
author maintainer
#135 lore raw

PATCH 131/149 usb: dwc3: xilinx: add missing depopulate in probe error path

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Krzysztof Kozlowski <[email protected]>

commit 16f2a21d9d7e48e1af02654fe3d926c0ce6cb3e5 upstream.

Depopulate device in probe error paths to fix leak of children resources.

---
 drivers/usb/dwc3/dwc3-xilinx.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/usb/dwc3/dwc3-xilinx.c +6 -1
@@ -298,9 +298,14 @@ static int dwc3_xlnx_probe(struct platfo
 		goto err_pm_set_suspended;
 
 	pm_suspend_ignore_children(dev, false);
-	return pm_runtime_resume_and_get(dev);
+	ret = pm_runtime_resume_and_get(dev);
+	if (ret < 0)
+		goto err_pm_set_suspended;
+
+	return 0;
 
 err_pm_set_suspended:
+	of_platform_depopulate(dev);
 	pm_runtime_set_suspended(dev);
 
 err_clk_put:
author maintainer
#136 lore raw

PATCH 132/149 usb: dwc3: omap: add missing depopulate in probe error path

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Krzysztof Kozlowski <[email protected]>

commit 2aa765a43817ec8add990f83c8e54a9a5d87aa9c upstream.

Depopulate device in probe error paths to fix leak of children resources.

---
 drivers/usb/dwc3/dwc3-omap.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/usb/dwc3/dwc3-omap.c +3 -1
@@ -522,11 +522,13 @@ static int dwc3_omap_probe(struct platfo
 	if (ret) {
 		dev_err(dev, "failed to request IRQ #%d --> %d\n",
 			omap->irq, ret);
-		goto err1;
+		goto err2;
 	}
 	dwc3_omap_enable_irqs(omap);
 	return 0;
 
+err2:
+	of_platform_depopulate(dev);
 err1:
 	pm_runtime_put_sync(dev);
 	pm_runtime_disable(dev);
author maintainer
#137 lore raw

PATCH 133/149 usb: dwc3: core: Prevent USB core invalid event buffer address access

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Selvarasu Ganesan <[email protected]>

commit 14e497183df28c006603cc67fd3797a537eef7b9 upstream.

This commit addresses an issue where the USB core could access an invalid event buffer address during runtime suspend, potentially causing SMMU faults and other memory issues in Exynos platforms. The problem arises from the following sequence.
1. In dwc3_gadget_suspend, there is a chance of a timeout when moving the USB core to the halt state after clearing the run/stop bit by software.
2. In dwc3_core_exit, the event buffer is cleared regardless of the USB core's status, which may lead to an SMMU faults and other memory issues. if the USB core tries to access the event buffer address.

To prevent this hardware quirk on Exynos platforms, this commit ensures that the event buffer address is not cleared by software when the USB core is active during runtime suspend by checking its status before clearing the buffer address.

---
 drivers/usb/dwc3/core.c |    8 ++++++++
 1 file changed, 8 insertions(+)
drivers/usb/dwc3/core.c +8 -0
@@ -559,9 +559,17 @@ int dwc3_event_buffers_setup(struct dwc3
 void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
 {
 	struct dwc3_event_buffer	*evt;
+	u32				reg;
 
 	if (!dwc->ev_buf)
 		return;
+	/*
+	 * Exynos platforms may not be able to access event buffer if the
+	 * controller failed to halt on dwc3_core_exit().
+	 */
+	reg = dwc3_readl(dwc->regs, DWC3_DSTS);
+	if (!(reg & DWC3_DSTS_DEVCTRLHLT))
+		return;
 
 	evt = dwc->ev_buf;
 
author maintainer
#138 lore raw

PATCH 134/149 usb: dwc3: st: fix probed platform device ref count on probe error path

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Krzysztof Kozlowski <[email protected]>

commit ddfcfeba891064b88bb844208b43bef2ef970f0c upstream.

The probe function never performs any paltform device allocation, thus error path "undo_platform_dev_alloc" is entirely bogus. It drops the reference count from the platform device being probed. If error path is triggered, this will lead to unbalanced device reference counts and premature release of device resources, thus possible use-after-free when releasing remaining devm-managed resources.

---
 drivers/usb/dwc3/dwc3-st.c |   11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)
drivers/usb/dwc3/dwc3-st.c +3 -8
@@ -219,10 +219,8 @@ static int st_dwc3_probe(struct platform
 	dwc3_data->regmap = regmap;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "syscfg-reg");
-	if (!res) {
-		ret = -ENXIO;
-		goto undo_platform_dev_alloc;
-	}
+	if (!res)
+		return -ENXIO;
 
 	dwc3_data->syscfg_reg_off = res->start;
 
@@ -233,8 +231,7 @@ static int st_dwc3_probe(struct platform
 		devm_reset_control_get_exclusive(dev, "powerdown");
 	if (IS_ERR(dwc3_data->rstc_pwrdn)) {
 		dev_err(&pdev->dev, "could not get power controller\n");
-		ret = PTR_ERR(dwc3_data->rstc_pwrdn);
-		goto undo_platform_dev_alloc;
+		return PTR_ERR(dwc3_data->rstc_pwrdn);
 	}
 
 	/* Manage PowerDown */
@@ -300,8 +297,6 @@ undo_softreset:
 	reset_control_assert(dwc3_data->rstc_rst);
 undo_powerdown:
 	reset_control_assert(dwc3_data->rstc_pwrdn);
-undo_platform_dev_alloc:
-	platform_device_put(pdev);
 	return ret;
 }
 
author maintainer
#139 lore raw

PATCH 135/149 usb: dwc3: st: add missing depopulate in probe error path

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Krzysztof Kozlowski <[email protected]>

commit cd4897bfd14f6a5388b21ba45a066541a0425199 upstream.

Depopulate device in probe error paths to fix leak of children resources.

---
 drivers/usb/dwc3/dwc3-st.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/usb/dwc3/dwc3-st.c +4 -1
@@ -266,7 +266,7 @@ static int st_dwc3_probe(struct platform
 	if (!child_pdev) {
 		dev_err(dev, "failed to find dwc3 core device\n");
 		ret = -ENODEV;
-		goto err_node_put;
+		goto depopulate;
 	}
 
 	dwc3_data->dr_mode = usb_get_dr_mode(&child_pdev->dev);
@@ -282,6 +282,7 @@ static int st_dwc3_probe(struct platform
 	ret = st_dwc3_drd_init(dwc3_data);
 	if (ret) {
 		dev_err(dev, "drd initialisation failed\n");
+		of_platform_depopulate(dev);
 		goto undo_softreset;
 	}
 
@@ -291,6 +292,8 @@ static int st_dwc3_probe(struct platform
 	platform_set_drvdata(pdev, dwc3_data);
 	return 0;
 
+depopulate:
+	of_platform_depopulate(dev);
 err_node_put:
 	of_node_put(child);
 undo_softreset:
author maintainer
#140 lore raw

PATCH 136/149 usb: core: sysfs: Unmerge @usb3_hardware_lpm_attr_group in remove_power_attributes()

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Zijun Hu <[email protected]>

commit 3a8839bbb86da7968a792123ed2296d063871a52 upstream.

Device attribute group @usb3_hardware_lpm_attr_group is merged by add_power_attributes(), but it is not unmerged explicitly, fixed by unmerging it in remove_power_attributes().

Fixes 655fe4effe0f ("usbcore: add sysfs support to xHCI usb3 hardware LPM")
---
 drivers/usb/core/sysfs.c |    1 +
 1 file changed, 1 insertion(+)
drivers/usb/core/sysfs.c +1 -0
@@ -670,6 +670,7 @@ static int add_power_attributes(struct d
 
 static void remove_power_attributes(struct device *dev)
 {
+	sysfs_unmerge_group(&dev->kobj, &usb3_hardware_lpm_attr_group);
 	sysfs_unmerge_group(&dev->kobj, &usb2_hardware_lpm_attr_group);
 	sysfs_unmerge_group(&dev->kobj, &power_attr_group);
 }
author maintainer
#141 lore raw

PATCH 137/149 usb: cdnsp: fix incorrect index in cdnsp_get_hw_deq function

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Pawel Laszczak <[email protected]>

commit 0497a356d3c498221eb0c1edc1e8985816092f12 upstream.

Patch fixes the incorrect "stream_id" table index instead of "ep_index" used in cdnsp_get_hw_deq function.

---
 drivers/usb/cdns3/cdnsp-ring.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/cdns3/cdnsp-ring.c +1 -1
index 02f297f5637d..a60c0cb991cd 100644
@@ -402,7 +402,7 @@ static u64 cdnsp_get_hw_deq(struct cdnsp_device *pdev,
 	struct cdnsp_stream_ctx *st_ctx;
 	struct cdnsp_ep *pep;
 
-	pep = &pdev->eps[stream_id];
+	pep = &pdev->eps[ep_index];
 
 	if (pep->ep_state & EP_HAS_STREAMS) {
 		st_ctx = &pep->stream_info.stream_ctx_array[stream_id];
Signature · 1 line
2.46.0
author maintainer
#142 lore raw

PATCH 138/149 usb: cdnsp: fix for Link TRB with TC

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Pawel Laszczak <[email protected]>

commit 740f2e2791b98e47288b3814c83a3f566518fed2 upstream.

Stop Endpoint command on LINK TRB with TC bit set to 1 causes that internal cycle bit can have incorrect state after command complete. In consequence empty transfer ring can be incorrectly detected when EP is resumed.
NOP TRB before LINK TRB avoid such scenario. Stop Endpoint command is then on NOP TRB and internal cycle bit is not changed and have correct value.

---
 drivers/usb/cdns3/cdnsp-gadget.h |    3 +++
 drivers/usb/cdns3/cdnsp-ring.c   |   28 ++++++++++++++++++++++++++++
 2 files changed, 31 insertions(+)
drivers/usb/cdns3/cdnsp-gadget.h +3 -0
@@ -811,6 +811,7 @@ struct cdnsp_stream_info {
  *        generate Missed Service Error Event.
  *        Set skip flag when receive a Missed Service Error Event and
  *        process the missed tds on the endpoint ring.
+ * @wa1_nop_trb: hold pointer to NOP trb.
  */
 struct cdnsp_ep {
 	struct usb_ep endpoint;
@@ -838,6 +839,8 @@ struct cdnsp_ep {
 #define EP_UNCONFIGURED		BIT(7)
 
 	bool skip;
+	union cdnsp_trb	 *wa1_nop_trb;
+
 };
 
 /**
drivers/usb/cdns3/cdnsp-ring.c +28 -0
@@ -1905,6 +1905,23 @@ int cdnsp_queue_bulk_tx(struct cdnsp_dev
 		return ret;
 
 	/*
+	 * workaround 1: STOP EP command on LINK TRB with TC bit set to 1
+	 * causes that internal cycle bit can have incorrect state after
+	 * command complete. In consequence empty transfer ring can be
+	 * incorrectly detected when EP is resumed.
+	 * NOP TRB before LINK TRB avoid such scenario. STOP EP command is
+	 * then on NOP TRB and internal cycle bit is not changed and have
+	 * correct value.
+	 */
+	if (pep->wa1_nop_trb) {
+		field = le32_to_cpu(pep->wa1_nop_trb->trans_event.flags);
+		field ^= TRB_CYCLE;
+
+		pep->wa1_nop_trb->trans_event.flags = cpu_to_le32(field);
+		pep->wa1_nop_trb = NULL;
+	}
+
+	/*
 	 * Don't give the first TRB to the hardware (by toggling the cycle bit)
 	 * until we've finished creating all the other TRBs. The ring's cycle
 	 * state may change as we enqueue the other TRBs, so save it too.
@@ -1999,6 +2016,17 @@ int cdnsp_queue_bulk_tx(struct cdnsp_dev
 		send_addr = addr;
 	}
 
+	if (cdnsp_trb_is_link(ring->enqueue + 1)) {
+		field = TRB_TYPE(TRB_TR_NOOP) | TRB_IOC;
+		if (!ring->cycle_state)
+			field |= TRB_CYCLE;
+
+		pep->wa1_nop_trb = ring->enqueue;
+
+		cdnsp_queue_trb(pdev, ring, 0, 0x0, 0x0,
+				TRB_INTR_TARGET(0), field);
+	}
+
 	cdnsp_check_trb_math(preq, enqd_len);
 	ret = cdnsp_giveback_first_trb(pdev, pep, preq->request.stream_id,
 				       start_cycle, start_trb);
author maintainer
#143 lore raw

PATCH 139/149 usb: typec: ucsi: Move unregister out of atomic section

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Bjorn Andersson <[email protected]>

commit 11bb2ffb679399f99041540cf662409905179e3a upstream.

Commit '9329933699b3 ("soc: qcom: pmic_glink: Make client-lock non-sleeping")' moved the pmic_glink client list under a spinlock, as it is accessed by the rpmsg/glink callback, which in turn is invoked from IRQ context.

This means that ucsi_unregister() is now called from atomic context, which isn't feasible as it's expecting a sleepable context. An effort is under way to get GLINK to invoke its callbacks in a sleepable context, but until then lets schedule the unregistration.

A side effect of this is that ucsi_unregister() can now happen after the remote processor, and thereby the communication link with it, is gone. pmic_glink_send() is amended with a check to avoid the resulting NULL pointer dereference.
This does however result in the user being informed about this error by the following entry in the kernel log:

ucsi_glink.pmic_glink_ucsi pmic_glink.ucsi.0: failed to send UCSI write request: -5

---
 drivers/soc/qcom/pmic_glink.c       |   10 +++++++++-
 drivers/usb/typec/ucsi/ucsi_glink.c |   27 ++++++++++++++++++++++-----
 2 files changed, 31 insertions(+), 6 deletions(-)
drivers/soc/qcom/pmic_glink.c +9 -1
@@ -112,8 +112,16 @@ EXPORT_SYMBOL_GPL(pmic_glink_client_regi
 int pmic_glink_send(struct pmic_glink_client *client, void *data, size_t len)
 {
 	struct pmic_glink *pg = client->pg;
+	int ret;
 
-	return rpmsg_send(pg->ept, data, len);
+	mutex_lock(&pg->state_lock);
+	if (!pg->ept)
+		ret = -ECONNRESET;
+	else
+		ret = rpmsg_send(pg->ept, data, len);
+	mutex_unlock(&pg->state_lock);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(pmic_glink_send);
 
drivers/usb/typec/ucsi/ucsi_glink.c +22 -5
@@ -72,6 +72,9 @@ struct pmic_glink_ucsi {
 
 	struct work_struct notify_work;
 	struct work_struct register_work;
+	spinlock_t state_lock;
+	bool ucsi_registered;
+	bool pd_running;
 
 	u8 read_buf[UCSI_BUF_SIZE];
 };
@@ -271,8 +274,20 @@ static void pmic_glink_ucsi_notify(struc
 static void pmic_glink_ucsi_register(struct work_struct *work)
 {
 	struct pmic_glink_ucsi *ucsi = container_of(work, struct pmic_glink_ucsi, register_work);
+	unsigned long flags;
+	bool pd_running;
 
-	ucsi_register(ucsi->ucsi);
+	spin_lock_irqsave(&ucsi->state_lock, flags);
+	pd_running = ucsi->pd_running;
+	spin_unlock_irqrestore(&ucsi->state_lock, flags);
+
+	if (!ucsi->ucsi_registered && pd_running) {
+		ucsi_register(ucsi->ucsi);
+		ucsi->ucsi_registered = true;
+	} else if (ucsi->ucsi_registered && !pd_running) {
+		ucsi_unregister(ucsi->ucsi);
+		ucsi->ucsi_registered = false;
+	}
 }
 
 static void pmic_glink_ucsi_callback(const void *data, size_t len, void *priv)
@@ -296,11 +311,12 @@ static void pmic_glink_ucsi_callback(con
 static void pmic_glink_ucsi_pdr_notify(void *priv, int state)
 {
 	struct pmic_glink_ucsi *ucsi = priv;
+	unsigned long flags;
 
-	if (state == SERVREG_SERVICE_STATE_UP)
-		schedule_work(&ucsi->register_work);
-	else if (state == SERVREG_SERVICE_STATE_DOWN)
-		ucsi_unregister(ucsi->ucsi);
+	spin_lock_irqsave(&ucsi->state_lock, flags);
+	ucsi->pd_running = (state == SERVREG_SERVICE_STATE_UP);
+	spin_unlock_irqrestore(&ucsi->state_lock, flags);
+	schedule_work(&ucsi->register_work);
 }
 
 static void pmic_glink_ucsi_destroy(void *data)
@@ -348,6 +364,7 @@ static int pmic_glink_ucsi_probe(struct
 	init_completion(&ucsi->read_ack);
 	init_completion(&ucsi->write_ack);
 	init_completion(&ucsi->sync_ack);
+	spin_lock_init(&ucsi->state_lock);
 	mutex_init(&ucsi->lock);
 
 	ucsi->ucsi = ucsi_create(dev, &pmic_glink_ucsi_ops);
author maintainer
#144 lore raw

PATCH 140/149 arm64: dts: qcom: ipq5332: Fix interrupt trigger type for usb

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Varadarajan Narayanan <[email protected]>

[ Upstream commit 60a76f7826b88ebf7697a56fdcd9596b23c2b616 ]

Trigger type is incorrectly specified as IRQ_TYPE_EDGE_BOTH instead of IRQ_TYPE_LEVEL_HIGH. This trigger type is not supported for SPIs and results in probe failure with -EINVAL.

Fixes 927173bf8a0e ("arm64: dts: qcom: Add missing interrupts for qcs404/ipq5332")
---
 arch/arm64/boot/dts/qcom/ipq5332.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/qcom/ipq5332.dtsi +2 -2
index 770d9c2fb4562..e3064568f0221 100644
@@ -321,8 +321,8 @@
 			reg = <0x08af8800 0x400>;
 
 			interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 53 IRQ_TYPE_EDGE_BOTH>,
-				     <GIC_SPI 52 IRQ_TYPE_EDGE_BOTH>;
+				     <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-names = "pwr_event",
 					  "dp_hs_phy_irq",
 					  "dm_hs_phy_irq";
Signature · 1 line
2.43.0
author maintainer
#145 lore raw

PATCH 141/149 ARM: dts: omap3-n900: correct the accelerometer orientation

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sicelo A. Mhlongo <[email protected]>

[ Upstream commit 5062d9c0cbbc202e495e9b20f147f64ef5cc2897 ]

Negate the values reported for the accelerometer z-axis in order to match Documentation/devicetree/bindings/iio/mount-matrix.txt.

Fixes 14a213dcb004 ("ARM: dts: n900: use iio driver for accelerometer")
---
 arch/arm/boot/dts/ti/omap/omap3-n900.dts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/boot/dts/ti/omap/omap3-n900.dts +1 -1
index 07c5b963af78a..4bde3342bb959 100644
@@ -781,7 +781,7 @@
 
 		mount-matrix =	 "-1",  "0",  "0",
 				  "0",  "1",  "0",
-				  "0",  "0",  "1";
+				  "0",  "0",  "-1";
 	};
 
 	cam1: camera@3e {
Signature · 1 line
2.43.0
author maintainer
#146 lore raw

PATCH 142/149 arm64: dts: imx8mp-beacon-kit: Fix Stereo Audio on WM8962

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Adam Ford <[email protected]>

[ Upstream commit 4e69cd835a2d5c3915838491f59a68ee697a87d0 ]

The L/R clock needs to be controlled by the SAI3 instead of the CODEC to properly achieve stereo sound. Doing this allows removes the need for unnecessary clock manipulation to try to get the CODEC's clock in sync with the SAI3 clock, since the CODEC can cope with a wide variety of clock inputs.

Fixes 161af16c18f3 ("arm64: dts: imx8mp-beacon-kit: Fix audio_pll2 clock")
Fixes 69e2f37a6ddc ("arm64: dts: imx8mp-beacon-kit: Enable WM8962 Audio CODEC")
---
 arch/arm64/boot/dts/freescale/imx8mp-beacon-kit.dts | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)
arch/arm64/boot/dts/freescale/imx8mp-beacon-kit.dts +5 -7
index e5d3901f29136..e1f59bdcae497 100644
@@ -211,13 +211,12 @@
 
 		simple-audio-card,cpu {
 			sound-dai = <&sai3>;
+			frame-master;
+			bitclock-master;
 		};
 
 		simple-audio-card,codec {
 			sound-dai = <&wm8962>;
-			clocks = <&clk IMX8MP_CLK_IPP_DO_CLKO1>;
-			frame-master;
-			bitclock-master;
 		};
 	};
 };
@@ -499,10 +498,9 @@
 &sai3 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_sai3>;
-	assigned-clocks = <&clk IMX8MP_CLK_SAI3>,
-			  <&clk IMX8MP_AUDIO_PLL2> ;
-	assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL2_OUT>;
-	assigned-clock-rates = <12288000>, <361267200>;
+	assigned-clocks = <&clk IMX8MP_CLK_SAI3>;
+	assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL1_OUT>;
+	assigned-clock-rates = <12288000>;
 	fsl,sai-mclk-direction-output;
 	status = "okay";
 };
Signature · 1 line
2.43.0
author maintainer
#147 lore raw

PATCH 143/149 arm64: dts: imx93: update default value for snps,clk-csr

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Shenwei Wang <[email protected]>

[ Upstream commit 109f256285dd6a5f8c3bd0d80d39b2ccd4fe314e ]

For the i.MX93 SoC, the default clock rate for the IP of STMMAC EQOS is 312.5 MHz. According to the following mapping table from the i.MX93 reference manual, this clock rate corresponds to a CSR value of 6.

0000: CSR clock = 60-100 MHz; MDC clock = CSR clock/42 0001: CSR clock = 100-150 MHz; MDC clock = CSR clock/62 0010: CSR clock = 20-35 MHz; MDC clock = CSR clock/16 0011: CSR clock = 35-60 MHz; MDC clock = CSR clock/26 0100: CSR clock = 150-250 MHz; MDC clock = CSR clock/102 0101: CSR clock = 250-300 MHz; MDC clock = CSR clock/124 0110: CSR clock = 300-500 MHz; MDC clock = CSR clock/204 0111: CSR clock = 500-800 MHz; MDC clock = CSR clock/324

Fixes f2d03ba997cb ("arm64: dts: imx93: reorder device nodes")
---
 arch/arm64/boot/dts/freescale/imx93.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/boot/dts/freescale/imx93.dtsi +1 -1
index 4a3f42355cb8f..a0993022c102d 100644
@@ -1105,7 +1105,7 @@
 							 <&clk IMX93_CLK_SYS_PLL_PFD0_DIV2>;
 				assigned-clock-rates = <100000000>, <250000000>;
 				intf_mode = <&wakeupmix_gpr 0x28>;
-				snps,clk-csr = <0>;
+				snps,clk-csr = <6>;
 				nvmem-cells = <&eth_mac2>;
 				nvmem-cell-names = "mac-address";
 				status = "disabled";
Signature · 1 line
2.43.0
author maintainer
#148 lore raw

PATCH 144/149 arm64: dts: freescale: imx93-tqma9352: fix CMA alloc-ranges

In reply to Greg Kroah-Hartman

6.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Markus Niebel <[email protected]>

[ Upstream commit cd0c6872aab4d2c556a5e953e6926a1b4485e543 ]

DRAM starts at 0x80000000.

Fixes c982ecfa7992 ("arm64: dts: freescale: add initial device tree for MBa93xxLA SBC board")
---
 arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi +1 -1
index 9d2328c185c90..fe951f86a96bd 100644
@@ -19,7 +19,7 @@
 		linux,cma {
 			compatible = "shared-dma-pool";
 			reusable;
-			alloc-ranges = <0 0x60000000 0 0x40000000>;
+			alloc-ranges = <0 0x80000000 0 0x40000000>;
 			size = <0 0x10000000>;
 			linux,cma-default;
 		};
Signature · 1 line
2.43.0